Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 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 #include "chrome/browser/prerender/prerender_histograms.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/metrics/field_trial.h" | |
| 10 #include "base/metrics/histogram.h" | |
| 11 #include "chrome/browser/prerender/prerender_util.h" | |
| 12 | |
| 13 namespace prerender { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // Time window for which we will record windowed PLT's from the last | |
| 18 // observed link rel=prefetch tag. | |
| 19 const int kWindowDurationSeconds = 30; | |
| 20 | |
| 21 } // namespace | |
| 22 | |
| 23 // Helper macros for experiment-based and origin-based histogram reporting. | |
| 24 #define PREFIXED_HISTOGRAM(histogram) \ | |
| 25 PREFIXED_HISTOGRAM_INTERNAL(GetCurrentOrigin(), GetCurrentExperimentId(), \ | |
| 26 IsOriginExperimentWash(), histogram) | |
| 27 | |
| 28 #define PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(origin, experiment, histogram) \ | |
| 29 PREFIXED_HISTOGRAM_INTERNAL(origin, experiment, false, histogram) | |
| 30 | |
| 31 #define PREFIXED_HISTOGRAM_INTERNAL(origin, experiment, wash, histogram) { \ | |
| 32 static uint8 recording_experiment = kNoExperiment; \ | |
| 33 if (recording_experiment == kNoExperiment && experiment != kNoExperiment) \ | |
| 34 recording_experiment = experiment; \ | |
| 35 if (wash) { \ | |
| 36 histogram; \ | |
| 37 } else if (experiment != kNoExperiment && \ | |
| 38 (origin != ORIGIN_GWS_PRERENDER || \ | |
| 39 experiment != recording_experiment)) { \ | |
| 40 } else if (origin == ORIGIN_LINK_REL_PRERENDER) { \ | |
| 41 histogram; \ | |
| 42 } else if (origin == ORIGIN_OMNIBOX) { \ | |
| 43 histogram; \ | |
| 44 } else if (experiment != kNoExperiment) { \ | |
| 45 histogram; \ | |
| 46 } else { \ | |
| 47 histogram; \ | |
| 48 } \ | |
| 49 } | |
| 50 | |
| 51 PrerenderHistograms::PrerenderHistograms(base::TimeDelta max_age) | |
| 52 : last_experiment_id_(kNoExperiment), | |
| 53 last_origin_(ORIGIN_LINK_REL_PRERENDER), | |
|
dominich
2011/08/10 00:32:46
Initialize to something invalid, like ORIGIN_MAX.
tburkard
2011/08/10 01:05:13
I don't think that's right, because for the PLT's
dominich
2011/08/10 15:53:37
That makes sense, but then I would try to make the
tburkard
2011/08/10 17:11:33
I could easily do that.. make another histogram ca
| |
| 54 origin_experiment_wash_(false), | |
| 55 max_age_(max_age) { | |
| 56 } | |
| 57 | |
| 58 void PrerenderHistograms::RecordPrerender(Origin origin, const GURL& url) { | |
| 59 // Check if we are doing an experiment. | |
| 60 uint8 experiment = GetQueryStringBasedExperiment(url); | |
| 61 | |
| 62 // We need to update last_experiment_id_, last_origin_, and | |
| 63 // origin_experiment_wash_. | |
| 64 if (!WithinWindow()) { | |
| 65 // If we are outside a window, this is a fresh start and we are fine, | |
| 66 // and there is no mix. | |
| 67 origin_experiment_wash_ = false; | |
| 68 } else { | |
| 69 // If we are inside the last window, there is a mish mash of origins | |
| 70 // and experiments if either there was a mish mash before, or the current | |
| 71 // experiment/origin does not match the previous one. | |
| 72 if (experiment != last_experiment_id_ || origin != last_origin_) | |
| 73 origin_experiment_wash_ = true; | |
| 74 } | |
| 75 | |
| 76 last_origin_ = origin; | |
| 77 last_experiment_id_ = experiment; | |
| 78 | |
| 79 // If we observe multiple tags within the 30 second window, we will still | |
| 80 // reset the window to begin at the most recent occurrence, so that we will | |
| 81 // always be in a window in the 30 seconds from each occurrence. | |
| 82 last_prerender_seen_time_ = GetCurrentTimeTicks(); | |
| 83 } | |
| 84 | |
| 85 base::TimeTicks PrerenderHistograms::GetCurrentTimeTicks() const { | |
| 86 return base::TimeTicks::Now(); | |
| 87 } | |
| 88 | |
| 89 // Helper macro for histograms. | |
| 90 #define RECORD_PLT(tag, perceived_page_load_time) { \ | |
| 91 PREFIXED_HISTOGRAM( \ | |
| 92 UMA_HISTOGRAM_CUSTOM_TIMES( \ | |
| 93 base::FieldTrial::MakeName(GetDefaultHistogramName(tag), "Prefetch"), \ | |
| 94 perceived_page_load_time, \ | |
| 95 base::TimeDelta::FromMilliseconds(10), \ | |
| 96 base::TimeDelta::FromSeconds(60), \ | |
| 97 100)); \ | |
| 98 } | |
| 99 | |
| 100 void PrerenderHistograms::RecordPerceivedPageLoadTime( | |
| 101 base::TimeDelta perceived_page_load_time, bool was_prerender) const { | |
| 102 bool within_window = WithinWindow(); | |
| 103 RECORD_PLT("PerceivedPLT", perceived_page_load_time); | |
| 104 if (within_window) | |
| 105 RECORD_PLT("PerceivedPLTWindowed", perceived_page_load_time); | |
| 106 if (was_prerender) { | |
| 107 RECORD_PLT("PerceivedPLTMatched", perceived_page_load_time); | |
| 108 } else { | |
| 109 if (within_window) | |
| 110 RECORD_PLT("PerceivedPLTWindowNotMatched", perceived_page_load_time); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 bool PrerenderHistograms::WithinWindow() const { | |
| 115 if (last_prerender_seen_time_.is_null()) | |
| 116 return false; | |
| 117 base::TimeDelta elapsed_time = | |
| 118 base::TimeTicks::Now() - last_prerender_seen_time_; | |
| 119 return elapsed_time <= base::TimeDelta::FromSeconds(kWindowDurationSeconds); | |
| 120 } | |
| 121 | |
| 122 | |
| 123 void PrerenderHistograms::RecordTimeUntilUsed( | |
| 124 base::TimeDelta time_until_used) const { | |
| 125 PREFIXED_HISTOGRAM(UMA_HISTOGRAM_CUSTOM_TIMES( | |
| 126 GetDefaultHistogramName("TimeUntilUsed"), | |
| 127 time_until_used, | |
| 128 base::TimeDelta::FromMilliseconds(10), | |
| 129 max_age_, | |
| 130 50)); | |
| 131 } | |
| 132 | |
| 133 void PrerenderHistograms::RecordPerSessionCount(int count) const { | |
| 134 PREFIXED_HISTOGRAM(UMA_HISTOGRAM_COUNTS( | |
| 135 GetDefaultHistogramName("PrerendersPerSessionCount"), count)); | |
| 136 } | |
| 137 | |
| 138 void PrerenderHistograms::RecordTimeBetweenPrerenderRequests( | |
| 139 base::TimeDelta time) const { | |
| 140 PREFIXED_HISTOGRAM(UMA_HISTOGRAM_TIMES( | |
| 141 GetDefaultHistogramName("TimeBetweenPrerenderRequests"), time)); | |
| 142 } | |
| 143 | |
| 144 void PrerenderHistograms::RecordFinalStatus(Origin origin, | |
| 145 uint8 experiment_id, | |
| 146 FinalStatus final_status) const { | |
| 147 DCHECK(final_status != FINAL_STATUS_MAX); | |
| 148 PREFIXED_HISTOGRAM_ORIGIN_EXPERIMENT(origin, experiment_id, | |
| 149 UMA_HISTOGRAM_ENUMERATION( | |
| 150 GetHistogramName(origin, experiment_id, "FinalStatus"), | |
| 151 final_status, | |
| 152 FINAL_STATUS_MAX)); | |
| 153 } | |
| 154 | |
| 155 std::string PrerenderHistograms::ComposeHistogramName( | |
|
dominich
2011/08/10 00:32:46
This does not need to be a member. Make it a funct
tburkard
2011/08/10 01:05:13
Done.
| |
| 156 const std::string& prefix_type, | |
| 157 const std::string& name) const { | |
| 158 if (prefix_type.empty()) | |
| 159 return std::string("Prerender.") + name; | |
| 160 return std::string("Prerender.") + prefix_type + std::string("_") + name; | |
| 161 } | |
| 162 | |
| 163 std::string PrerenderHistograms::GetHistogramName( | |
|
dominich
2011/08/10 00:32:46
This does not need to be a member. Make it a funct
tburkard
2011/08/10 01:05:13
Done.
| |
| 164 Origin origin, | |
| 165 uint8 experiment_id, | |
| 166 const std::string& name) const { | |
| 167 switch (origin) { | |
| 168 case ORIGIN_OMNIBOX: | |
| 169 if (experiment_id != kNoExperiment) | |
| 170 return ComposeHistogramName("wash", name); | |
| 171 return ComposeHistogramName("omnibox", name); | |
| 172 case ORIGIN_LINK_REL_PRERENDER: | |
| 173 if (experiment_id != kNoExperiment) | |
| 174 return ComposeHistogramName("wash", name); | |
| 175 return ComposeHistogramName("", name); | |
| 176 case ORIGIN_GWS_PRERENDER: | |
| 177 if (experiment_id == kNoExperiment) | |
| 178 return ComposeHistogramName("gws", name); | |
| 179 return ComposeHistogramName("exp" + std::string(1, experiment_id + '0'), | |
| 180 name); | |
| 181 default: | |
| 182 NOTREACHED(); | |
| 183 break; | |
| 184 }; | |
| 185 | |
| 186 // Dummy return value to make the compiler happy. | |
| 187 NOTREACHED(); | |
| 188 return ComposeHistogramName("wash", name); | |
| 189 } | |
| 190 | |
| 191 std::string PrerenderHistograms::GetDefaultHistogramName( | |
| 192 const std::string& name) const { | |
| 193 if (!WithinWindow()) | |
| 194 return ComposeHistogramName("", name); | |
| 195 if (origin_experiment_wash_) | |
| 196 return ComposeHistogramName("wash", name); | |
| 197 return GetHistogramName(last_origin_, last_experiment_id_, name); | |
| 198 } | |
| 199 | |
| 200 uint8 PrerenderHistograms::GetCurrentExperimentId() const { | |
| 201 if (!WithinWindow()) | |
| 202 return kNoExperiment; | |
| 203 return last_experiment_id_; | |
| 204 } | |
| 205 | |
| 206 Origin PrerenderHistograms::GetCurrentOrigin() const { | |
| 207 if (!WithinWindow()) | |
| 208 return ORIGIN_LINK_REL_PRERENDER; | |
| 209 return last_origin_; | |
| 210 } | |
| 211 | |
| 212 bool PrerenderHistograms::IsOriginExperimentWash() const { | |
| 213 if (!WithinWindow()) | |
| 214 return false; | |
| 215 return origin_experiment_wash_; | |
| 216 } | |
| 217 | |
| 218 } // namespace prerender | |
| OLD | NEW |