1 // Copyright 2017 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.
5 // ReportingService specialized to report UKM metrics.
7 #include "components/ukm/ukm_reporting_service.h"
11 #include "base/command_line.h"
12 #include "base/metrics/field_trial_params.h"
13 #include "base/metrics/histogram_functions.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "build/build_config.h"
16 #include "components/metrics/metrics_service_client.h"
17 #include "components/metrics/metrics_switches.h"
18 #include "components/metrics/url_constants.h"
19 #include "components/prefs/pref_registry_simple.h"
20 #include "components/ukm/ukm_pref_names.h"
21 #include "components/ukm/ukm_service.h"
22 #include "components/ukm/unsent_log_store_metrics_impl.h"
23 #include "third_party/zlib/google/compression_utils.h"
26 #include "components/ukm/ios/ukm_reporting_ios_util.h"
33 // The number of UKM logs that will be stored in UnsentLogStore before logs
34 // start being dropped.
35 constexpr int kMinUnsentLogCount = 8;
37 // The number of bytes UKM logs that will be stored in UnsentLogStore before
38 // logs start being dropped.
39 // This ensures that a reasonable amount of history will be stored even if there
40 // is a long series of very small logs.
41 constexpr int kMinUnsentLogBytes = 300000;
43 // If an upload fails, and the transmission was over this byte count, then we
44 // will discard the log, and not try to retransmit it. We also don't persist
45 // the log to the prefs for transmission during the next chrome session if this
47 constexpr size_t kMaxLogRetransmitSize = 100 * 1024;
51 // Only allow overriding the server URL through the command line in debug
52 // builds. This is to prevent, for example, rerouting metrics due to malware.
53 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
54 if (command_line->HasSwitch(metrics::switches::kUkmServerUrl)) {
56 command_line->GetSwitchValueASCII(metrics::switches::kUkmServerUrl));
60 std::string server_url =
61 base::GetFieldTrialParamValueByFeature(kUkmFeature, "ServerUrl");
62 if (!server_url.empty())
63 return GURL(server_url);
64 return GURL(metrics::kDefaultUkmServerUrl);
70 void UkmReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
71 registry->RegisterListPref(prefs::kUkmUnsentLogStore);
72 // Base class already registered by MetricsReportingService::RegisterPrefs
73 // ReportingService::RegisterPrefs(registry);
76 UkmReportingService::UkmReportingService(metrics::MetricsServiceClient* client,
77 PrefService* local_state)
78 : ReportingService(client,
80 kMaxLogRetransmitSize,
81 /*logs_event_manager=*/nullptr),
82 unsent_log_store_(std::make_unique<ukm::UnsentLogStoreMetricsImpl>(),
84 prefs::kUkmUnsentLogStore,
88 kMaxLogRetransmitSize,
89 client->GetUploadSigningKey(),
90 /*logs_event_manager=*/nullptr) {}
92 UkmReportingService::~UkmReportingService() {}
94 metrics::LogStore* UkmReportingService::log_store() {
95 return &unsent_log_store_;
98 GURL UkmReportingService::GetUploadUrl() const {
99 return GetServerUrl();
102 GURL UkmReportingService::GetInsecureUploadUrl() const {
106 base::StringPiece UkmReportingService::upload_mime_type() const {
107 return metrics::kUkmMimeType;
110 metrics::MetricsLogUploader::MetricServiceType
111 UkmReportingService::service_type() const {
112 return metrics::MetricsLogUploader::UKM;
115 void UkmReportingService::LogCellularConstraint(bool upload_canceled) {
116 UMA_HISTOGRAM_BOOLEAN("UKM.LogUpload.Canceled.CellularConstraint",
120 void UkmReportingService::LogResponseOrErrorCode(int response_code,
123 // |was_https| is ignored since all UKM logs are received over HTTPS.
124 base::UmaHistogramSparse("UKM.LogUpload.ResponseOrErrorCode",
125 response_code >= 0 ? response_code : error_code);
128 void UkmReportingService::LogSuccessLogSize(size_t log_size) {
129 #if BUILDFLAG(IS_IOS)
130 IncrementUkmLogSizeOnSuccessCounter();
132 UMA_HISTOGRAM_COUNTS_10000("UKM.LogSize.OnSuccess", log_size / 1024);
135 void UkmReportingService::LogSuccessMetadata(const std::string& staged_log) {
136 // Recover the report from the compressed staged log.
137 // Note: We don't use metrics::DecodeLogDataToProto() since we to use
138 // |uncompressed_log_data| later in the function.
139 std::string uncompressed_log_data;
140 bool uncompress_successful =
141 compression::GzipUncompress(staged_log, &uncompressed_log_data);
142 DCHECK(uncompress_successful);
144 report.ParseFromString(uncompressed_log_data);
146 // Log the relative size of the report with relevant UKM data omitted. This
147 // helps us to estimate the bandwidth usage of logs upload that is not
148 // directly attributed to UKM data, for example the system profile info.
149 // Note that serialized logs are further compressed before upload, thus the
150 // percentages here are not the exact percentage of bandwidth they ended up
152 std::string log_without_ukm_data;
153 report.clear_sources();
154 report.clear_source_counts();
155 report.clear_entries();
156 report.clear_aggregates();
157 report.SerializeToString(&log_without_ukm_data);
159 int non_ukm_percentage =
160 log_without_ukm_data.length() * 100 / uncompressed_log_data.length();
161 DCHECK_GE(non_ukm_percentage, 0);
162 DCHECK_LE(non_ukm_percentage, 100);
163 base::UmaHistogramPercentage("UKM.ReportSize.NonUkmPercentage",
167 void UkmReportingService::LogLargeRejection(size_t log_size) {}