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.
5 #include "remoting/client/chromoting_stats.h"
6 #include "remoting/proto/video.pb.h"
10 // We take the last 10 latency numbers and report the average.
11 const int kLatencySampleSize
= 10;
13 // UMA histogram names.
14 const char kRoundTripLatencyHistogram
[] = "Chromoting.Video.RoundTripLatency";
15 const char kVideoCaptureLatencyHistogram
[] = "Chromoting.Video.CaptureLatency";
16 const char kVideoEncodeLatencyHistogram
[] = "Chromoting.Video.EncodeLatency";
17 const char kVideoDecodeLatencyHistogram
[] = "Chromoting.Video.DecodeLatency";
18 const char kVideoPaintLatencyHistogram
[] = "Chromoting.Video.PaintLatency";
19 const char kVideoFrameRateHistogram
[] = "Chromoting.Video.FrameRate";
20 const char kVideoPacketRateHistogram
[] = "Chromoting.Video.PacketRate";
21 const char kVideoBandwidthHistogram
[] = "Chromoting.Video.Bandwidth";
23 // Custom count and custom time histograms are log-scaled by default. This
24 // results in fine-grained buckets at lower values and wider-ranged buckets
25 // closer to the maximum.
26 // The values defined for each histogram below are based on the 99th percentile
27 // numbers for the corresponding metric over a recent 28-day period.
28 // Values above the maximum defined for a histogram end up in the max-bucket.
29 // If the minimum for a UMA histogram is set to be < 1, it is implicitly
31 // See $/src/base/metrics/histogram.h for more details.
33 // Video-specific metrics are stored in a custom times histogram.
34 const int kVideoActionsHistogramsMinMs
= 1;
35 const int kVideoActionsHistogramsMaxMs
= 250;
36 const int kVideoActionsHistogramsBuckets
= 50;
38 // Round-trip latency values are stored in a custom times histogram.
39 const int kLatencyHistogramMinMs
= 1;
40 const int kLatencyHistogramMaxMs
= 20000;
41 const int kLatencyHistogramBuckets
= 50;
43 // Bandwidth statistics are stored in a custom counts histogram.
44 const int kBandwidthHistogramMinBps
= 0;
45 const int kBandwidthHistogramMaxBps
= 10 * 1000 * 1000;
46 const int kBandwidthHistogramBuckets
= 100;
48 // Frame rate is stored in a custom enum histogram, because we we want to record
49 // the frequency of each discrete value, rather than using log-scaled buckets.
50 // We don't expect video frame rate to be greater than 40fps. Setting a maximum
51 // of 100fps will leave some room for future improvements, and account for any
52 // bursts of packets. Enum histograms expect samples to be less than the
53 // boundary value, so set to 101.
54 const int kMaxFramesPerSec
= 101;
59 ChromotingStats::ChromotingStats()
61 base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds
)),
63 base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds
)),
65 base::TimeDelta::FromSeconds(kStatsUpdateFrequencyInSeconds
)),
66 video_capture_ms_(kLatencySampleSize
),
67 video_encode_ms_(kLatencySampleSize
),
68 video_decode_ms_(kLatencySampleSize
),
69 video_paint_ms_(kLatencySampleSize
),
70 round_trip_ms_(kLatencySampleSize
) {}
72 ChromotingStats::~ChromotingStats() {
75 void ChromotingStats::SetUpdateUmaCallbacks(
76 UpdateUmaCustomHistogramCallback update_uma_custom_counts_callback
,
77 UpdateUmaCustomHistogramCallback update_uma_custom_times_callback
,
78 UpdateUmaEnumHistogramCallback update_uma_enum_histogram_callback
) {
79 uma_custom_counts_updater_
= update_uma_custom_counts_callback
;
80 uma_custom_times_updater_
= update_uma_custom_times_callback
;
81 uma_enum_histogram_updater_
= update_uma_enum_histogram_callback
;
84 void ChromotingStats::RecordVideoPacketStats(const VideoPacket
& packet
) {
85 // Record this received packet, even if it is empty.
86 video_packet_rate_
.Record(1);
88 // Record the RTT, even for empty packets, otherwise input events that
89 // do not cause an on-screen change can give very large, bogus RTTs.
90 if (packet
.has_latest_event_timestamp() &&
91 packet
.latest_event_timestamp() > latest_input_event_timestamp_
) {
92 latest_input_event_timestamp_
= packet
.latest_event_timestamp();
94 base::TimeDelta round_trip_latency
=
96 base::Time::FromInternalValue(packet
.latest_event_timestamp());
98 round_trip_ms_
.Record(round_trip_latency
.InMilliseconds());
100 if (!uma_custom_times_updater_
.is_null())
101 uma_custom_times_updater_
.Run(
102 kRoundTripLatencyHistogram
, round_trip_latency
.InMilliseconds(),
103 kLatencyHistogramMinMs
, kLatencyHistogramMaxMs
,
104 kLatencyHistogramBuckets
);
107 // If the packet is empty, there are no other stats to update.
108 if (!packet
.data().size())
111 video_frame_rate_
.Record(1);
112 video_bandwidth_
.Record(packet
.data().size());
114 if (packet
.has_capture_time_ms()) {
115 video_capture_ms_
.Record(packet
.capture_time_ms());
116 if (!uma_custom_times_updater_
.is_null())
117 uma_custom_times_updater_
.Run(
118 kVideoCaptureLatencyHistogram
, packet
.capture_time_ms(),
119 kVideoActionsHistogramsMinMs
, kVideoActionsHistogramsMaxMs
,
120 kVideoActionsHistogramsBuckets
);
123 if (packet
.has_encode_time_ms()) {
124 video_encode_ms_
.Record(packet
.encode_time_ms());
125 if (!uma_custom_times_updater_
.is_null())
126 uma_custom_times_updater_
.Run(
127 kVideoEncodeLatencyHistogram
, packet
.encode_time_ms(),
128 kVideoActionsHistogramsMinMs
, kVideoActionsHistogramsMaxMs
,
129 kVideoActionsHistogramsBuckets
);
133 void ChromotingStats::RecordDecodeTime(double value
) {
134 video_decode_ms_
.Record(value
);
135 if (!uma_custom_times_updater_
.is_null())
136 uma_custom_times_updater_
.Run(
137 kVideoDecodeLatencyHistogram
, value
, kVideoActionsHistogramsMinMs
,
138 kVideoActionsHistogramsMaxMs
, kVideoActionsHistogramsBuckets
);
141 void ChromotingStats::RecordPaintTime(double value
) {
142 video_paint_ms_
.Record(value
);
143 if (!uma_custom_times_updater_
.is_null())
144 uma_custom_times_updater_
.Run(
145 kVideoPaintLatencyHistogram
, value
, kVideoActionsHistogramsMinMs
,
146 kVideoActionsHistogramsMaxMs
, kVideoActionsHistogramsBuckets
);
149 void ChromotingStats::UploadRateStatsToUma() {
150 if (!uma_enum_histogram_updater_
.is_null()) {
151 uma_enum_histogram_updater_
.Run(kVideoFrameRateHistogram
,
152 video_frame_rate(), kMaxFramesPerSec
);
153 uma_enum_histogram_updater_
.Run(kVideoPacketRateHistogram
,
154 video_packet_rate(), kMaxFramesPerSec
);
155 uma_custom_counts_updater_
.Run(
156 kVideoBandwidthHistogram
, video_bandwidth(), kBandwidthHistogramMinBps
,
157 kBandwidthHistogramMaxBps
, kBandwidthHistogramBuckets
);
161 } // namespace remoting