Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1645)

Side by Side Diff: components/network_time/network_time_tracker.cc

Issue 2415703005: Refine NetworkTimeTracker histograms (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/network_time/network_time_tracker.h" 5 #include "components/network_time/network_time_tracker.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string> 8 #include <string>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 std::unique_ptr<base::Clock> clock, 181 std::unique_ptr<base::Clock> clock,
182 std::unique_ptr<base::TickClock> tick_clock, 182 std::unique_ptr<base::TickClock> tick_clock,
183 PrefService* pref_service, 183 PrefService* pref_service,
184 scoped_refptr<net::URLRequestContextGetter> getter) 184 scoped_refptr<net::URLRequestContextGetter> getter)
185 : server_url_(kTimeServiceURL), 185 : server_url_(kTimeServiceURL),
186 max_response_size_(1024), 186 max_response_size_(1024),
187 backoff_(base::TimeDelta::FromMinutes(kBackoffMinutes)), 187 backoff_(base::TimeDelta::FromMinutes(kBackoffMinutes)),
188 getter_(std::move(getter)), 188 getter_(std::move(getter)),
189 clock_(std::move(clock)), 189 clock_(std::move(clock)),
190 tick_clock_(std::move(tick_clock)), 190 tick_clock_(std::move(tick_clock)),
191 pref_service_(pref_service) { 191 pref_service_(pref_service),
192 time_query_failed_(false) {
192 const base::DictionaryValue* time_mapping = 193 const base::DictionaryValue* time_mapping =
193 pref_service_->GetDictionary(prefs::kNetworkTimeMapping); 194 pref_service_->GetDictionary(prefs::kNetworkTimeMapping);
194 double time_js = 0; 195 double time_js = 0;
195 double ticks_js = 0; 196 double ticks_js = 0;
196 double network_time_js = 0; 197 double network_time_js = 0;
197 double uncertainty_js = 0; 198 double uncertainty_js = 0;
198 if (time_mapping->GetDouble(kPrefTime, &time_js) && 199 if (time_mapping->GetDouble(kPrefTime, &time_js) &&
199 time_mapping->GetDouble(kPrefTicks, &ticks_js) && 200 time_mapping->GetDouble(kPrefTicks, &ticks_js) &&
200 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) && 201 time_mapping->GetDouble(kPrefUncertainty, &uncertainty_js) &&
201 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) { 202 time_mapping->GetDouble(kPrefNetworkTime, &network_time_js)) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 DCHECK(timer_.IsRunning()); 304 DCHECK(timer_.IsRunning());
304 return timer_.GetCurrentDelay(); 305 return timer_.GetCurrentDelay();
305 } 306 }
306 307
307 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime( 308 NetworkTimeTracker::NetworkTimeResult NetworkTimeTracker::GetNetworkTime(
308 base::Time* network_time, 309 base::Time* network_time,
309 base::TimeDelta* uncertainty) const { 310 base::TimeDelta* uncertainty) const {
310 DCHECK(thread_checker_.CalledOnValidThread()); 311 DCHECK(thread_checker_.CalledOnValidThread());
311 DCHECK(network_time); 312 DCHECK(network_time);
312 if (network_time_at_last_measurement_.is_null()) { 313 if (network_time_at_last_measurement_.is_null()) {
313 return NETWORK_TIME_NO_SYNC; 314 if (time_query_failed_) {
315 // Time query attempts have been made in the past and failed.
316 if (time_fetcher_) {
317 // A fetch (not the first attempt) is in progress.
318 return NETWORK_TIME_SUBSEQUENT_SYNC_PENDING;
319 } else {
320 return NETWORK_TIME_NO_SUCCESSFUL_SYNC;
321 }
322 } else {
323 // No time queries have happened yet.
324 if (time_fetcher_) {
325 return NETWORK_TIME_FIRST_SYNC_PENDING;
326 } else {
327 return NETWORK_TIME_NO_SYNC_ATTEMPT;
328 }
329 }
314 } 330 }
315 DCHECK(!ticks_at_last_measurement_.is_null()); 331 DCHECK(!ticks_at_last_measurement_.is_null());
316 DCHECK(!time_at_last_measurement_.is_null()); 332 DCHECK(!time_at_last_measurement_.is_null());
317 base::TimeDelta tick_delta = 333 base::TimeDelta tick_delta =
318 tick_clock_->NowTicks() - ticks_at_last_measurement_; 334 tick_clock_->NowTicks() - ticks_at_last_measurement_;
319 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_; 335 base::TimeDelta time_delta = clock_->Now() - time_at_last_measurement_;
320 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward? 336 if (time_delta.InMilliseconds() < 0) { // Has wall clock run backward?
321 DVLOG(1) << "Discarding network time due to wall clock running backward"; 337 DVLOG(1) << "Discarding network time due to wall clock running backward";
322 UMA_HISTOGRAM_CUSTOM_TIMES( 338 UMA_HISTOGRAM_CUSTOM_TIMES(
323 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(), 339 "NetworkTimeTracker.WallClockRanBackwards", time_delta.magnitude(),
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 409
394 time_fetcher_->Start(); 410 time_fetcher_->Start();
395 fetch_started_ = tick_clock_->NowTicks(); 411 fetch_started_ = tick_clock_->NowTicks();
396 412
397 timer_.Stop(); // Restarted in OnURLFetchComplete(). 413 timer_.Stop(); // Restarted in OnURLFetchComplete().
398 } 414 }
399 415
400 bool NetworkTimeTracker::UpdateTimeFromResponse() { 416 bool NetworkTimeTracker::UpdateTimeFromResponse() {
401 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS || 417 if (time_fetcher_->GetStatus().status() != net::URLRequestStatus::SUCCESS ||
402 time_fetcher_->GetResponseCode() != 200) { 418 time_fetcher_->GetResponseCode() != 200) {
419 time_query_failed_ = true;
403 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status() 420 DVLOG(1) << "fetch failed, status=" << time_fetcher_->GetStatus().status()
404 << ",code=" << time_fetcher_->GetResponseCode(); 421 << ",code=" << time_fetcher_->GetResponseCode();
405 // The error code is negated because net errors are negative, but 422 // The error code is negated because net errors are negative, but
406 // the corresponding histogram enum is positive. 423 // the corresponding histogram enum is positive.
407 UMA_HISTOGRAM_SPARSE_SLOWLY("NetworkTimeTracker.UpdateTimeFetchFailed", 424 UMA_HISTOGRAM_SPARSE_SLOWLY("NetworkTimeTracker.UpdateTimeFetchFailed",
408 -time_fetcher_->GetStatus().error()); 425 -time_fetcher_->GetStatus().error());
409 return false; 426 return false;
410 } 427 }
411 428
412 std::string response_body; 429 std::string response_body;
413 if (!time_fetcher_->GetResponseAsString(&response_body)) { 430 if (!time_fetcher_->GetResponseAsString(&response_body)) {
414 DVLOG(1) << "failed to get response"; 431 DVLOG(1) << "failed to get response";
432 time_query_failed_ = true;
415 return false; 433 return false;
416 } 434 }
417 DCHECK(query_signer_); 435 DCHECK(query_signer_);
418 if (!query_signer_->ValidateResponse(response_body, 436 if (!query_signer_->ValidateResponse(response_body,
419 GetServerProof(time_fetcher_.get()))) { 437 GetServerProof(time_fetcher_.get()))) {
420 DVLOG(1) << "invalid signature"; 438 DVLOG(1) << "invalid signature";
439 time_query_failed_ = true;
421 RecordFetchValidHistogram(false); 440 RecordFetchValidHistogram(false);
422 return false; 441 return false;
423 } 442 }
424 response_body = response_body.substr(5); // Skips leading )]}'\n 443 response_body = response_body.substr(5); // Skips leading )]}'\n
425 std::unique_ptr<base::Value> value = base::JSONReader::Read(response_body); 444 std::unique_ptr<base::Value> value = base::JSONReader::Read(response_body);
426 if (!value) { 445 if (!value) {
427 DVLOG(1) << "bad JSON"; 446 DVLOG(1) << "bad JSON";
447 time_query_failed_ = true;
428 RecordFetchValidHistogram(false); 448 RecordFetchValidHistogram(false);
429 return false; 449 return false;
430 } 450 }
431 const base::DictionaryValue* dict; 451 const base::DictionaryValue* dict;
432 if (!value->GetAsDictionary(&dict)) { 452 if (!value->GetAsDictionary(&dict)) {
433 DVLOG(1) << "not a dictionary"; 453 DVLOG(1) << "not a dictionary";
454 time_query_failed_ = true;
434 RecordFetchValidHistogram(false); 455 RecordFetchValidHistogram(false);
435 return false; 456 return false;
436 } 457 }
437 double current_time_millis; 458 double current_time_millis;
438 if (!dict->GetDouble("current_time_millis", &current_time_millis)) { 459 if (!dict->GetDouble("current_time_millis", &current_time_millis)) {
439 DVLOG(1) << "no current_time_millis"; 460 DVLOG(1) << "no current_time_millis";
461 time_query_failed_ = true;
440 RecordFetchValidHistogram(false); 462 RecordFetchValidHistogram(false);
441 return false; 463 return false;
442 } 464 }
443 465
444 RecordFetchValidHistogram(true); 466 RecordFetchValidHistogram(true);
445 467
446 // There is a "server_nonce" key here too, but it serves no purpose other than 468 // There is a "server_nonce" key here too, but it serves no purpose other than
447 // to make the server's response unpredictable. 469 // to make the server's response unpredictable.
448 base::Time current_time = base::Time::FromJsTime(current_time_millis); 470 base::Time current_time = base::Time::FromJsTime(current_time_millis);
449 base::TimeDelta resolution = 471 base::TimeDelta resolution =
450 base::TimeDelta::FromMilliseconds(1) + 472 base::TimeDelta::FromMilliseconds(1) +
451 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds); 473 base::TimeDelta::FromSeconds(kTimeServerMaxSkewSeconds);
452 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_; 474 base::TimeDelta latency = tick_clock_->NowTicks() - fetch_started_;
475 UMA_HISTOGRAM_TIMES("NetworkTimeTracker.TimeQueryLatency", latency);
453 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks()); 476 UpdateNetworkTime(current_time, resolution, latency, tick_clock_->NowTicks());
454 return true; 477 return true;
455 } 478 }
456 479
457 void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) { 480 void NetworkTimeTracker::OnURLFetchComplete(const net::URLFetcher* source) {
458 DCHECK(thread_checker_.CalledOnValidThread()); 481 DCHECK(thread_checker_.CalledOnValidThread());
459 DCHECK(time_fetcher_); 482 DCHECK(time_fetcher_);
460 DCHECK_EQ(source, time_fetcher_.get()); 483 DCHECK_EQ(source, time_fetcher_.get());
461 484
462 // After completion of a query, whether succeeded or failed, go to sleep for a 485 // After completion of a query, whether succeeded or failed, go to sleep for a
463 // long time. 486 // long time.
464 if (!UpdateTimeFromResponse()) { // On error, back off. 487 if (!UpdateTimeFromResponse()) { // On error, back off.
mab 2016/10/14 06:35:01 Could you set time_query_failed_ here?
estark 2016/10/14 07:23:46 Oh, yes, that's much better, thanks. Done.
465 if (backoff_ < base::TimeDelta::FromDays(2)) { 488 if (backoff_ < base::TimeDelta::FromDays(2)) {
466 backoff_ *= 2; 489 backoff_ *= 2;
467 } 490 }
468 } else { 491 } else {
469 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes); 492 backoff_ = base::TimeDelta::FromMinutes(kBackoffMinutes);
470 } 493 }
471 QueueCheckTime(backoff_); 494 QueueCheckTime(backoff_);
472 time_fetcher_.reset(); 495 time_fetcher_.reset();
473 if (run_loop_for_testing_ != nullptr) 496 if (run_loop_for_testing_ != nullptr)
474 run_loop_for_testing_->QuitWhenIdle(); 497 run_loop_for_testing_->QuitWhenIdle();
(...skipping 14 matching lines...) Expand all
489 base::Time network_time; 512 base::Time network_time;
490 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) { 513 if (GetNetworkTime(&network_time, nullptr) != NETWORK_TIME_AVAILABLE) {
491 return true; 514 return true;
492 } 515 }
493 516
494 // Otherwise, make the decision at random. 517 // Otherwise, make the decision at random.
495 return base::RandDouble() < RandomQueryProbability(); 518 return base::RandDouble() < RandomQueryProbability();
496 } 519 }
497 520
498 } // namespace network_time 521 } // namespace network_time
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698