statistics_recorder_unittest.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/metrics/statistics_recorder.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/json/json_reader.h"
  11. #include "base/logging.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "base/metrics/histogram_base.h"
  14. #include "base/metrics/histogram_macros.h"
  15. #include "base/metrics/metrics_hashes.h"
  16. #include "base/metrics/persistent_histogram_allocator.h"
  17. #include "base/metrics/record_histogram_checker.h"
  18. #include "base/metrics/sparse_histogram.h"
  19. #include "base/test/task_environment.h"
  20. #include "base/values.h"
  21. #include "testing/gmock/include/gmock/gmock.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/abseil-cpp/absl/types/optional.h"
  24. namespace {
  25. // Class to make sure any manipulations we do to the min log level are
  26. // contained (i.e., do not affect other unit tests).
  27. class LogStateSaver {
  28. public:
  29. LogStateSaver() = default;
  30. LogStateSaver(const LogStateSaver&) = delete;
  31. LogStateSaver& operator=(const LogStateSaver&) = delete;
  32. ~LogStateSaver() { logging::SetMinLogLevel(old_min_log_level_); }
  33. private:
  34. int old_min_log_level_ = logging::GetMinLogLevel();
  35. };
  36. // Test implementation of RecordHistogramChecker interface.
  37. class OddRecordHistogramChecker : public base::RecordHistogramChecker {
  38. public:
  39. ~OddRecordHistogramChecker() override = default;
  40. // base::RecordHistogramChecker:
  41. bool ShouldRecord(uint32_t histogram_hash) const override {
  42. return histogram_hash % 2;
  43. }
  44. };
  45. } // namespace
  46. namespace base {
  47. using testing::IsEmpty;
  48. using testing::SizeIs;
  49. using testing::UnorderedElementsAre;
  50. class StatisticsRecorderTest : public testing::TestWithParam<bool> {
  51. public:
  52. StatisticsRecorderTest(const StatisticsRecorderTest&) = delete;
  53. StatisticsRecorderTest& operator=(const StatisticsRecorderTest&) = delete;
  54. protected:
  55. const int32_t kAllocatorMemorySize = 64 << 10; // 64 KiB
  56. StatisticsRecorderTest() : use_persistent_histogram_allocator_(GetParam()) {
  57. // Each test will have a clean state (no Histogram / BucketRanges
  58. // registered).
  59. InitializeStatisticsRecorder();
  60. // Use persistent memory for histograms if so indicated by test parameter.
  61. if (use_persistent_histogram_allocator_) {
  62. GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0,
  63. "StatisticsRecorderTest");
  64. }
  65. }
  66. ~StatisticsRecorderTest() override {
  67. GlobalHistogramAllocator::ReleaseForTesting();
  68. UninitializeStatisticsRecorder();
  69. }
  70. void InitializeStatisticsRecorder() {
  71. DCHECK(!statistics_recorder_);
  72. statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
  73. }
  74. // Deletes the global recorder if there is any. This is used by test
  75. // NotInitialized to ensure a clean global state.
  76. void UninitializeStatisticsRecorder() {
  77. statistics_recorder_.reset();
  78. delete StatisticsRecorder::top_;
  79. DCHECK(!StatisticsRecorder::top_);
  80. }
  81. bool HasGlobalRecorder() { return StatisticsRecorder::top_ != nullptr; }
  82. Histogram* CreateHistogram(const char* name,
  83. HistogramBase::Sample min,
  84. HistogramBase::Sample max,
  85. size_t bucket_count) {
  86. BucketRanges* ranges = new BucketRanges(bucket_count + 1);
  87. Histogram::InitializeBucketRanges(min, max, ranges);
  88. const BucketRanges* registered_ranges =
  89. StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
  90. return new Histogram(name, registered_ranges);
  91. }
  92. void InitLogOnShutdown() { StatisticsRecorder::InitLogOnShutdown(); }
  93. bool IsVLogInitialized() { return StatisticsRecorder::is_vlog_initialized_; }
  94. void ResetVLogInitialized() {
  95. UninitializeStatisticsRecorder();
  96. StatisticsRecorder::is_vlog_initialized_ = false;
  97. }
  98. const bool use_persistent_histogram_allocator_;
  99. std::unique_ptr<StatisticsRecorder> statistics_recorder_;
  100. std::unique_ptr<GlobalHistogramAllocator> old_global_allocator_;
  101. private:
  102. LogStateSaver log_state_saver_;
  103. };
  104. // Run all HistogramTest cases with both heap and persistent memory.
  105. INSTANTIATE_TEST_SUITE_P(Allocator, StatisticsRecorderTest, testing::Bool());
  106. TEST_P(StatisticsRecorderTest, NotInitialized) {
  107. UninitializeStatisticsRecorder();
  108. EXPECT_FALSE(HasGlobalRecorder());
  109. HistogramBase* const histogram =
  110. CreateHistogram("TestHistogram", 1, 1000, 10);
  111. EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicate(histogram),
  112. histogram);
  113. EXPECT_TRUE(HasGlobalRecorder());
  114. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  115. UnorderedElementsAre(histogram));
  116. UninitializeStatisticsRecorder();
  117. EXPECT_FALSE(HasGlobalRecorder());
  118. BucketRanges* const ranges = new BucketRanges(3);
  119. ranges->ResetChecksum();
  120. EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges),
  121. ranges);
  122. EXPECT_TRUE(HasGlobalRecorder());
  123. EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
  124. UnorderedElementsAre(ranges));
  125. }
  126. TEST_P(StatisticsRecorderTest, RegisterHistogram) {
  127. // Create a Histogram that was not registered.
  128. Histogram* const histogram1 = CreateHistogram("TestHistogram1", 1, 1000, 10);
  129. EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
  130. // Register the Histogram.
  131. EXPECT_EQ(histogram1,
  132. StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
  133. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  134. UnorderedElementsAre(histogram1));
  135. // Register the same Histogram again.
  136. EXPECT_EQ(histogram1,
  137. StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
  138. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  139. UnorderedElementsAre(histogram1));
  140. // Register another Histogram with the same name.
  141. Histogram* const histogram2 = CreateHistogram("TestHistogram1", 1, 1000, 10);
  142. EXPECT_NE(histogram1, histogram2);
  143. EXPECT_EQ(histogram1,
  144. StatisticsRecorder::RegisterOrDeleteDuplicate(histogram2));
  145. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  146. UnorderedElementsAre(histogram1));
  147. // Register another Histogram with a different name.
  148. Histogram* const histogram3 = CreateHistogram("TestHistogram0", 1, 1000, 10);
  149. EXPECT_NE(histogram1, histogram3);
  150. EXPECT_EQ(histogram3,
  151. StatisticsRecorder::RegisterOrDeleteDuplicate(histogram3));
  152. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  153. UnorderedElementsAre(histogram1, histogram3));
  154. }
  155. TEST_P(StatisticsRecorderTest, FindHistogram) {
  156. HistogramBase* histogram1 = Histogram::FactoryGet(
  157. "TestHistogram1", 1, 1000, 10, HistogramBase::kNoFlags);
  158. HistogramBase* histogram2 = Histogram::FactoryGet(
  159. "TestHistogram2", 1, 1000, 10, HistogramBase::kNoFlags);
  160. EXPECT_EQ(histogram1, StatisticsRecorder::FindHistogram("TestHistogram1"));
  161. EXPECT_EQ(histogram2, StatisticsRecorder::FindHistogram("TestHistogram2"));
  162. EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
  163. // Create a new global allocator using the same memory as the old one. Any
  164. // old one is kept around so the memory doesn't get released.
  165. old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
  166. if (use_persistent_histogram_allocator_) {
  167. GlobalHistogramAllocator::CreateWithPersistentMemory(
  168. const_cast<void*>(old_global_allocator_->data()),
  169. old_global_allocator_->length(), 0, old_global_allocator_->Id(),
  170. old_global_allocator_->Name());
  171. }
  172. // Reset statistics-recorder to validate operation from a clean start.
  173. UninitializeStatisticsRecorder();
  174. InitializeStatisticsRecorder();
  175. if (use_persistent_histogram_allocator_) {
  176. EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram1"));
  177. EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram2"));
  178. } else {
  179. EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram1"));
  180. EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram2"));
  181. }
  182. EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
  183. }
  184. TEST_P(StatisticsRecorderTest, WithName) {
  185. Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, Histogram::kNoFlags);
  186. Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, Histogram::kNoFlags);
  187. Histogram::FactoryGet("TestHistogram3", 1, 1000, 10, Histogram::kNoFlags);
  188. const auto histograms = StatisticsRecorder::GetHistograms();
  189. EXPECT_THAT(histograms, SizeIs(3));
  190. EXPECT_THAT(StatisticsRecorder::WithName(histograms, ""), SizeIs(3));
  191. EXPECT_THAT(StatisticsRecorder::WithName(histograms, "Test"), SizeIs(3));
  192. EXPECT_THAT(StatisticsRecorder::WithName(histograms, "1"), SizeIs(1));
  193. EXPECT_THAT(StatisticsRecorder::WithName(histograms, "hello"), IsEmpty());
  194. }
  195. TEST_P(StatisticsRecorderTest, RegisterHistogramWithFactoryGet) {
  196. EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
  197. // Create a histogram.
  198. HistogramBase* const histogram1 = Histogram::FactoryGet(
  199. "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
  200. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  201. UnorderedElementsAre(histogram1));
  202. // Get an existing histogram.
  203. HistogramBase* const histogram2 = Histogram::FactoryGet(
  204. "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
  205. EXPECT_EQ(histogram1, histogram2);
  206. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  207. UnorderedElementsAre(histogram1));
  208. // Create a LinearHistogram.
  209. HistogramBase* const histogram3 = LinearHistogram::FactoryGet(
  210. "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
  211. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  212. UnorderedElementsAre(histogram1, histogram3));
  213. // Create a BooleanHistogram.
  214. HistogramBase* const histogram4 = BooleanHistogram::FactoryGet(
  215. "TestBooleanHistogram", HistogramBase::kNoFlags);
  216. EXPECT_THAT(StatisticsRecorder::GetHistograms(),
  217. UnorderedElementsAre(histogram1, histogram3, histogram4));
  218. // Create a CustomHistogram.
  219. std::vector<int> custom_ranges;
  220. custom_ranges.push_back(1);
  221. custom_ranges.push_back(5);
  222. HistogramBase* const histogram5 = CustomHistogram::FactoryGet(
  223. "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
  224. EXPECT_THAT(
  225. StatisticsRecorder::GetHistograms(),
  226. UnorderedElementsAre(histogram1, histogram3, histogram4, histogram5));
  227. }
  228. TEST_P(StatisticsRecorderTest, RegisterHistogramWithMacros) {
  229. // Macros cache pointers and so tests that use them can only be run once.
  230. // Stop immediately if this test has run previously.
  231. static bool already_run = false;
  232. if (already_run)
  233. return;
  234. already_run = true;
  235. StatisticsRecorder::Histograms registered_histograms;
  236. HistogramBase* histogram = Histogram::FactoryGet(
  237. "TestHistogramCounts", 1, 1000000, 50, HistogramBase::kNoFlags);
  238. // The histogram we got from macro is the same as from FactoryGet.
  239. LOCAL_HISTOGRAM_COUNTS("TestHistogramCounts", 30);
  240. registered_histograms = StatisticsRecorder::GetHistograms();
  241. ASSERT_EQ(1u, registered_histograms.size());
  242. EXPECT_EQ(histogram, registered_histograms[0]);
  243. LOCAL_HISTOGRAM_TIMES("TestHistogramTimes", Days(1));
  244. LOCAL_HISTOGRAM_ENUMERATION("TestHistogramEnumeration", 20, 200);
  245. EXPECT_THAT(StatisticsRecorder::GetHistograms(), SizeIs(3));
  246. }
  247. TEST_P(StatisticsRecorderTest, BucketRangesSharing) {
  248. EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), IsEmpty());
  249. Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags);
  250. Histogram::FactoryGet("Histogram2", 1, 64, 8, HistogramBase::kNoFlags);
  251. EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(1));
  252. Histogram::FactoryGet("Histogram3", 1, 64, 16, HistogramBase::kNoFlags);
  253. EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(2));
  254. }
  255. TEST_P(StatisticsRecorderTest, ToJSON) {
  256. Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
  257. ->Add(30);
  258. Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
  259. ->Add(40);
  260. Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
  261. ->Add(30);
  262. Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
  263. ->Add(40);
  264. std::string json(StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_FULL));
  265. // Check for valid JSON.
  266. absl::optional<Value> root = JSONReader::Read(json);
  267. ASSERT_TRUE(root);
  268. Value::Dict* root_dict = root->GetIfDict();
  269. ASSERT_TRUE(root_dict);
  270. // No query should be set.
  271. ASSERT_FALSE(root_dict->Find("query"));
  272. const Value::List* histogram_list = root_dict->FindList("histograms");
  273. ASSERT_TRUE(histogram_list);
  274. ASSERT_EQ(2u, histogram_list->size());
  275. // Examine the first histogram.
  276. const Value::Dict* histogram_dict = (*histogram_list)[0].GetIfDict();
  277. ASSERT_TRUE(histogram_dict);
  278. auto sample_count = histogram_dict->FindInt("count");
  279. ASSERT_TRUE(sample_count);
  280. EXPECT_EQ(2, *sample_count);
  281. const Value::List* buckets_list = histogram_dict->FindList("buckets");
  282. ASSERT_TRUE(buckets_list);
  283. EXPECT_EQ(2u, buckets_list->size());
  284. // Check the serialized JSON with a different verbosity level.
  285. json = StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_OMIT_BUCKETS);
  286. root = JSONReader::Read(json);
  287. ASSERT_TRUE(root);
  288. root_dict = root->GetIfDict();
  289. ASSERT_TRUE(root_dict);
  290. histogram_list = root_dict->FindList("histograms");
  291. ASSERT_TRUE(histogram_list);
  292. ASSERT_EQ(2u, histogram_list->size());
  293. const Value::Dict* histogram_dict2 = (*histogram_list)[0].GetIfDict();
  294. ASSERT_TRUE(histogram_dict2);
  295. sample_count = histogram_dict2->FindInt("count");
  296. ASSERT_TRUE(sample_count);
  297. EXPECT_EQ(2, *sample_count);
  298. buckets_list = histogram_dict2->FindList("buckets");
  299. // Bucket information should be omitted.
  300. ASSERT_FALSE(buckets_list);
  301. }
  302. TEST_P(StatisticsRecorderTest, IterationTest) {
  303. Histogram::FactoryGet("IterationTest1", 1, 64, 16, HistogramBase::kNoFlags);
  304. Histogram::FactoryGet("IterationTest2", 1, 64, 16, HistogramBase::kNoFlags);
  305. auto histograms = StatisticsRecorder::GetHistograms();
  306. EXPECT_THAT(histograms, SizeIs(2));
  307. histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
  308. EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 0 : 2));
  309. // Create a new global allocator using the same memory as the old one. Any
  310. // old one is kept around so the memory doesn't get released.
  311. old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
  312. if (use_persistent_histogram_allocator_) {
  313. GlobalHistogramAllocator::CreateWithPersistentMemory(
  314. const_cast<void*>(old_global_allocator_->data()),
  315. old_global_allocator_->length(), 0, old_global_allocator_->Id(),
  316. old_global_allocator_->Name());
  317. }
  318. // Reset statistics-recorder to validate operation from a clean start.
  319. UninitializeStatisticsRecorder();
  320. InitializeStatisticsRecorder();
  321. histograms = StatisticsRecorder::GetHistograms();
  322. EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 2 : 0));
  323. histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
  324. EXPECT_THAT(histograms, IsEmpty());
  325. }
  326. namespace {
  327. // CallbackCheckWrapper is simply a convenient way to check and store that
  328. // a callback was actually run.
  329. struct CallbackCheckWrapper {
  330. CallbackCheckWrapper()
  331. : called(false),
  332. last_histogram_name(""),
  333. last_name_hash(HashMetricName("")),
  334. last_histogram_value(0) {}
  335. void OnHistogramChanged(const char* histogram_name,
  336. uint64_t name_hash,
  337. base::HistogramBase::Sample histogram_value) {
  338. called = true;
  339. last_histogram_name = histogram_name;
  340. last_name_hash = name_hash;
  341. last_histogram_value = histogram_value;
  342. }
  343. bool called;
  344. const char* last_histogram_name;
  345. uint64_t last_name_hash;
  346. base::HistogramBase::Sample last_histogram_value;
  347. };
  348. } // namespace
  349. TEST_P(StatisticsRecorderTest,
  350. AddHistogramCallbackBeforeHistogramRegistration) {
  351. test::TaskEnvironment task_environment;
  352. const char* histogram_name = "TestHistogram";
  353. CallbackCheckWrapper callback_wrapper;
  354. auto callback =
  355. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  356. histogram_name,
  357. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  358. base::Unretained(&callback_wrapper)));
  359. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  360. HistogramBase* const histogram = CreateHistogram(histogram_name, 1, 1000, 10);
  361. EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicate(histogram),
  362. histogram);
  363. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
  364. base::HistogramBase::kCallbackExists);
  365. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  366. }
  367. TEST_P(StatisticsRecorderTest,
  368. RemoveHistogramCallbackBeforeHistogramRegistrationWithMultipleClients) {
  369. test::TaskEnvironment task_environment;
  370. const char* histogram_name = "TestHistogram";
  371. CallbackCheckWrapper callback_wrapper1;
  372. CallbackCheckWrapper callback_wrapper2;
  373. auto callback1 =
  374. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  375. histogram_name,
  376. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  377. base::Unretained(&callback_wrapper1)));
  378. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  379. auto callback2 =
  380. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  381. histogram_name,
  382. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  383. base::Unretained(&callback_wrapper2)));
  384. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  385. callback1.reset();
  386. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  387. callback2.reset();
  388. EXPECT_FALSE(base::StatisticsRecorder::have_active_callbacks());
  389. HistogramBase* const histogram = CreateHistogram(histogram_name, 1, 1000, 10);
  390. EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicate(histogram),
  391. histogram);
  392. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0);
  393. EXPECT_FALSE(base::StatisticsRecorder::have_active_callbacks());
  394. }
  395. TEST_P(StatisticsRecorderTest, AddHistogramCallbackWithMultipleClients) {
  396. test::TaskEnvironment task_environment;
  397. std::string histogram_name = "TestHistogram";
  398. HistogramBase* histogram = Histogram::FactoryGet(histogram_name, 1, 1000, 10,
  399. HistogramBase::kNoFlags);
  400. EXPECT_TRUE(histogram);
  401. CallbackCheckWrapper callback_wrapper1;
  402. CallbackCheckWrapper callback_wrapper2;
  403. auto callback1 =
  404. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  405. histogram_name,
  406. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  407. base::Unretained(&callback_wrapper1)));
  408. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
  409. base::HistogramBase::kCallbackExists);
  410. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  411. auto callback2 =
  412. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  413. histogram_name,
  414. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  415. base::Unretained(&callback_wrapper2)));
  416. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
  417. base::HistogramBase::kCallbackExists);
  418. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  419. histogram->Add(1);
  420. base::RunLoop().RunUntilIdle();
  421. EXPECT_TRUE(callback_wrapper1.called);
  422. histogram->Add(1);
  423. EXPECT_TRUE(callback_wrapper2.called);
  424. }
  425. TEST_P(StatisticsRecorderTest, RemoveHistogramCallbackWithMultipleClients) {
  426. test::TaskEnvironment task_environment;
  427. std::string histogram_name = "TestHistogram";
  428. HistogramBase* histogram = Histogram::FactoryGet(histogram_name, 1, 1000, 10,
  429. HistogramBase::kNoFlags);
  430. EXPECT_TRUE(histogram);
  431. CallbackCheckWrapper callback_wrapper1;
  432. CallbackCheckWrapper callback_wrapper2;
  433. auto callback1 =
  434. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  435. histogram_name,
  436. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  437. base::Unretained(&callback_wrapper1)));
  438. auto callback2 =
  439. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  440. histogram_name,
  441. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  442. base::Unretained(&callback_wrapper2)));
  443. callback1.reset();
  444. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
  445. base::HistogramBase::kCallbackExists);
  446. EXPECT_TRUE(base::StatisticsRecorder::have_active_callbacks());
  447. callback2.reset();
  448. EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0);
  449. EXPECT_FALSE(base::StatisticsRecorder::have_active_callbacks());
  450. histogram->Add(1);
  451. base::RunLoop().RunUntilIdle();
  452. EXPECT_FALSE(callback_wrapper1.called);
  453. EXPECT_FALSE(callback_wrapper2.called);
  454. }
  455. // Check that callback is used.
  456. TEST_P(StatisticsRecorderTest, CallbackUsedTest) {
  457. test::TaskEnvironment task_environment;
  458. {
  459. HistogramBase* histogram = Histogram::FactoryGet(
  460. "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
  461. EXPECT_TRUE(histogram);
  462. CallbackCheckWrapper callback_wrapper;
  463. auto callback = std::make_unique<
  464. base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  465. "TestHistogram",
  466. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  467. base::Unretained(&callback_wrapper)));
  468. histogram->Add(1);
  469. base::RunLoop().RunUntilIdle();
  470. EXPECT_TRUE(callback_wrapper.called);
  471. EXPECT_STREQ(callback_wrapper.last_histogram_name, "TestHistogram");
  472. EXPECT_EQ(callback_wrapper.last_name_hash, HashMetricName("TestHistogram"));
  473. EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
  474. }
  475. {
  476. HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
  477. "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
  478. CallbackCheckWrapper callback_wrapper;
  479. auto callback = std::make_unique<
  480. base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  481. "TestLinearHistogram",
  482. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  483. base::Unretained(&callback_wrapper)));
  484. linear_histogram->Add(1);
  485. base::RunLoop().RunUntilIdle();
  486. EXPECT_TRUE(callback_wrapper.called);
  487. EXPECT_STREQ(callback_wrapper.last_histogram_name, "TestLinearHistogram");
  488. EXPECT_EQ(callback_wrapper.last_name_hash,
  489. HashMetricName("TestLinearHistogram"));
  490. EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
  491. }
  492. {
  493. std::vector<int> custom_ranges;
  494. custom_ranges.push_back(1);
  495. custom_ranges.push_back(5);
  496. HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
  497. "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
  498. CallbackCheckWrapper callback_wrapper;
  499. auto callback = std::make_unique<
  500. base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  501. "TestCustomHistogram",
  502. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  503. base::Unretained(&callback_wrapper)));
  504. custom_histogram->Add(1);
  505. base::RunLoop().RunUntilIdle();
  506. EXPECT_TRUE(callback_wrapper.called);
  507. EXPECT_STREQ(callback_wrapper.last_histogram_name, "TestCustomHistogram");
  508. EXPECT_EQ(callback_wrapper.last_name_hash,
  509. HashMetricName("TestCustomHistogram"));
  510. EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
  511. }
  512. {
  513. HistogramBase* custom_histogram = SparseHistogram::FactoryGet(
  514. "TestSparseHistogram", HistogramBase::kNoFlags);
  515. CallbackCheckWrapper callback_wrapper;
  516. auto callback = std::make_unique<
  517. base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  518. "TestSparseHistogram",
  519. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  520. base::Unretained(&callback_wrapper)));
  521. custom_histogram->Add(1);
  522. base::RunLoop().RunUntilIdle();
  523. EXPECT_TRUE(callback_wrapper.called);
  524. EXPECT_STREQ(callback_wrapper.last_histogram_name, "TestSparseHistogram");
  525. EXPECT_EQ(callback_wrapper.last_name_hash,
  526. HashMetricName("TestSparseHistogram"));
  527. EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
  528. }
  529. }
  530. // Check that setting a callback before the histogram exists works.
  531. TEST_P(StatisticsRecorderTest, CallbackUsedBeforeHistogramCreatedTest) {
  532. test::TaskEnvironment task_environment;
  533. CallbackCheckWrapper callback_wrapper;
  534. auto callback =
  535. std::make_unique<base::StatisticsRecorder::ScopedHistogramSampleObserver>(
  536. "TestHistogram",
  537. base::BindRepeating(&CallbackCheckWrapper::OnHistogramChanged,
  538. base::Unretained(&callback_wrapper)));
  539. HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
  540. HistogramBase::kNoFlags);
  541. EXPECT_TRUE(histogram);
  542. histogram->Add(1);
  543. base::RunLoop().RunUntilIdle();
  544. EXPECT_TRUE(callback_wrapper.called);
  545. EXPECT_STREQ(callback_wrapper.last_histogram_name, "TestHistogram");
  546. EXPECT_EQ(callback_wrapper.last_name_hash, HashMetricName("TestHistogram"));
  547. EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
  548. }
  549. TEST_P(StatisticsRecorderTest, GlobalCallbackCalled) {
  550. HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
  551. HistogramBase::kNoFlags);
  552. EXPECT_TRUE(histogram);
  553. // This is a static rather than passing the variable to the lambda
  554. // as a reference capture, as only stateless lambdas can be cast to a raw
  555. // function pointer.
  556. static size_t callback_callcount;
  557. callback_callcount = 0;
  558. auto callback = [](const char* histogram_name, uint64_t name_hash,
  559. HistogramBase::Sample sample) {
  560. EXPECT_STREQ(histogram_name, "TestHistogram");
  561. EXPECT_EQ(sample, 1);
  562. ++callback_callcount;
  563. };
  564. base::StatisticsRecorder::SetGlobalSampleCallback(callback);
  565. // Test that adding a histogram sample calls our callback.
  566. histogram->Add(1);
  567. EXPECT_EQ(callback_callcount, 1u);
  568. // Test that the callback gets correctly unregistered.
  569. base::StatisticsRecorder::SetGlobalSampleCallback(nullptr);
  570. histogram->Add(2);
  571. EXPECT_EQ(callback_callcount, 1u);
  572. }
  573. #if BUILDFLAG(USE_RUNTIME_VLOG)
  574. // The following check that StatisticsRecorder::InitLogOnShutdownWhileLocked
  575. // dumps the histogram graph to vlog if VLOG_IS_ON(1) at runtime. When
  576. // USE_RUNTIME_VLOG is not set, all vlog levels are determined at build time
  577. // and default to off. Since we do not want StatisticsRecorder to dump all the
  578. // time, VLOG in its code stays off. As a result, the following tests would
  579. // fail.
  580. TEST_P(StatisticsRecorderTest, LogOnShutdownNotInitialized) {
  581. ResetVLogInitialized();
  582. logging::SetMinLogLevel(logging::LOG_WARNING);
  583. InitializeStatisticsRecorder();
  584. EXPECT_FALSE(VLOG_IS_ON(1));
  585. EXPECT_FALSE(IsVLogInitialized());
  586. InitLogOnShutdown();
  587. EXPECT_FALSE(IsVLogInitialized());
  588. }
  589. TEST_P(StatisticsRecorderTest, LogOnShutdownInitializedExplicitly) {
  590. ResetVLogInitialized();
  591. logging::SetMinLogLevel(logging::LOG_WARNING);
  592. InitializeStatisticsRecorder();
  593. EXPECT_FALSE(VLOG_IS_ON(1));
  594. EXPECT_FALSE(IsVLogInitialized());
  595. logging::SetMinLogLevel(logging::LOG_VERBOSE);
  596. EXPECT_TRUE(VLOG_IS_ON(1));
  597. InitLogOnShutdown();
  598. EXPECT_TRUE(IsVLogInitialized());
  599. }
  600. TEST_P(StatisticsRecorderTest, LogOnShutdownInitialized) {
  601. ResetVLogInitialized();
  602. logging::SetMinLogLevel(logging::LOG_VERBOSE);
  603. InitializeStatisticsRecorder();
  604. EXPECT_TRUE(VLOG_IS_ON(1));
  605. EXPECT_TRUE(IsVLogInitialized());
  606. }
  607. #endif // BUILDFLAG(USE_RUNTIME_VLOG)
  608. class TestHistogramProvider : public StatisticsRecorder::HistogramProvider {
  609. public:
  610. explicit TestHistogramProvider(
  611. std::unique_ptr<PersistentHistogramAllocator> allocator)
  612. : allocator_(std::move(allocator)) {
  613. StatisticsRecorder::RegisterHistogramProvider(weak_factory_.GetWeakPtr());
  614. }
  615. TestHistogramProvider(const TestHistogramProvider&) = delete;
  616. TestHistogramProvider& operator=(const TestHistogramProvider&) = delete;
  617. void MergeHistogramDeltas() override {
  618. PersistentHistogramAllocator::Iterator hist_iter(allocator_.get());
  619. while (true) {
  620. std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext();
  621. if (!histogram)
  622. break;
  623. allocator_->MergeHistogramDeltaToStatisticsRecorder(histogram.get());
  624. }
  625. }
  626. private:
  627. std::unique_ptr<PersistentHistogramAllocator> allocator_;
  628. WeakPtrFactory<TestHistogramProvider> weak_factory_{this};
  629. };
  630. TEST_P(StatisticsRecorderTest, ImportHistogramsTest) {
  631. // Create a second SR to create some histograms for later import.
  632. std::unique_ptr<StatisticsRecorder> temp_sr =
  633. StatisticsRecorder::CreateTemporaryForTesting();
  634. // Extract any existing global allocator so a new one can be created.
  635. std::unique_ptr<GlobalHistogramAllocator> old_allocator =
  636. GlobalHistogramAllocator::ReleaseForTesting();
  637. // Create a histogram inside a new allocator for testing.
  638. GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0, "");
  639. HistogramBase* histogram = LinearHistogram::FactoryGet("Foo", 1, 10, 11, 0);
  640. histogram->Add(3);
  641. // Undo back to the starting point.
  642. std::unique_ptr<GlobalHistogramAllocator> new_allocator =
  643. GlobalHistogramAllocator::ReleaseForTesting();
  644. GlobalHistogramAllocator::Set(std::move(old_allocator));
  645. temp_sr.reset();
  646. // Create a provider that can supply histograms to the current SR.
  647. TestHistogramProvider provider(std::move(new_allocator));
  648. // Verify that the created histogram is no longer known.
  649. ASSERT_FALSE(StatisticsRecorder::FindHistogram(histogram->histogram_name()));
  650. // Now test that it merges.
  651. StatisticsRecorder::ImportProvidedHistograms();
  652. HistogramBase* found =
  653. StatisticsRecorder::FindHistogram(histogram->histogram_name());
  654. ASSERT_TRUE(found);
  655. EXPECT_NE(histogram, found);
  656. std::unique_ptr<HistogramSamples> snapshot = found->SnapshotSamples();
  657. EXPECT_EQ(1, snapshot->TotalCount());
  658. EXPECT_EQ(1, snapshot->GetCount(3));
  659. // Finally, verify that updates can also be merged.
  660. histogram->Add(3);
  661. histogram->Add(5);
  662. StatisticsRecorder::ImportProvidedHistograms();
  663. snapshot = found->SnapshotSamples();
  664. EXPECT_EQ(3, snapshot->TotalCount());
  665. EXPECT_EQ(2, snapshot->GetCount(3));
  666. EXPECT_EQ(1, snapshot->GetCount(5));
  667. }
  668. TEST_P(StatisticsRecorderTest, RecordHistogramChecker) {
  669. // Before record checker is set all histograms should be recorded.
  670. EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(1));
  671. EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(2));
  672. auto record_checker = std::make_unique<OddRecordHistogramChecker>();
  673. StatisticsRecorder::SetRecordChecker(std::move(record_checker));
  674. EXPECT_TRUE(StatisticsRecorder::ShouldRecordHistogram(1));
  675. EXPECT_FALSE(StatisticsRecorder::ShouldRecordHistogram(2));
  676. }
  677. } // namespace base