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

Side by Side Diff: chromecast/base/metrics/cast_metrics_helper.cc

Issue 652353003: Chromecast: adds class to help record complex histograms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: resets initial buffering state on flush Created 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chromecast/base/metrics/cast_metrics_helper.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/metrics/histogram.h"
12 #include "base/metrics/user_metrics.h"
13 #include "chromecast/base/metrics/cast_histograms.h"
14
15 namespace chromecast {
16 namespace metrics {
17
18 // A useful macro to make sure current member function runs on the valid thread.
19 #define MAKE_SURE_THREAD(callback, ...) \
20 if (!message_loop_proxy_->BelongsToCurrentThread()) { \
21 message_loop_proxy_->PostTask(FROM_HERE, base::Bind( \
22 &CastMetricsHelper::callback, \
23 base::Unretained(this), ##__VA_ARGS__)); \
24 return; \
25 }
26
27 namespace {
28
29 CastMetricsHelper* g_instance = NULL;
30
31 // Displayed frames are logged in frames per second (but sampling can be over
32 // a longer period of time, e.g. 5 seconds).
33 const int kDisplayedFramesPerSecondPeriod = 1000000;
34
35 // Sample every 5 seconds, represented in microseconds.
36 const int kNominalVideoSamplePeriod = 5000000;
37
38 } // namespace
39
40 CastMetricsHelper* CastMetricsHelper::GetInstance() {
41 DCHECK(g_instance);
42 return g_instance;
43 }
44
45 CastMetricsHelper::CastMetricsHelper(
46 scoped_refptr<base::MessageLoopProxy> message_loop_proxy)
47 : message_loop_proxy_(message_loop_proxy),
48 metrics_sink_(NULL) {
49 DCHECK(message_loop_proxy_.get());
50 DCHECK(!g_instance);
51 g_instance = this;
52 }
53
54 CastMetricsHelper::CastMetricsHelper()
55 : metrics_sink_(NULL) {
56 DCHECK(!g_instance);
57 g_instance = this;
58 }
59
60 CastMetricsHelper::~CastMetricsHelper() {
61 DCHECK_EQ(g_instance, this);
62 g_instance = NULL;
63 }
64
65 void CastMetricsHelper::TagAppStart(const std::string& arg_app_name) {
66 MAKE_SURE_THREAD(TagAppStart, arg_app_name);
67 app_name_ = arg_app_name;
68 app_start_time_ = base::TimeTicks::Now();
69 new_startup_time_ = true;
70 }
71
72 void CastMetricsHelper::LogMediaPlay() {
73 MAKE_SURE_THREAD(LogMediaPlay);
74 base::RecordComputedAction(GetMetricsNameWithAppName("MediaPlay", ""));
75 }
76
77 void CastMetricsHelper::LogMediaPause() {
78 MAKE_SURE_THREAD(LogMediaPause);
79 base::RecordComputedAction(GetMetricsNameWithAppName("MediaPause", ""));
80 }
81
82 void CastMetricsHelper::LogTimeToDisplayVideo() {
83 if (!new_startup_time_) { // For faster check.
84 return;
85 }
86 MAKE_SURE_THREAD(LogTimeToDisplayVideo);
87 new_startup_time_ = false;
88 base::TimeDelta launch_time = base::TimeTicks::Now() - app_start_time_;
89 const std::string uma_name(GetMetricsNameWithAppName("Startup",
90 "TimeToDisplayVideo"));
91 LogMediumTimeHistogramEvent(uma_name, launch_time);
92 LOG(INFO) << uma_name << " is " << launch_time.InSecondsF() << " seconds.";
93 }
94
95 void CastMetricsHelper::LogTimeToBufferAv(BufferingType buffering_type,
96 base::TimeDelta time) {
97 MAKE_SURE_THREAD(LogTimeToBufferAv, buffering_type, time);
98 if (time < base::TimeDelta::FromSeconds(0)) {
99 LOG(WARNING) << "Negative time";
100 return;
101 }
102
103 const std::string uma_name(GetMetricsNameWithAppName(
104 "Media",
105 (buffering_type == kInitialBuffering ? "TimeToBufferAv" :
106 buffering_type == kBufferingAfterUnderrun ?
107 "TimeToBufferAvAfterUnderrun" :
108 buffering_type == kAbortedBuffering ? "TimeToBufferAvAfterAbort" : "")));
109
110 // Histogram from 250ms to 30s with 50 buckets.
111 // The ratio between 2 consecutive buckets is:
112 // exp( (ln(30000) - ln(250)) / 50 ) = 1.1
113 LogTimeHistogramEvent(
114 uma_name,
115 time,
116 base::TimeDelta::FromMilliseconds(250),
117 base::TimeDelta::FromMilliseconds(30000),
118 50);
119 }
120
121 void CastMetricsHelper::ResetVideoFrameSampling() {
122 MAKE_SURE_THREAD(ResetVideoFrameSampling);
123 previous_video_stat_sample_time_ = base::TimeTicks();
124 }
125
126 void CastMetricsHelper::LogFramesPer5Seconds(int displayed_frames,
127 int dropped_frames,
128 int delayed_frames,
129 int error_frames) {
130 MAKE_SURE_THREAD(LogFramesPer5Seconds, displayed_frames, dropped_frames,
131 delayed_frames, error_frames);
132 base::TimeTicks sample_time = base::TimeTicks::Now();
133
134 if (!previous_video_stat_sample_time_.is_null()) {
135 base::TimeDelta time_diff = sample_time - previous_video_stat_sample_time_;
136 int value = 0;
137 const int64 rounding = time_diff.InMicroseconds() / 2;
138
139 if (displayed_frames >= 0) {
140 value = (displayed_frames * kDisplayedFramesPerSecondPeriod + rounding) /
141 time_diff.InMicroseconds();
142 LogEnumerationHistogramEvent(
143 GetMetricsNameWithAppName("Media", "DisplayedFramesPerSecond"),
144 value, 50);
145 }
146 if (delayed_frames >= 0) {
147 value = (delayed_frames * kNominalVideoSamplePeriod + rounding) /
148 time_diff.InMicroseconds();
149 LogEnumerationHistogramEvent(
150 GetMetricsNameWithAppName("Media", "DelayedVideoFramesPer5Sec"),
151 value, 50);
152 }
153 if (dropped_frames >= 0) {
154 value = (dropped_frames * kNominalVideoSamplePeriod + rounding) /
155 time_diff.InMicroseconds();
156 LogEnumerationHistogramEvent(
157 GetMetricsNameWithAppName("Media", "DroppedVideoFramesPer5Sec"),
158 value, 50);
159 }
160 if (error_frames >= 0) {
161 value = (error_frames * kNominalVideoSamplePeriod + rounding) /
162 time_diff.InMicroseconds();
163 LogEnumerationHistogramEvent(
164 GetMetricsNameWithAppName("Media", "ErrorVideoFramesPer5Sec"),
165 value, 50);
166 }
167 }
168
169 previous_video_stat_sample_time_ = sample_time;
170 }
171
172 std::string CastMetricsHelper::GetMetricsNameWithAppName(
173 const std::string& prefix,
174 const std::string& suffix) const {
175 DCHECK(message_loop_proxy_->BelongsToCurrentThread());
176 std::string metrics_name(prefix);
177 if (!app_name_.empty()) {
178 if (!metrics_name.empty())
179 metrics_name.push_back('.');
180 metrics_name.append(app_name_);
181 }
182 if (!suffix.empty()) {
183 if (!metrics_name.empty())
184 metrics_name.push_back('.');
185 metrics_name.append(suffix);
186 }
187 return metrics_name;
188 }
189
190 void CastMetricsHelper::SetMetricsSink(MetricsSink* delegate) {
191 MAKE_SURE_THREAD(SetMetricsSink, delegate);
192 metrics_sink_ = delegate;
193 }
194
195 void CastMetricsHelper::LogEnumerationHistogramEvent(
196 const std::string& name, int value, int num_buckets) {
197 MAKE_SURE_THREAD(LogEnumerationHistogramEvent, name, value, num_buckets);
198
199 if (metrics_sink_) {
200 metrics_sink_->OnEnumerationEvent(name, value, num_buckets);
201 } else {
202 UMA_HISTOGRAM_ENUMERATION_NO_CACHE(name, value, num_buckets);
203 }
204 }
205
206 void CastMetricsHelper::LogTimeHistogramEvent(const std::string& name,
207 const base::TimeDelta& value,
208 const base::TimeDelta& min,
209 const base::TimeDelta& max,
210 int num_buckets) {
211 MAKE_SURE_THREAD(LogTimeHistogramEvent, name, value, min, max, num_buckets);
212
213 if (metrics_sink_) {
214 metrics_sink_->OnTimeEvent(name, value, min, max, num_buckets);
215 } else {
216 UMA_HISTOGRAM_CUSTOM_TIMES_NO_CACHE(name, value, min, max, num_buckets);
217 }
218 }
219
220 void CastMetricsHelper::LogMediumTimeHistogramEvent(
221 const std::string& name,
222 const base::TimeDelta& value) {
223 // Follow UMA_HISTOGRAM_MEDIUM_TIMES definition.
224 LogTimeHistogramEvent(name, value,
225 base::TimeDelta::FromMilliseconds(10),
226 base::TimeDelta::FromMinutes(3),
227 50);
228 }
229
230 } // namespace metrics
231 } // namespace chromecast
OLDNEW
« no previous file with comments | « chromecast/base/metrics/cast_metrics_helper.h ('k') | chromecast/base/metrics/cast_metrics_test_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698