blob: ac35ce396a32a8f06f1a7a7d913953cbb161e290 [file] [log] [blame]
[email protected]91b1d912014-06-05 10:52:081// Copyright 2014 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]91b1d912014-06-05 10:52:085#include "components/metrics/metrics_log.h"
initial.commit09911bf2008-07-26 23:55:296
avi26062922015-12-26 00:14:187#include <stddef.h>
8
[email protected]76869ff2013-01-15 16:13:479#include <algorithm>
[email protected]1eeb5e02010-07-20 23:02:1110#include <string>
[email protected]1eeb5e02010-07-20 23:02:1111
sebmarchand2f4ed502014-10-31 15:28:1912#include "base/build_time.h"
[email protected]5c8f89f692013-07-18 11:13:2813#include "base/cpu.h"
asvitkinef5d4ee562016-11-07 18:57:0814#include "base/metrics/histogram_macros.h"
[email protected]bfb77b52014-06-07 01:54:0115#include "base/metrics/histogram_samples.h"
bcwhite502b2292015-11-30 22:31:0116#include "base/metrics/metrics_hashes.h"
[email protected]fadf97f2008-09-18 12:18:1417#include "base/sys_info.h"
[email protected]84813472013-06-28 00:25:1918#include "base/time/time.h"
avi26062922015-12-26 00:14:1819#include "build/build_config.h"
holte1bf273c2017-02-23 00:22:2820#include "components/metrics/environment_recorder.h"
rtenneti72546962014-12-15 21:41:5921#include "components/metrics/histogram_encoder.h"
[email protected]91b1d912014-06-05 10:52:0822#include "components/metrics/metrics_pref_names.h"
[email protected]85791b0b2014-05-20 15:18:5823#include "components/metrics/metrics_provider.h"
[email protected]09dee82d2014-05-22 14:00:5324#include "components/metrics/metrics_service_client.h"
[email protected]bfb77b52014-06-07 01:54:0125#include "components/metrics/proto/histogram_event.pb.h"
[email protected]064107e2014-05-02 00:59:0626#include "components/metrics/proto/system_profile.pb.h"
[email protected]bfb77b52014-06-07 01:54:0127#include "components/metrics/proto/user_action_event.pb.h"
brettw066508682016-02-03 08:22:0228#include "components/prefs/pref_registry_simple.h"
29#include "components/prefs/pref_service.h"
[email protected]b3610d42014-05-19 18:07:2330#include "components/variations/active_field_trials.h"
initial.commit09911bf2008-07-26 23:55:2931
[email protected]5106b3a2012-10-03 20:10:4432#if defined(OS_ANDROID)
33#include "base/android/build_info.h"
34#endif
35
[email protected]d1be67b2008-11-19 20:28:3836#if defined(OS_WIN)
thakisd62f54472016-04-04 02:21:1037#include "base/win/current_module.h"
[email protected]d1be67b2008-11-19 20:28:3838#endif
39
[email protected]bfb77b52014-06-07 01:54:0140using base::SampleCountIterator;
[email protected]b3610d42014-05-19 18:07:2341typedef variations::ActiveGroupId ActiveGroupId;
[email protected]79078df2012-02-16 01:22:3242
asvitkinecbd420732014-08-26 22:15:4043namespace metrics {
44
[email protected]1df44b72012-01-19 05:20:3445namespace {
46
[email protected]bfb77b52014-06-07 01:54:0147// Any id less than 16 bytes is considered to be a testing id.
48bool IsTestingID(const std::string& id) {
49 return id.size() < 16;
50}
51
[email protected]0c8b7ad2012-11-06 07:08:1452void WriteFieldTrials(const std::vector<ActiveGroupId>& field_trial_ids,
[email protected]767c9d92012-03-02 16:04:3453 SystemProfileProto* system_profile) {
[email protected]0c8b7ad2012-11-06 07:08:1454 for (std::vector<ActiveGroupId>::const_iterator it =
[email protected]ad2461c2012-04-27 21:11:0355 field_trial_ids.begin(); it != field_trial_ids.end(); ++it) {
[email protected]767c9d92012-03-02 16:04:3456 SystemProfileProto::FieldTrial* field_trial =
57 system_profile->add_field_trial();
58 field_trial->set_name_id(it->name);
59 field_trial->set_group_id(it->group);
60 }
61}
62
[email protected]86573d12013-07-11 19:48:3263// Round a timestamp measured in seconds since epoch to one with a granularity
64// of an hour. This can be used before uploaded potentially sensitive
65// timestamps.
avi26062922015-12-26 00:14:1866int64_t RoundSecondsToHour(int64_t time_in_seconds) {
[email protected]86573d12013-07-11 19:48:3267 return 3600 * (time_in_seconds / 3600);
68}
69
[email protected]1df44b72012-01-19 05:20:3470} // namespace
71
[email protected]9eae4032014-04-09 19:15:1972MetricsLog::MetricsLog(const std::string& client_id,
73 int session_id,
[email protected]09dee82d2014-05-22 14:00:5374 LogType log_type,
asvitkine4c1d1ef2014-09-29 20:57:3275 MetricsServiceClient* client,
[email protected]24f81ca2014-05-26 15:59:3476 PrefService* local_state)
[email protected]bfb77b52014-06-07 01:54:0177 : closed_(false),
78 log_type_(log_type),
[email protected]09dee82d2014-05-22 14:00:5379 client_(client),
[email protected]24f81ca2014-05-26 15:59:3480 creation_time_(base::TimeTicks::Now()),
81 local_state_(local_state) {
[email protected]bfb77b52014-06-07 01:54:0182 if (IsTestingID(client_id))
83 uma_proto_.set_client_id(0);
84 else
85 uma_proto_.set_client_id(Hash(client_id));
86
87 uma_proto_.set_session_id(session_id);
88
avi26062922015-12-26 00:14:1889 const int32_t product = client_->GetProduct();
asvitkine4c1d1ef2014-09-29 20:57:3290 // Only set the product if it differs from the default value.
91 if (product != uma_proto_.product())
92 uma_proto_.set_product(product);
93
rkaplow2b85c622017-01-30 16:57:1794 RecordCoreSystemProfile(client_, uma_proto_.mutable_system_profile());
[email protected]afc03f02013-10-11 06:01:3595}
[email protected]5ed7d4572009-12-23 17:42:4196
[email protected]bfb77b52014-06-07 01:54:0197MetricsLog::~MetricsLog() {
98}
initial.commit09911bf2008-07-26 23:55:2999
[email protected]91b1d912014-06-05 10:52:08100// static
101void MetricsLog::RegisterPrefs(PrefRegistrySimple* registry) {
holte1bf273c2017-02-23 00:22:28102 EnvironmentRecorder::RegisterPrefs(registry);
[email protected]91b1d912014-06-05 10:52:08103}
104
[email protected]bfb77b52014-06-07 01:54:01105// static
avi26062922015-12-26 00:14:18106uint64_t MetricsLog::Hash(const std::string& value) {
107 uint64_t hash = base::HashMetricName(value);
[email protected]bfb77b52014-06-07 01:54:01108
109 // The following log is VERY helpful when folks add some named histogram into
110 // the code, but forgot to update the descriptive list of histograms. When
111 // that happens, all we get to see (server side) is a hash of the histogram
112 // name. We can then use this logging to find out what histogram name was
113 // being hashed to a given MD5 value by just running the version of Chromium
114 // in question with --enable-logging.
115 DVLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
116
117 return hash;
118}
119
120// static
avi26062922015-12-26 00:14:18121int64_t MetricsLog::GetBuildTime() {
122 static int64_t integral_build_time = 0;
sebmarchand2f4ed502014-10-31 15:28:19123 if (!integral_build_time)
avi26062922015-12-26 00:14:18124 integral_build_time = static_cast<int64_t>(base::GetBuildTime().ToTimeT());
[email protected]bfb77b52014-06-07 01:54:01125 return integral_build_time;
126}
127
128// static
avi26062922015-12-26 00:14:18129int64_t MetricsLog::GetCurrentTime() {
[email protected]bfb77b52014-06-07 01:54:01130 return (base::TimeTicks::Now() - base::TimeTicks()).InSeconds();
131}
132
133void MetricsLog::RecordUserAction(const std::string& key) {
134 DCHECK(!closed_);
135
136 UserActionEventProto* user_action = uma_proto_.add_user_action_event();
137 user_action->set_name_hash(Hash(key));
138 user_action->set_time(GetCurrentTime());
139}
140
rkaplow2b85c622017-01-30 16:57:17141void MetricsLog::RecordCoreSystemProfile(MetricsServiceClient* client,
142 SystemProfileProto* system_profile) {
143 system_profile->set_build_timestamp(metrics::MetricsLog::GetBuildTime());
144 system_profile->set_app_version(client->GetVersionString());
145 system_profile->set_channel(client->GetChannel());
146 system_profile->set_application_locale(client->GetApplicationLocale());
147
148#if defined(SYZYASAN)
149 system_profile->set_is_asan_build(true);
150#endif
151
152 metrics::SystemProfileProto::Hardware* hardware =
153 system_profile->mutable_hardware();
asvitkinea86e8e12017-02-01 19:33:59154#if !defined(OS_IOS)
155 // On iOS, OperatingSystemArchitecture() returns values like iPad4,4 which is
156 // not the actual CPU architecture. Don't set it until the API is fixed. See
157 // crbug.com/370104 for details.
rkaplow2b85c622017-01-30 16:57:17158 hardware->set_cpu_architecture(base::SysInfo::OperatingSystemArchitecture());
asvitkinea86e8e12017-02-01 19:33:59159#endif
rkaplow2b85c622017-01-30 16:57:17160 hardware->set_system_ram_mb(base::SysInfo::AmountOfPhysicalMemoryMB());
161 hardware->set_hardware_class(base::SysInfo::HardwareModelName());
162#if defined(OS_WIN)
163 hardware->set_dll_base(reinterpret_cast<uint64_t>(CURRENT_MODULE()));
164#endif
165
166 metrics::SystemProfileProto::OS* os = system_profile->mutable_os();
167 os->set_name(base::SysInfo::OperatingSystemName());
168 os->set_version(base::SysInfo::OperatingSystemVersion());
169#if defined(OS_ANDROID)
170 os->set_fingerprint(
171 base::android::BuildInfo::GetInstance()->android_build_fp());
172#endif
173}
174
[email protected]bfb77b52014-06-07 01:54:01175void MetricsLog::RecordHistogramDelta(const std::string& histogram_name,
176 const base::HistogramSamples& snapshot) {
177 DCHECK(!closed_);
rtenneti72546962014-12-15 21:41:59178 EncodeHistogramDelta(histogram_name, snapshot, &uma_proto_);
[email protected]bfb77b52014-06-07 01:54:01179}
180
[email protected]85791b0b2014-05-20 15:18:58181void MetricsLog::RecordStabilityMetrics(
ke.hea9da80c2017-02-16 12:45:00182 const std::vector<std::unique_ptr<MetricsProvider>>& metrics_providers,
[email protected]85791b0b2014-05-20 15:18:58183 base::TimeDelta incremental_uptime,
184 base::TimeDelta uptime) {
[email protected]bfb77b52014-06-07 01:54:01185 DCHECK(!closed_);
[email protected]0f2f7792013-11-28 16:09:14186 DCHECK(HasEnvironment());
187 DCHECK(!HasStabilityMetrics());
[email protected]0b33f80b2008-12-17 21:34:36188
[email protected]0edf8762013-11-21 18:33:30189 // Record recent delta for critical stability metrics. We can't wait for a
190 // restart to gather these, as that delay biases our observation away from
191 // users that run happily for a looooong time. We send increments with each
192 // uma log upload, just as we send histogram data.
holte1bf273c2017-02-23 00:22:28193 WriteRealtimeStabilityAttributes(incremental_uptime, uptime);
initial.commit09911bf2008-07-26 23:55:29194
[email protected]48ff2c7f2014-05-23 09:57:45195 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
lpromeroca8cb6f2015-04-30 18:16:53196 for (size_t i = 0; i < metrics_providers.size(); ++i) {
197 if (log_type() == INITIAL_STABILITY_LOG)
198 metrics_providers[i]->ProvideInitialStabilityMetrics(system_profile);
[email protected]48ff2c7f2014-05-23 09:57:45199 metrics_providers[i]->ProvideStabilityMetrics(system_profile);
lpromeroca8cb6f2015-04-30 18:16:53200 }
[email protected]0edf8762013-11-21 18:33:30201}
[email protected]fe58acc22012-02-29 01:29:58202
[email protected]85791b0b2014-05-20 15:18:58203void MetricsLog::RecordGeneralMetrics(
ke.hea9da80c2017-02-16 12:45:00204 const std::vector<std::unique_ptr<MetricsProvider>>& metrics_providers) {
asvitkine1359e8d2017-02-06 17:37:10205 if (local_state_->GetBoolean(prefs::kMetricsResetIds))
206 UMA_HISTOGRAM_BOOLEAN("UMA.IsClonedInstall", true);
207
[email protected]85791b0b2014-05-20 15:18:58208 for (size_t i = 0; i < metrics_providers.size(); ++i)
209 metrics_providers[i]->ProvideGeneralMetrics(uma_proto());
210}
211
[email protected]0edf8762013-11-21 18:33:30212void MetricsLog::GetFieldTrialIds(
213 std::vector<ActiveGroupId>* field_trial_ids) const {
[email protected]b3610d42014-05-19 18:07:23214 variations::GetFieldTrialActiveGroupIds(field_trial_ids);
[email protected]147bbc0b2009-01-06 19:37:40215}
216
[email protected]0f2f7792013-11-28 16:09:14217bool MetricsLog::HasEnvironment() const {
218 return uma_proto()->system_profile().has_uma_enabled_date();
219}
220
gayanedaaf3a02016-06-15 16:30:21221void MetricsLog::WriteMetricsEnableDefault(EnableMetricsDefault metrics_default,
222 SystemProfileProto* system_profile) {
jwd421086f2016-03-21 14:40:42223 if (client_->IsReportingPolicyManaged()) {
224 // If it's managed, then it must be reporting, otherwise we wouldn't be
225 // sending metrics.
226 system_profile->set_uma_default_state(
227 SystemProfileProto_UmaDefaultState_POLICY_FORCED_ENABLED);
228 return;
229 }
230
231 switch (metrics_default) {
gayanedaaf3a02016-06-15 16:30:21232 case EnableMetricsDefault::DEFAULT_UNKNOWN:
jwd421086f2016-03-21 14:40:42233 // Don't set the field if it's unknown.
234 break;
gayanedaaf3a02016-06-15 16:30:21235 case EnableMetricsDefault::OPT_IN:
jwd421086f2016-03-21 14:40:42236 system_profile->set_uma_default_state(
237 SystemProfileProto_UmaDefaultState_OPT_IN);
238 break;
gayanedaaf3a02016-06-15 16:30:21239 case EnableMetricsDefault::OPT_OUT:
jwd421086f2016-03-21 14:40:42240 system_profile->set_uma_default_state(
241 SystemProfileProto_UmaDefaultState_OPT_OUT);
242 }
243}
244
[email protected]0f2f7792013-11-28 16:09:14245bool MetricsLog::HasStabilityMetrics() const {
246 return uma_proto()->system_profile().stability().has_launch_count();
247}
248
[email protected]c68a2b9b2013-10-09 18:16:36249void MetricsLog::WriteRealtimeStabilityAttributes(
[email protected]076961c2014-03-12 22:23:56250 base::TimeDelta incremental_uptime,
251 base::TimeDelta uptime) {
[email protected]0b33f80b2008-12-17 21:34:36252 // Update the stats which are critical for real-time stability monitoring.
253 // Since these are "optional," only list ones that are non-zero, as the counts
[email protected]250f7b662013-11-23 02:36:51254 // are aggregated (summed) server side.
[email protected]0b33f80b2008-12-17 21:34:36255
[email protected]fe58acc22012-02-29 01:29:58256 SystemProfileProto::Stability* stability =
[email protected]767c9d92012-03-02 16:04:34257 uma_proto()->mutable_system_profile()->mutable_stability();
[email protected]0b33f80b2008-12-17 21:34:36258
avi26062922015-12-26 00:14:18259 const uint64_t incremental_uptime_sec = incremental_uptime.InSeconds();
[email protected]076961c2014-03-12 22:23:56260 if (incremental_uptime_sec)
261 stability->set_incremental_uptime_sec(incremental_uptime_sec);
avi26062922015-12-26 00:14:18262 const uint64_t uptime_sec = uptime.InSeconds();
[email protected]c68a2b9b2013-10-09 18:16:36263 if (uptime_sec)
264 stability->set_uptime_sec(uptime_sec);
[email protected]0b33f80b2008-12-17 21:34:36265}
266
manzagopa5d6688d2016-10-25 20:16:03267std::string MetricsLog::RecordEnvironment(
ke.hea9da80c2017-02-16 12:45:00268 const std::vector<std::unique_ptr<MetricsProvider>>& metrics_providers,
[email protected]65801452014-07-09 05:42:41269 const std::vector<variations::ActiveGroupId>& synthetic_trials,
avi26062922015-12-26 00:14:18270 int64_t install_date,
271 int64_t metrics_reporting_enabled_date) {
[email protected]0f2f7792013-11-28 16:09:14272 DCHECK(!HasEnvironment());
273
[email protected]bc66d532012-03-23 01:57:05274 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
[email protected]24b9bb392013-01-29 20:29:29275
gayanedaaf3a02016-06-15 16:30:21276 WriteMetricsEnableDefault(client_->GetMetricsReportingDefaultState(),
277 system_profile);
jwd421086f2016-03-21 14:40:42278
[email protected]24b9bb392013-01-29 20:29:29279 std::string brand_code;
[email protected]09dee82d2014-05-22 14:00:53280 if (client_->GetBrand(&brand_code))
[email protected]24b9bb392013-01-29 20:29:29281 system_profile->set_brand_code(brand_code);
282
[email protected]86573d12013-07-11 19:48:32283 // Reduce granularity of the enabled_date field to nearest hour.
olivierrobinc3dfc5b2015-04-07 19:12:00284 system_profile->set_uma_enabled_date(
285 RoundSecondsToHour(metrics_reporting_enabled_date));
[email protected]86573d12013-07-11 19:48:32286
[email protected]86573d12013-07-11 19:48:32287 // Reduce granularity of the install_date field to nearest hour.
288 system_profile->set_install_date(RoundSecondsToHour(install_date));
[email protected]bc66d532012-03-23 01:57:05289
rkaplow2b85c622017-01-30 16:57:17290 SystemProfileProto::Hardware::CPU* cpu =
291 system_profile->mutable_hardware()->mutable_cpu();
[email protected]5c8f89f692013-07-18 11:13:28292 base::CPU cpu_info;
[email protected]5c8f89f692013-07-18 11:13:28293 cpu->set_vendor_name(cpu_info.vendor_name());
294 cpu->set_signature(cpu_info.signature());
gayanef550f50f2015-03-11 00:44:59295 cpu->set_num_cores(base::SysInfo::NumberOfProcessors());
[email protected]5c8f89f692013-07-18 11:13:28296
[email protected]0c8b7ad2012-11-06 07:08:14297 std::vector<ActiveGroupId> field_trial_ids;
[email protected]767c9d92012-03-02 16:04:34298 GetFieldTrialIds(&field_trial_ids);
299 WriteFieldTrials(field_trial_ids, system_profile);
[email protected]60677562013-11-17 15:52:55300 WriteFieldTrials(synthetic_trials, system_profile);
[email protected]f65859e2013-02-04 20:00:25301
[email protected]85791b0b2014-05-20 15:18:58302 for (size_t i = 0; i < metrics_providers.size(); ++i)
303 metrics_providers[i]->ProvideSystemProfileMetrics(system_profile);
304
holte1bf273c2017-02-23 00:22:28305 EnvironmentRecorder recorder(local_state_);
306 return recorder.SerializeAndRecordEnvironmentToPrefs(*system_profile);
[email protected]0f2f7792013-11-28 16:09:14307}
308
manzagopea99d1952016-09-08 23:40:05309bool MetricsLog::LoadSavedEnvironmentFromPrefs(std::string* app_version) {
310 DCHECK(app_version);
311 app_version->clear();
312
[email protected]0f2f7792013-11-28 16:09:14313 SystemProfileProto* system_profile = uma_proto()->mutable_system_profile();
holte1bf273c2017-02-23 00:22:28314 EnvironmentRecorder recorder(local_state_);
315 bool success = recorder.LoadEnvironmentFromPrefs(system_profile);
manzagopea99d1952016-09-08 23:40:05316 if (success)
317 *app_version = system_profile->app_version();
318 return success;
initial.commit09911bf2008-07-26 23:55:29319}
320
[email protected]bfb77b52014-06-07 01:54:01321void MetricsLog::CloseLog() {
322 DCHECK(!closed_);
323 closed_ = true;
324}
325
326void MetricsLog::GetEncodedLog(std::string* encoded_log) {
327 DCHECK(closed_);
328 uma_proto_.SerializeToString(encoded_log);
329}
asvitkinecbd420732014-08-26 22:15:40330
331} // namespace metrics