• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/metrics/histogram_snapshot_manager.h"
6 
7 #include <memory>
8 #include <string>
9 #include <vector>
10 
11 #include "base/containers/contains.h"
12 #include "base/metrics/histogram_delta_serialization.h"
13 #include "base/metrics/histogram_functions.h"
14 #include "base/metrics/sample_vector.h"
15 #include "base/metrics/statistics_recorder.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace base {
19 
20 namespace {
21 
22 const std::string kHistogramName = "UmaHistogram";
23 
24 const std::string kStabilityHistogramName = "UmaStabilityHistogram";
25 
UmaStabilityHistogramBoolean(const std::string & name,bool sample)26 void UmaStabilityHistogramBoolean(const std::string& name, bool sample) {
27   HistogramBase* histogram = BooleanHistogram::FactoryGet(
28       name, HistogramBase::kUmaStabilityHistogramFlag);
29   histogram->Add(sample);
30 }
31 
32 }  // namespace
33 
34 class HistogramFlattenerDeltaRecorder : public HistogramFlattener {
35  public:
36   HistogramFlattenerDeltaRecorder() = default;
37 
38   HistogramFlattenerDeltaRecorder(const HistogramFlattenerDeltaRecorder&) =
39       delete;
40   HistogramFlattenerDeltaRecorder& operator=(
41       const HistogramFlattenerDeltaRecorder&) = delete;
42 
RecordDelta(const HistogramBase & histogram,const HistogramSamples & snapshot)43   void RecordDelta(const HistogramBase& histogram,
44                    const HistogramSamples& snapshot) override {
45     recorded_delta_histograms_.push_back(&histogram);
46     // Use CHECK instead of ASSERT to get full stack-trace and thus origin.
47     CHECK(!Contains(recorded_delta_histogram_sum_, histogram.histogram_name()));
48     // Keep pointer to snapshot for testing. This really isn't ideal but the
49     // snapshot-manager keeps the snapshot alive until it's "forgotten".
50     recorded_delta_histogram_sum_[histogram.histogram_name()] = snapshot.sum();
51   }
52 
Reset()53   void Reset() {
54     recorded_delta_histograms_.clear();
55     recorded_delta_histogram_sum_.clear();
56   }
57 
GetRecordedDeltaHistograms()58   std::vector<const HistogramBase*>& GetRecordedDeltaHistograms() {
59     return recorded_delta_histograms_;
60   }
61 
GetRecordedDeltaHistogramSum(const std::string & name)62   int64_t GetRecordedDeltaHistogramSum(const std::string& name) {
63     EXPECT_TRUE(Contains(recorded_delta_histogram_sum_, name));
64     return recorded_delta_histogram_sum_[name];
65   }
66 
67  private:
68   std::vector<const HistogramBase*> recorded_delta_histograms_;
69   std::map<std::string, int64_t> recorded_delta_histogram_sum_;
70 };
71 
72 class HistogramSnapshotManagerTest : public testing::Test {
73  protected:
HistogramSnapshotManagerTest()74   HistogramSnapshotManagerTest()
75       : statistics_recorder_(StatisticsRecorder::CreateTemporaryForTesting()),
76         histogram_snapshot_manager_(&histogram_flattener_delta_recorder_) {}
77 
78   ~HistogramSnapshotManagerTest() override = default;
79 
GetRecordedDeltaHistogramSum(const std::string & name)80   int64_t GetRecordedDeltaHistogramSum(const std::string& name) {
81     return histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramSum(
82         name);
83   }
84 
85   std::unique_ptr<StatisticsRecorder> statistics_recorder_;
86   HistogramFlattenerDeltaRecorder histogram_flattener_delta_recorder_;
87   HistogramSnapshotManager histogram_snapshot_manager_;
88 };
89 
TEST_F(HistogramSnapshotManagerTest,PrepareDeltasNoFlagsFilter)90 TEST_F(HistogramSnapshotManagerTest, PrepareDeltasNoFlagsFilter) {
91   // kNoFlags filter should record all histograms.
92   base::UmaHistogramBoolean(kHistogramName, true);
93   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
94 
95   StatisticsRecorder::PrepareDeltas(
96       /*include_persistent=*/false, /*flags_to_set=*/HistogramBase::kNoFlags,
97       /*required_flags=*/HistogramBase::kNoFlags, &histogram_snapshot_manager_);
98 
99   // Verify that the snapshots were recorded.
100   const std::vector<const HistogramBase*>& histograms =
101       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
102   ASSERT_EQ(2U, histograms.size());
103   ASSERT_EQ(kHistogramName, histograms[0]->histogram_name());
104   EXPECT_EQ(GetRecordedDeltaHistogramSum(kHistogramName), 1);
105   ASSERT_EQ(kStabilityHistogramName, histograms[1]->histogram_name());
106   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
107 
108   // The samples should have been marked as logged.
109   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
110   EXPECT_EQ(histograms[1]->SnapshotUnloggedSamples()->TotalCount(), 0);
111 }
112 
TEST_F(HistogramSnapshotManagerTest,PrepareDeltasUmaHistogramFlagFilter)113 TEST_F(HistogramSnapshotManagerTest, PrepareDeltasUmaHistogramFlagFilter) {
114   // Note that kUmaStabilityHistogramFlag includes kUmaTargetedHistogramFlag.
115   base::UmaHistogramBoolean(kHistogramName, true);
116   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
117 
118   StatisticsRecorder::PrepareDeltas(
119       /*include_persistent=*/false, /*flags_to_set=*/HistogramBase::kNoFlags,
120       /*required_flags=*/HistogramBase::kUmaTargetedHistogramFlag,
121       &histogram_snapshot_manager_);
122 
123   // Verify that the snapshots were recorded.
124   const std::vector<const HistogramBase*>& histograms =
125       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
126   ASSERT_EQ(2U, histograms.size());
127   ASSERT_EQ(kHistogramName, histograms[0]->histogram_name());
128   EXPECT_EQ(GetRecordedDeltaHistogramSum(kHistogramName), 1);
129   ASSERT_EQ(kStabilityHistogramName, histograms[1]->histogram_name());
130   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
131 
132   // The samples should have been marked as logged.
133   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
134   EXPECT_EQ(histograms[1]->SnapshotUnloggedSamples()->TotalCount(), 0);
135 }
136 
TEST_F(HistogramSnapshotManagerTest,PrepareDeltasUmaStabilityHistogramFlagFilter)137 TEST_F(HistogramSnapshotManagerTest,
138        PrepareDeltasUmaStabilityHistogramFlagFilter) {
139   base::UmaHistogramBoolean(kHistogramName, true);
140   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
141 
142   StatisticsRecorder::PrepareDeltas(
143       /*include_persistent=*/false, /*flags_to_set=*/HistogramBase::kNoFlags,
144       /*required_flags=*/HistogramBase::kUmaStabilityHistogramFlag,
145       &histogram_snapshot_manager_);
146 
147   // Verify that only the stability histogram was snapshotted and recorded.
148   const std::vector<const HistogramBase*>& histograms =
149       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
150   ASSERT_EQ(1U, histograms.size());
151   ASSERT_EQ(kStabilityHistogramName, histograms[0]->histogram_name());
152   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
153 
154   // The samples should have been marked as logged.
155   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
156 }
157 
TEST_F(HistogramSnapshotManagerTest,SnapshotUnloggedSamplesNoFlagsFilter)158 TEST_F(HistogramSnapshotManagerTest, SnapshotUnloggedSamplesNoFlagsFilter) {
159   // kNoFlags filter should record all histograms.
160   base::UmaHistogramBoolean(kHistogramName, true);
161   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
162 
163   StatisticsRecorder::SnapshotUnloggedSamples(
164       /*required_flags=*/HistogramBase::kNoFlags, &histogram_snapshot_manager_);
165 
166   // Verify that the snapshots were recorded.
167   const std::vector<const HistogramBase*>& histograms =
168       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
169   ASSERT_EQ(2U, histograms.size());
170   ASSERT_EQ(kHistogramName, histograms[0]->histogram_name());
171   EXPECT_EQ(GetRecordedDeltaHistogramSum(kHistogramName), 1);
172   ASSERT_EQ(kStabilityHistogramName, histograms[1]->histogram_name());
173   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
174 
175   // The samples should NOT have been marked as logged.
176   std::unique_ptr<HistogramSamples> samples =
177       histograms[0]->SnapshotUnloggedSamples();
178   EXPECT_EQ(samples->TotalCount(), 1);
179   EXPECT_EQ(samples->sum(), 1);
180   samples = histograms[1]->SnapshotUnloggedSamples();
181   EXPECT_EQ(samples->TotalCount(), 1);
182   EXPECT_EQ(samples->sum(), 1);
183 
184   // Mark the samples as logged and verify that they are correctly marked as so.
185   histogram_snapshot_manager_.MarkUnloggedSamplesAsLogged();
186   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
187   EXPECT_EQ(histograms[1]->SnapshotUnloggedSamples()->TotalCount(), 0);
188 }
189 
TEST_F(HistogramSnapshotManagerTest,SnapshotUnloggedSamplesUmaHistogramFlagFilter)190 TEST_F(HistogramSnapshotManagerTest,
191        SnapshotUnloggedSamplesUmaHistogramFlagFilter) {
192   // Note that kUmaStabilityHistogramFlag includes kUmaTargetedHistogramFlag.
193   base::UmaHistogramBoolean(kHistogramName, true);
194   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
195 
196   StatisticsRecorder::SnapshotUnloggedSamples(
197       /*required_flags=*/HistogramBase::kUmaTargetedHistogramFlag,
198       &histogram_snapshot_manager_);
199 
200   // Verify that the snapshots were recorded.
201   const std::vector<const HistogramBase*>& histograms =
202       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
203   ASSERT_EQ(2U, histograms.size());
204   ASSERT_EQ(kHistogramName, histograms[0]->histogram_name());
205   EXPECT_EQ(GetRecordedDeltaHistogramSum(kHistogramName), 1);
206   ASSERT_EQ(kStabilityHistogramName, histograms[1]->histogram_name());
207   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
208 
209   // The samples should NOT have been marked as logged.
210   std::unique_ptr<HistogramSamples> samples =
211       histograms[0]->SnapshotUnloggedSamples();
212   EXPECT_EQ(samples->TotalCount(), 1);
213   EXPECT_EQ(samples->sum(), 1);
214   samples = histograms[1]->SnapshotUnloggedSamples();
215   EXPECT_EQ(samples->TotalCount(), 1);
216   EXPECT_EQ(samples->sum(), 1);
217 
218   // Mark the samples as logged and verify that they are correctly marked as so.
219   histogram_snapshot_manager_.MarkUnloggedSamplesAsLogged();
220   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
221   EXPECT_EQ(histograms[1]->SnapshotUnloggedSamples()->TotalCount(), 0);
222 }
223 
TEST_F(HistogramSnapshotManagerTest,SnapshotUnloggedSamplesUmaStabilityHistogramFlagFilter)224 TEST_F(HistogramSnapshotManagerTest,
225        SnapshotUnloggedSamplesUmaStabilityHistogramFlagFilter) {
226   base::UmaHistogramBoolean(kHistogramName, true);
227   UmaStabilityHistogramBoolean(kStabilityHistogramName, true);
228 
229   StatisticsRecorder::SnapshotUnloggedSamples(
230       /*required_flags=*/HistogramBase::kUmaStabilityHistogramFlag,
231       &histogram_snapshot_manager_);
232 
233   // Verify that only the stability histogram was snapshotted and recorded.
234   const std::vector<const HistogramBase*>& histograms =
235       histogram_flattener_delta_recorder_.GetRecordedDeltaHistograms();
236   ASSERT_EQ(1U, histograms.size());
237   ASSERT_EQ(kStabilityHistogramName, histograms[0]->histogram_name());
238   EXPECT_EQ(GetRecordedDeltaHistogramSum(kStabilityHistogramName), 1);
239 
240   // The samples should NOT have been marked as logged.
241   std::unique_ptr<HistogramSamples> samples =
242       histograms[0]->SnapshotUnloggedSamples();
243   EXPECT_EQ(samples->TotalCount(), 1);
244   EXPECT_EQ(samples->sum(), 1);
245 
246   // Mark the samples as logged and verify that they are correctly marked as so.
247   histogram_snapshot_manager_.MarkUnloggedSamplesAsLogged();
248   EXPECT_EQ(histograms[0]->SnapshotUnloggedSamples()->TotalCount(), 0);
249 }
250 
251 }  // namespace base
252