Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 //------------------------------------------------------------------------------ | 5 //------------------------------------------------------------------------------ |
| 6 // Description of the life cycle of a instance of MetricsService. | 6 // Description of the life cycle of a instance of MetricsService. |
| 7 // | 7 // |
| 8 // OVERVIEW | 8 // OVERVIEW |
| 9 // | 9 // |
| 10 // A MetricsService instance is typically created at application startup. It | 10 // A MetricsService instance is typically created at application startup. It |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 | 232 |
| 233 // If an upload fails, and the transmission was over this byte count, then we | 233 // If an upload fails, and the transmission was over this byte count, then we |
| 234 // will discard the log, and not try to retransmit it. We also don't persist | 234 // will discard the log, and not try to retransmit it. We also don't persist |
| 235 // the log to the prefs for transmission during the next chrome session if this | 235 // the log to the prefs for transmission during the next chrome session if this |
| 236 // limit is exceeded. | 236 // limit is exceeded. |
| 237 const size_t kUploadLogAvoidRetransmitSize = 50000; | 237 const size_t kUploadLogAvoidRetransmitSize = 50000; |
| 238 | 238 |
| 239 // Interval, in minutes, between state saves. | 239 // Interval, in minutes, between state saves. |
| 240 const int kSaveStateIntervalMinutes = 5; | 240 const int kSaveStateIntervalMinutes = 5; |
| 241 | 241 |
| 242 // Used to indicate that the response code is currently not set at all -- | |
| 243 // RESPONSE_CODE_INVALID can sometimes be returned in response to a request if, | |
| 244 // e.g., the server is down. | |
| 245 const int kNoResponseCode = net::URLFetcher::RESPONSE_CODE_INVALID - 1; | |
| 246 | |
| 247 enum ResponseStatus { | 242 enum ResponseStatus { |
| 248 UNKNOWN_FAILURE, | 243 UNKNOWN_FAILURE, |
| 249 SUCCESS, | 244 SUCCESS, |
| 250 BAD_REQUEST, // Invalid syntax or log too large. | 245 BAD_REQUEST, // Invalid syntax or log too large. |
| 251 NO_RESPONSE, | 246 NO_RESPONSE, |
| 252 NUM_RESPONSE_STATUSES | 247 NUM_RESPONSE_STATUSES |
| 253 }; | 248 }; |
| 254 | 249 |
| 255 ResponseStatus ResponseCodeToStatus(int response_code) { | 250 ResponseStatus ResponseCodeToStatus(int response_code) { |
| 256 switch (response_code) { | 251 switch (response_code) { |
| (...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 } | 1005 } |
| 1011 | 1006 |
| 1012 void MetricsService::PushPendingLogsToPersistentStorage() { | 1007 void MetricsService::PushPendingLogsToPersistentStorage() { |
| 1013 if (state_ < INITIAL_LOG_READY) | 1008 if (state_ < INITIAL_LOG_READY) |
| 1014 return; // We didn't and still don't have time to get plugin list etc. | 1009 return; // We didn't and still don't have time to get plugin list etc. |
| 1015 | 1010 |
| 1016 if (log_manager_.has_staged_log()) { | 1011 if (log_manager_.has_staged_log()) { |
| 1017 // We may race here, and send second copy of initial log later. | 1012 // We may race here, and send second copy of initial log later. |
| 1018 if (state_ == INITIAL_LOG_READY) | 1013 if (state_ == INITIAL_LOG_READY) |
| 1019 state_ = SENDING_OLD_LOGS; | 1014 state_ = SENDING_OLD_LOGS; |
| 1020 MetricsLogManager::StoreType store_type = current_fetch_xml_.get() ? | 1015 |
| 1021 MetricsLogManager::PROVISIONAL_STORE : MetricsLogManager::NORMAL_STORE; | 1016 MetricsLogManager::StoreType store_type; |
| 1017 if (current_fetch_xml_.get() || current_fetch_proto_.get()) | |
| 1018 store_type = MetricsLogManager::PROVISIONAL_STORE; | |
| 1019 else | |
| 1020 store_type = MetricsLogManager::NORMAL_STORE; | |
| 1022 log_manager_.StoreStagedLogAsUnsent(store_type); | 1021 log_manager_.StoreStagedLogAsUnsent(store_type); |
| 1023 } | 1022 } |
| 1024 DCHECK(!log_manager_.has_staged_log()); | 1023 DCHECK(!log_manager_.has_staged_log()); |
| 1025 StopRecording(); | 1024 StopRecording(); |
| 1026 StoreUnsentLogs(); | 1025 StoreUnsentLogs(); |
| 1027 } | 1026 } |
| 1028 | 1027 |
| 1029 //------------------------------------------------------------------------------ | 1028 //------------------------------------------------------------------------------ |
| 1030 // Transmission of logs methods | 1029 // Transmission of logs methods |
| 1031 | 1030 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1117 !recording_active() || !reporting_active()) { | 1116 !recording_active() || !reporting_active()) { |
| 1118 scheduler_->Stop(); | 1117 scheduler_->Stop(); |
| 1119 scheduler_->UploadCancelled(); | 1118 scheduler_->UploadCancelled(); |
| 1120 return; | 1119 return; |
| 1121 } | 1120 } |
| 1122 | 1121 |
| 1123 MakeStagedLog(); | 1122 MakeStagedLog(); |
| 1124 | 1123 |
| 1125 // MakeStagedLog should have prepared log text; if it didn't, skip this | 1124 // MakeStagedLog should have prepared log text; if it didn't, skip this |
| 1126 // upload and hope things work out next time. | 1125 // upload and hope things work out next time. |
| 1127 if (log_manager_.staged_log_text().empty()) { | 1126 if (!log_manager_.has_staged_log()) { |
| 1128 scheduler_->UploadCancelled(); | 1127 scheduler_->UploadCancelled(); |
| 1128 // TODO(jar): If compression failed, we should have created a tiny log and | |
| 1129 // compressed that, so that we can signal that we're losing logs. | |
| 1129 return; | 1130 return; |
| 1130 } | 1131 } |
| 1131 | 1132 |
| 1132 SendStagedLog(); | 1133 SendStagedLog(); |
| 1133 } | 1134 } |
| 1134 | 1135 |
| 1135 void MetricsService::MakeStagedLog() { | 1136 void MetricsService::MakeStagedLog() { |
| 1136 if (log_manager_.has_staged_log()) | 1137 if (log_manager_.has_staged_log()) |
| 1137 return; | 1138 return; |
| 1138 | 1139 |
| 1139 switch (state_) { | 1140 switch (state_) { |
| 1140 case INITIALIZED: | 1141 case INITIALIZED: |
| 1141 case INIT_TASK_SCHEDULED: // We should be further along by now. | 1142 case INIT_TASK_SCHEDULED: // We should be further along by now. |
| 1142 DCHECK(false); | 1143 NOTREACHED(); |
| 1143 return; | 1144 return; |
| 1144 | 1145 |
| 1145 case INIT_TASK_DONE: | 1146 case INIT_TASK_DONE: |
| 1146 // We need to wait for the initial log to be ready before sending | 1147 // We need to wait for the initial log to be ready before sending |
| 1147 // anything, because the server will tell us whether it wants to hear | 1148 // anything, because the server will tell us whether it wants to hear |
| 1148 // from us. | 1149 // from us. |
| 1149 PrepareInitialLog(); | 1150 PrepareInitialLog(); |
| 1150 DCHECK_EQ(INIT_TASK_DONE, state_); | 1151 DCHECK_EQ(INIT_TASK_DONE, state_); |
| 1151 log_manager_.LoadPersistedUnsentLogs(); | 1152 log_manager_.LoadPersistedUnsentLogs(); |
| 1152 state_ = INITIAL_LOG_READY; | 1153 state_ = INITIAL_LOG_READY; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1200 return; // We never Recalled the prior unsent logs. | 1201 return; // We never Recalled the prior unsent logs. |
| 1201 | 1202 |
| 1202 log_manager_.PersistUnsentLogs(); | 1203 log_manager_.PersistUnsentLogs(); |
| 1203 } | 1204 } |
| 1204 | 1205 |
| 1205 void MetricsService::SendStagedLog() { | 1206 void MetricsService::SendStagedLog() { |
| 1206 DCHECK(log_manager_.has_staged_log()); | 1207 DCHECK(log_manager_.has_staged_log()); |
| 1207 | 1208 |
| 1208 PrepareFetchWithStagedLog(); | 1209 PrepareFetchWithStagedLog(); |
| 1209 | 1210 |
| 1210 if (!current_fetch_xml_.get()) { | 1211 DCHECK(!waiting_for_asynchronous_reporting_step_); |
| 1211 DCHECK(!current_fetch_proto_.get()); | 1212 waiting_for_asynchronous_reporting_step_ = true; |
| 1212 // Compression failed, and log discarded :-/. | |
| 1213 log_manager_.DiscardStagedLog(); | |
| 1214 scheduler_->UploadCancelled(); | |
|
stuartmorgan
2012/06/08 08:26:42
It's vital that UploadCancelled be called if somet
Ilya Sherman
2012/06/08 22:20:26
This check was logically redundant with the check
| |
| 1215 // TODO(jar): If compression failed, we should have created a tiny log and | |
| 1216 // compressed that, so that we can signal that we're losing logs. | |
| 1217 return; | |
| 1218 } | |
| 1219 // Currently, the staged log for the protobuf version of the data is discarded | |
| 1220 // after we create the URL request, so that there is no chance for | |
| 1221 // re-transmission in case the corresponding XML request fails. We will | |
| 1222 // handle protobuf failures more carefully once that becomes the main | |
| 1223 // pipeline, i.e. once we switch away from the XML pipeline. | |
| 1224 DCHECK(current_fetch_proto_.get() || !log_manager_.has_staged_log_proto()); | |
| 1225 | 1213 |
| 1226 DCHECK(!waiting_for_asynchronous_reporting_step_); | 1214 if (current_fetch_xml_.get()) |
| 1227 | 1215 current_fetch_xml_->Start(); |
| 1228 waiting_for_asynchronous_reporting_step_ = true; | |
| 1229 current_fetch_xml_->Start(); | |
| 1230 if (current_fetch_proto_.get()) | 1216 if (current_fetch_proto_.get()) |
| 1231 current_fetch_proto_->Start(); | 1217 current_fetch_proto_->Start(); |
| 1232 | 1218 |
| 1233 HandleIdleSinceLastTransmission(true); | 1219 HandleIdleSinceLastTransmission(true); |
| 1234 } | 1220 } |
| 1235 | 1221 |
| 1236 void MetricsService::PrepareFetchWithStagedLog() { | 1222 void MetricsService::PrepareFetchWithStagedLog() { |
| 1237 DCHECK(!log_manager_.staged_log_text().empty()); | 1223 DCHECK(log_manager_.has_staged_log()); |
| 1238 | 1224 |
| 1239 // Prepare the XML version. | 1225 // Prepare the XML version. |
| 1240 DCHECK(!current_fetch_xml_.get()); | 1226 DCHECK(!current_fetch_xml_.get()); |
| 1241 current_fetch_xml_.reset(content::URLFetcher::Create( | 1227 if (log_manager_.has_staged_log_xml()) { |
| 1242 GURL(server_url_xml_), net::URLFetcher::POST, this)); | 1228 current_fetch_xml_.reset(content::URLFetcher::Create( |
| 1243 current_fetch_xml_->SetRequestContext( | 1229 GURL(server_url_xml_), net::URLFetcher::POST, this)); |
| 1244 g_browser_process->system_request_context()); | 1230 current_fetch_xml_->SetRequestContext( |
| 1245 current_fetch_xml_->SetUploadData(kMimeTypeXml, | 1231 g_browser_process->system_request_context()); |
| 1246 log_manager_.staged_log_text().xml); | 1232 current_fetch_xml_->SetUploadData(kMimeTypeXml, |
| 1247 // We already drop cookies server-side, but we might as well strip them out | 1233 log_manager_.staged_log_text().xml); |
| 1248 // client-side as well. | 1234 // We already drop cookies server-side, but we might as well strip them out |
| 1249 current_fetch_xml_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 1235 // client-side as well. |
| 1250 net::LOAD_DO_NOT_SEND_COOKIES); | 1236 current_fetch_xml_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
| 1237 net::LOAD_DO_NOT_SEND_COOKIES); | |
| 1238 } | |
| 1251 | 1239 |
| 1252 // Prepare the protobuf version. | 1240 // Prepare the protobuf version. |
| 1253 DCHECK(!current_fetch_proto_.get()); | 1241 DCHECK(!current_fetch_proto_.get()); |
| 1254 if (log_manager_.has_staged_log_proto()) { | 1242 if (log_manager_.has_staged_log_proto()) { |
| 1255 current_fetch_proto_.reset(content::URLFetcher::Create( | 1243 current_fetch_proto_.reset(content::URLFetcher::Create( |
| 1256 GURL(server_url_proto_), net::URLFetcher::POST, this)); | 1244 GURL(server_url_proto_), net::URLFetcher::POST, this)); |
| 1257 current_fetch_proto_->SetRequestContext( | 1245 current_fetch_proto_->SetRequestContext( |
| 1258 g_browser_process->system_request_context()); | 1246 g_browser_process->system_request_context()); |
| 1259 current_fetch_proto_->SetUploadData(kMimeTypeProto, | 1247 current_fetch_proto_->SetUploadData(kMimeTypeProto, |
| 1260 log_manager_.staged_log_text().proto); | 1248 log_manager_.staged_log_text().proto); |
| 1261 // We already drop cookies server-side, but we might as well strip them out | 1249 // We already drop cookies server-side, but we might as well strip them out |
| 1262 // client-side as well. | 1250 // client-side as well. |
| 1263 current_fetch_proto_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 1251 current_fetch_proto_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
| 1264 net::LOAD_DO_NOT_SEND_COOKIES); | 1252 net::LOAD_DO_NOT_SEND_COOKIES); |
| 1265 | |
| 1266 // Discard the protobuf version of the staged log, so that we will avoid | |
| 1267 // re-uploading it even if we need to re-upload the XML version. | |
| 1268 // TODO(isherman): Handle protobuf upload failures more gracefully once we | |
| 1269 // transition away from the XML-based pipeline. | |
| 1270 log_manager_.DiscardStagedLogProto(); | |
| 1271 } | 1253 } |
| 1272 } | 1254 } |
| 1273 | 1255 |
| 1274 static const char* StatusToString(const net::URLRequestStatus& status) { | 1256 static const char* StatusToString(const net::URLRequestStatus& status) { |
| 1275 switch (status.status()) { | 1257 switch (status.status()) { |
| 1276 case net::URLRequestStatus::SUCCESS: | 1258 case net::URLRequestStatus::SUCCESS: |
| 1277 return "SUCCESS"; | 1259 return "SUCCESS"; |
| 1278 | 1260 |
| 1279 case net::URLRequestStatus::IO_PENDING: | 1261 case net::URLRequestStatus::IO_PENDING: |
| 1280 return "IO_PENDING"; | 1262 return "IO_PENDING"; |
| 1281 | 1263 |
| 1282 case net::URLRequestStatus::HANDLED_EXTERNALLY: | 1264 case net::URLRequestStatus::HANDLED_EXTERNALLY: |
| 1283 return "HANDLED_EXTERNALLY"; | 1265 return "HANDLED_EXTERNALLY"; |
| 1284 | 1266 |
| 1285 case net::URLRequestStatus::CANCELED: | 1267 case net::URLRequestStatus::CANCELED: |
| 1286 return "CANCELED"; | 1268 return "CANCELED"; |
| 1287 | 1269 |
| 1288 case net::URLRequestStatus::FAILED: | 1270 case net::URLRequestStatus::FAILED: |
| 1289 return "FAILED"; | 1271 return "FAILED"; |
| 1290 | 1272 |
| 1291 default: | 1273 default: |
| 1292 NOTREACHED(); | 1274 NOTREACHED(); |
| 1293 return "Unknown"; | 1275 return "Unknown"; |
| 1294 } | 1276 } |
| 1295 } | 1277 } |
| 1296 | 1278 |
| 1297 // We need to wait for two responses: the response to the XML upload, and the | 1279 // We need to wait for two responses: the response to the XML upload, and the |
| 1298 // response to the protobuf upload. For now, only the XML upload's response | 1280 // response to the protobuf upload. In the case that exactly one of the uploads |
| 1299 // affects decisions like whether to retry the upload, whether to abandon the | 1281 // fails and needs to be retried, we "zap" the other pipeline's staged log to |
| 1300 // upload because it is too large, etc. However, we still need to wait for the | 1282 // avoid incorrectly re-uploading it as well. |
| 1301 // protobuf upload, as we cannot reset |current_fetch_proto_| until we have | |
| 1302 // confirmation that the network request was sent; and the easiest way to do | |
| 1303 // that is to wait for the response. In case the XML upload's response arrives | |
| 1304 // first, we cache that response until the protobuf upload's response also | |
| 1305 // arrives. | |
| 1306 // | |
| 1307 // Note that if the XML upload succeeds but the protobuf upload fails, we will | |
| 1308 // not retry the protobuf upload. If the XML upload fails while the protobuf | |
| 1309 // upload succeeds, we will still avoid re-uploading the protobuf data because | |
| 1310 // we "zap" the data after the first upload attempt. This means that we might | |
| 1311 // lose protobuf uploads when XML ones succeed; but we will never duplicate any | |
| 1312 // protobuf uploads. Protobuf failures should be rare enough to where this | |
| 1313 // should be ok while we have the two pipelines running in parallel. | |
| 1314 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) { | 1283 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) { |
| 1315 DCHECK(waiting_for_asynchronous_reporting_step_); | 1284 DCHECK(waiting_for_asynchronous_reporting_step_); |
| 1316 | 1285 |
| 1317 // We're not allowed to re-use the existing |URLFetcher|s, so free them here. | 1286 // We're not allowed to re-use the existing |URLFetcher|s, so free them here. |
| 1318 // Note however that |source| is aliased to one of these, so we should be | 1287 // Note however that |source| is aliased to one of these, so we should be |
| 1319 // careful not to delete it too early. | 1288 // careful not to delete it too early. |
| 1320 scoped_ptr<net::URLFetcher> s; | 1289 scoped_ptr<net::URLFetcher> s; |
| 1290 bool is_xml; | |
| 1321 if (source == current_fetch_xml_.get()) { | 1291 if (source == current_fetch_xml_.get()) { |
| 1322 s.reset(current_fetch_xml_.release()); | 1292 s.reset(current_fetch_xml_.release()); |
| 1323 | 1293 is_xml = true; |
| 1324 // Cache the XML responses, in case we still need to wait for the protobuf | |
| 1325 // response. | |
| 1326 response_code_ = source->GetResponseCode(); | |
| 1327 response_status_ = StatusToString(source->GetStatus()); | |
| 1328 source->GetResponseAsString(&response_data_); | |
| 1329 | |
| 1330 // Log a histogram to track response success vs. failure rates. | |
| 1331 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.XML", | |
| 1332 ResponseCodeToStatus(response_code_), | |
| 1333 NUM_RESPONSE_STATUSES); | |
| 1334 } else if (source == current_fetch_proto_.get()) { | 1294 } else if (source == current_fetch_proto_.get()) { |
| 1335 s.reset(current_fetch_proto_.release()); | 1295 s.reset(current_fetch_proto_.release()); |
| 1336 | 1296 is_xml = false; |
| 1337 // Log a histogram to track response success vs. failure rates. | |
| 1338 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", | |
| 1339 ResponseCodeToStatus(source->GetResponseCode()), | |
| 1340 NUM_RESPONSE_STATUSES); | |
| 1341 } else { | 1297 } else { |
| 1342 NOTREACHED(); | 1298 NOTREACHED(); |
| 1343 return; | 1299 return; |
| 1344 } | 1300 } |
| 1345 | 1301 |
| 1302 int response_code = source->GetResponseCode(); | |
| 1303 | |
| 1304 // Log a histogram to track response success vs. failure rates. | |
| 1305 if (is_xml) { | |
| 1306 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.XML", | |
| 1307 ResponseCodeToStatus(response_code), | |
| 1308 NUM_RESPONSE_STATUSES); | |
| 1309 } else { | |
| 1310 UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf", | |
| 1311 ResponseCodeToStatus(response_code), | |
| 1312 NUM_RESPONSE_STATUSES); | |
| 1313 } | |
| 1314 | |
| 1315 // If the upload was provisionally stored, drop it now that the upload is | |
| 1316 // known to have gone through. | |
| 1317 log_manager_.DiscardLastProvisionalStore(); | |
| 1318 | |
| 1319 // Confirm send so that we can move on. | |
| 1320 VLOG(1) << "Metrics response code: " << response_code | |
| 1321 << " status=" << StatusToString(source->GetStatus()) << " for " | |
| 1322 << (is_xml ? "xml" : "protobuf") << " upload."; | |
| 1323 | |
| 1324 bool upload_succeeded = response_code == 200; | |
| 1325 | |
| 1326 // Provide boolean for error recovery (allow us to ignore response_code). | |
| 1327 bool discard_log = false; | |
| 1328 const size_t log_size = is_xml ? | |
| 1329 log_manager_.staged_log_text().xml.length() : | |
| 1330 log_manager_.staged_log_text().proto.length(); | |
| 1331 if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) { | |
| 1332 UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", | |
| 1333 static_cast<int>(log_size)); | |
| 1334 discard_log = true; | |
| 1335 } else if (response_code == 400) { | |
| 1336 // Bad syntax. Retransmission won't work. | |
| 1337 discard_log = true; | |
| 1338 } | |
| 1339 | |
| 1340 if (!upload_succeeded && !discard_log) { | |
| 1341 LogBadResponseCode(response_code, is_xml); | |
| 1342 } else { // Successful receipt (or we are discarding log). | |
| 1343 std::string response_data; | |
| 1344 source->GetResponseAsString(&response_data); | |
| 1345 VLOG(1) << "Metrics response data: " << response_data; | |
| 1346 | |
| 1347 if (is_xml) | |
| 1348 log_manager_.DiscardStagedLogXml(); | |
| 1349 else | |
| 1350 log_manager_.DiscardStagedLogProto(); | |
| 1351 } | |
| 1352 | |
| 1346 // If we're still waiting for one of the responses, keep waiting... | 1353 // If we're still waiting for one of the responses, keep waiting... |
| 1347 if (current_fetch_xml_.get() || current_fetch_proto_.get()) | 1354 if (current_fetch_xml_.get() || current_fetch_proto_.get()) |
| 1348 return; | 1355 return; |
| 1349 | 1356 |
| 1350 // We should only be able to reach here once we've received responses to both | |
| 1351 // the XML and the protobuf requests. We should always have the response code | |
| 1352 // available. | |
| 1353 DCHECK_NE(response_code_, kNoResponseCode); | |
| 1354 waiting_for_asynchronous_reporting_step_ = false; | 1357 waiting_for_asynchronous_reporting_step_ = false; |
| 1355 | 1358 |
| 1356 // If the upload was provisionally stored, drop it now that the upload is | 1359 if (!log_manager_.has_staged_log()) { |
| 1357 // known to have gone through. | |
| 1358 log_manager_.DiscardLastProvisionalStore(); | |
| 1359 | |
| 1360 // Confirm send so that we can move on. | |
| 1361 VLOG(1) << "Metrics response code: " << response_code_ | |
| 1362 << " status=" << response_status_; | |
| 1363 | |
| 1364 bool upload_succeeded = response_code_ == 200; | |
| 1365 | |
| 1366 // Provide boolean for error recovery (allow us to ignore response_code). | |
| 1367 bool discard_log = false; | |
| 1368 | |
| 1369 if (!upload_succeeded && | |
| 1370 log_manager_.staged_log_text().xml.length() > | |
| 1371 kUploadLogAvoidRetransmitSize) { | |
| 1372 UMA_HISTOGRAM_COUNTS( | |
| 1373 "UMA.Large Rejected Log was Discarded", | |
| 1374 static_cast<int>(log_manager_.staged_log_text().xml.length())); | |
| 1375 discard_log = true; | |
| 1376 } else if (response_code_ == 400) { | |
| 1377 // Bad syntax. Retransmission won't work. | |
| 1378 discard_log = true; | |
| 1379 } | |
| 1380 | |
| 1381 if (!upload_succeeded && !discard_log) { | |
| 1382 VLOG(1) << "Metrics: transmission attempt returned a failure code: " | |
| 1383 << response_code_ << ". Verify network connectivity"; | |
| 1384 LogBadResponseCode(); | |
| 1385 } else { // Successful receipt (or we are discarding log). | |
| 1386 VLOG(1) << "Metrics response data: " << response_data_; | |
| 1387 switch (state_) { | 1360 switch (state_) { |
| 1388 case INITIAL_LOG_READY: | 1361 case INITIAL_LOG_READY: |
| 1389 state_ = SENDING_OLD_LOGS; | 1362 state_ = SENDING_OLD_LOGS; |
| 1390 break; | 1363 break; |
| 1391 | 1364 |
| 1392 case SENDING_OLD_LOGS: | 1365 case SENDING_OLD_LOGS: |
| 1393 // Store the updated list to disk now that the removed log is uploaded. | 1366 // Store the updated list to disk now that the removed log is uploaded. |
| 1394 StoreUnsentLogs(); | 1367 StoreUnsentLogs(); |
| 1395 break; | 1368 break; |
| 1396 | 1369 |
| 1397 case SENDING_CURRENT_LOGS: | 1370 case SENDING_CURRENT_LOGS: |
| 1398 break; | 1371 break; |
| 1399 | 1372 |
| 1400 default: | 1373 default: |
| 1401 NOTREACHED(); | 1374 NOTREACHED(); |
| 1402 break; | 1375 break; |
| 1403 } | 1376 } |
| 1404 | 1377 |
| 1405 log_manager_.DiscardStagedLog(); | |
| 1406 | |
| 1407 if (log_manager_.has_unsent_logs()) | 1378 if (log_manager_.has_unsent_logs()) |
| 1408 DCHECK_LT(state_, SENDING_CURRENT_LOGS); | 1379 DCHECK_LT(state_, SENDING_CURRENT_LOGS); |
| 1409 } | 1380 } |
| 1410 | 1381 |
| 1411 // Error 400 indicates a problem with the log, not with the server, so | 1382 // Error 400 indicates a problem with the log, not with the server, so |
| 1412 // don't consider that a sign that the server is in trouble. | 1383 // don't consider that a sign that the server is in trouble. |
| 1413 bool server_is_healthy = upload_succeeded || response_code_ == 400; | 1384 bool server_is_healthy = upload_succeeded || response_code == 400; |
| 1414 | 1385 |
| 1415 scheduler_->UploadFinished(server_is_healthy, | 1386 // Note that we are essentially randomly choosing to report either the XML or |
| 1416 log_manager_.has_unsent_logs()); | 1387 // the protobuf server's health status, but this is ok: In the case that the |
| 1388 // two statuses are not the same, one of the uploads succeeded but the other | |
| 1389 // did not. In this case, we'll re-try only the upload that failed. This first | |
| 1390 // re-try might ignore the server's unhealthiness; but the response to the | |
| 1391 // re-tried upload will correctly propagate the server's health status for any | |
| 1392 // subsequent re-tries. Hence, we'll at most delay slowing the upload rate by | |
| 1393 // one re-try, which is fine. | |
| 1394 scheduler_->UploadFinished(server_is_healthy, log_manager_.has_unsent_logs()); | |
| 1417 | 1395 |
| 1418 // Collect network stats if UMA upload succeeded. | 1396 // Collect network stats if UMA upload succeeded. |
| 1419 IOThread* io_thread = g_browser_process->io_thread(); | 1397 IOThread* io_thread = g_browser_process->io_thread(); |
| 1420 if (server_is_healthy && io_thread) { | 1398 if (server_is_healthy && io_thread) { |
| 1421 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread); | 1399 chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread); |
| 1422 chrome_browser_net::CollectPipeliningCapabilityStatsOnUIThread( | 1400 chrome_browser_net::CollectPipeliningCapabilityStatsOnUIThread( |
| 1423 http_pipelining_test_server_, io_thread); | 1401 http_pipelining_test_server_, io_thread); |
| 1424 } | 1402 } |
| 1425 | |
| 1426 // Reset the cached response data. | |
| 1427 response_code_ = kNoResponseCode; | |
| 1428 response_data_ = std::string(); | |
| 1429 response_status_ = std::string(); | |
| 1430 } | 1403 } |
| 1431 | 1404 |
| 1432 void MetricsService::LogBadResponseCode() { | 1405 void MetricsService::LogBadResponseCode(int response_code, bool is_xml) { |
| 1433 VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " | 1406 VLOG(1) << "Metrics: transmission attempt returned a failure code: " |
| 1434 "is active at " << server_url_xml_; | 1407 << response_code << ". Verify network connectivity and that your " |
| 1408 << "metrics logs are formatted correctly. Verify server is active at " | |
| 1409 << (is_xml ? server_url_xml_ : server_url_proto_) << "."; | |
| 1410 | |
| 1435 if (!log_manager_.has_staged_log()) { | 1411 if (!log_manager_.has_staged_log()) { |
| 1436 VLOG(1) << "METRICS: Recorder shutdown during log transmission."; | 1412 // TODO(isherman): I don't think this code is reachable... |
| 1413 VLOG(1) << "Metrics: Recorder shutdown during log transmission."; | |
| 1437 } else { | 1414 } else { |
| 1438 VLOG(1) << "METRICS: transmission retry being scheduled for " | 1415 if (is_xml) { |
| 1439 << log_manager_.staged_log_text().xml; | 1416 VLOG(1) << "Metrics: transmission retry being scheduled for \n" |
| 1417 << log_manager_.staged_log_text().xml; | |
| 1418 } else { | |
| 1419 VLOG(1) | |
| 1420 << "Metrics: transmission retry being scheduled for protobuf upload."; | |
| 1421 } | |
| 1440 } | 1422 } |
| 1441 } | 1423 } |
| 1442 | 1424 |
| 1443 void MetricsService::LogWindowChange( | 1425 void MetricsService::LogWindowChange( |
| 1444 int type, | 1426 int type, |
| 1445 const content::NotificationSource& source, | 1427 const content::NotificationSource& source, |
| 1446 const content::NotificationDetails& details) { | 1428 const content::NotificationDetails& details) { |
| 1447 int controller_id = -1; | 1429 int controller_id = -1; |
| 1448 uintptr_t window_or_tab = source.map_key(); | 1430 uintptr_t window_or_tab = source.map_key(); |
| 1449 MetricsLog::WindowEventType window_type; | 1431 MetricsLog::WindowEventType window_type; |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1821 if (local_state) { | 1803 if (local_state) { |
| 1822 const PrefService::Preference* uma_pref = | 1804 const PrefService::Preference* uma_pref = |
| 1823 local_state->FindPreference(prefs::kMetricsReportingEnabled); | 1805 local_state->FindPreference(prefs::kMetricsReportingEnabled); |
| 1824 if (uma_pref) { | 1806 if (uma_pref) { |
| 1825 bool success = uma_pref->GetValue()->GetAsBoolean(&result); | 1807 bool success = uma_pref->GetValue()->GetAsBoolean(&result); |
| 1826 DCHECK(success); | 1808 DCHECK(success); |
| 1827 } | 1809 } |
| 1828 } | 1810 } |
| 1829 return result; | 1811 return result; |
| 1830 } | 1812 } |
| OLD | NEW |