1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/statistics_recorder.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/at_exit.h" 1094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/debug/leak_annotations.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/json/string_escape.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 130c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez#include "base/memory/ptr_util.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/metrics/histogram.h" 150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/metrics/metrics_hashes.h" 1694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/metrics/persistent_histogram_allocator.h" 170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/stl_util.h" 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/stringprintf.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/synchronization/lock.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/values.h" 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 2345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Initialize histogram statistics gathering system. 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::LazyInstance<base::StatisticsRecorder>::Leaky g_statistics_recorder_ = 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat LAZY_INSTANCE_INITIALIZER; 2745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 2845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkobool HistogramNameLesser(const base::HistogramBase* a, 2945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const base::HistogramBase* b) { 3045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return a->histogram_name() < b->histogram_name(); 3145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 3245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 3745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator::HistogramIterator( 3845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const HistogramMap::iterator& iter, bool include_persistent) 3945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko : iter_(iter), 4045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko include_persistent_(include_persistent) { 4194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // The starting location could point to a persistent histogram when such 4294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // is not wanted. If so, skip it. 4394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (!include_persistent_ && iter_ != histograms_->end() && 4494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez (iter_->second->flags() & HistogramBase::kIsPersistent)) { 4594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // This operator will continue to skip until a non-persistent histogram 4694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // is found. 4794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez operator++(); 4894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez } 4945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 5045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 5145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator::HistogramIterator( 5245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const HistogramIterator& rhs) 5345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko : iter_(rhs.iter_), 5445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko include_persistent_(rhs.include_persistent_) { 5545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 5645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 5745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator::~HistogramIterator() {} 5845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 5945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator& 6045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator::operator++() { 6145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko const HistogramMap::iterator histograms_end = histograms_->end(); 6245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (iter_ == histograms_end || lock_ == NULL) 6345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return *this; 6445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 6545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko base::AutoLock auto_lock(*lock_); 6645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 6745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (;;) { 6845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ++iter_; 6945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (iter_ == histograms_end) 7045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko break; 7145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!include_persistent_ && (iter_->second->flags() & 7245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko HistogramBase::kIsPersistent)) { 7345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko continue; 7445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 7545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko break; 7645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 7745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 7845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return *this; 7945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 8045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 8145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::~StatisticsRecorder() { 8245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DCHECK(lock_); 8345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DCHECK(histograms_); 8445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko DCHECK(ranges_); 8545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 8694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Clean out what this object created and then restore what existed before. 8745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko Reset(); 8894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez base::AutoLock auto_lock(*lock_); 8994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez histograms_ = existing_histograms_.release(); 9094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez callbacks_ = existing_callbacks_.release(); 9194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ranges_ = existing_ranges_.release(); 9245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 9345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid StatisticsRecorder::Initialize() { 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Ensure that an instance of the StatisticsRecorder object is created. 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat g_statistics_recorder_.Get(); 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool StatisticsRecorder::IsActive() { 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return false; 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL != histograms_; 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratHistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase* histogram) { 11194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // As per crbug.com/79322 the histograms are intentionally leaked, so we need 11294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // to annotate them. Because ANNOTATE_LEAKING_OBJECT_PTR may be used only once 11394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // for an object, the duplicates should not be annotated. 11494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Callers are responsible for not calling RegisterOrDeleteDuplicate(ptr) 11594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // twice if (lock_ == NULL) || (!histograms_). 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) { 11794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return histogram; 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase* histogram_to_delete = NULL; 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat HistogramBase* histogram_to_return = NULL; 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (histograms_ == NULL) { 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_to_return = histogram; 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& name = histogram->histogram_name(); 12994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HistogramMap::iterator it = histograms_->find(name); 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (histograms_->end() == it) { 13194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // The StringKey references the name within |histogram| rather than 13294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // making a copy. 13394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez (*histograms_)[name] = histogram; 13494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(histogram); // see crbug.com/79322 1350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // If there are callbacks for this histogram, we set the kCallbackExists 1360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // flag. 1370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko auto callback_iterator = callbacks_->find(name); 1380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (callback_iterator != callbacks_->end()) { 1390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (!callback_iterator->second.is_null()) 1400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko histogram->SetFlags(HistogramBase::kCallbackExists); 1410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko else 1420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko histogram->ClearFlags(HistogramBase::kCallbackExists); 1430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_to_return = histogram; 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else if (histogram == it->second) { 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The histogram was registered before. 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_to_return = histogram; 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We already have one histogram with this name. 1500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_EQ(histogram->histogram_name(), 1510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko it->second->histogram_name()) << "hash collision"; 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_to_return = it->second; 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram_to_delete = histogram; 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete histogram_to_delete; 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return histogram_to_return; 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst BucketRanges* StatisticsRecorder::RegisterOrDeleteDuplicateRanges( 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const BucketRanges* ranges) { 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(ranges->HasValidChecksum()); 16594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<const BucketRanges> ranges_deleter; 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) { 16894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(ranges); 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ranges; 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ranges_ == NULL) { 17494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(ranges); 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ranges; 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::list<const BucketRanges*>* checksum_matching_list; 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat RangesMap::iterator ranges_it = ranges_->find(ranges->checksum()); 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ranges_->end() == ranges_it) { 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Add a new matching list to map. 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat checksum_matching_list = new std::list<const BucketRanges*>(); 18394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ANNOTATE_LEAKING_OBJECT_PTR(checksum_matching_list); 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*ranges_)[ranges->checksum()] = checksum_matching_list; 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat checksum_matching_list = ranges_it->second; 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const BucketRanges* existing_ranges : *checksum_matching_list) { 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (existing_ranges->Equals(ranges)) { 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (existing_ranges == ranges) { 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ranges; 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } else { 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ranges_deleter.reset(ranges); 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return existing_ranges; 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We haven't found a BucketRanges which has the same ranges. Register the 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // new BucketRanges. 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat checksum_matching_list->push_front(ranges); 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ranges; 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid StatisticsRecorder::WriteHTMLGraph(const std::string& query, 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string* output) { 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!IsActive()) 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Histograms snapshot; 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat GetSnapshot(query, &snapshot); 21345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::sort(snapshot.begin(), snapshot.end(), &HistogramNameLesser); 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const HistogramBase* histogram : snapshot) { 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram->WriteHTMLGraph(output); 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append("<br><hr><br>"); 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid StatisticsRecorder::WriteGraph(const std::string& query, 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string* output) { 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!IsActive()) 224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (query.length()) 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else 228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append("Collections of all histograms\n"); 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Histograms snapshot; 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat GetSnapshot(query, &snapshot); 23245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::sort(snapshot.begin(), snapshot.end(), &HistogramNameLesser); 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const HistogramBase* histogram : snapshot) { 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram->WriteAscii(output); 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->append("\n"); 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstd::string StatisticsRecorder::ToJSON(const std::string& query) { 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!IsActive()) 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return std::string(); 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string output("{"); 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (!query.empty()) { 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += "\"query\":"; 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EscapeJSONString(query, true, &output); 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += ","; 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Histograms snapshot; 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat GetSnapshot(query, &snapshot); 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += "\"histograms\":["; 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat bool first_histogram = true; 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const HistogramBase* histogram : snapshot) { 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (first_histogram) 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat first_histogram = false; 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat else 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += ","; 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string json; 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histogram->WriteJSON(&json); 262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += json; 263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output += "]}"; 265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return output; 266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid StatisticsRecorder::GetHistograms(Histograms* output) { 270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) 271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (histograms_ == NULL) 274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 276b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& entry : *histograms_) { 277b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->push_back(entry.second); 278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid StatisticsRecorder::GetBucketRanges( 283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::vector<const BucketRanges*>* output) { 284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) 285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (ranges_ == NULL) 288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 290b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& entry : *ranges_) { 2910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez for (auto* range_entry : *entry.second) { 292b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat output->push_back(range_entry); 293b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 294b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 295b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 296b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 297b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 29845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoHistogramBase* StatisticsRecorder::FindHistogram(base::StringPiece name) { 29994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // This must be called *before* the lock is acquired below because it will 30094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // call back into this object to register histograms. Those called methods 30194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // will acquire the lock at that time. 30294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ImportGlobalPersistentHistograms(); 30394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 304b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) 305b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 306b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 307b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (histograms_ == NULL) 308b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 309b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 31094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HistogramMap::iterator it = histograms_->find(name); 311b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (histograms_->end() == it) 312b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return NULL; 313b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return it->second; 314b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 315b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 3160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// static 31745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator StatisticsRecorder::begin( 31845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko bool include_persistent) { 31994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez DCHECK(histograms_); 32094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez ImportGlobalPersistentHistograms(); 32194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 32294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HistogramMap::iterator iter_begin; 32394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez { 32494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez base::AutoLock auto_lock(*lock_); 32594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez iter_begin = histograms_->begin(); 32694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez } 32794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return HistogramIterator(iter_begin, include_persistent); 32845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 32945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 33045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 33145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoStatisticsRecorder::HistogramIterator StatisticsRecorder::end() { 33294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HistogramMap::iterator iter_end; 33394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez { 33494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez base::AutoLock auto_lock(*lock_); 33594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez iter_end = histograms_->end(); 33694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez } 33794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return HistogramIterator(iter_end, true); 33845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 33945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 34045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 3410c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid StatisticsRecorder::InitLogOnShutdown() { 3420c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (lock_ == nullptr) 3430c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez return; 3440c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::AutoLock auto_lock(*lock_); 3450c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez g_statistics_recorder_.Get().InitLogOnShutdownWithoutLock(); 3460c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez} 3470c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 3480c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez// static 34945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkovoid StatisticsRecorder::GetSnapshot(const std::string& query, 35045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko Histograms* snapshot) { 35145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (lock_ == NULL) 35245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return; 35345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko base::AutoLock auto_lock(*lock_); 35445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (histograms_ == NULL) 35545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return; 35645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 35745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko for (const auto& entry : *histograms_) { 35845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (entry.second->histogram_name().find(query) != std::string::npos) 35945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko snapshot->push_back(entry.second); 36045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 36145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 36245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 36345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 3640d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkobool StatisticsRecorder::SetCallback( 3650d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const std::string& name, 3660d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const StatisticsRecorder::OnSampleCallback& cb) { 3670d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!cb.is_null()); 3680d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (lock_ == NULL) 3690d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return false; 3700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::AutoLock auto_lock(*lock_); 3710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (histograms_ == NULL) 3720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return false; 3730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3740d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (ContainsKey(*callbacks_, name)) 3750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return false; 3760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko callbacks_->insert(std::make_pair(name, cb)); 3770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 37894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez auto it = histograms_->find(name); 37994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (it != histograms_->end()) 3800d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko it->second->SetFlags(HistogramBase::kCallbackExists); 3810d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3820d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return true; 3830d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3840d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3850d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// static 3860d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid StatisticsRecorder::ClearCallback(const std::string& name) { 3870d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (lock_ == NULL) 3880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return; 3890d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::AutoLock auto_lock(*lock_); 3900d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (histograms_ == NULL) 3910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return; 3920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3930d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko callbacks_->erase(name); 3940d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // We also clear the flag from the histogram (if it exists). 39694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez auto it = histograms_->find(name); 39794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (it != histograms_->end()) 3980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko it->second->ClearFlags(HistogramBase::kCallbackExists); 3990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 4000d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 4010d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// static 4020d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoStatisticsRecorder::OnSampleCallback StatisticsRecorder::FindCallback( 4030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const std::string& name) { 4040d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (lock_ == NULL) 4050d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return OnSampleCallback(); 4060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko base::AutoLock auto_lock(*lock_); 4070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (histograms_ == NULL) 4080d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return OnSampleCallback(); 4090d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 4100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko auto callback_iterator = callbacks_->find(name); 4110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return callback_iterator != callbacks_->end() ? callback_iterator->second 4120d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko : OnSampleCallback(); 4130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 4140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 41545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 41645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkosize_t StatisticsRecorder::GetHistogramCount() { 41745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!lock_) 41845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return 0; 41945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 42145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!histograms_) 42245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return 0; 42345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return histograms_->size(); 42445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 42645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 42794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid StatisticsRecorder::ForgetHistogramForTesting(base::StringPiece name) { 42894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (histograms_) 42994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez histograms_->erase(name); 43045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 43145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 43245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 4330c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezstd::unique_ptr<StatisticsRecorder> 4340c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector ChavezStatisticsRecorder::CreateTemporaryForTesting() { 4350c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez return WrapUnique(new StatisticsRecorder()); 4360c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez} 4370c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 4380c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez// static 43994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid StatisticsRecorder::UninitializeForTesting() { 44094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Stop now if it's never been initialized. 44194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (lock_ == NULL || histograms_ == NULL) 44294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return; 44394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 44494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Get the global instance and destruct it. It's held in static memory so 44594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // can't "delete" it; call the destructor explicitly. 44694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez DCHECK(g_statistics_recorder_.private_instance_); 44794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez g_statistics_recorder_.Get().~StatisticsRecorder(); 44894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 44994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Now the ugly part. There's no official way to release a LazyInstance once 45094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // created so it's necessary to clear out an internal variable which 45194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // shouldn't be publicly visible but is for initialization reasons. 45294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez g_statistics_recorder_.private_instance_ = 0; 45394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez} 45494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 45594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez// static 45694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid StatisticsRecorder::ImportGlobalPersistentHistograms() { 45794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (lock_ == NULL) 45894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return; 45994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 46094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // Import histograms from known persistent storage. Histograms could have 46194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // been added by other processes and they must be fetched and recognized 46294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // locally. If the persistent memory segment is not shared between processes, 46394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez // this call does nothing. 46494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez GlobalHistogramAllocator* allocator = GlobalHistogramAllocator::Get(); 46594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez if (allocator) 46694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez allocator->ImportHistogramsToStatisticsRecorder(); 467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// This singleton instance should be started during the single threaded portion 470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// of main(), and hence it is not thread safe. It initializes globals to 471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// provide support for all future calls. 472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratStatisticsRecorder::StatisticsRecorder() { 473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (lock_ == NULL) { 474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // This will leak on purpose. It's the only way to make sure we won't race 475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // against the static uninitialization of the module while one of our 476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // static methods relying on the lock get called at an inappropriate time 477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // during the termination phase. Since it's a static data member, we will 478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // leak one per process, which would be similar to the instance allocated 479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // during static initialization and released only on process termination. 480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat lock_ = new base::Lock; 481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 48294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 48494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 48594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez existing_histograms_.reset(histograms_); 48694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez existing_callbacks_.reset(callbacks_); 48794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez existing_ranges_.reset(ranges_); 48894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histograms_ = new HistogramMap; 4900d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko callbacks_ = new CallbackMap; 491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ranges_ = new RangesMap; 492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 4930c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez InitLogOnShutdownWithoutLock(); 4940c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez} 4950c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 4960c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezvoid StatisticsRecorder::InitLogOnShutdownWithoutLock() { 4970c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (!vlog_initialized_ && VLOG_IS_ON(1)) { 4980c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez vlog_initialized_ = true; 499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this); 5000c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez } 501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 503b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 50445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenkovoid StatisticsRecorder::Reset() { 50545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // If there's no lock then there is nothing to reset. 50645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!lock_) 50745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko return; 508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 50994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<HistogramMap> histograms_deleter; 51094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<CallbackMap> callbacks_deleter; 51194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<RangesMap> ranges_deleter; 512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We don't delete lock_ on purpose to avoid having to properly protect 513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // against it going away after we checked for NULL in the static methods. 514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::AutoLock auto_lock(*lock_); 516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histograms_deleter.reset(histograms_); 5170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko callbacks_deleter.reset(callbacks_); 518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ranges_deleter.reset(ranges_); 519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat histograms_ = NULL; 5200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko callbacks_ = NULL; 521b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ranges_ = NULL; 522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // We are going to leak the histograms and the ranges. 524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 52645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko// static 52794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid StatisticsRecorder::DumpHistogramsToVlog(void* /*instance*/) { 52845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko std::string output; 52945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko StatisticsRecorder::WriteGraph(std::string(), &output); 53045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko VLOG(1) << output; 53145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 53245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratStatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; 536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 5370d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoStatisticsRecorder::CallbackMap* StatisticsRecorder::callbacks_ = NULL; 5380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// static 539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratStatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL; 540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::Lock* StatisticsRecorder::lock_ = NULL; 542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 544