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