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 } |
| 174 |
| 175 } // namespace ukm |
OLD | NEW |