xref: /aosp_15_r20/external/cronet/components/metrics/persistent_histograms.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "components/metrics/persistent_histograms.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/files/file_enumerator.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/metrics/field_trial_params.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_functions.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/metrics/persistent_histogram_allocator.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/system/sys_info.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
19*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/chromeos_buildflags.h"
21*6777b538SAndroid Build Coastguard Worker #include "components/metrics/persistent_system_profile.h"
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker namespace {
24*6777b538SAndroid Build Coastguard Worker // Creating a "spare" file for persistent metrics involves a lot of I/O and
25*6777b538SAndroid Build Coastguard Worker // isn't important so delay the operation for a while after startup.
26*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
27*6777b538SAndroid Build Coastguard Worker // Android needs the spare file and also launches faster.
28*6777b538SAndroid Build Coastguard Worker constexpr bool kSpareFileRequired = true;
29*6777b538SAndroid Build Coastguard Worker constexpr int kSpareFileCreateDelaySeconds = 10;
30*6777b538SAndroid Build Coastguard Worker #else
31*6777b538SAndroid Build Coastguard Worker // Desktop may have to restore a lot of tabs so give it more time before doing
32*6777b538SAndroid Build Coastguard Worker // non-essential work. The spare file is still a performance boost but not as
33*6777b538SAndroid Build Coastguard Worker // significant of one so it's not required.
34*6777b538SAndroid Build Coastguard Worker constexpr bool kSpareFileRequired = false;
35*6777b538SAndroid Build Coastguard Worker constexpr int kSpareFileCreateDelaySeconds = 90;
36*6777b538SAndroid Build Coastguard Worker #endif
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker // Windows sometimes creates files of the form MyFile.pma~RF71cb1793.TMP
41*6777b538SAndroid Build Coastguard Worker // when trying to rename a file to something that exists but is in-use, and
42*6777b538SAndroid Build Coastguard Worker // then fails to remove them. See https://crbug.com/934164
DeleteOldWindowsTempFiles(const base::FilePath & dir)43*6777b538SAndroid Build Coastguard Worker void DeleteOldWindowsTempFiles(const base::FilePath& dir) {
44*6777b538SAndroid Build Coastguard Worker   // Look for any temp files older than one day and remove them. The time check
45*6777b538SAndroid Build Coastguard Worker   // ensures that nothing in active transition gets deleted; these names only
46*6777b538SAndroid Build Coastguard Worker   // exists on the order of milliseconds when working properly so "one day" is
47*6777b538SAndroid Build Coastguard Worker   // generous but still ensures no big build up of these files. This is an
48*6777b538SAndroid Build Coastguard Worker   // I/O intensive task so do it in the background (enforced by "file" calls).
49*6777b538SAndroid Build Coastguard Worker   base::Time one_day_ago = base::Time::Now() - base::Days(1);
50*6777b538SAndroid Build Coastguard Worker   base::FileEnumerator file_iter(dir, /*recursive=*/false,
51*6777b538SAndroid Build Coastguard Worker                                  base::FileEnumerator::FILES);
52*6777b538SAndroid Build Coastguard Worker   for (base::FilePath path = file_iter.Next(); !path.empty();
53*6777b538SAndroid Build Coastguard Worker        path = file_iter.Next()) {
54*6777b538SAndroid Build Coastguard Worker     if (base::ToUpperASCII(path.FinalExtension()) !=
55*6777b538SAndroid Build Coastguard Worker             FILE_PATH_LITERAL(".TMP") ||
56*6777b538SAndroid Build Coastguard Worker         base::ToUpperASCII(path.BaseName().value())
57*6777b538SAndroid Build Coastguard Worker                 .find(FILE_PATH_LITERAL(".PMA~RF")) < 0) {
58*6777b538SAndroid Build Coastguard Worker       continue;
59*6777b538SAndroid Build Coastguard Worker     }
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker     const auto& info = file_iter.GetInfo();
62*6777b538SAndroid Build Coastguard Worker     if (info.IsDirectory())
63*6777b538SAndroid Build Coastguard Worker       continue;
64*6777b538SAndroid Build Coastguard Worker     if (info.GetLastModifiedTime() > one_day_ago)
65*6777b538SAndroid Build Coastguard Worker       continue;
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker     base::DeleteFile(path);
68*6777b538SAndroid Build Coastguard Worker   }
69*6777b538SAndroid Build Coastguard Worker }
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker // How much time after startup to run the above function. Two minutes is
72*6777b538SAndroid Build Coastguard Worker // enough for the system to stabilize and get the user what they want before
73*6777b538SAndroid Build Coastguard Worker // spending time on clean-up efforts.
74*6777b538SAndroid Build Coastguard Worker constexpr base::TimeDelta kDeleteOldWindowsTempFilesDelay = base::Minutes(2);
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker // Create persistent/shared memory and allow histograms to be stored in
79*6777b538SAndroid Build Coastguard Worker // it. Memory that is not actually used won't be physically mapped by the
80*6777b538SAndroid Build Coastguard Worker // system. BrowserMetrics usage, as reported in UMA, has the 99.99
81*6777b538SAndroid Build Coastguard Worker // percentile around 3MiB as of 2018-10-22.
82*6777b538SAndroid Build Coastguard Worker // Please update ServicificationBackgroundServiceTest.java if the |kAllocSize|
83*6777b538SAndroid Build Coastguard Worker // is changed.
84*6777b538SAndroid Build Coastguard Worker const size_t kAllocSize = 4 << 20;     // 4 MiB
85*6777b538SAndroid Build Coastguard Worker const uint32_t kAllocId = 0x935DDD43;  // SHA1(BrowserMetrics)
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker // Logged to UMA - keep in sync with enums.xml.
88*6777b538SAndroid Build Coastguard Worker enum InitResult {
89*6777b538SAndroid Build Coastguard Worker   kLocalMemorySuccess,
90*6777b538SAndroid Build Coastguard Worker   kLocalMemoryFailed,
91*6777b538SAndroid Build Coastguard Worker   kMappedFileSuccess,
92*6777b538SAndroid Build Coastguard Worker   kMappedFileFailed,
93*6777b538SAndroid Build Coastguard Worker   kMappedFileExists,
94*6777b538SAndroid Build Coastguard Worker   kNoSpareFile,
95*6777b538SAndroid Build Coastguard Worker   kNoUploadDir,
96*6777b538SAndroid Build Coastguard Worker   kMaxValue = kNoUploadDir
97*6777b538SAndroid Build Coastguard Worker };
98*6777b538SAndroid Build Coastguard Worker 
GetSpareFilePath(const base::FilePath & metrics_dir)99*6777b538SAndroid Build Coastguard Worker base::FilePath GetSpareFilePath(const base::FilePath& metrics_dir) {
100*6777b538SAndroid Build Coastguard Worker   return base::GlobalHistogramAllocator::ConstructFilePath(
101*6777b538SAndroid Build Coastguard Worker       metrics_dir, kBrowserMetricsName + std::string("-spare"));
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker // Initializes persistent histograms with a memory-mapped file.
InitWithMappedFile(const base::FilePath & metrics_dir,const base::FilePath & upload_dir)105*6777b538SAndroid Build Coastguard Worker InitResult InitWithMappedFile(const base::FilePath& metrics_dir,
106*6777b538SAndroid Build Coastguard Worker                               const base::FilePath& upload_dir) {
107*6777b538SAndroid Build Coastguard Worker   // The spare file in the user data dir ("BrowserMetrics-spare.pma") would
108*6777b538SAndroid Build Coastguard Worker   // have been created in the previous session. We will move it to |upload_dir|
109*6777b538SAndroid Build Coastguard Worker   // and rename it with the current time and process id for use as |active_file|
110*6777b538SAndroid Build Coastguard Worker   // (e.g. "BrowserMetrics/BrowserMetrics-1234ABCD-12345.pma").
111*6777b538SAndroid Build Coastguard Worker   // Any unreported metrics in this file will be uploaded next session.
112*6777b538SAndroid Build Coastguard Worker   base::FilePath spare_file = GetSpareFilePath(metrics_dir);
113*6777b538SAndroid Build Coastguard Worker   base::FilePath active_file =
114*6777b538SAndroid Build Coastguard Worker       base::GlobalHistogramAllocator::ConstructFilePathForUploadDir(
115*6777b538SAndroid Build Coastguard Worker           upload_dir, kBrowserMetricsName, base::Time::Now(),
116*6777b538SAndroid Build Coastguard Worker           base::GetCurrentProcId());
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   InitResult result;
119*6777b538SAndroid Build Coastguard Worker   if (!base::PathExists(upload_dir)) {
120*6777b538SAndroid Build Coastguard Worker     // Handle failure to create the directory.
121*6777b538SAndroid Build Coastguard Worker     result = kNoUploadDir;
122*6777b538SAndroid Build Coastguard Worker   } else if (base::PathExists(active_file)) {
123*6777b538SAndroid Build Coastguard Worker     // "active" filename is supposed to be unique so this shouldn't happen.
124*6777b538SAndroid Build Coastguard Worker     result = kMappedFileExists;
125*6777b538SAndroid Build Coastguard Worker   } else {
126*6777b538SAndroid Build Coastguard Worker     // Disallow multiple writers (Windows only). Needed to ensure multiple
127*6777b538SAndroid Build Coastguard Worker     // instances of Chrome aren't writing to the same file, which could happen
128*6777b538SAndroid Build Coastguard Worker     // in some rare circumstances observed in the wild (e.g. on FAT FS where the
129*6777b538SAndroid Build Coastguard Worker     // file name ends up not being unique due to truncation and two processes
130*6777b538SAndroid Build Coastguard Worker     // racing on base::PathExists(active_file) above).
131*6777b538SAndroid Build Coastguard Worker     const bool exclusive_write = true;
132*6777b538SAndroid Build Coastguard Worker     // Move any spare file into the active position.
133*6777b538SAndroid Build Coastguard Worker     base::ReplaceFile(spare_file, active_file, nullptr);
134*6777b538SAndroid Build Coastguard Worker     // Create global allocator using the |active_file|.
135*6777b538SAndroid Build Coastguard Worker     if (kSpareFileRequired && !base::PathExists(active_file)) {
136*6777b538SAndroid Build Coastguard Worker       result = kNoSpareFile;
137*6777b538SAndroid Build Coastguard Worker     } else if (base::GlobalHistogramAllocator::CreateWithFile(
138*6777b538SAndroid Build Coastguard Worker                    active_file, kAllocSize, kAllocId, kBrowserMetricsName,
139*6777b538SAndroid Build Coastguard Worker                    exclusive_write)) {
140*6777b538SAndroid Build Coastguard Worker       result = kMappedFileSuccess;
141*6777b538SAndroid Build Coastguard Worker     } else {
142*6777b538SAndroid Build Coastguard Worker       result = kMappedFileFailed;
143*6777b538SAndroid Build Coastguard Worker     }
144*6777b538SAndroid Build Coastguard Worker   }
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   return result;
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker enum PersistentHistogramsMode {
150*6777b538SAndroid Build Coastguard Worker   kNotEnabled,
151*6777b538SAndroid Build Coastguard Worker   kMappedFile,
152*6777b538SAndroid Build Coastguard Worker   kLocalMemory,
153*6777b538SAndroid Build Coastguard Worker };
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker // Implementation of InstantiatePersistentHistograms() that does the work after
156*6777b538SAndroid Build Coastguard Worker // the desired |mode| has been determined.
InstantiatePersistentHistogramsImpl(const base::FilePath & metrics_dir,PersistentHistogramsMode mode)157*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistogramsImpl(const base::FilePath& metrics_dir,
158*6777b538SAndroid Build Coastguard Worker                                          PersistentHistogramsMode mode) {
159*6777b538SAndroid Build Coastguard Worker   // Create a directory for storing completed metrics files. Files in this
160*6777b538SAndroid Build Coastguard Worker   // directory must have embedded system profiles. If the directory can't be
161*6777b538SAndroid Build Coastguard Worker   // created, the file will just be deleted below.
162*6777b538SAndroid Build Coastguard Worker   base::FilePath upload_dir = metrics_dir.AppendASCII(kBrowserMetricsName);
163*6777b538SAndroid Build Coastguard Worker   // TODO(crbug.com/1183166): Only create the dir in kMappedFile mode.
164*6777b538SAndroid Build Coastguard Worker   base::CreateDirectory(upload_dir);
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker   InitResult result;
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker   // Create a global histogram allocator using the desired storage type.
169*6777b538SAndroid Build Coastguard Worker   switch (mode) {
170*6777b538SAndroid Build Coastguard Worker     case kMappedFile:
171*6777b538SAndroid Build Coastguard Worker       result = InitWithMappedFile(metrics_dir, upload_dir);
172*6777b538SAndroid Build Coastguard Worker       break;
173*6777b538SAndroid Build Coastguard Worker     case kLocalMemory:
174*6777b538SAndroid Build Coastguard Worker       // Use local memory for storage even though it will not persist across
175*6777b538SAndroid Build Coastguard Worker       // an unclean shutdown. This sets the result but the actual creation is
176*6777b538SAndroid Build Coastguard Worker       // done below.
177*6777b538SAndroid Build Coastguard Worker       result = kLocalMemorySuccess;
178*6777b538SAndroid Build Coastguard Worker       break;
179*6777b538SAndroid Build Coastguard Worker     case kNotEnabled:
180*6777b538SAndroid Build Coastguard Worker       // Persistent metric storage is disabled. Must return here.
181*6777b538SAndroid Build Coastguard Worker       // TODO(crbug.com/1183166): Log the histogram below in this case too.
182*6777b538SAndroid Build Coastguard Worker       return;
183*6777b538SAndroid Build Coastguard Worker   }
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Get the allocator that was just created and report result. Exit if the
186*6777b538SAndroid Build Coastguard Worker   // allocator could not be created.
187*6777b538SAndroid Build Coastguard Worker   base::UmaHistogramEnumeration("UMA.PersistentHistograms.InitResult", result);
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   base::GlobalHistogramAllocator* allocator =
190*6777b538SAndroid Build Coastguard Worker       base::GlobalHistogramAllocator::Get();
191*6777b538SAndroid Build Coastguard Worker   if (!allocator) {
192*6777b538SAndroid Build Coastguard Worker     // If no allocator was created above, try to create a LocalMemory one here.
193*6777b538SAndroid Build Coastguard Worker     // This avoids repeating the call many times above. In the case where
194*6777b538SAndroid Build Coastguard Worker     // persistence is disabled, an early return is done above.
195*6777b538SAndroid Build Coastguard Worker     base::GlobalHistogramAllocator::CreateWithLocalMemory(kAllocSize, kAllocId,
196*6777b538SAndroid Build Coastguard Worker                                                           kBrowserMetricsName);
197*6777b538SAndroid Build Coastguard Worker     allocator = base::GlobalHistogramAllocator::Get();
198*6777b538SAndroid Build Coastguard Worker     if (!allocator) {
199*6777b538SAndroid Build Coastguard Worker       return;
200*6777b538SAndroid Build Coastguard Worker     }
201*6777b538SAndroid Build Coastguard Worker   }
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   // Store a copy of the system profile in this allocator.
204*6777b538SAndroid Build Coastguard Worker   metrics::GlobalPersistentSystemProfile::GetInstance()
205*6777b538SAndroid Build Coastguard Worker       ->RegisterPersistentAllocator(allocator->memory_allocator());
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker   // Create tracking histograms for the allocator and record storage file.
208*6777b538SAndroid Build Coastguard Worker   allocator->CreateTrackingHistograms(kBrowserMetricsName);
209*6777b538SAndroid Build Coastguard Worker }
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker }  // namespace
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker BASE_FEATURE(
214*6777b538SAndroid Build Coastguard Worker     kPersistentHistogramsFeature,
215*6777b538SAndroid Build Coastguard Worker     "PersistentHistograms",
216*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_FUCHSIA)
217*6777b538SAndroid Build Coastguard Worker     // TODO(crbug.com/42050425): Enable once writable mmap() is supported. Also
218*6777b538SAndroid Build Coastguard Worker     // move the initialization earlier to chrome/app/chrome_main_delegate.cc.
219*6777b538SAndroid Build Coastguard Worker     base::FEATURE_DISABLED_BY_DEFAULT
220*6777b538SAndroid Build Coastguard Worker #else
221*6777b538SAndroid Build Coastguard Worker     base::FEATURE_ENABLED_BY_DEFAULT
222*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_FUCHSIA)
223*6777b538SAndroid Build Coastguard Worker );
224*6777b538SAndroid Build Coastguard Worker 
225*6777b538SAndroid Build Coastguard Worker const char kPersistentHistogramStorageMappedFile[] = "MappedFile";
226*6777b538SAndroid Build Coastguard Worker const char kPersistentHistogramStorageLocalMemory[] = "LocalMemory";
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker const base::FeatureParam<std::string> kPersistentHistogramsStorage{
229*6777b538SAndroid Build Coastguard Worker     &kPersistentHistogramsFeature, "storage",
230*6777b538SAndroid Build Coastguard Worker     kPersistentHistogramStorageMappedFile};
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker const char kBrowserMetricsName[] = "BrowserMetrics";
233*6777b538SAndroid Build Coastguard Worker const char kDeferredBrowserMetricsName[] = "DeferredBrowserMetrics";
234*6777b538SAndroid Build Coastguard Worker 
InstantiatePersistentHistograms(const base::FilePath & metrics_dir,bool persistent_histograms_enabled,base::StringPiece storage)235*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistograms(const base::FilePath& metrics_dir,
236*6777b538SAndroid Build Coastguard Worker                                      bool persistent_histograms_enabled,
237*6777b538SAndroid Build Coastguard Worker                                      base::StringPiece storage) {
238*6777b538SAndroid Build Coastguard Worker   PersistentHistogramsMode mode = kNotEnabled;
239*6777b538SAndroid Build Coastguard Worker   // Note: The extra feature check is needed so that we don't use the default
240*6777b538SAndroid Build Coastguard Worker   // value of the storage param if the feature is disabled.
241*6777b538SAndroid Build Coastguard Worker   if (persistent_histograms_enabled) {
242*6777b538SAndroid Build Coastguard Worker     if (storage == kPersistentHistogramStorageMappedFile) {
243*6777b538SAndroid Build Coastguard Worker       mode = kMappedFile;
244*6777b538SAndroid Build Coastguard Worker     } else if (storage == kPersistentHistogramStorageLocalMemory) {
245*6777b538SAndroid Build Coastguard Worker       mode = kLocalMemory;
246*6777b538SAndroid Build Coastguard Worker     }
247*6777b538SAndroid Build Coastguard Worker   }
248*6777b538SAndroid Build Coastguard Worker 
249*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
250*6777b538SAndroid Build Coastguard Worker // of lacros-chrome is complete.
251*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
252*6777b538SAndroid Build Coastguard Worker   // Linux kernel 4.4.0.* shows a huge number of SIGBUS crashes with persistent
253*6777b538SAndroid Build Coastguard Worker   // histograms enabled using a mapped file.  Change this to use local memory.
254*6777b538SAndroid Build Coastguard Worker   // https://bugs.chromium.org/p/chromium/issues/detail?id=753741
255*6777b538SAndroid Build Coastguard Worker   if (mode == kMappedFile) {
256*6777b538SAndroid Build Coastguard Worker     int major, minor, bugfix;
257*6777b538SAndroid Build Coastguard Worker     base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
258*6777b538SAndroid Build Coastguard Worker     if (major == 4 && minor == 4 && bugfix == 0)
259*6777b538SAndroid Build Coastguard Worker       mode = kLocalMemory;
260*6777b538SAndroid Build Coastguard Worker   }
261*6777b538SAndroid Build Coastguard Worker #endif
262*6777b538SAndroid Build Coastguard Worker 
263*6777b538SAndroid Build Coastguard Worker   InstantiatePersistentHistogramsImpl(metrics_dir, mode);
264*6777b538SAndroid Build Coastguard Worker }
265*6777b538SAndroid Build Coastguard Worker 
PersistentHistogramsCleanup(const base::FilePath & metrics_dir)266*6777b538SAndroid Build Coastguard Worker void PersistentHistogramsCleanup(const base::FilePath& metrics_dir) {
267*6777b538SAndroid Build Coastguard Worker   base::FilePath spare_file = GetSpareFilePath(metrics_dir);
268*6777b538SAndroid Build Coastguard Worker 
269*6777b538SAndroid Build Coastguard Worker   // Schedule the creation of a "spare" file for use on the next run.
270*6777b538SAndroid Build Coastguard Worker   base::ThreadPool::PostDelayedTask(
271*6777b538SAndroid Build Coastguard Worker       FROM_HERE,
272*6777b538SAndroid Build Coastguard Worker       {base::MayBlock(), base::TaskPriority::LOWEST,
273*6777b538SAndroid Build Coastguard Worker        base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
274*6777b538SAndroid Build Coastguard Worker       base::BindOnce(
275*6777b538SAndroid Build Coastguard Worker           base::IgnoreResult(&base::GlobalHistogramAllocator::CreateSpareFile),
276*6777b538SAndroid Build Coastguard Worker           std::move(spare_file), kAllocSize),
277*6777b538SAndroid Build Coastguard Worker       base::Seconds(kSpareFileCreateDelaySeconds));
278*6777b538SAndroid Build Coastguard Worker 
279*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
280*6777b538SAndroid Build Coastguard Worker   // Post a best effort task that will delete files. Unlike SKIP_ON_SHUTDOWN,
281*6777b538SAndroid Build Coastguard Worker   // which will block on the deletion if the task already started,
282*6777b538SAndroid Build Coastguard Worker   // CONTINUE_ON_SHUTDOWN will not block shutdown on the task completing. It's
283*6777b538SAndroid Build Coastguard Worker   // not a *necessity* to delete the files the same session they are "detected".
284*6777b538SAndroid Build Coastguard Worker   // On shutdown, the deletion will be interrupted.
285*6777b538SAndroid Build Coastguard Worker   base::ThreadPool::PostDelayedTask(
286*6777b538SAndroid Build Coastguard Worker       FROM_HERE,
287*6777b538SAndroid Build Coastguard Worker       {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
288*6777b538SAndroid Build Coastguard Worker        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
289*6777b538SAndroid Build Coastguard Worker       base::BindOnce(&DeleteOldWindowsTempFiles, metrics_dir),
290*6777b538SAndroid Build Coastguard Worker       kDeleteOldWindowsTempFilesDelay);
291*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_WIN)
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker 
InstantiatePersistentHistogramsWithFeaturesAndCleanup(const base::FilePath & metrics_dir)294*6777b538SAndroid Build Coastguard Worker void InstantiatePersistentHistogramsWithFeaturesAndCleanup(
295*6777b538SAndroid Build Coastguard Worker     const base::FilePath& metrics_dir) {
296*6777b538SAndroid Build Coastguard Worker   InstantiatePersistentHistograms(
297*6777b538SAndroid Build Coastguard Worker       metrics_dir, base::FeatureList::IsEnabled(kPersistentHistogramsFeature),
298*6777b538SAndroid Build Coastguard Worker       kPersistentHistogramsStorage.Get());
299*6777b538SAndroid Build Coastguard Worker   PersistentHistogramsCleanup(metrics_dir);
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker 
DeferBrowserMetrics(const base::FilePath & metrics_dir)302*6777b538SAndroid Build Coastguard Worker bool DeferBrowserMetrics(const base::FilePath& metrics_dir) {
303*6777b538SAndroid Build Coastguard Worker   base::GlobalHistogramAllocator* allocator =
304*6777b538SAndroid Build Coastguard Worker       base::GlobalHistogramAllocator::Get();
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   if (!allocator || !allocator->HasPersistentLocation()) {
307*6777b538SAndroid Build Coastguard Worker     return false;
308*6777b538SAndroid Build Coastguard Worker   }
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker   base::FilePath deferred_metrics_dir =
311*6777b538SAndroid Build Coastguard Worker       metrics_dir.AppendASCII(kDeferredBrowserMetricsName);
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker   if (!base::CreateDirectory(deferred_metrics_dir)) {
314*6777b538SAndroid Build Coastguard Worker     return false;
315*6777b538SAndroid Build Coastguard Worker   }
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   return allocator->MovePersistentFile(deferred_metrics_dir);
318*6777b538SAndroid Build Coastguard Worker }
319