This source file includes following definitions.
- ComposeHistogramName
- GetHistogramName
- OriginIsOmnibox
- seen_pageload_started_after_prerender_
- RecordPrerender
- RecordPrerenderStarted
- RecordConcurrency
- RecordUsedPrerender
- RecordTimeSinceLastRecentVisit
- GetCurrentTimeTicks
- RecordPerceivedPageLoadTime
- RecordPageLoadTimeNotSwappedIn
- RecordPercentLoadDoneAtSwapin
- GetTimeSinceLastPrerender
- WithinWindow
- RecordTimeUntilUsed
- RecordAbandonTimeUntilUsed
- RecordPerSessionCount
- RecordTimeBetweenPrerenderRequests
- RecordFinalStatus
- RecordEvent
- RecordCookieStatus
- RecordCookieSendType
- RecordPrerenderPageVisitedStatus
- RecordNetworkBytes
- GetCurrentExperimentId
- IsOriginExperimentWash
#include "chrome/browser/prerender/prerender_histograms.h"
#include <string>
#include "base/format_macros.h"
#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/predictors/autocomplete_action_predictor.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_util.h"
using predictors::AutocompleteActionPredictor;
namespace prerender {
namespace {
const int kWindowDurationSeconds = 30;
std::string ComposeHistogramName(const std::string& prefix_type,
const std::string& name) {
if (prefix_type.empty())
return std::string("Prerender.") + name;
return std::string("Prerender.") + prefix_type + std::string("_") + name;
}
std::string GetHistogramName(Origin origin, uint8 experiment_id,
bool is_wash, const std::string& name) {
if (is_wash)
return ComposeHistogramName("wash", name);
if (origin == ORIGIN_GWS_PRERENDER) {
if (experiment_id == kNoExperiment)
return ComposeHistogramName("gws", name);
return ComposeHistogramName("exp" + std::string(1, experiment_id + '0'),
name);
}
if (experiment_id != kNoExperiment)
return ComposeHistogramName("wash", name);
switch (origin) {
case ORIGIN_OMNIBOX:
return ComposeHistogramName("omnibox", name);
case ORIGIN_NONE:
return ComposeHistogramName("none", name);
case ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN:
return ComposeHistogramName("websame", name);
case ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN:
return ComposeHistogramName("webcross", name);
case ORIGIN_LOCAL_PREDICTOR:
return ComposeHistogramName("localpredictor", name);
case ORIGIN_EXTERNAL_REQUEST:
return ComposeHistogramName("externalrequest", name);
case ORIGIN_INSTANT:
return ComposeHistogramName("Instant", name);
case ORIGIN_LINK_REL_NEXT:
return ComposeHistogramName("webnext", name);
case ORIGIN_GWS_PRERENDER:
default:
NOTREACHED();
break;
};
NOTREACHED();
return ComposeHistogramName("wash", name);
}
bool OriginIsOmnibox(Origin origin) {
return origin == ORIGIN_OMNIBOX;
}
}
#define PREFIXED_HISTOGRAM(histogram_name, origin, HISTOGRAM) \
PREFIXED_HISTOGRAM_INTERNAL(origin, GetCurrentExperimentId(), \
IsOriginExperimentWash(), HISTOGRAM, \
histogram_name)
#define PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(histogram_name, origin, \
experiment, HISTOGRAM) \
PREFIXED_HISTOGRAM_INTERNAL(origin, experiment, false, HISTOGRAM, \
histogram_name)
#define PREFIXED_HISTOGRAM_INTERNAL(origin, experiment, wash, HISTOGRAM, \
histogram_name) do { \
{ \
\
std::string name = ComposeHistogramName(std::string(), histogram_name); \
HISTOGRAM; \
} \
\
std::string name = GetHistogramName(origin, experiment, wash, \
histogram_name); \
\
\
\
\
\
\
static uint8 recording_experiment = kNoExperiment; \
if (recording_experiment == kNoExperiment && experiment != kNoExperiment) \
recording_experiment = experiment; \
if (wash) { \
HISTOGRAM; \
} else if (experiment != kNoExperiment && \
(origin != ORIGIN_GWS_PRERENDER || \
experiment != recording_experiment)) { \
} else if (origin == ORIGIN_OMNIBOX) { \
HISTOGRAM; \
} else if (origin == ORIGIN_NONE) { \
HISTOGRAM; \
} else if (origin == ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN) { \
HISTOGRAM; \
} else if (origin == ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN) { \
HISTOGRAM; \
} else if (origin == ORIGIN_LOCAL_PREDICTOR) { \
HISTOGRAM; \
} else if (origin == ORIGIN_EXTERNAL_REQUEST) { \
HISTOGRAM; \
} else if (origin == ORIGIN_INSTANT) { \
HISTOGRAM; \
} else if (origin == ORIGIN_LINK_REL_NEXT) { \
HISTOGRAM; \
} else if (experiment != kNoExperiment) { \
HISTOGRAM; \
} else { \
HISTOGRAM; \
} \
} while (0)
PrerenderHistograms::PrerenderHistograms()
: last_experiment_id_(kNoExperiment),
last_origin_(ORIGIN_MAX),
origin_experiment_wash_(false),
seen_any_pageload_(true),
seen_pageload_started_after_prerender_(true) {
}
void PrerenderHistograms::RecordPrerender(Origin origin, const GURL& url) {
uint8 experiment = GetQueryStringBasedExperiment(url);
if (!WithinWindow()) {
origin_experiment_wash_ = false;
} else {
if (experiment != last_experiment_id_ || origin != last_origin_)
origin_experiment_wash_ = true;
}
last_origin_ = origin;
last_experiment_id_ = experiment;
last_prerender_seen_time_ = GetCurrentTimeTicks();
seen_any_pageload_ = false;
seen_pageload_started_after_prerender_ = false;
}
void PrerenderHistograms::RecordPrerenderStarted(Origin origin) const {
if (OriginIsOmnibox(origin)) {
UMA_HISTOGRAM_ENUMERATION(
base::StringPrintf("Prerender.OmniboxPrerenderCount%s",
PrerenderManager::GetModeString()), 1, 2);
}
}
void PrerenderHistograms::RecordConcurrency(size_t prerender_count) const {
static const size_t kMaxRecordableConcurrency = 20;
DCHECK_GE(kMaxRecordableConcurrency, Config().max_link_concurrency);
UMA_HISTOGRAM_ENUMERATION(
base::StringPrintf("Prerender.PrerenderCountOf%" PRIuS "Max",
kMaxRecordableConcurrency),
prerender_count, kMaxRecordableConcurrency + 1);
}
void PrerenderHistograms::RecordUsedPrerender(Origin origin) const {
if (OriginIsOmnibox(origin)) {
UMA_HISTOGRAM_ENUMERATION(
base::StringPrintf("Prerender.OmniboxNavigationsUsedPrerenderCount%s",
PrerenderManager::GetModeString()), 1, 2);
}
}
void PrerenderHistograms::RecordTimeSinceLastRecentVisit(
Origin origin,
base::TimeDelta delta) const {
PREFIXED_HISTOGRAM(
"TimeSinceLastRecentVisit", origin,
UMA_HISTOGRAM_TIMES(name, delta));
}
base::TimeTicks PrerenderHistograms::GetCurrentTimeTicks() const {
return base::TimeTicks::Now();
}
#define RECORD_PLT(tag, perceived_page_load_time) \
PREFIXED_HISTOGRAM( \
tag, origin, \
UMA_HISTOGRAM_CUSTOM_TIMES( \
name, \
perceived_page_load_time, \
base::TimeDelta::FromMilliseconds(10), \
base::TimeDelta::FromSeconds(60), \
100))
void PrerenderHistograms::RecordPerceivedPageLoadTime(
Origin origin,
base::TimeDelta perceived_page_load_time,
NavigationType navigation_type,
const GURL& url) {
if (!url.SchemeIsHTTPOrHTTPS())
return;
bool within_window = WithinWindow();
bool is_google_url = IsGoogleDomain(url);
RECORD_PLT("PerceivedPLT", perceived_page_load_time);
if (within_window)
RECORD_PLT("PerceivedPLTWindowed", perceived_page_load_time);
if (navigation_type != NAVIGATION_TYPE_NORMAL) {
DCHECK(navigation_type == NAVIGATION_TYPE_WOULD_HAVE_BEEN_PRERENDERED ||
navigation_type == NAVIGATION_TYPE_PRERENDERED);
RECORD_PLT("PerceivedPLTMatchedComplete", perceived_page_load_time);
if (navigation_type == NAVIGATION_TYPE_PRERENDERED)
RECORD_PLT("PerceivedPLTMatched", perceived_page_load_time);
seen_any_pageload_ = true;
seen_pageload_started_after_prerender_ = true;
} else if (within_window) {
RECORD_PLT("PerceivedPLTWindowNotMatched", perceived_page_load_time);
if (!is_google_url) {
bool recorded_any = false;
bool recorded_non_overlapping = false;
if (!seen_any_pageload_) {
seen_any_pageload_ = true;
RECORD_PLT("PerceivedPLTFirstAfterMiss", perceived_page_load_time);
recorded_any = true;
}
if (!seen_pageload_started_after_prerender_ &&
perceived_page_load_time <= GetTimeSinceLastPrerender()) {
seen_pageload_started_after_prerender_ = true;
RECORD_PLT("PerceivedPLTFirstAfterMissNonOverlapping",
perceived_page_load_time);
recorded_non_overlapping = true;
}
if (recorded_any || recorded_non_overlapping) {
if (recorded_any && recorded_non_overlapping) {
RECORD_PLT("PerceivedPLTFirstAfterMissBoth",
perceived_page_load_time);
} else if (recorded_any) {
RECORD_PLT("PerceivedPLTFirstAfterMissAnyOnly",
perceived_page_load_time);
} else if (recorded_non_overlapping) {
RECORD_PLT("PerceivedPLTFirstAfterMissNonOverlappingOnly",
perceived_page_load_time);
}
}
}
}
}
void PrerenderHistograms::RecordPageLoadTimeNotSwappedIn(
Origin origin,
base::TimeDelta page_load_time,
const GURL& url) const {
if (!url.SchemeIsHTTPOrHTTPS() || IsGoogleDomain(url))
return;
RECORD_PLT("PrerenderNotSwappedInPLT", page_load_time);
}
void PrerenderHistograms::RecordPercentLoadDoneAtSwapin(Origin origin,
double fraction) const {
if (fraction < 0.0 || fraction > 1.0)
return;
int percentage = static_cast<int>(fraction * 100);
if (percentage < 0 || percentage > 100)
return;
PREFIXED_HISTOGRAM("PercentLoadDoneAtSwapin",
origin, UMA_HISTOGRAM_PERCENTAGE(name, percentage));
}
base::TimeDelta PrerenderHistograms::GetTimeSinceLastPrerender() const {
return base::TimeTicks::Now() - last_prerender_seen_time_;
}
bool PrerenderHistograms::WithinWindow() const {
if (last_prerender_seen_time_.is_null())
return false;
return GetTimeSinceLastPrerender() <=
base::TimeDelta::FromSeconds(kWindowDurationSeconds);
}
void PrerenderHistograms::RecordTimeUntilUsed(
Origin origin,
base::TimeDelta time_until_used) const {
PREFIXED_HISTOGRAM(
"TimeUntilUsed2", origin,
UMA_HISTOGRAM_CUSTOM_TIMES(
name,
time_until_used,
base::TimeDelta::FromMilliseconds(10),
base::TimeDelta::FromMinutes(30),
50));
}
void PrerenderHistograms::RecordAbandonTimeUntilUsed(
Origin origin,
base::TimeDelta time_until_used) const {
PREFIXED_HISTOGRAM(
"AbandonTimeUntilUsed", origin,
UMA_HISTOGRAM_CUSTOM_TIMES(
name,
time_until_used,
base::TimeDelta::FromMilliseconds(10),
base::TimeDelta::FromSeconds(30),
50));
}
void PrerenderHistograms::RecordPerSessionCount(Origin origin,
int count) const {
PREFIXED_HISTOGRAM(
"PrerendersPerSessionCount", origin,
UMA_HISTOGRAM_COUNTS(name, count));
}
void PrerenderHistograms::RecordTimeBetweenPrerenderRequests(
Origin origin, base::TimeDelta time) const {
PREFIXED_HISTOGRAM(
"TimeBetweenPrerenderRequests", origin,
UMA_HISTOGRAM_TIMES(name, time));
}
void PrerenderHistograms::RecordFinalStatus(
Origin origin,
uint8 experiment_id,
PrerenderContents::MatchCompleteStatus mc_status,
FinalStatus final_status) const {
DCHECK(final_status != FINAL_STATUS_MAX);
if (mc_status == PrerenderContents::MATCH_COMPLETE_DEFAULT ||
mc_status == PrerenderContents::MATCH_COMPLETE_REPLACED) {
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"FinalStatus", origin, experiment_id,
UMA_HISTOGRAM_ENUMERATION(name, final_status, FINAL_STATUS_MAX));
}
if (mc_status == PrerenderContents::MATCH_COMPLETE_DEFAULT ||
mc_status == PrerenderContents::MATCH_COMPLETE_REPLACEMENT ||
mc_status == PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING) {
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"FinalStatusMatchComplete", origin, experiment_id,
UMA_HISTOGRAM_ENUMERATION(name, final_status, FINAL_STATUS_MAX));
}
}
void PrerenderHistograms::RecordEvent(Origin origin, uint8 experiment_id,
PrerenderEvent event) const {
DCHECK_LT(event, PRERENDER_EVENT_MAX);
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"Event", origin, experiment_id,
UMA_HISTOGRAM_ENUMERATION(name, event, PRERENDER_EVENT_MAX));
}
void PrerenderHistograms::RecordCookieStatus(Origin origin,
uint8 experiment_id,
int cookie_status) const {
DCHECK_GE(cookie_status, 0);
DCHECK_LT(cookie_status, PrerenderContents::kNumCookieStatuses);
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"CookieStatus", origin, experiment_id,
UMA_HISTOGRAM_ENUMERATION(name, cookie_status,
PrerenderContents::kNumCookieStatuses));
}
void PrerenderHistograms::RecordCookieSendType(
Origin origin,
uint8 experiment_id,
int cookie_send_type) const {
DCHECK_GE(cookie_send_type, 0);
DCHECK_LT(cookie_send_type, PrerenderContents::kNumCookieSendTypes);
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"CookieSendType", origin, experiment_id,
UMA_HISTOGRAM_ENUMERATION(name, cookie_send_type,
PrerenderContents::kNumCookieSendTypes));
}
void PrerenderHistograms::RecordPrerenderPageVisitedStatus(
Origin origin,
uint8 experiment_id,
bool visited_before) const {
PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(
"PageVisitedStatus", origin, experiment_id,
UMA_HISTOGRAM_BOOLEAN(name, visited_before));
}
void PrerenderHistograms::RecordNetworkBytes(bool used,
int64 prerender_bytes,
int64 profile_bytes) {
const int kHistogramMin = 1;
const int kHistogramMax = 100000000;
const int kBucketCount = 50;
if (used) {
UMA_HISTOGRAM_CUSTOM_COUNTS("Prerender.NetworkBytes.Used",
prerender_bytes,
kHistogramMin,
kHistogramMax,
kBucketCount);
} else {
UMA_HISTOGRAM_CUSTOM_COUNTS("Prerender.NetworkBytes.Wasted",
prerender_bytes,
kHistogramMin,
kHistogramMax,
kBucketCount);
}
UMA_HISTOGRAM_CUSTOM_COUNTS("Prerender.NetworkBytes.TotalForProfile",
profile_bytes,
kHistogramMin,
1000000000,
kBucketCount);
}
uint8 PrerenderHistograms::GetCurrentExperimentId() const {
if (!WithinWindow())
return kNoExperiment;
return last_experiment_id_;
}
bool PrerenderHistograms::IsOriginExperimentWash() const {
if (!WithinWindow())
return false;
return origin_experiment_wash_;
}
}