OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/page_load_metrics/browser/metrics_web_contents_observer.h" | 5 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h" |
6 | 6 |
7 #include "base/location.h" | 7 #include "base/location.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "components/page_load_metrics/browser/page_load_metrics_macros.h" | 10 #include "components/page_load_metrics/browser/page_load_metrics_macros.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 75 |
76 return true; | 76 return true; |
77 } | 77 } |
78 | 78 |
79 base::Time WallTimeFromTimeTicks(const base::TimeTicks& time) { | 79 base::Time WallTimeFromTimeTicks(const base::TimeTicks& time) { |
80 return base::Time::FromDoubleT( | 80 return base::Time::FromDoubleT( |
81 (time - base::TimeTicks::UnixEpoch()).InSecondsF()); | 81 (time - base::TimeTicks::UnixEpoch()).InSecondsF()); |
82 } | 82 } |
83 | 83 |
84 void RecordInternalError(InternalErrorLoadEvent event) { | 84 void RecordInternalError(InternalErrorLoadEvent event) { |
85 UMA_HISTOGRAM_ENUMERATION( | 85 UMA_HISTOGRAM_ENUMERATION(kErrorEvents, event, ERR_LAST_ENTRY); |
86 "PageLoad.Events.InternalError", event, ERR_LAST_ENTRY); | |
87 } | 86 } |
88 | 87 |
89 base::TimeDelta GetFirstContentfulPaint(const PageLoadTiming& timing) { | 88 base::TimeDelta GetFirstContentfulPaint(const PageLoadTiming& timing) { |
90 if (timing.first_text_paint.is_zero()) | 89 if (timing.first_text_paint.is_zero()) |
91 return timing.first_image_paint; | 90 return timing.first_image_paint; |
92 if (timing.first_image_paint.is_zero()) | 91 if (timing.first_image_paint.is_zero()) |
93 return timing.first_text_paint; | 92 return timing.first_text_paint; |
94 return std::min(timing.first_text_paint, timing.first_image_paint); | 93 return std::min(timing.first_text_paint, timing.first_image_paint); |
95 } | 94 } |
96 | 95 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 227 } |
229 | 228 |
230 PageLoadExtraInfo info = GetPageLoadMetricsInfo(); | 229 PageLoadExtraInfo info = GetPageLoadMetricsInfo(); |
231 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, | 230 FOR_EACH_OBSERVER(PageLoadMetricsObserver, *observers_, |
232 OnComplete(timing_, info)); | 231 OnComplete(timing_, info)); |
233 | 232 |
234 base::TimeDelta background_delta = GetBackgroundDelta(); | 233 base::TimeDelta background_delta = GetBackgroundDelta(); |
235 | 234 |
236 if (!timing_.dom_content_loaded_event_start.is_zero()) { | 235 if (!timing_.dom_content_loaded_event_start.is_zero()) { |
237 if (timing_.dom_content_loaded_event_start < background_delta) { | 236 if (timing_.dom_content_loaded_event_start < background_delta) { |
238 PAGE_LOAD_HISTOGRAM( | 237 PAGE_LOAD_HISTOGRAM(kHistogramDomContentLoaded, |
239 "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired", | 238 timing_.dom_content_loaded_event_start); |
240 timing_.dom_content_loaded_event_start); | |
241 } else { | 239 } else { |
242 PAGE_LOAD_HISTOGRAM( | 240 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramDomContentLoaded, |
243 "PageLoad.Timing2.NavigationToDOMContentLoadedEventFired.Background", | 241 timing_.dom_content_loaded_event_start); |
244 timing_.dom_content_loaded_event_start); | |
245 } | 242 } |
246 } | 243 } |
247 if (!timing_.load_event_start.is_zero()) { | 244 if (!timing_.load_event_start.is_zero()) { |
248 if (timing_.load_event_start < background_delta) { | 245 if (timing_.load_event_start < background_delta) { |
249 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToLoadEventFired", | 246 PAGE_LOAD_HISTOGRAM(kHistogramLoad, timing_.load_event_start); |
250 timing_.load_event_start); | |
251 } else { | 247 } else { |
252 PAGE_LOAD_HISTOGRAM( | 248 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramLoad, timing_.load_event_start); |
253 "PageLoad.Timing2.NavigationToLoadEventFired.Background", | |
254 timing_.load_event_start); | |
255 } | 249 } |
256 } | 250 } |
257 if (timing_.first_layout.is_zero()) { | 251 if (timing_.first_layout.is_zero()) { |
258 RecordCommittedEvent(COMMITTED_LOAD_FAILED_BEFORE_FIRST_LAYOUT, | 252 RecordCommittedEvent(COMMITTED_LOAD_FAILED_BEFORE_FIRST_LAYOUT, |
259 HasBackgrounded()); | 253 HasBackgrounded()); |
260 } else { | 254 } else { |
261 if (timing_.first_layout < background_delta) { | 255 if (timing_.first_layout < background_delta) { |
262 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout", | 256 PAGE_LOAD_HISTOGRAM(kHistogramFirstLayout, timing_.first_layout); |
263 timing_.first_layout); | |
264 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, false); | 257 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, false); |
265 } else { | 258 } else { |
266 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstLayout.Background", | 259 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstLayout, |
267 timing_.first_layout); | 260 timing_.first_layout); |
268 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, true); | 261 RecordCommittedEvent(COMMITTED_LOAD_SUCCESSFUL_FIRST_LAYOUT, true); |
269 } | 262 } |
270 } | 263 } |
271 if (!timing_.first_paint.is_zero()) { | 264 if (!timing_.first_paint.is_zero()) { |
272 if (timing_.first_paint < background_delta) { | 265 if (timing_.first_paint < background_delta) { |
273 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstPaint", | 266 PAGE_LOAD_HISTOGRAM(kHistogramFirstPaint, timing_.first_paint); |
274 timing_.first_paint); | |
275 } else { | 267 } else { |
276 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstPaint.Background", | 268 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstPaint, timing_.first_paint); |
277 timing_.first_paint); | |
278 } | 269 } |
279 } | 270 } |
280 if (!timing_.first_text_paint.is_zero()) { | 271 if (!timing_.first_text_paint.is_zero()) { |
281 if (timing_.first_text_paint < background_delta) { | 272 if (timing_.first_text_paint < background_delta) { |
282 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstTextPaint", | 273 PAGE_LOAD_HISTOGRAM(kHistogramFirstTextPaint, timing_.first_text_paint); |
| 274 } else { |
| 275 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstTextPaint, |
283 timing_.first_text_paint); | 276 timing_.first_text_paint); |
284 } else { | |
285 PAGE_LOAD_HISTOGRAM( | |
286 "PageLoad.Timing2.NavigationToFirstTextPaint.Background", | |
287 timing_.first_text_paint); | |
288 } | 277 } |
289 } | 278 } |
290 if (!timing_.first_image_paint.is_zero()) { | 279 if (!timing_.first_image_paint.is_zero()) { |
291 if (timing_.first_image_paint < background_delta) { | 280 if (timing_.first_image_paint < background_delta) { |
292 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstImagePaint", | 281 PAGE_LOAD_HISTOGRAM(kHistogramFirstImagePaint, timing_.first_image_paint); |
| 282 } else { |
| 283 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstImagePaint, |
293 timing_.first_image_paint); | 284 timing_.first_image_paint); |
294 } else { | |
295 PAGE_LOAD_HISTOGRAM( | |
296 "PageLoad.Timing2.NavigationToFirstImagePaint.Background", | |
297 timing_.first_image_paint); | |
298 } | 285 } |
299 } | 286 } |
300 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); | 287 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); |
301 if (!first_contentful_paint.is_zero()) { | 288 if (!first_contentful_paint.is_zero()) { |
302 if (first_contentful_paint < background_delta) { | 289 if (first_contentful_paint < background_delta) { |
303 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstContentfulPaint", | 290 PAGE_LOAD_HISTOGRAM(kHistogramFirstContentfulPaint, |
304 first_contentful_paint); | 291 first_contentful_paint); |
305 } else { | 292 } else { |
306 PAGE_LOAD_HISTOGRAM( | 293 PAGE_LOAD_HISTOGRAM(kBackgroundHistogramFirstContentfulPaint, |
307 "PageLoad.Timing2.NavigationToFirstContentfulPaint.Background", | 294 first_contentful_paint); |
308 first_contentful_paint); | |
309 } | 295 } |
310 } | 296 } |
311 | 297 |
312 // Log time to first foreground / time to first background. Log counts that we | 298 // Log time to first foreground / time to first background. Log counts that we |
313 // started a relevant page load in the foreground / background. | 299 // started a relevant page load in the foreground / background. |
314 if (!background_time_.is_null()) { | 300 if (!background_time_.is_null()) { |
315 PAGE_LOAD_HISTOGRAM("PageLoad.Timing2.NavigationToFirstBackground", | 301 PAGE_LOAD_HISTOGRAM(kHistogramFirstBackground, background_delta); |
316 background_delta); | |
317 } else if (!foreground_time_.is_null()) { | 302 } else if (!foreground_time_.is_null()) { |
318 PAGE_LOAD_HISTOGRAM( | 303 PAGE_LOAD_HISTOGRAM( |
319 "PageLoad.Timing2.NavigationToFirstForeground", | 304 kHistogramFirstForeground, |
320 WallTimeFromTimeTicks(foreground_time_) - timing_.navigation_start); | 305 WallTimeFromTimeTicks(foreground_time_) - timing_.navigation_start); |
321 } | 306 } |
322 } | 307 } |
323 | 308 |
324 void PageLoadTracker::RecordProvisionalEvent(ProvisionalLoadEvent event) { | 309 void PageLoadTracker::RecordProvisionalEvent(ProvisionalLoadEvent event) { |
325 if (HasBackgrounded()) { | 310 if (HasBackgrounded()) { |
326 UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Provisional.Background", event, | 311 UMA_HISTOGRAM_ENUMERATION(kBackgroundProvisionalEvents, event, |
327 PROVISIONAL_LOAD_LAST_ENTRY); | 312 PROVISIONAL_LOAD_LAST_ENTRY); |
328 } else { | 313 } else { |
329 UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Provisional", event, | 314 UMA_HISTOGRAM_ENUMERATION(kProvisionalEvents, event, |
330 PROVISIONAL_LOAD_LAST_ENTRY); | 315 PROVISIONAL_LOAD_LAST_ENTRY); |
331 } | 316 } |
332 } | 317 } |
333 | 318 |
334 // RecordCommittedEvent needs a backgrounded input because we need to special | 319 // RecordCommittedEvent needs a backgrounded input because we need to special |
335 // case a few events that need either precise timing measurements, or different | 320 // case a few events that need either precise timing measurements, or different |
336 // logic than simply "Did I background before logging this event?" | 321 // logic than simply "Did I background before logging this event?" |
337 void PageLoadTracker::RecordCommittedEvent(CommittedLoadEvent event, | 322 void PageLoadTracker::RecordCommittedEvent(CommittedLoadEvent event, |
338 bool backgrounded) { | 323 bool backgrounded) { |
339 if (backgrounded) { | 324 if (backgrounded) { |
340 UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Committed.Background", event, | 325 UMA_HISTOGRAM_ENUMERATION(kBackgroundCommittedEvents, event, |
341 COMMITTED_LOAD_LAST_ENTRY); | 326 COMMITTED_LOAD_LAST_ENTRY); |
342 } else { | 327 } else { |
343 UMA_HISTOGRAM_ENUMERATION("PageLoad.Events.Committed", event, | 328 UMA_HISTOGRAM_ENUMERATION(kCommittedEvents, event, |
344 COMMITTED_LOAD_LAST_ENTRY); | 329 COMMITTED_LOAD_LAST_ENTRY); |
345 } | 330 } |
346 } | 331 } |
347 | 332 |
348 void PageLoadTracker::RecordRappor() { | 333 void PageLoadTracker::RecordRappor() { |
349 DCHECK(!GetCommittedURL().is_empty()); | 334 DCHECK(!GetCommittedURL().is_empty()); |
350 rappor::RapporService* rappor_service = | 335 rappor::RapporService* rappor_service = |
351 embedder_interface_->GetRapporService(); | 336 embedder_interface_->GetRapporService(); |
352 if (!rappor_service) | 337 if (!rappor_service) |
353 return; | 338 return; |
354 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); | 339 base::TimeDelta first_contentful_paint = GetFirstContentfulPaint(timing_); |
355 // Log the eTLD+1 of sites that show poor loading performance. | 340 // Log the eTLD+1 of sites that show poor loading performance. |
356 if (!first_contentful_paint.is_zero() && | 341 if (!first_contentful_paint.is_zero() && |
357 first_contentful_paint < GetBackgroundDelta()) { | 342 first_contentful_paint < GetBackgroundDelta()) { |
358 scoped_ptr<rappor::Sample> sample = | 343 scoped_ptr<rappor::Sample> sample = |
359 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); | 344 rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE); |
360 sample->SetStringField("Domain", rappor::GetDomainAndRegistrySampleFromGURL( | 345 sample->SetStringField("Domain", rappor::GetDomainAndRegistrySampleFromGURL( |
361 GetCommittedURL())); | 346 GetCommittedURL())); |
362 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint); | 347 uint64_t bucket_index = RapporHistogramBucketIndex(first_contentful_paint); |
363 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index, | 348 sample->SetFlagsField("Bucket", uint64_t(1) << bucket_index, |
364 kNumRapporHistogramBuckets); | 349 kNumRapporHistogramBuckets); |
365 // The IsSlow flag is just a one bit boolean if the first layout was > 10s. | 350 // The IsSlow flag is just a one bit boolean if the first layout was > 10s. |
366 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10, | 351 sample->SetFlagsField("IsSlow", first_contentful_paint.InSecondsF() >= 10, |
367 1); | 352 1); |
368 rappor_service->RecordSampleObj( | 353 rappor_service->RecordSampleObj(kRapporMetricsNameCoarseTiming, |
369 "PageLoad.CoarseTiming.NavigationToFirstContentfulPaint", | 354 sample.Pass()); |
370 sample.Pass()); | |
371 } | 355 } |
372 } | 356 } |
373 | 357 |
374 // static | 358 // static |
375 MetricsWebContentsObserver::MetricsWebContentsObserver( | 359 MetricsWebContentsObserver::MetricsWebContentsObserver( |
376 content::WebContents* web_contents, | 360 content::WebContents* web_contents, |
377 scoped_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) | 361 scoped_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) |
378 : content::WebContentsObserver(web_contents), | 362 : content::WebContentsObserver(web_contents), |
379 in_foreground_(false), | 363 in_foreground_(false), |
380 embedder_interface_(embedder_interface.Pass()) {} | 364 embedder_interface_(embedder_interface.Pass()) {} |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 | 526 |
543 if (!committed_load_->UpdateTiming(timing)) { | 527 if (!committed_load_->UpdateTiming(timing)) { |
544 // If the page load tracker cannot update its timing, something is wrong | 528 // If the page load tracker cannot update its timing, something is wrong |
545 // with the IPC (it's from another load, or it's invalid in some other way). | 529 // with the IPC (it's from another load, or it's invalid in some other way). |
546 // We expect this to be a rare occurrence. | 530 // We expect this to be a rare occurrence. |
547 RecordInternalError(ERR_BAD_TIMING_IPC); | 531 RecordInternalError(ERR_BAD_TIMING_IPC); |
548 } | 532 } |
549 } | 533 } |
550 | 534 |
551 } // namespace page_load_metrics | 535 } // namespace page_load_metrics |
OLD | NEW |