Commit 3159c939 authored by Steven Holte's avatar Steven Holte Committed by Commit Bot

Group Ukm Recordings into a struct.

This both helps organize the members of UkmRecorderImpl a bit, and
also simplifies the code for Purge(), so that it doesn't need to know
about all of the different fields. This should help make it harder to
accidently add a new field and not delete it during a Purge().

Change-Id: I49558468cfb491c34ef76d2c2801aae72ddc8364
Reviewed-on: https://chromium-review.googlesource.com/1054142
Commit-Queue: Steven Holte <holte@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#573526}
parent 675b0b58
...@@ -62,11 +62,11 @@ std::string UkmDebugDataExtractor::GetHTMLData(UkmService* ukm_service) { ...@@ -62,11 +62,11 @@ std::string UkmDebugDataExtractor::GetHTMLData(UkmService* ukm_service) {
const auto& decode_map = ukm_service->decode_map_; const auto& decode_map = ukm_service->decode_map_;
std::map<SourceId, SourceData> source_data; std::map<SourceId, SourceData> source_data;
for (const auto& kv : ukm_service->sources_) { for (const auto& kv : ukm_service->recordings_.sources) {
source_data[kv.first].source = kv.second.get(); source_data[kv.first].source = kv.second.get();
} }
for (const auto& v : ukm_service->entries_) { for (const auto& v : ukm_service->recordings_.entries) {
source_data[v->source_id].entries.push_back(v.get()); source_data[v->source_id].entries.push_back(v.get());
} }
......
...@@ -210,7 +210,19 @@ void UkmRecorderImpl::CreateFallbackSamplingTrial( ...@@ -210,7 +210,19 @@ void UkmRecorderImpl::CreateFallbackSamplingTrial(
trial.get()); trial.get());
} }
void UkmRecorderImpl::SourceCounts::Reset() { UkmRecorderImpl::EventAggregate::EventAggregate() = default;
UkmRecorderImpl::EventAggregate::~EventAggregate() = default;
UkmRecorderImpl::Recordings::Recordings() = default;
UkmRecorderImpl::Recordings& UkmRecorderImpl::Recordings::operator=(
Recordings&&) = default;
UkmRecorderImpl::Recordings::~Recordings() = default;
void UkmRecorderImpl::Recordings::Reset() {
*this = Recordings();
}
void UkmRecorderImpl::Recordings::SourceCounts::Reset() {
*this = SourceCounts(); *this = SourceCounts();
} }
...@@ -232,11 +244,7 @@ void UkmRecorderImpl::DisableSamplingForTesting() { ...@@ -232,11 +244,7 @@ void UkmRecorderImpl::DisableSamplingForTesting() {
void UkmRecorderImpl::Purge() { void UkmRecorderImpl::Purge() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
sources_.clear(); recordings_.Reset();
source_counts_.Reset();
carryover_urls_whitelist_.clear();
entries_.clear();
event_aggregations_.clear();
} }
void UkmRecorderImpl::SetIsWebstoreExtensionCallback( void UkmRecorderImpl::SetIsWebstoreExtensionCallback(
...@@ -248,19 +256,19 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { ...@@ -248,19 +256,19 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::set<SourceId> ids_seen; std::set<SourceId> ids_seen;
for (const auto& entry : entries_) { for (const auto& entry : recordings_.entries) {
Entry* proto_entry = report->add_entries(); Entry* proto_entry = report->add_entries();
StoreEntryProto(*entry, proto_entry); StoreEntryProto(*entry, proto_entry);
ids_seen.insert(entry->source_id); ids_seen.insert(entry->source_id);
} }
std::unordered_set<std::string> url_whitelist; std::unordered_set<std::string> url_whitelist;
carryover_urls_whitelist_.swap(url_whitelist); recordings_.carryover_urls_whitelist.swap(url_whitelist);
AppendWhitelistedUrls(sources_, &url_whitelist); AppendWhitelistedUrls(recordings_.sources, &url_whitelist);
std::vector<std::unique_ptr<UkmSource>> unsent_sources; std::vector<std::unique_ptr<UkmSource>> unsent_sources;
int unmatched_sources = 0; int unmatched_sources = 0;
for (auto& kv : sources_) { for (auto& kv : recordings_.sources) {
// If the source id is not whitelisted, don't send it unless it has // If the source id is not whitelisted, don't send it unless it has
// associated entries and the URL matches a URL of a whitelisted source. // associated entries and the URL matches a URL of a whitelisted source.
// Note: If ShouldRestrictToWhitelistedSourceIds() is true, this logic will // Note: If ShouldRestrictToWhitelistedSourceIds() is true, this logic will
...@@ -284,7 +292,7 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { ...@@ -284,7 +292,7 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
if (!ShouldRecordInitialUrl()) if (!ShouldRecordInitialUrl())
proto_source->clear_initial_url(); proto_source->clear_initial_url();
} }
for (const auto& event_and_aggregate : event_aggregations_) { for (const auto& event_and_aggregate : recordings_.event_aggregations) {
if (event_and_aggregate.second.metrics.empty()) if (event_and_aggregate.second.metrics.empty())
continue; continue;
const EventAggregate& event_aggregate = event_and_aggregate.second; const EventAggregate& event_aggregate = event_and_aggregate.second;
...@@ -326,23 +334,25 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { ...@@ -326,23 +334,25 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
} }
UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount", UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount",
sources_.size() - unsent_sources.size()); recordings_.sources.size() - unsent_sources.size());
UMA_HISTOGRAM_COUNTS_100000("UKM.Entries.SerializedCount2", entries_.size()); UMA_HISTOGRAM_COUNTS_100000("UKM.Entries.SerializedCount2",
recordings_.entries.size());
UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.UnsentSourcesCount", UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.UnsentSourcesCount",
unsent_sources.size()); unsent_sources.size());
Report::SourceCounts* source_counts_proto = report->mutable_source_counts(); Report::SourceCounts* source_counts_proto = report->mutable_source_counts();
source_counts_proto->set_observed(source_counts_.observed); source_counts_proto->set_observed(recordings_.source_counts.observed);
source_counts_proto->set_navigation_sources( source_counts_proto->set_navigation_sources(
source_counts_.navigation_sources); recordings_.source_counts.navigation_sources);
source_counts_proto->set_unmatched_sources(unmatched_sources); source_counts_proto->set_unmatched_sources(unmatched_sources);
source_counts_proto->set_deferred_sources(unsent_sources.size()); source_counts_proto->set_deferred_sources(unsent_sources.size());
source_counts_proto->set_carryover_sources(source_counts_.carryover_sources); source_counts_proto->set_carryover_sources(
recordings_.source_counts.carryover_sources);
sources_.clear(); recordings_.sources.clear();
source_counts_.Reset(); recordings_.source_counts.Reset();
entries_.clear(); recordings_.entries.clear();
event_aggregations_.clear(); recordings_.event_aggregations.clear();
// Keep at most |max_kept_sources|, prioritizing most-recent entries (by // Keep at most |max_kept_sources|, prioritizing most-recent entries (by
// creation time). // creation time).
...@@ -361,11 +371,12 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { ...@@ -361,11 +371,12 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) {
for (auto& source : unsent_sources) { for (auto& source : unsent_sources) {
// We already matched these sources against the URL whitelist. // We already matched these sources against the URL whitelist.
// Re-whitelist them for the next report. // Re-whitelist them for the next report.
carryover_urls_whitelist_.insert(source->url().spec()); recordings_.carryover_urls_whitelist.insert(source->url().spec());
sources_.emplace(source->id(), std::move(source)); recordings_.sources.emplace(source->id(), std::move(source));
} }
UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.KeptSourcesCount", sources_.size()); UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.KeptSourcesCount",
source_counts_.carryover_sources = sources_.size(); recordings_.sources.size());
recordings_.source_counts.carryover_sources = recordings_.sources.size();
} }
bool UkmRecorderImpl::ShouldRestrictToWhitelistedSourceIds() const { bool UkmRecorderImpl::ShouldRestrictToWhitelistedSourceIds() const {
...@@ -377,9 +388,6 @@ bool UkmRecorderImpl::ShouldRestrictToWhitelistedEntries() const { ...@@ -377,9 +388,6 @@ bool UkmRecorderImpl::ShouldRestrictToWhitelistedEntries() const {
return true; return true;
} }
UkmRecorderImpl::EventAggregate::EventAggregate() = default;
UkmRecorderImpl::EventAggregate::~EventAggregate() = default;
void UkmRecorderImpl::UpdateSourceURL(SourceId source_id, void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
const GURL& unsanitized_url) { const GURL& unsanitized_url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -400,9 +408,9 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id, ...@@ -400,9 +408,9 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
return; return;
} }
source_counts_.observed++; recordings_.source_counts.observed++;
if (GetSourceIdType(source_id) == SourceIdType::NAVIGATION_ID) if (GetSourceIdType(source_id) == SourceIdType::NAVIGATION_ID)
source_counts_.navigation_sources++; recordings_.source_counts.navigation_sources++;
GURL url = SanitizeURL(unsanitized_url); GURL url = SanitizeURL(unsanitized_url);
...@@ -430,16 +438,17 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id, ...@@ -430,16 +438,17 @@ void UkmRecorderImpl::UpdateSourceURL(SourceId source_id,
// Update the pre-existing source if there is any. This happens when the // Update the pre-existing source if there is any. This happens when the
// initial URL is different from the committed URL for the same source, e.g., // initial URL is different from the committed URL for the same source, e.g.,
// when there is redirection. // when there is redirection.
if (base::ContainsKey(sources_, source_id)) { if (base::ContainsKey(recordings_.sources, source_id)) {
sources_[source_id]->UpdateUrl(url); recordings_.sources[source_id]->UpdateUrl(url);
return; return;
} }
if (sources_.size() >= GetMaxSources()) { if (recordings_.sources.size() >= GetMaxSources()) {
RecordDroppedSource(DroppedDataReason::MAX_HIT); RecordDroppedSource(DroppedDataReason::MAX_HIT);
return; return;
} }
sources_.emplace(source_id, std::make_unique<UkmSource>(source_id, url)); recordings_.sources.emplace(source_id,
std::make_unique<UkmSource>(source_id, url));
} }
void UkmRecorderImpl::UpdateAppURL(SourceId source_id, const GURL& url) { void UkmRecorderImpl::UpdateAppURL(SourceId source_id, const GURL& url) {
...@@ -460,7 +469,8 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { ...@@ -460,7 +469,8 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
return; return;
} }
EventAggregate& event_aggregate = event_aggregations_[entry->event_hash]; EventAggregate& event_aggregate =
recordings_.event_aggregations[entry->event_hash];
event_aggregate.total_count++; event_aggregate.total_count++;
for (const auto& metric : entry->metrics) { for (const auto& metric : entry->metrics) {
MetricAggregate& aggregate = event_aggregate.metrics[metric.first]; MetricAggregate& aggregate = event_aggregate.metrics[metric.first];
...@@ -496,7 +506,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { ...@@ -496,7 +506,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
return; return;
} }
if (entries_.size() >= GetMaxEntries()) { if (recordings_.entries.size() >= GetMaxEntries()) {
RecordDroppedEntry(DroppedDataReason::MAX_HIT); RecordDroppedEntry(DroppedDataReason::MAX_HIT);
event_aggregate.dropped_due_to_limits++; event_aggregate.dropped_due_to_limits++;
for (auto& metric : entry->metrics) for (auto& metric : entry->metrics)
...@@ -504,7 +514,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { ...@@ -504,7 +514,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) {
return; return;
} }
entries_.push_back(std::move(entry)); recordings_.entries.push_back(std::move(entry));
} }
void UkmRecorderImpl::LoadExperimentSamplingInfo() { void UkmRecorderImpl::LoadExperimentSamplingInfo() {
......
...@@ -74,10 +74,12 @@ class UkmRecorderImpl : public UkmRecorder { ...@@ -74,10 +74,12 @@ class UkmRecorderImpl : public UkmRecorder {
void StoreRecordingsInReport(Report* report); void StoreRecordingsInReport(Report* report);
const std::map<SourceId, std::unique_ptr<UkmSource>>& sources() const { const std::map<SourceId, std::unique_ptr<UkmSource>>& sources() const {
return sources_; return recordings_.sources;
} }
const std::vector<mojom::UkmEntryPtr>& entries() const { return entries_; } const std::vector<mojom::UkmEntryPtr>& entries() const {
return recordings_.entries;
}
// UkmRecorder: // UkmRecorder:
void UpdateSourceURL(SourceId source_id, const GURL& url) override; void UpdateSourceURL(SourceId source_id, const GURL& url) override;
...@@ -132,16 +134,6 @@ class UkmRecorderImpl : public UkmRecorder { ...@@ -132,16 +134,6 @@ class UkmRecorderImpl : public UkmRecorder {
// Callback for checking extension IDs. // Callback for checking extension IDs.
IsWebstoreExtensionCallback is_webstore_extension_callback_; IsWebstoreExtensionCallback is_webstore_extension_callback_;
// Contains newly added sources and entries of UKM metrics which periodically
// get serialized and cleared by StoreRecordingsInReport().
std::map<SourceId, std::unique_ptr<UkmSource>> sources_;
std::vector<mojom::UkmEntryPtr> entries_;
// URLs of sources that matched a whitelist url, but were not included in
// the report generated by the last log rotation because we haven't seen any
// events for that source yet.
std::unordered_set<std::string> carryover_urls_whitelist_;
// Map from hashes to entry and metric names. // Map from hashes to entry and metric names.
ukm::builders::DecodeMap decode_map_; ukm::builders::DecodeMap decode_map_;
...@@ -152,22 +144,45 @@ class UkmRecorderImpl : public UkmRecorder { ...@@ -152,22 +144,45 @@ class UkmRecorderImpl : public UkmRecorder {
int default_sampling_rate_ = 0; int default_sampling_rate_ = 0;
base::flat_map<uint64_t, int> event_sampling_rates_; base::flat_map<uint64_t, int> event_sampling_rates_;
// Aggregate information for collected event metrics. // Contains data from various recordings which periodically get serialized
std::map<uint64_t, EventAggregate> event_aggregations_; // and cleared by StoreRecordingsInReport() and may be Purged().
struct Recordings {
// Aggregated counters about Sources recorded in the current log. Recordings();
struct SourceCounts { Recordings& operator=(Recordings&&);
// Count of URLs recorded for all sources. ~Recordings();
size_t observed = 0;
// Count of URLs recorded for all SourceIdType::NAVIGATION_ID Sources. // Data captured by UpdateSourceUrl().
size_t navigation_sources = 0; std::map<SourceId, std::unique_ptr<UkmSource>> sources;
// Sources carried over (not recorded) from a previous logging rotation.
size_t carryover_sources = 0; // Data captured by AddEntry().
std::vector<mojom::UkmEntryPtr> entries;
// URLs of sources that matched a whitelist url, but were not included in
// the report generated by the last log rotation because we haven't seen any
// events for that source yet.
std::unordered_set<std::string> carryover_urls_whitelist;
// Aggregate information for collected event metrics.
std::map<uint64_t, EventAggregate> event_aggregations;
// Aggregated counters about Sources recorded in the current log.
struct SourceCounts {
// Count of URLs recorded for all sources.
size_t observed = 0;
// Count of URLs recorded for all SourceIdType::NAVIGATION_ID Sources.
size_t navigation_sources = 0;
// Sources carried over (not recorded) from a previous logging rotation.
size_t carryover_sources = 0;
// Resets all of the data.
void Reset();
};
SourceCounts source_counts;
// Resets all of the data. // Resets all of the data.
void Reset(); void Reset();
}; };
SourceCounts source_counts_; Recordings recordings_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
}; };
......
...@@ -222,6 +222,27 @@ TEST_F(UkmServiceTest, PersistAndPurge) { ...@@ -222,6 +222,27 @@ TEST_F(UkmServiceTest, PersistAndPurge) {
EXPECT_EQ(GetPersistedLogCount(), 0); EXPECT_EQ(GetPersistedLogCount(), 0);
} }
TEST_F(UkmServiceTest, Purge) {
UkmService service(&prefs_, &client_,
true /* restrict_to_whitelisted_entries */);
TestRecordingHelper recorder(&service);
EXPECT_EQ(GetPersistedLogCount(), 0);
service.Initialize();
task_runner_->RunUntilIdle();
service.EnableRecording(/*extensions=*/false);
service.EnableReporting();
// Record some data
auto id = GetWhitelistedSourceId(0);
recorder.UpdateSourceURL(id, GURL("https://google.com/foobar1"));
TestEvent1(id).Record(&service);
// Purge should delete data, so there shouldn't be anything left to upload.
service.Purge();
service.Flush();
EXPECT_EQ(0, GetPersistedLogCount());
}
TEST_F(UkmServiceTest, SourceSerialization) { TEST_F(UkmServiceTest, SourceSerialization) {
UkmService service(&prefs_, &client_, UkmService service(&prefs_, &client_,
true /* restrict_to_whitelisted_entries */); true /* restrict_to_whitelisted_entries */);
...@@ -557,6 +578,7 @@ TEST_F(UkmServiceTest, PurgeMidUpload) { ...@@ -557,6 +578,7 @@ TEST_F(UkmServiceTest, PurgeMidUpload) {
task_runner_->RunUntilIdle(); task_runner_->RunUntilIdle();
service.EnableRecording(/*extensions=*/false); service.EnableRecording(/*extensions=*/false);
service.EnableReporting(); service.EnableReporting();
auto id = GetWhitelistedSourceId(0); auto id = GetWhitelistedSourceId(0);
recorder.UpdateSourceURL(id, GURL("https://google.com/foobar1")); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar1"));
// Should init, generate a log, and start an upload. // Should init, generate a log, and start an upload.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment