OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "components/ukm/ukm_recorder_impl.h" | |
6 | |
7 #include "base/metrics/field_trial.h" | |
8 #include "base/metrics/field_trial_params.h" | |
9 #include "base/metrics/histogram_macros.h" | |
10 #include "base/metrics/metrics_hashes.h" | |
11 #include "base/strings/string_split.h" | |
12 #include "components/metrics/proto/ukm/entry.pb.h" | |
13 #include "components/metrics/proto/ukm/report.pb.h" | |
14 #include "components/metrics/proto/ukm/source.pb.h" | |
15 #include "components/ukm/ukm_source.h" | |
16 | |
17 namespace ukm { | |
18 | |
19 namespace { | |
20 | |
21 // Gets the list of whitelisted Entries as string. Format is a comma seperated | |
22 // list of Entry names (as strings). | |
23 std::string GetWhitelistEntries() { | |
24 return base::GetFieldTrialParamValueByFeature(kUkmFeature, | |
25 "WhitelistEntries"); | |
26 } | |
27 | |
28 // Gets the maximum number of Sources we'll keep in memory before discarding any | |
29 // new ones being added. | |
30 size_t GetMaxSources() { | |
31 constexpr size_t kDefaultMaxSources = 500; | |
32 return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( | |
33 kUkmFeature, "MaxSources", kDefaultMaxSources)); | |
34 } | |
35 | |
36 // Gets the maximum number of Entries we'll keep in memory before discarding any | |
37 // new ones being added. | |
38 size_t GetMaxEntries() { | |
39 constexpr size_t kDefaultMaxEntries = 5000; | |
40 return static_cast<size_t>(base::GetFieldTrialParamByFeatureAsInt( | |
41 kUkmFeature, "MaxEntries", kDefaultMaxEntries)); | |
42 } | |
43 | |
44 // True if we should record the initial_url field of the UKM Source proto. | |
45 bool ShouldRecordInitialUrl() { | |
46 return base::GetFieldTrialParamByFeatureAsBool(kUkmFeature, | |
47 "RecordInitialUrl", false); | |
48 } | |
49 | |
50 enum class DroppedDataReason { | |
51 NOT_DROPPED = 0, | |
52 RECORDING_DISABLED = 1, | |
53 MAX_HIT = 2, | |
54 NOT_WHITELISTED = 3, | |
55 NUM_DROPPED_DATA_REASONS | |
56 }; | |
57 | |
58 void RecordDroppedSource(DroppedDataReason reason) { | |
59 UMA_HISTOGRAM_ENUMERATION( | |
60 "UKM.Sources.Dropped", static_cast<int>(reason), | |
61 static_cast<int>(DroppedDataReason::NUM_DROPPED_DATA_REASONS)); | |
62 } | |
63 | |
64 void RecordDroppedEntry(DroppedDataReason reason) { | |
65 UMA_HISTOGRAM_ENUMERATION( | |
66 "UKM.Entries.Dropped", static_cast<int>(reason), | |
67 static_cast<int>(DroppedDataReason::NUM_DROPPED_DATA_REASONS)); | |
68 } | |
69 | |
70 void StoreEntryProto(const mojom::UkmEntry& in, Entry* out) { | |
71 DCHECK(!out->has_source_id()); | |
72 DCHECK(!out->has_event_hash()); | |
73 | |
74 out->set_source_id(in.source_id); | |
75 out->set_event_hash(in.event_hash); | |
76 for (const auto& metric : in.metrics) { | |
77 Entry::Metric* proto_metric = out->add_metrics(); | |
78 proto_metric->set_metric_hash(metric->metric_hash); | |
79 proto_metric->set_value(metric->value); | |
80 } | |
81 } | |
82 | |
83 } // namespace | |
84 | |
85 UkmRecorderImpl::UkmRecorderImpl() : recording_enabled_(false) {} | |
86 UkmRecorderImpl::~UkmRecorderImpl() = default; | |
87 | |
88 void UkmRecorderImpl::EnableRecording() { | |
89 recording_enabled_ = true; | |
90 } | |
91 | |
92 void UkmRecorderImpl::DisableRecording() { | |
93 recording_enabled_ = false; | |
94 } | |
95 | |
96 void UkmRecorderImpl::Purge() { | |
97 sources_.clear(); | |
98 entries_.clear(); | |
99 } | |
100 | |
101 void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { | |
102 for (const auto& kv : sources_) { | |
103 Source* proto_source = report->add_sources(); | |
104 kv.second->PopulateProto(proto_source); | |
105 if (!ShouldRecordInitialUrl()) | |
106 proto_source->clear_initial_url(); | |
107 } | |
108 for (const auto& entry : entries_) { | |
109 Entry* proto_entry = report->add_entries(); | |
110 StoreEntryProto(*entry, proto_entry); | |
111 } | |
112 | |
113 UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount", sources_.size()); | |
114 UMA_HISTOGRAM_COUNTS_1000("UKM.Entries.SerializedCount", entries_.size()); | |
115 sources_.clear(); | |
116 entries_.clear(); | |
117 } | |
118 | |
119 void UkmRecorderImpl::UpdateSourceURL(ukm::SourceId source_id, | |
120 const GURL& url) { | |
121 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); | |
122 | |
123 if (!recording_enabled_) { | |
124 RecordDroppedSource(DroppedDataReason::RECORDING_DISABLED); | |
125 return; | |
126 } | |
127 | |
128 // Update the pre-existing source if there is any. This happens when the | |
129 // initial URL is different from the committed URL for the same source, e.g., | |
130 // when there is redirection. | |
131 if (base::ContainsKey(sources_, source_id)) { | |
132 sources_[source_id]->UpdateUrl(url); | |
133 return; | |
134 } | |
135 | |
136 if (sources_.size() >= GetMaxSources()) { | |
137 RecordDroppedSource(DroppedDataReason::MAX_HIT); | |
138 return; | |
139 } | |
140 std::unique_ptr<UkmSource> source = base::MakeUnique<UkmSource>(); | |
141 source->set_id(source_id); | |
142 source->set_url(url); | |
143 sources_.insert(std::make_pair(source_id, std::move(source))); | |
144 } | |
145 | |
146 void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { | |
147 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); | |
148 | |
149 if (!recording_enabled_) { | |
150 RecordDroppedEntry(DroppedDataReason::RECORDING_DISABLED); | |
151 return; | |
152 } | |
153 if (entries_.size() >= GetMaxEntries()) { | |
154 RecordDroppedEntry(DroppedDataReason::MAX_HIT); | |
155 return; | |
156 } | |
157 | |
158 if (!whitelisted_entry_hashes_.empty() && | |
159 !base::ContainsKey(whitelisted_entry_hashes_, entry->event_hash)) { | |
160 RecordDroppedEntry(DroppedDataReason::NOT_WHITELISTED); | |
161 return; | |
162 } | |
163 | |
164 entries_.push_back(std::move(entry)); | |
165 } | |
166 | |
167 void UkmRecorderImpl::StoreWhitelistedEntries() { | |
168 const auto entries = | |
169 base::SplitString(GetWhitelistEntries(), ",", base::TRIM_WHITESPACE, | |
170 base::SPLIT_WANT_NONEMPTY); | |
171 for (const auto& entry_string : entries) { | |
172 whitelisted_entry_hashes_.insert(base::HashMetricName(entry_string)); | |
173 } | |
oystein (OOO til 10th of July)
2017/05/17 18:25:06
nit: Some inconsistency in whether single-line blo
Steven Holte
2017/05/17 20:44:31
Removed it here.
| |
174 } | |
175 } | |
OLD | NEW |