1 // Copyright 2017 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.
5 #ifndef COMPONENTS_UKM_UKM_RECORDER_IMPL_H_
6 #define COMPONENTS_UKM_UKM_RECORDER_IMPL_H_
12 #include <unordered_set>
15 #include "base/callback_forward.h"
16 #include "base/containers/flat_map.h"
17 #include "base/sequence_checker.h"
18 #include "base/strings/string_piece.h"
19 #include "services/metrics/public/cpp/ukm_decode.h"
20 #include "services/metrics/public/cpp/ukm_recorder.h"
21 #include "services/metrics/public/mojom/ukm_interface.mojom.h"
24 class UkmBrowserTestBase;
25 class UkmEGTestHelper;
31 class UkmUtilsForTest;
34 class UkmDebugDataExtractor;
37 class UkmRecorderImpl : public UkmRecorder {
38 using IsWebstoreExtensionCallback =
39 base::RepeatingCallback<bool(base::StringPiece id)>;
43 ~UkmRecorderImpl() override;
45 // Unconditionally attempts to create a field trial to control client side
46 // metrics/crash sampling to use as a fallback when one hasn't been
47 // provided. This is expected to occur on first-run on platforms that don't
48 // have first-run variations support. This should only be called when there is
49 // no existing field trial controlling the sampling feature.
50 static void CreateFallbackSamplingTrial(bool is_stable_channel,
51 base::FeatureList* feature_list);
53 // Enables/disables recording control if data is allowed to be collected. The
54 // |extensions| flag separately controls recording of chrome-extension://
55 // URLs; this flag should reflect the "sync extensions" user setting.
56 void EnableRecording(bool extensions);
57 void DisableRecording();
59 // Disables sampling for testing purposes.
60 void DisableSamplingForTesting() override;
62 // Deletes stored recordings.
65 // Sets a callback for determining if an extension URL can be recorded.
66 void SetIsWebstoreExtensionCallback(
67 const IsWebstoreExtensionCallback& callback);
70 // Cache the list of whitelisted entries from the field trial parameter.
71 void StoreWhitelistedEntries();
73 // Writes recordings into a report proto, and clears recordings.
74 void StoreRecordingsInReport(Report* report);
76 const std::map<SourceId, std::unique_ptr<UkmSource>>& sources() const {
77 return recordings_.sources;
80 const std::vector<mojom::UkmEntryPtr>& entries() const {
81 return recordings_.entries;
85 void AddEntry(mojom::UkmEntryPtr entry) override;
86 void UpdateSourceURL(SourceId source_id, const GURL& url) override;
87 void UpdateAppURL(SourceId source_id, const GURL& url) override;
88 void RecordNavigation(
90 const UkmSource::NavigationData& navigation_data) override;
91 using UkmRecorder::RecordOtherURL;
93 virtual bool ShouldRestrictToWhitelistedSourceIds() const;
95 virtual bool ShouldRestrictToWhitelistedEntries() const;
98 friend ::metrics::UkmBrowserTestBase;
99 friend ::metrics::UkmEGTestHelper;
100 friend ::ukm::debug::UkmDebugDataExtractor;
101 friend ::ukm::UkmUtilsForTest;
103 struct MetricAggregate {
104 uint64_t total_count = 0;
105 double value_sum = 0;
106 double value_square_sum = 0.0;
107 uint64_t dropped_due_to_limits = 0;
108 uint64_t dropped_due_to_sampling = 0;
109 uint64_t dropped_due_to_whitelist = 0;
112 struct EventAggregate {
116 base::flat_map<uint64_t, MetricAggregate> metrics;
117 uint64_t total_count = 0;
118 uint64_t dropped_due_to_limits = 0;
119 uint64_t dropped_due_to_sampling = 0;
120 uint64_t dropped_due_to_whitelist = 0;
123 using MetricAggregateMap = std::map<uint64_t, MetricAggregate>;
125 // Returns true if |sanitized_url| should be recorded.
126 bool ShouldRecordUrl(SourceId source_id, const GURL& sanitized_url) const;
128 void RecordSource(std::unique_ptr<UkmSource> source);
130 // Load sampling configurations from field-trial information.
131 void LoadExperimentSamplingInfo();
133 // Whether recording new data is currently allowed.
134 bool recording_enabled_ = false;
136 // Indicates whether recording is enabled for extensions.
137 bool extensions_enabled_ = false;
139 // Indicates whether recording continuity has been broken since last report.
140 bool recording_is_continuous_ = true;
142 // Indicates if sampling has been enabled.
143 bool sampling_enabled_ = true;
145 // Callback for checking extension IDs.
146 IsWebstoreExtensionCallback is_webstore_extension_callback_;
148 // Map from hashes to entry and metric names.
149 ukm::builders::DecodeMap decode_map_;
151 // Whitelisted Entry hashes, only the ones in this set will be recorded.
152 std::set<uint64_t> whitelisted_entry_hashes_;
154 // Sampling configurations, loaded from a field-trial.
155 int default_sampling_rate_ = 0;
156 base::flat_map<uint64_t, int> event_sampling_rates_;
158 // Contains data from various recordings which periodically get serialized
159 // and cleared by StoreRecordingsInReport() and may be Purged().
162 Recordings& operator=(Recordings&&);
165 // Data captured by UpdateSourceUrl().
166 std::map<SourceId, std::unique_ptr<UkmSource>> sources;
168 // Data captured by AddEntry().
169 std::vector<mojom::UkmEntryPtr> entries;
171 // URLs of sources that matched a whitelist url, but were not included in
172 // the report generated by the last log rotation because we haven't seen any
173 // events for that source yet.
174 std::unordered_set<std::string> carryover_urls_whitelist;
176 // Aggregate information for collected event metrics.
177 std::map<uint64_t, EventAggregate> event_aggregations;
179 // Aggregated counters about Sources recorded in the current log.
180 struct SourceCounts {
181 // Count of URLs recorded for all sources.
183 // Count of URLs recorded for all SourceIdType::NAVIGATION_ID Sources.
184 size_t navigation_sources = 0;
185 // Sources carried over (not recorded) from a previous logging rotation.
186 size_t carryover_sources = 0;
188 // Resets all of the data.
191 SourceCounts source_counts;
193 // Resets all of the data.
196 Recordings recordings_;
198 SEQUENCE_CHECKER(sequence_checker_);
203 #endif // COMPONENTS_UKM_UKM_RECORDER_IMPL_H_