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

Side by Side Diff: chrome/renderer/page_load_histograms.cc

Issue 2437863005: Remove PLT.* histograms. (Closed)
Patch Set: rebase Created 4 years, 1 month 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
« no previous file with comments | « chrome/renderer/page_load_histograms.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 // TODO(bmcquade): delete this class in October 2016, as it is deprecated by the
6 // new PageLoad.* UMA histograms.
7
8 #include "chrome/renderer/page_load_histograms.h"
9
10 #include <stddef.h>
11
12 #include <memory>
13 #include <string>
14
15 #include "base/command_line.h"
16 #include "base/logging.h"
17 #include "base/metrics/field_trial.h"
18 #include "base/metrics/histogram.h"
19 #include "base/metrics/persistent_histogram_allocator.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/time/time.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/renderer/searchbox/search_bouncer.h"
28 #include "content/public/common/content_constants.h"
29 #include "content/public/renderer/document_state.h"
30 #include "content/public/renderer/render_frame.h"
31 #include "content/public/renderer/render_thread.h"
32 #include "content/public/renderer/render_view.h"
33 #include "extensions/common/url_pattern.h"
34 #include "net/base/url_util.h"
35 #include "net/http/http_response_headers.h"
36 #include "third_party/WebKit/public/platform/URLConversion.h"
37 #include "third_party/WebKit/public/platform/WebURLRequest.h"
38 #include "third_party/WebKit/public/platform/WebURLResponse.h"
39 #include "third_party/WebKit/public/web/WebDocument.h"
40 #include "third_party/WebKit/public/web/WebLocalFrame.h"
41 #include "third_party/WebKit/public/web/WebPerformance.h"
42 #include "third_party/WebKit/public/web/WebView.h"
43 #include "url/gurl.h"
44
45 #if defined(ENABLE_EXTENSIONS)
46 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h"
47 #include "extensions/renderer/dispatcher.h"
48 #endif
49
50 using blink::WebDataSource;
51 using blink::WebLocalFrame;
52 using blink::WebPerformance;
53 using blink::WebString;
54 using base::Time;
55 using base::TimeDelta;
56 using content::DocumentState;
57
58 const size_t kPLTCount = 100;
59
60 namespace {
61
62 // ID indicating that no GWS-Chrome joint experiment is active.
63 const int kNoExperiment = 0;
64
65 // Max ID of GWS-Chrome joint experiment. If you change this value, please
66 // update PLT_HISTOGRAM_WITH_GWS_VARIANT accordingly.
67 const int kMaxExperimentID = 20;
68
69 TimeDelta kPLTMin() {
70 return TimeDelta::FromMilliseconds(10);
71 }
72 TimeDelta kPLTMax() {
73 return TimeDelta::FromMinutes(10);
74 }
75
76 // This function corresponds to PLT_HISTOGRAM macro invocation without caching.
77 // Use this for PLT histograms with dynamically generated names, which
78 // otherwise can't use the caching PLT_HISTOGRAM macro without code duplication.
79 void PltHistogramWithNoMacroCaching(const std::string& name,
80 const TimeDelta& sample) {
81 // The parameters should exacly match the parameters in
82 // UMA_HISTOGRAM_CUSTOM_TIMES macro.
83 base::HistogramBase* histogram_pointer = base::Histogram::FactoryTimeGet(
84 name, kPLTMin(), kPLTMax(), kPLTCount,
85 base::HistogramBase::kUmaTargetedHistogramFlag);
86 histogram_pointer->AddTime(sample);
87 }
88
89 // This records UMA corresponding to the PLT_HISTOGRAM macro without caching.
90 void PltHistogramWithGwsPreview(const char* name,
91 const TimeDelta& sample,
92 bool is_preview,
93 int experiment_id) {
94 std::string preview_suffix = is_preview ? "_Preview" : "_NoPreview";
95 PltHistogramWithNoMacroCaching(name + preview_suffix, sample);
96
97 if (experiment_id != kNoExperiment) {
98 std::string name_with_experiment_id = base::StringPrintf(
99 "%s%s_Experiment%d", name, preview_suffix.c_str(), experiment_id);
100 PltHistogramWithNoMacroCaching(name_with_experiment_id, sample);
101 }
102 }
103
104 #define PLT_HISTOGRAM(name, sample) \
105 UMA_HISTOGRAM_CUSTOM_TIMES(name, sample, kPLTMin(), kPLTMax(), kPLTCount);
106
107 #define PLT_HISTOGRAM_WITH_GWS_VARIANT( \
108 name, sample, came_from_websearch, websearch_chrome_joint_experiment_id, \
109 is_preview) { \
110 PLT_HISTOGRAM(name, sample); \
111 if (came_from_websearch) { \
112 PLT_HISTOGRAM(base::StringPrintf("%s_FromGWS", name), sample) \
113 if (websearch_chrome_joint_experiment_id != kNoExperiment) { \
114 std::string name_with_experiment_id = base::StringPrintf( \
115 "%s_FromGWS_Experiment%d", \
116 name, websearch_chrome_joint_experiment_id); \
117 PltHistogramWithNoMacroCaching(name_with_experiment_id, sample); \
118 } \
119 } \
120 PltHistogramWithGwsPreview(name, sample, is_preview, \
121 websearch_chrome_joint_experiment_id); \
122 }
123
124 // Returns the scheme type of the given URL if its type is one for which we
125 // dump page load histograms. Otherwise returns NULL.
126 URLPattern::SchemeMasks GetSupportedSchemeType(const GURL& url) {
127 if (url.SchemeIs("http"))
128 return URLPattern::SCHEME_HTTP;
129 else if (url.SchemeIs("https"))
130 return URLPattern::SCHEME_HTTPS;
131 return static_cast<URLPattern::SchemeMasks>(0);
132 }
133
134 // Helper function to check for string in 'via' header. Returns true if
135 // |via_value| is one of the values listed in the Via header.
136 bool ViaHeaderContains(WebLocalFrame* frame, const std::string& via_value) {
137 const char kViaHeaderName[] = "Via";
138 std::vector<std::string> values;
139 // Multiple via headers have already been coalesced and hence each value
140 // separated by a comma corresponds to a proxy. The value added by a proxy is
141 // not expected to contain any commas.
142 // Example., Via: 1.0 Compression proxy, 1.1 Google Instant Proxy Preview
143 values = base::SplitString(
144 frame->dataSource()->response().httpHeaderField(kViaHeaderName).utf8(),
145 ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
146 return std::find(values.begin(), values.end(), via_value) != values.end();
147 }
148
149 // Returns true if the provided URL is a referrer string that came from
150 // a Google Web Search results page. This is a little non-deterministic
151 // because desktop and mobile websearch differ and sometimes just provide
152 // http://www.google.com/ as the referrer. In the case of /url we can be sure
153 // that it came from websearch but we will be generous and allow for cases
154 // where a non-Google URL was provided a bare Google URL as a referrer.
155 // The domain validation matches the code used by the prerenderer for similar
156 // purposes.
157 // TODO(pmeenan): Remove the fuzzy logic when the referrer is reliable
158 bool IsFromGoogleSearchResult(const GURL& url, const GURL& referrer) {
159 if (!base::StartsWith(referrer.host(), "www.google.",
160 base::CompareCase::SENSITIVE))
161 return false;
162 if (base::StartsWith(referrer.path(), "/url",
163 base::CompareCase::SENSITIVE))
164 return true;
165 bool is_possible_search_referrer =
166 referrer.path().empty() || referrer.path() == "/" ||
167 base::StartsWith(referrer.path(), "/search",
168 base::CompareCase::SENSITIVE) ||
169 base::StartsWith(referrer.path(), "/webhp",
170 base::CompareCase::SENSITIVE);
171 if (is_possible_search_referrer &&
172 !base::StartsWith(url.host(), "www.google",
173 base::CompareCase::SENSITIVE))
174 return true;
175 return false;
176 }
177
178 // Extracts a Google Web Search and Chrome joint experiment ID from a referrer
179 // that came from a Google Web Search results page. An experiment ID is embedded
180 // in a query string as a "gcjeid=" parameter value.
181 int GetQueryStringBasedExperiment(const GURL& referrer) {
182 std::string value;
183 if (!net::GetValueForKeyInQuery(referrer, "gcjeid", &value))
184 return kNoExperiment;
185
186 int experiment_id;
187 if (!base::StringToInt(value, &experiment_id))
188 return kNoExperiment;
189 if (0 < experiment_id && experiment_id <= kMaxExperimentID)
190 return experiment_id;
191 return kNoExperiment;
192 }
193
194 void DumpHistograms(const WebPerformance& performance,
195 DocumentState* document_state,
196 bool came_from_websearch,
197 int websearch_chrome_joint_experiment_id,
198 bool is_preview,
199 URLPattern::SchemeMasks scheme_type) {
200 // This function records new histograms based on the Navigation Timing
201 // records. As such, the histograms should not depend on the deprecated timing
202 // information collected in DocumentState. However, here for some reason we
203 // check if document_state->request_time() is null. TODO(ppi): find out why
204 // and remove DocumentState from the parameter list.
205 Time request = document_state->request_time();
206
207 Time navigation_start = Time::FromDoubleT(performance.navigationStart());
208 Time request_start = Time::FromDoubleT(performance.requestStart());
209 Time response_start = Time::FromDoubleT(performance.responseStart());
210 Time dom_content_loaded_start =
211 Time::FromDoubleT(performance.domContentLoadedEventStart());
212 Time load_event_start = Time::FromDoubleT(performance.loadEventStart());
213 Time load_event_end = Time::FromDoubleT(performance.loadEventEnd());
214 Time begin = (request.is_null() ? navigation_start : request_start);
215
216 DCHECK(!navigation_start.is_null());
217
218 // It is possible for a document to have navigation_start time, but no
219 // request_start. An example is doing a window.open, which synchronously
220 // loads "about:blank", then using document.write add a meta http-equiv
221 // refresh tag, which causes a navigation. In such case, we will arrive at
222 // this function with no request/response timing data and identical load
223 // start/end values. Avoid logging this case, as it doesn't add any
224 // meaningful information to the histogram.
225 if (request_start.is_null())
226 return;
227
228 // TODO(dominich): Investigate conditions under which |load_event_start| and
229 // |load_event_end| may be NULL as in the non-PT_ case below. Examples in
230 // http://crbug.com/112006.
231 // DCHECK(!load_event_start.is_null());
232 // DCHECK(!load_event_end.is_null());
233
234 if (document_state->web_timing_histograms_recorded())
235 return;
236 document_state->set_web_timing_histograms_recorded(true);
237
238 // TODO(simonjam): There is no way to distinguish between abandonment and
239 // intentional Javascript navigation before the load event fires.
240 // TODO(dominich): Load type breakdown
241 if (!load_event_start.is_null()) {
242 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_BeginToFinishDoc",
243 load_event_start - begin,
244 came_from_websearch,
245 websearch_chrome_joint_experiment_id,
246 is_preview);
247 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_CommitToFinishDoc",
248 load_event_start - response_start,
249 came_from_websearch,
250 websearch_chrome_joint_experiment_id,
251 is_preview);
252 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_RequestToFinishDoc",
253 load_event_start - navigation_start,
254 came_from_websearch,
255 websearch_chrome_joint_experiment_id,
256 is_preview);
257 }
258 if (!load_event_end.is_null()) {
259 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_BeginToFinish",
260 load_event_end - begin,
261 came_from_websearch,
262 websearch_chrome_joint_experiment_id,
263 is_preview);
264 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_CommitToFinish",
265 load_event_end - response_start,
266 came_from_websearch,
267 websearch_chrome_joint_experiment_id,
268 is_preview);
269 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_RequestToFinish",
270 load_event_end - navigation_start,
271 came_from_websearch,
272 websearch_chrome_joint_experiment_id,
273 is_preview);
274 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_StartToFinish",
275 load_event_end - request_start,
276 came_from_websearch,
277 websearch_chrome_joint_experiment_id,
278 is_preview);
279 }
280 if (!load_event_start.is_null() && !load_event_end.is_null()) {
281 PLT_HISTOGRAM("PLT.PT_FinishDocToFinish",
282 load_event_end - load_event_start);
283 }
284 if (!dom_content_loaded_start.is_null()) {
285 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_RequestToDomContentLoaded",
286 dom_content_loaded_start - navigation_start,
287 came_from_websearch,
288 websearch_chrome_joint_experiment_id,
289 is_preview);
290 }
291 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_BeginToCommit",
292 response_start - begin,
293 came_from_websearch,
294 websearch_chrome_joint_experiment_id,
295 is_preview);
296 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_RequestToStart",
297 request_start - navigation_start,
298 came_from_websearch,
299 websearch_chrome_joint_experiment_id,
300 is_preview);
301 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_StartToCommit",
302 response_start - request_start,
303 came_from_websearch,
304 websearch_chrome_joint_experiment_id,
305 is_preview);
306 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.PT_RequestToCommit",
307 response_start - navigation_start,
308 came_from_websearch,
309 websearch_chrome_joint_experiment_id,
310 is_preview);
311 }
312
313 bool WasWebRequestUsedBySomeExtensions() {
314 #if defined(ENABLE_EXTENSIONS)
315 return ChromeExtensionsRendererClient::GetInstance()->extension_dispatcher()
316 ->WasWebRequestUsedBySomeExtensions();
317 #else
318 return false;
319 #endif
320 }
321
322 // These histograms are based on the timing information collected in
323 // DocumentState. They should be transitioned to equivalents based on the
324 // Navigation Timing records (see DumpPerformanceTiming()) or dropped if not
325 // needed. Please do not add new metrics based on DocumentState.
326 void DumpDeprecatedHistograms(const WebPerformance& performance,
327 DocumentState* document_state,
328 bool came_from_websearch,
329 int websearch_chrome_joint_experiment_id,
330 bool is_preview,
331 URLPattern::SchemeMasks scheme_type) {
332 // If we've already dumped, do nothing.
333 // This simple bool works because we only dump for the main frame.
334 if (document_state->load_histograms_recorded())
335 return;
336
337 // Abort if any of these is missing.
338 Time start = document_state->start_load_time();
339 Time commit = document_state->commit_load_time();
340 Time navigation_start =
341 Time::FromDoubleT(performance.navigationStart());
342 if (start.is_null() || commit.is_null() || navigation_start.is_null())
343 return;
344
345 // We properly handle null values for the next 3 variables.
346 Time request = document_state->request_time();
347 Time first_paint = document_state->first_paint_time();
348 Time first_paint_after_load = document_state->first_paint_after_load_time();
349 Time finish_doc = document_state->finish_document_load_time();
350 Time finish_all_loads = document_state->finish_load_time();
351
352 // Handle case where user hits "stop" or "back" before loading completely.
353 // Note that this makes abandoned page loads be recorded as if they were
354 // completed, polluting the metrics with artifically short completion times.
355 // We are not fixing this as these metrics are being dropped as deprecated.
356 if (finish_doc.is_null()) {
357 finish_doc = Time::Now();
358 document_state->set_finish_document_load_time(finish_doc);
359 }
360 if (finish_all_loads.is_null()) {
361 finish_all_loads = Time::Now();
362 document_state->set_finish_load_time(finish_all_loads);
363 }
364
365 document_state->set_load_histograms_recorded(true);
366
367 // Note: Client side redirects will have no request time.
368 Time begin = request.is_null() ? start : request;
369 TimeDelta begin_to_finish_doc = finish_doc - begin;
370 TimeDelta begin_to_finish_all_loads = finish_all_loads - begin;
371 TimeDelta start_to_finish_all_loads = finish_all_loads - start;
372 TimeDelta start_to_commit = commit - start;
373
374 DocumentState::LoadType load_type = document_state->load_type();
375
376 // The above code sanitized all values of times, in preparation for creating
377 // actual histograms. The remainder of this code could be run at destructor
378 // time for the document_state, since all data is intact.
379
380 // Aggregate PLT data across all link types.
381 UMA_HISTOGRAM_ENUMERATION("PLT.LoadType", load_type,
382 DocumentState::kLoadTypeMax);
383 PLT_HISTOGRAM("PLT.StartToCommit", start_to_commit);
384 PLT_HISTOGRAM("PLT.CommitToFinishDoc", finish_doc - commit);
385 PLT_HISTOGRAM("PLT.FinishDocToFinish", finish_all_loads - finish_doc);
386 PLT_HISTOGRAM("PLT.BeginToCommit", commit - begin);
387 PLT_HISTOGRAM("PLT.StartToFinish", start_to_finish_all_loads);
388 if (!request.is_null()) {
389 PLT_HISTOGRAM("PLT.RequestToStart", start - request);
390 PLT_HISTOGRAM("PLT.RequestToFinish", finish_all_loads - request);
391 }
392 PLT_HISTOGRAM("PLT.CommitToFinish", finish_all_loads - commit);
393
394 std::unique_ptr<TimeDelta> begin_to_first_paint;
395 std::unique_ptr<TimeDelta> commit_to_first_paint;
396 if (!first_paint.is_null()) {
397 // 'first_paint' can be before 'begin' for an unknown reason.
398 // See bug http://crbug.com/125273 for details.
399 if (begin <= first_paint) {
400 begin_to_first_paint.reset(new TimeDelta(first_paint - begin));
401 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.BeginToFirstPaint",
402 *begin_to_first_paint,
403 came_from_websearch,
404 websearch_chrome_joint_experiment_id,
405 is_preview);
406 } else {
407 // Track the frequency and magnitude of cases where first_paint precedes
408 // begin. The current hypothesis is that this is due to using the
409 // non-monotonic timer. If that's the case, we expect first_paint
410 // preceding begin to be rare, and the delta between values to be close to
411 // zero. This is a temporary addition that we will remove once we better
412 // understand the frequency and magnitude of first_paint preceding begin.
413 PLT_HISTOGRAM("PLT.BeginToFirstPaint_Negative", begin - first_paint);
414 }
415
416 // Conditional was previously a DCHECK. Changed due to multiple bot
417 // failures, listed in crbug.com/383963
418 if (commit <= first_paint) {
419 commit_to_first_paint.reset(new TimeDelta(first_paint - commit));
420 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.CommitToFirstPaint",
421 *commit_to_first_paint,
422 came_from_websearch,
423 websearch_chrome_joint_experiment_id,
424 is_preview);
425 }
426 }
427 if (!first_paint_after_load.is_null()) {
428 // 'first_paint_after_load' can be before 'begin' for an unknown reason.
429 // See bug http://crbug.com/125273 for details.
430 if (begin <= first_paint_after_load) {
431 PLT_HISTOGRAM("PLT.BeginToFirstPaintAfterLoad",
432 first_paint_after_load - begin);
433 }
434 // Both following conditionals were previously DCHECKs. Changed due to
435 // multiple bot failures, listed in crbug.com/383963
436 if (commit <= first_paint_after_load) {
437 PLT_HISTOGRAM("PLT.CommitToFirstPaintAfterLoad",
438 first_paint_after_load - commit);
439 }
440 if (finish_all_loads <= first_paint_after_load) {
441 PLT_HISTOGRAM("PLT.FinishToFirstPaintAfterLoad",
442 first_paint_after_load - finish_all_loads);
443 }
444 }
445 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.BeginToFinishDoc", begin_to_finish_doc,
446 came_from_websearch,
447 websearch_chrome_joint_experiment_id,
448 is_preview);
449 PLT_HISTOGRAM_WITH_GWS_VARIANT("PLT.BeginToFinish", begin_to_finish_all_loads,
450 came_from_websearch,
451 websearch_chrome_joint_experiment_id,
452 is_preview);
453
454 // Load type related histograms.
455 switch (load_type) {
456 case DocumentState::UNDEFINED_LOAD:
457 PLT_HISTOGRAM("PLT.BeginToFinishDoc_UndefLoad", begin_to_finish_doc);
458 PLT_HISTOGRAM("PLT.BeginToFinish_UndefLoad", begin_to_finish_all_loads);
459 break;
460 case DocumentState::RELOAD:
461 PLT_HISTOGRAM("PLT.BeginToFinishDoc_Reload", begin_to_finish_doc);
462 PLT_HISTOGRAM("PLT.BeginToFinish_Reload", begin_to_finish_all_loads);
463 break;
464 case DocumentState::HISTORY_LOAD:
465 PLT_HISTOGRAM("PLT.BeginToFinishDoc_HistoryLoad", begin_to_finish_doc);
466 PLT_HISTOGRAM("PLT.BeginToFinish_HistoryLoad", begin_to_finish_all_loads);
467 break;
468 case DocumentState::NORMAL_LOAD:
469 PLT_HISTOGRAM("PLT.BeginToFinishDoc_NormalLoad", begin_to_finish_doc);
470 PLT_HISTOGRAM("PLT.BeginToFinish_NormalLoad", begin_to_finish_all_loads);
471 break;
472 case DocumentState::LINK_LOAD_NORMAL:
473 PLT_HISTOGRAM("PLT.BeginToFinishDoc_LinkLoadNormal",
474 begin_to_finish_doc);
475 PLT_HISTOGRAM("PLT.BeginToFinish_LinkLoadNormal",
476 begin_to_finish_all_loads);
477 break;
478 case DocumentState::LINK_LOAD_RELOAD:
479 PLT_HISTOGRAM("PLT.BeginToFinishDoc_LinkLoadReload",
480 begin_to_finish_doc);
481 PLT_HISTOGRAM("PLT.BeginToFinish_LinkLoadReload",
482 begin_to_finish_all_loads);
483 break;
484 case DocumentState::LINK_LOAD_CACHE_STALE_OK:
485 PLT_HISTOGRAM("PLT.BeginToFinishDoc_LinkLoadStaleOk",
486 begin_to_finish_doc);
487 PLT_HISTOGRAM("PLT.BeginToFinish_LinkLoadStaleOk",
488 begin_to_finish_all_loads);
489 break;
490 case DocumentState::LINK_LOAD_CACHE_ONLY:
491 PLT_HISTOGRAM("PLT.BeginToFinishDoc_LinkLoadCacheOnly",
492 begin_to_finish_doc);
493 PLT_HISTOGRAM("PLT.BeginToFinish_LinkLoadCacheOnly",
494 begin_to_finish_all_loads);
495 break;
496 default:
497 break;
498 }
499
500 const bool use_webrequest_histogram = WasWebRequestUsedBySomeExtensions();
501 if (use_webrequest_histogram) {
502 switch (load_type) {
503 case DocumentState::NORMAL_LOAD:
504 PLT_HISTOGRAM(
505 "PLT.BeginToFinish_NormalLoad_ExtensionWebRequest",
506 begin_to_finish_all_loads);
507 break;
508 case DocumentState::LINK_LOAD_NORMAL:
509 PLT_HISTOGRAM(
510 "PLT.BeginToFinish_LinkLoadNormal_ExtensionWebRequest",
511 begin_to_finish_all_loads);
512 break;
513 case DocumentState::LINK_LOAD_RELOAD:
514 PLT_HISTOGRAM(
515 "PLT.BeginToFinish_LinkLoadReload_ExtensionWebRequest",
516 begin_to_finish_all_loads);
517 break;
518 case DocumentState::LINK_LOAD_CACHE_STALE_OK:
519 PLT_HISTOGRAM(
520 "PLT.BeginToFinish_LinkLoadStaleOk_ExtensionWebRequest",
521 begin_to_finish_all_loads);
522 break;
523 default:
524 break;
525 }
526 }
527 }
528
529 } // namespace
530
531 PageLoadHistograms::PageLoadHistograms(content::RenderFrame* render_frame)
532 : content::RenderFrameObserver(render_frame), helper_(this) {}
533
534 PageLoadHistograms::~PageLoadHistograms() {
535 }
536
537 void PageLoadHistograms::Dump() {
538 WebLocalFrame* frame = render_frame()->GetWebFrame();
539
540 // We only dump histograms for main frames.
541 // In the future, it may be interesting to tag subframes and dump them too.
542 DCHECK(frame && !frame->parent());
543
544 // Only dump for supported schemes.
545 URLPattern::SchemeMasks scheme_type =
546 GetSupportedSchemeType(frame->document().url());
547 if (scheme_type == 0)
548 return;
549
550 // Don't dump stats for the NTP, as PageLoadHistograms should only be recorded
551 // for pages visited due to an explicit user navigation.
552 if (SearchBouncer::GetInstance()->IsNewTabPage(frame->document().url())) {
553 return;
554 }
555
556 DocumentState* document_state =
557 DocumentState::FromDataSource(frame->dataSource());
558
559 bool came_from_websearch = IsFromGoogleSearchResult(
560 frame->document().url(),
561 blink::WebStringToGURL(frame->document().referrer()));
562 int websearch_chrome_joint_experiment_id = kNoExperiment;
563 bool is_preview = false;
564 if (came_from_websearch) {
565 websearch_chrome_joint_experiment_id = GetQueryStringBasedExperiment(
566 blink::WebStringToGURL(frame->document().referrer()));
567 is_preview = ViaHeaderContains(frame, "1.1 Google Instant Proxy Preview");
568 }
569
570 // Metrics based on the timing information recorded for the Navigation Timing
571 // API - http://www.w3.org/TR/navigation-timing/.
572 DumpHistograms(frame->performance(), document_state, came_from_websearch,
573 websearch_chrome_joint_experiment_id, is_preview, scheme_type);
574
575 // Old metrics based on the timing information stored in DocumentState. These
576 // are deprecated and should go away.
577 DumpDeprecatedHistograms(
578 frame->performance(), document_state, came_from_websearch,
579 websearch_chrome_joint_experiment_id, is_preview, scheme_type);
580
581 // Log the PLT to the info log.
582 LogPageLoadTime(document_state, frame->dataSource());
583
584 // If persistent histograms are not enabled, initiate a PostTask here to be
585 // sure that we send the histograms generated. Without this call, pages
586 // that don't have an on-close-handler might generate data that is lost if
587 // the renderer is shutdown abruptly (e.g. the user closed the tab).
588 // TODO(bcwhite): Remove completely when persistence is on-by-default.
589 if (!base::GlobalHistogramAllocator::Get()) {
590 content::RenderThread::Get()->UpdateHistograms(
591 content::kHistogramSynchronizerReservedSequenceNumber);
592 }
593 }
594
595 void PageLoadHistograms::WillCommitProvisionalLoad() {
596 Dump();
597 }
598
599 void PageLoadHistograms::LogPageLoadTime(const DocumentState* document_state,
600 const WebDataSource* ds) const {
601 // Because this function gets called on every page load,
602 // take extra care to optimize it away if logging is turned off.
603 if (logging::LOG_INFO < logging::GetMinLogLevel())
604 return;
605
606 DCHECK(document_state);
607 DCHECK(ds);
608 GURL url(ds->request().url());
609 Time start = document_state->start_load_time();
610 Time finish = document_state->finish_load_time();
611 // TODO(mbelshe): should we log more stats?
612 VLOG(1) << "PLT: " << (finish - start).InMilliseconds() << "ms "
613 << url.spec();
614 }
615
616 void PageLoadHistograms::OnDestruct() {
617 delete this;
618 }
619
620 PageLoadHistograms::Helper::Helper(PageLoadHistograms* histograms)
621 : RenderViewObserver(histograms->render_frame()->GetRenderView()),
622 histograms_(histograms) {
623 }
624
625 void PageLoadHistograms::Helper::ClosePage() {
626 histograms_->Dump();
627 }
628
629 void PageLoadHistograms::Helper::OnDestruct() {
630 }
OLDNEW
« no previous file with comments | « chrome/renderer/page_load_histograms.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698