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.
9 from telemetry
.internal
.util
import camel_case
10 from telemetry
.value
import list_of_scalar_values
12 from metrics
import Metric
15 INTERESTING_METRICS
= {
18 'description': 'Packets received by the peer connection',
22 'description': 'Packets sent by the peer connection',
26 'description': 'Time spent decoding.',
30 'description': 'Maximum time spent decoding one frame.',
34 'description': 'Measured round-trip time.',
36 'googJitterReceived': {
38 'description': 'Receive-side jitter in milliseconds.',
40 'googCaptureJitterMs': {
42 'description': 'Capture device (audio/video) jitter.',
44 'googTargetDelayMs': {
46 'description': 'The delay we are targeting.',
50 'description': 'How much we have NetEQ-expanded the audio (0-100%)',
52 'googFrameRateReceived': {
54 'description': 'Receive-side frames per second (video)',
56 'googFrameRateSent': {
58 'description': 'Send-side frames per second (video)',
60 # Bandwidth estimation stats.
61 'googAvailableSendBandwidth': {
63 'description': 'How much send bandwidth we estimate we have.'
65 'googAvailableReceiveBandwidth': {
67 'description': 'How much receive bandwidth we estimate we have.'
69 'googTargetEncBitrate': {
71 'description': ('The target encoding bitrate we estimate is good to '
72 'aim for given our bandwidth estimates.')
74 'googTransmitBitrate': {
76 'description': 'The actual transmit bitrate.'
81 def GetReportKind(report
):
82 if 'audioInputLevel' in report
or 'audioOutputLevel' in report
:
84 if 'googFrameRateSent' in report
or 'googFrameRateReceived' in report
:
86 if 'googAvailableSendBandwidth' in report
:
89 logging
.debug('Did not recognize report batch: %s.', report
.keys())
91 # There are other kinds of reports, such as transport types, which we don't
92 # care about here. For these cases just return 'unknown' which will ignore the
97 def DistinguishAudioVideoOrBwe(report
, stat_name
):
98 return GetReportKind(report
) + '_' + stat_name
101 def StripAudioVideoBweDistinction(stat_name
):
102 return re
.sub('^(audio|video|bwe)_', '', stat_name
)
105 def SortStatsIntoTimeSeries(report_batches
):
107 for report_batch
in report_batches
:
108 for report
in report_batch
:
109 for stat_name
, value
in report
.iteritems():
110 if stat_name
not in INTERESTING_METRICS
:
112 if GetReportKind(report
) == 'unknown':
114 full_stat_name
= DistinguishAudioVideoOrBwe(report
, stat_name
)
115 time_series
.setdefault(full_stat_name
, []).append(float(value
))
120 class WebRtcStatisticsMetric(Metric
):
121 """Makes it possible to measure stats from peer connections."""
124 super(WebRtcStatisticsMetric
, self
).__init
__()
125 self
._all
_reports
= None
127 def Start(self
, page
, tab
):
130 def Stop(self
, page
, tab
):
131 """Digs out stats from data populated by the javascript in webrtc_cases."""
132 self
._all
_reports
= tab
.EvaluateJavaScript(
133 'JSON.stringify(window.peerConnectionReports)')
135 def AddResults(self
, tab
, results
):
136 if not self
._all
_reports
:
139 reports
= json
.loads(self
._all
_reports
)
140 for i
, report
in enumerate(reports
):
141 time_series
= SortStatsIntoTimeSeries(report
)
143 for stat_name
, values
in time_series
.iteritems():
144 stat_name_underscored
= camel_case
.ToUnderscore(stat_name
)
145 trace_name
= 'peer_connection_%d_%s' % (i
, stat_name_underscored
)
146 general_name
= StripAudioVideoBweDistinction(stat_name
)
147 results
.AddValue(list_of_scalar_values
.ListOfScalarValues(
148 results
.current_page
, trace_name
,
149 INTERESTING_METRICS
[general_name
]['units'], values
,
150 description
=INTERESTING_METRICS
[general_name
]['description'],