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

Unified 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromecast/base/metrics/cast_metrics_helper.cc
diff --git a/chromecast/base/metrics/cast_metrics_helper.cc b/chromecast/base/metrics/cast_metrics_helper.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e4923552e1ff328ae79a0e205c17eeb8efc0599d
--- /dev/null
+++ b/chromecast/base/metrics/cast_metrics_helper.cc
@@ -0,0 +1,231 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/base/metrics/cast_metrics_helper.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/user_metrics.h"
+#include "chromecast/base/metrics/cast_histograms.h"
+
+namespace chromecast {
+namespace metrics {
+
+// A useful macro to make sure current member function runs on the valid thread.
+#define MAKE_SURE_THREAD(callback, ...) \
+ if (!message_loop_proxy_->BelongsToCurrentThread()) { \
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind( \
+ &CastMetricsHelper::callback, \
+ base::Unretained(this), ##__VA_ARGS__)); \
+ return; \
+ }
+
+namespace {
+
+CastMetricsHelper* g_instance = NULL;
+
+// Displayed frames are logged in frames per second (but sampling can be over
+// a longer period of time, e.g. 5 seconds).
+const int kDisplayedFramesPerSecondPeriod = 1000000;
+
+// Sample every 5 seconds, represented in microseconds.
+const int kNominalVideoSamplePeriod = 5000000;
+
+} // namespace
+
+CastMetricsHelper* CastMetricsHelper::GetInstance() {
+ DCHECK(g_instance);
+ return g_instance;
+}
+
+CastMetricsHelper::CastMetricsHelper(
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy)
+ : message_loop_proxy_(message_loop_proxy),
+ metrics_sink_(NULL) {
+ DCHECK(message_loop_proxy_.get());
+ DCHECK(!g_instance);
+ g_instance = this;
+}
+
+CastMetricsHelper::CastMetricsHelper()
+ : metrics_sink_(NULL) {
+ DCHECK(!g_instance);
+ g_instance = this;
+}
+
+CastMetricsHelper::~CastMetricsHelper() {
+ DCHECK_EQ(g_instance, this);
+ g_instance = NULL;
+}
+
+void CastMetricsHelper::TagAppStart(const std::string& arg_app_name) {
+ MAKE_SURE_THREAD(TagAppStart, arg_app_name);
+ app_name_ = arg_app_name;
+ app_start_time_ = base::TimeTicks::Now();
+ new_startup_time_ = true;
+}
+
+void CastMetricsHelper::LogMediaPlay() {
+ MAKE_SURE_THREAD(LogMediaPlay);
+ base::RecordComputedAction(GetMetricsNameWithAppName("MediaPlay", ""));
+}
+
+void CastMetricsHelper::LogMediaPause() {
+ MAKE_SURE_THREAD(LogMediaPause);
+ base::RecordComputedAction(GetMetricsNameWithAppName("MediaPause", ""));
+}
+
+void CastMetricsHelper::LogTimeToDisplayVideo() {
+ if (!new_startup_time_) { // For faster check.
+ return;
+ }
+ MAKE_SURE_THREAD(LogTimeToDisplayVideo);
+ new_startup_time_ = false;
+ base::TimeDelta launch_time = base::TimeTicks::Now() - app_start_time_;
+ const std::string uma_name(GetMetricsNameWithAppName("Startup",
+ "TimeToDisplayVideo"));
+ LogMediumTimeHistogramEvent(uma_name, launch_time);
+ LOG(INFO) << uma_name << " is " << launch_time.InSecondsF() << " seconds.";
+}
+
+void CastMetricsHelper::LogTimeToBufferAv(BufferingType buffering_type,
+ base::TimeDelta time) {
+ MAKE_SURE_THREAD(LogTimeToBufferAv, buffering_type, time);
+ if (time < base::TimeDelta::FromSeconds(0)) {
+ LOG(WARNING) << "Negative time";
+ return;
+ }
+
+ const std::string uma_name(GetMetricsNameWithAppName(
+ "Media",
+ (buffering_type == kInitialBuffering ? "TimeToBufferAv" :
+ buffering_type == kBufferingAfterUnderrun ?
+ "TimeToBufferAvAfterUnderrun" :
+ buffering_type == kAbortedBuffering ? "TimeToBufferAvAfterAbort" : "")));
+
+ // Histogram from 250ms to 30s with 50 buckets.
+ // The ratio between 2 consecutive buckets is:
+ // exp( (ln(30000) - ln(250)) / 50 ) = 1.1
+ LogTimeHistogramEvent(
+ uma_name,
+ time,
+ base::TimeDelta::FromMilliseconds(250),
+ base::TimeDelta::FromMilliseconds(30000),
+ 50);
+}
+
+void CastMetricsHelper::ResetVideoFrameSampling() {
+ MAKE_SURE_THREAD(ResetVideoFrameSampling);
+ previous_video_stat_sample_time_ = base::TimeTicks();
+}
+
+void CastMetricsHelper::LogFramesPer5Seconds(int displayed_frames,
+ int dropped_frames,
+ int delayed_frames,
+ int error_frames) {
+ MAKE_SURE_THREAD(LogFramesPer5Seconds, displayed_frames, dropped_frames,
+ delayed_frames, error_frames);
+ base::TimeTicks sample_time = base::TimeTicks::Now();
+
+ if (!previous_video_stat_sample_time_.is_null()) {
+ base::TimeDelta time_diff = sample_time - previous_video_stat_sample_time_;
+ int value = 0;
+ const int64 rounding = time_diff.InMicroseconds() / 2;
+
+ if (displayed_frames >= 0) {
+ value = (displayed_frames * kDisplayedFramesPerSecondPeriod + rounding) /
+ time_diff.InMicroseconds();
+ LogEnumerationHistogramEvent(
+ GetMetricsNameWithAppName("Media", "DisplayedFramesPerSecond"),
+ value, 50);
+ }
+ if (delayed_frames >= 0) {
+ value = (delayed_frames * kNominalVideoSamplePeriod + rounding) /
+ time_diff.InMicroseconds();
+ LogEnumerationHistogramEvent(
+ GetMetricsNameWithAppName("Media", "DelayedVideoFramesPer5Sec"),
+ value, 50);
+ }
+ if (dropped_frames >= 0) {
+ value = (dropped_frames * kNominalVideoSamplePeriod + rounding) /
+ time_diff.InMicroseconds();
+ LogEnumerationHistogramEvent(
+ GetMetricsNameWithAppName("Media", "DroppedVideoFramesPer5Sec"),
+ value, 50);
+ }
+ if (error_frames >= 0) {
+ value = (error_frames * kNominalVideoSamplePeriod + rounding) /
+ time_diff.InMicroseconds();
+ LogEnumerationHistogramEvent(
+ GetMetricsNameWithAppName("Media", "ErrorVideoFramesPer5Sec"),
+ value, 50);
+ }
+ }
+
+ previous_video_stat_sample_time_ = sample_time;
+}
+
+std::string CastMetricsHelper::GetMetricsNameWithAppName(
+ const std::string& prefix,
+ const std::string& suffix) const {
+ DCHECK(message_loop_proxy_->BelongsToCurrentThread());
+ std::string metrics_name(prefix);
+ if (!app_name_.empty()) {
+ if (!metrics_name.empty())
+ metrics_name.push_back('.');
+ metrics_name.append(app_name_);
+ }
+ if (!suffix.empty()) {
+ if (!metrics_name.empty())
+ metrics_name.push_back('.');
+ metrics_name.append(suffix);
+ }
+ return metrics_name;
+}
+
+void CastMetricsHelper::SetMetricsSink(MetricsSink* delegate) {
+ MAKE_SURE_THREAD(SetMetricsSink, delegate);
+ metrics_sink_ = delegate;
+}
+
+void CastMetricsHelper::LogEnumerationHistogramEvent(
+ const std::string& name, int value, int num_buckets) {
+ MAKE_SURE_THREAD(LogEnumerationHistogramEvent, name, value, num_buckets);
+
+ if (metrics_sink_) {
+ metrics_sink_->OnEnumerationEvent(name, value, num_buckets);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION_NO_CACHE(name, value, num_buckets);
+ }
+}
+
+void CastMetricsHelper::LogTimeHistogramEvent(const std::string& name,
+ const base::TimeDelta& value,
+ const base::TimeDelta& min,
+ const base::TimeDelta& max,
+ int num_buckets) {
+ MAKE_SURE_THREAD(LogTimeHistogramEvent, name, value, min, max, num_buckets);
+
+ if (metrics_sink_) {
+ metrics_sink_->OnTimeEvent(name, value, min, max, num_buckets);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_TIMES_NO_CACHE(name, value, min, max, num_buckets);
+ }
+}
+
+void CastMetricsHelper::LogMediumTimeHistogramEvent(
+ const std::string& name,
+ const base::TimeDelta& value) {
+ // Follow UMA_HISTOGRAM_MEDIUM_TIMES definition.
+ LogTimeHistogramEvent(name, value,
+ base::TimeDelta::FromMilliseconds(10),
+ base::TimeDelta::FromMinutes(3),
+ 50);
+}
+
+} // namespace metrics
+} // namespace chromecast
« 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