| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/ukm/ukm_service.h" | 5 #include "components/ukm/ukm_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 const size_t kMaxSources = 100; | 62 const size_t kMaxSources = 100; |
| 63 | 63 |
| 64 std::string GetServerUrl() { | 64 std::string GetServerUrl() { |
| 65 std::string server_url = | 65 std::string server_url = |
| 66 variations::GetVariationParamValueByFeature(kUkmFeature, "ServerUrl"); | 66 variations::GetVariationParamValueByFeature(kUkmFeature, "ServerUrl"); |
| 67 if (!server_url.empty()) | 67 if (!server_url.empty()) |
| 68 return server_url; | 68 return server_url; |
| 69 return kDefaultServerUrl; | 69 return kDefaultServerUrl; |
| 70 } | 70 } |
| 71 | 71 |
| 72 // Generates a new client id and stores it in prefs. |
| 73 uint64_t GenerateClientId(PrefService* pref_service) { |
| 74 uint64_t client_id = 0; |
| 75 while (!client_id) |
| 76 client_id = base::RandUint64(); |
| 77 pref_service->SetInt64(prefs::kUkmClientId, client_id); |
| 78 return client_id; |
| 79 } |
| 80 |
| 72 uint64_t LoadOrGenerateClientId(PrefService* pref_service) { | 81 uint64_t LoadOrGenerateClientId(PrefService* pref_service) { |
| 73 uint64_t client_id = pref_service->GetInt64(prefs::kUkmClientId); | 82 uint64_t client_id = pref_service->GetInt64(prefs::kUkmClientId); |
| 74 if (!client_id) { | 83 if (!client_id) |
| 75 // Generate and store a new client id. | 84 client_id = GenerateClientId(pref_service); |
| 76 while (!client_id) | |
| 77 client_id = base::RandUint64(); | |
| 78 pref_service->SetInt64(prefs::kUkmClientId, client_id); | |
| 79 } | |
| 80 return client_id; | 85 return client_id; |
| 81 } | 86 } |
| 82 | 87 |
| 88 enum class DroppedSourceReason { |
| 89 NOT_DROPPED = 0, |
| 90 RECORDING_DISABLED = 1, |
| 91 MAX_SOURCES_HIT = 2, |
| 92 NUM_DROPPED_SOURCES_REASONS |
| 93 }; |
| 94 |
| 95 void RecordDroppedSource(DroppedSourceReason reason) { |
| 96 UMA_HISTOGRAM_ENUMERATION( |
| 97 "UKM.Sources.Dropped", static_cast<int>(reason), |
| 98 static_cast<int>(DroppedSourceReason::NUM_DROPPED_SOURCES_REASONS)); |
| 99 } |
| 100 |
| 83 } // namespace | 101 } // namespace |
| 84 | 102 |
| 85 const base::Feature kUkmFeature = {"Ukm", base::FEATURE_DISABLED_BY_DEFAULT}; | 103 const base::Feature kUkmFeature = {"Ukm", base::FEATURE_DISABLED_BY_DEFAULT}; |
| 86 | 104 |
| 87 UkmService::UkmService(PrefService* pref_service, | 105 UkmService::UkmService(PrefService* pref_service, |
| 88 metrics::MetricsServiceClient* client) | 106 metrics::MetricsServiceClient* client) |
| 89 : pref_service_(pref_service), | 107 : pref_service_(pref_service), |
| 108 recording_enabled_(false), |
| 90 client_(client), | 109 client_(client), |
| 91 persisted_logs_(std::unique_ptr<ukm::PersistedLogsMetricsImpl>( | 110 persisted_logs_(std::unique_ptr<ukm::PersistedLogsMetricsImpl>( |
| 92 new ukm::PersistedLogsMetricsImpl()), | 111 new ukm::PersistedLogsMetricsImpl()), |
| 93 pref_service, | 112 pref_service, |
| 94 prefs::kUkmPersistedLogs, | 113 prefs::kUkmPersistedLogs, |
| 95 kMinPersistedLogs, | 114 kMinPersistedLogs, |
| 96 kMinPersistedBytes, | 115 kMinPersistedBytes, |
| 97 kMaxLogRetransmitSize), | 116 kMaxLogRetransmitSize), |
| 98 initialize_started_(false), | 117 initialize_started_(false), |
| 99 initialize_complete_(false), | 118 initialize_complete_(false), |
| (...skipping 27 matching lines...) Expand all Loading... |
| 127 DCHECK(thread_checker_.CalledOnValidThread()); | 146 DCHECK(thread_checker_.CalledOnValidThread()); |
| 128 DVLOG(1) << "UkmService::Initialize"; | 147 DVLOG(1) << "UkmService::Initialize"; |
| 129 initialize_started_ = true; | 148 initialize_started_ = true; |
| 130 | 149 |
| 131 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 150 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 132 FROM_HERE, | 151 FROM_HERE, |
| 133 base::Bind(&UkmService::StartInitTask, self_ptr_factory_.GetWeakPtr()), | 152 base::Bind(&UkmService::StartInitTask, self_ptr_factory_.GetWeakPtr()), |
| 134 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); | 153 base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); |
| 135 } | 154 } |
| 136 | 155 |
| 156 void UkmService::EnableRecording() { |
| 157 recording_enabled_ = true; |
| 158 } |
| 159 |
| 160 void UkmService::DisableRecording() { |
| 161 recording_enabled_ = false; |
| 162 } |
| 163 |
| 137 void UkmService::EnableReporting() { | 164 void UkmService::EnableReporting() { |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); | 165 DCHECK(thread_checker_.CalledOnValidThread()); |
| 139 DVLOG(1) << "UkmService::EnableReporting"; | 166 DVLOG(1) << "UkmService::EnableReporting"; |
| 140 | 167 |
| 141 for (auto& provider : metrics_providers_) | 168 for (auto& provider : metrics_providers_) |
| 142 provider->OnRecordingEnabled(); | 169 provider->OnRecordingEnabled(); |
| 143 | 170 |
| 144 if (!initialize_started_) | 171 if (!initialize_started_) |
| 145 Initialize(); | 172 Initialize(); |
| 146 scheduler_->Start(); | 173 scheduler_->Start(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 162 BuildAndStoreLog(); | 189 BuildAndStoreLog(); |
| 163 persisted_logs_.SerializeLogs(); | 190 persisted_logs_.SerializeLogs(); |
| 164 } | 191 } |
| 165 | 192 |
| 166 void UkmService::Purge() { | 193 void UkmService::Purge() { |
| 167 DVLOG(1) << "UkmService::Purge"; | 194 DVLOG(1) << "UkmService::Purge"; |
| 168 persisted_logs_.Purge(); | 195 persisted_logs_.Purge(); |
| 169 sources_.clear(); | 196 sources_.clear(); |
| 170 } | 197 } |
| 171 | 198 |
| 199 void UkmService::ResetClientId() { |
| 200 client_id_ = GenerateClientId(pref_service_); |
| 201 } |
| 202 |
| 172 void UkmService::RegisterMetricsProvider( | 203 void UkmService::RegisterMetricsProvider( |
| 173 std::unique_ptr<metrics::MetricsProvider> provider) { | 204 std::unique_ptr<metrics::MetricsProvider> provider) { |
| 174 metrics_providers_.push_back(std::move(provider)); | 205 metrics_providers_.push_back(std::move(provider)); |
| 175 } | 206 } |
| 176 | 207 |
| 177 // static | 208 // static |
| 178 void UkmService::RegisterPrefs(PrefRegistrySimple* registry) { | 209 void UkmService::RegisterPrefs(PrefRegistrySimple* registry) { |
| 179 registry->RegisterInt64Pref(prefs::kUkmClientId, 0); | 210 registry->RegisterInt64Pref(prefs::kUkmClientId, 0); |
| 180 registry->RegisterListPref(prefs::kUkmPersistedLogs); | 211 registry->RegisterListPref(prefs::kUkmPersistedLogs); |
| 181 } | 212 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 201 DVLOG(1) << "UkmService::RotateLog"; | 232 DVLOG(1) << "UkmService::RotateLog"; |
| 202 if (persisted_logs_.empty()) { | 233 if (persisted_logs_.empty()) { |
| 203 BuildAndStoreLog(); | 234 BuildAndStoreLog(); |
| 204 } | 235 } |
| 205 StartScheduledUpload(); | 236 StartScheduledUpload(); |
| 206 } | 237 } |
| 207 | 238 |
| 208 void UkmService::BuildAndStoreLog() { | 239 void UkmService::BuildAndStoreLog() { |
| 209 DCHECK(thread_checker_.CalledOnValidThread()); | 240 DCHECK(thread_checker_.CalledOnValidThread()); |
| 210 DVLOG(1) << "UkmService::BuildAndStoreLog"; | 241 DVLOG(1) << "UkmService::BuildAndStoreLog"; |
| 242 // Suppress generating a log if we have no new data to include. |
| 243 if (sources_.empty()) |
| 244 return; |
| 245 |
| 211 Report report; | 246 Report report; |
| 212 report.set_client_id(client_id_); | 247 report.set_client_id(client_id_); |
| 213 | 248 |
| 214 for (const auto& source : sources_) { | 249 for (const auto& source : sources_) { |
| 215 Source* proto_source = report.add_sources(); | 250 Source* proto_source = report.add_sources(); |
| 216 source->PopulateProto(proto_source); | 251 source->PopulateProto(proto_source); |
| 217 } | 252 } |
| 218 UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount", sources_.size()); | 253 UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount", sources_.size()); |
| 219 sources_.clear(); | 254 sources_.clear(); |
| 220 | 255 |
| 221 metrics::MetricsLog::RecordCoreSystemProfile(client_, | 256 metrics::MetricsLog::RecordCoreSystemProfile(client_, |
| 222 report.mutable_system_profile()); | 257 report.mutable_system_profile()); |
| 223 | 258 |
| 224 for (auto& provider : metrics_providers_) { | 259 for (auto& provider : metrics_providers_) { |
| 225 provider->ProvideSystemProfileMetrics(report.mutable_system_profile()); | 260 provider->ProvideSystemProfileMetrics(report.mutable_system_profile()); |
| 226 } | 261 } |
| 227 | 262 |
| 228 std::string serialized_log; | 263 std::string serialized_log; |
| 229 report.SerializeToString(&serialized_log); | 264 report.SerializeToString(&serialized_log); |
| 230 persisted_logs_.StoreLog(serialized_log); | 265 persisted_logs_.StoreLog(serialized_log); |
| 231 } | 266 } |
| 232 | 267 |
| 233 void UkmService::StartScheduledUpload() { | 268 void UkmService::StartScheduledUpload() { |
| 234 DCHECK(thread_checker_.CalledOnValidThread()); | 269 DCHECK(thread_checker_.CalledOnValidThread()); |
| 235 DCHECK(!log_upload_in_progress_); | 270 DCHECK(!log_upload_in_progress_); |
| 271 if (persisted_logs_.empty()) { |
| 272 // No logs to send, so early out and schedule the next rotation. |
| 273 scheduler_->UploadFinished(true, /* has_unsent_logs */ false); |
| 274 return; |
| 275 } |
| 236 if (!persisted_logs_.has_staged_log()) | 276 if (!persisted_logs_.has_staged_log()) |
| 237 persisted_logs_.StageLog(); | 277 persisted_logs_.StageLog(); |
| 238 // TODO(holte): Handle data usage on cellular, etc. | 278 // TODO(holte): Handle data usage on cellular, etc. |
| 239 if (!log_uploader_) { | 279 if (!log_uploader_) { |
| 240 log_uploader_ = client_->CreateUploader( | 280 log_uploader_ = client_->CreateUploader( |
| 241 GetServerUrl(), kMimeType, base::Bind(&UkmService::OnLogUploadComplete, | 281 GetServerUrl(), kMimeType, base::Bind(&UkmService::OnLogUploadComplete, |
| 242 self_ptr_factory_.GetWeakPtr())); | 282 self_ptr_factory_.GetWeakPtr())); |
| 243 } | 283 } |
| 244 log_upload_in_progress_ = true; | 284 log_upload_in_progress_ = true; |
| 245 | 285 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 275 persisted_logs_.SerializeLogs(); | 315 persisted_logs_.SerializeLogs(); |
| 276 } | 316 } |
| 277 | 317 |
| 278 // Error 400 indicates a problem with the log, not with the server, so | 318 // Error 400 indicates a problem with the log, not with the server, so |
| 279 // don't consider that a sign that the server is in trouble. | 319 // don't consider that a sign that the server is in trouble. |
| 280 bool server_is_healthy = upload_succeeded || response_code == 400; | 320 bool server_is_healthy = upload_succeeded || response_code == 400; |
| 281 scheduler_->UploadFinished(server_is_healthy, !persisted_logs_.empty()); | 321 scheduler_->UploadFinished(server_is_healthy, !persisted_logs_.empty()); |
| 282 } | 322 } |
| 283 | 323 |
| 284 void UkmService::RecordSource(std::unique_ptr<UkmSource> source) { | 324 void UkmService::RecordSource(std::unique_ptr<UkmSource> source) { |
| 325 if (!recording_enabled_) { |
| 326 RecordDroppedSource(DroppedSourceReason::RECORDING_DISABLED); |
| 327 return; |
| 328 } |
| 285 if (sources_.size() >= kMaxSources) { | 329 if (sources_.size() >= kMaxSources) { |
| 286 UMA_HISTOGRAM_BOOLEAN("UKM.Sources.MaxSourcesHit", true); | 330 RecordDroppedSource(DroppedSourceReason::MAX_SOURCES_HIT); |
| 287 return; | 331 return; |
| 288 } | 332 } |
| 289 | 333 |
| 290 sources_.push_back(std::move(source)); | 334 sources_.push_back(std::move(source)); |
| 291 } | 335 } |
| 292 | 336 |
| 293 } // namespace ukm | 337 } // namespace ukm |
| OLD | NEW |