Commit ca001940 authored by jiayl@chromium.org's avatar jiayl@chromium.org

Gets the debug level stats for webrtc-internals.

This will enable displaying the BWE debug stats on chrome://webrtc-internals.
The JS is updated to special case the propagation delta value because the
value of the stat is a list and its timestamp is in the value of stat
receivedPacketGroupArrivalTime.

BUG=338380

Review URL: https://codereview.chromium.org/139473006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251795 0039d316-1c4b-4281-b951-d872f2087c98
parent f5bb29d2
......@@ -811,4 +811,54 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdateGetUserMedia) {
list.erase(list.begin());
VerifyUserMediaRequest(list);
}
// Tests that the received propagation delta values are converted and drawn
// correctly.
IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
ReceivedPropagationDelta) {
GURL url("chrome://webrtc-internals");
NavigateToURL(shell(), url);
PeerConnectionEntry pc(1, 0);
ExecuteAddPeerConnectionJs(pc);
StatsUnit stats = {FAKE_TIME_STAMP};
stats.values["googReceivedPacketGroupArrivalTimeDebug"] =
"[1000, 1100, 1200]";
stats.values["googReceivedPacketGroupPropagationDeltaDebug"] =
"[10, 20, 30]";
const string stats_type = "bwe";
const string stats_id = "videobwe";
ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
string graph_id = pc.getIdString() + "-" + stats_id +
"-googReceivedPacketGroupPropagationDeltaDebug";
string data_series_id =
stats_id + "-googReceivedPacketGroupPropagationDeltaDebug";
bool result = false;
// Verify that the graph exists.
ASSERT_TRUE(ExecuteScriptAndExtractBool(
shell()->web_contents(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'] != null)",
&result));
EXPECT_TRUE(result);
// Verify that the graph contains multiple data points.
int count = 0;
ASSERT_TRUE(ExecuteScriptAndExtractInt(
shell()->web_contents(),
"window.domAutomationController.send("
" graphViews['" + graph_id + "'].getDataSeriesCount())",
&count));
EXPECT_EQ(1, count);
ASSERT_TRUE(ExecuteScriptAndExtractInt(
shell()->web_contents(),
"window.domAutomationController.send("
" peerConnectionDataStore['" + pc.getIdString() + "']" +
" .getDataSeries('" + data_series_id + "').getCount())",
&count));
EXPECT_EQ(3, count);
}
} // namespace content
......@@ -76,6 +76,9 @@ var TimelineDataSeries = (function() {
this.color_ = color;
},
getCount: function() {
return this.dataPoints_.length;
},
/**
* Returns a list containing the values of the data series at |count|
* points, starting at |startTime|, and |stepSize| milliseconds apart.
......
......@@ -15,6 +15,11 @@
var STATS_GRAPH_CONTAINER_HEADING_CLASS = 'stats-graph-container-heading';
var RECEIVED_PROPAGATION_DELTA_LABEL =
'googReceivedPacketGroupPropagationDeltaDebug';
var RECEIVED_PACKET_GROUP_ARRIVAL_TIME_LABEL =
'googReceivedPacketGroupArrivalTimeDebug';
// Specifies which stats should be drawn on the 'bweCompound' graph and how.
var bweCompoundGraphConfig = {
googAvailableSendBandwidth: {color: 'red'},
......@@ -110,14 +115,22 @@ function drawSingleReport(peerConnectionElement, report) {
for (var i = 0; i < stats.values.length - 1; i = i + 2) {
var rawLabel = stats.values[i];
// Propagation deltas are handled separately.
if (rawLabel == RECEIVED_PROPAGATION_DELTA_LABEL) {
drawReceivedPropagationDelta(
peerConnectionElement, report, stats.values[i + 1]);
continue;
}
var rawDataSeriesId = reportId + '-' + rawLabel;
var rawValue = getNumberFromValue(rawLabel, stats.values[i + 1]);
if (isNaN(rawValue)) {
// We do not draw non-numerical values, but still want to record it in the
// data series.
addDataSeriesPoint(peerConnectionElement,
rawDataSeriesId, stats.timestamp,
rawLabel, stats.values[i + 1]);
addDataSeriesPoints(peerConnectionElement,
rawDataSeriesId,
rawLabel,
[stats.timestamp],
[stats.values[i + 1]]);
continue;
}
......@@ -127,9 +140,11 @@ function drawSingleReport(peerConnectionElement, report) {
// We need to convert the value if dataConversionConfig[rawLabel] exists.
if (dataConversionConfig[rawLabel]) {
// Updates the original dataSeries before the conversion.
addDataSeriesPoint(peerConnectionElement,
rawDataSeriesId, stats.timestamp,
rawLabel, rawValue);
addDataSeriesPoints(peerConnectionElement,
rawDataSeriesId,
rawLabel,
[stats.timestamp],
[rawValue]);
// Convert to another value to draw on graph, using the original
// dataSeries as input.
......@@ -141,11 +156,11 @@ function drawSingleReport(peerConnectionElement, report) {
}
// Updates the final dataSeries to draw.
addDataSeriesPoint(peerConnectionElement,
finalDataSeriesId,
stats.timestamp,
finalLabel,
finalValue);
addDataSeriesPoints(peerConnectionElement,
finalDataSeriesId,
finalLabel,
[stats.timestamp],
[finalValue]);
// Updates the graph.
var graphType = bweCompoundGraphConfig[finalLabel] ?
......@@ -172,9 +187,10 @@ function drawSingleReport(peerConnectionElement, report) {
}
// Makes sure the TimelineDataSeries with id |dataSeriesId| is created,
// and adds the new data point to it.
function addDataSeriesPoint(
peerConnectionElement, dataSeriesId, time, label, value) {
// and adds the new data points to it. |times| is the list of timestamps for
// each data point, and |values| is the list of the data point values.
function addDataSeriesPoints(
peerConnectionElement, dataSeriesId, label, times, values) {
var dataSeries =
peerConnectionDataStore[peerConnectionElement.id].getDataSeries(
dataSeriesId);
......@@ -186,7 +202,62 @@ function addDataSeriesPoint(
dataSeries.setColor(bweCompoundGraphConfig[label].color);
}
}
dataSeries.addPoint(time, value);
for (var i = 0; i < times.length; ++i)
dataSeries.addPoint(times[i], values[i]);
}
// Draws the received propagation deltas using the packet group arrival time as
// the x-axis. For example, |report.stats.values| should be like
// ['googReceivedPacketGroupArrivalTimeDebug', '[123456, 234455, 344566]',
// 'googReceivedPacketGroupPropagationDeltaDebug', '[23, 45, 56]', ...].
function drawReceivedPropagationDelta(peerConnectionElement, report, deltas) {
var reportId = report.id;
var stats = report.stats;
var times = null;
// Find the packet group arrival times.
for (var i = 0; i < stats.values.length - 1; i = i + 2) {
if (stats.values[i] == RECEIVED_PACKET_GROUP_ARRIVAL_TIME_LABEL) {
times = stats.values[i + 1];
break;
}
}
// Unexpected.
if (times == null)
return;
// Convert |deltas| and |times| from strings to arrays of numbers.
try {
deltas = JSON.parse(deltas);
times = JSON.parse(times);
} catch (e) {
console.log(e);
return;
}
// Update the data series.
var dataSeriesId = reportId + '-' + RECEIVED_PROPAGATION_DELTA_LABEL;
addDataSeriesPoints(
peerConnectionElement,
dataSeriesId,
RECEIVED_PROPAGATION_DELTA_LABEL,
times,
deltas);
// Update the graph.
var graphViewId = peerConnectionElement.id + '-' + reportId + '-' +
RECEIVED_PROPAGATION_DELTA_LABEL;
var date = new Date(times[times.length - 1]);
if (!graphViews[graphViewId]) {
graphViews[graphViewId] = createStatsGraphView(
peerConnectionElement,
report,
RECEIVED_PROPAGATION_DELTA_LABEL);
graphViews[graphViewId].setScale(10);
graphViews[graphViewId].setDateRange(date, date);
var dataSeries = peerConnectionDataStore[peerConnectionElement.id]
.getDataSeries(dataSeriesId);
graphViews[graphViewId].addDataSeries(dataSeries);
}
graphViews[graphViewId].updateEndDate(date);
}
// Ensures a div container to hold all stats graphs for one track is created as
......
......@@ -8,9 +8,6 @@
var TimelineGraphView = (function() {
'use strict';
// Default starting scale factor, in terms of milliseconds per pixel.
var DEFAULT_SCALE = 1000;
// Maximum number of labels placed vertically along the sides of the graph.
var MAX_VERTICAL_LABELS = 6;
......@@ -51,17 +48,24 @@ var TimelineGraphView = (function() {
this.graph_ = null;
// Horizontal scale factor, in terms of milliseconds per pixel.
this.scale_ = 1000;
// Initialize the scrollbar.
this.updateScrollbarRange_(true);
}
TimelineGraphView.prototype = {
setScale: function(scale) {
this.scale_ = scale;
},
// Returns the total length of the graph, in pixels.
getLength_: function() {
var timeRange = this.endTime_ - this.startTime_;
// Math.floor is used to ignore the last partial area, of length less
// than DEFAULT_SCALE.
return Math.floor(timeRange / DEFAULT_SCALE);
// than this.scale_.
return Math.floor(timeRange / this.scale_);
},
/**
......@@ -114,8 +118,8 @@ var TimelineGraphView = (function() {
* all the way to the right, keeps it all the way to the right. Otherwise,
* leaves the view as-is and doesn't redraw anything.
*/
updateEndDate: function() {
this.endTime_ = (new Date()).getTime();
updateEndDate: function(opt_date) {
this.endTime_ = opt_date || (new Date()).getTime();
this.updateScrollbarRange_(this.graphScrolledToRightEdge_());
},
......@@ -182,7 +186,7 @@ var TimelineGraphView = (function() {
// the graph to the end of the time range.
if (this.scrollbar_.range_ == 0)
position = this.getLength_() - this.canvas_.width;
var visibleStartTime = this.startTime_ + position * DEFAULT_SCALE;
var visibleStartTime = this.startTime_ + position * this.scale_;
// Make space at the bottom of the graph for the time labels, and then
// draw the labels.
......@@ -197,7 +201,7 @@ var TimelineGraphView = (function() {
if (this.graph_) {
// Layout graph and have them draw their tick marks.
this.graph_.layout(
width, height, fontHeight, visibleStartTime, DEFAULT_SCALE);
width, height, fontHeight, visibleStartTime, this.scale_);
this.graph_.drawTicks(context);
// Draw the lines of all graphs, and then draw their labels.
......@@ -229,7 +233,7 @@ var TimelineGraphView = (function() {
// Draw labels and vertical grid lines.
while (true) {
var x = Math.round((time - startTime) / DEFAULT_SCALE);
var x = Math.round((time - startTime) / this.scale_);
if (x >= width)
break;
var text = (new Date(time)).toLocaleTimeString();
......
......@@ -43,7 +43,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
virtual bool GetStats(webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track,
StatsOutputLevel level) OVERRIDE {
return false;
return GetStats(observer, track);
}
// Set Call this function to make sure next call to GetStats fail.
void SetGetStatsResult(bool result) { getstats_result_ = result; }
......
......@@ -245,7 +245,10 @@ void PeerConnectionTracker::OnGetAllStats() {
talk_base::scoped_refptr<InternalStatsObserver> observer(
new talk_base::RefCountedObject<InternalStatsObserver>(it->second));
it->first->GetStats(observer, NULL);
it->first->GetStats(
observer,
NULL,
webrtc::PeerConnectionInterface::kStatsOutputLevelDebug);
}
}
......
......@@ -608,13 +608,16 @@ void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
return;
}
}
GetStats(observer, track);
GetStats(observer,
track,
webrtc::PeerConnectionInterface::kStatsOutputLevelStandard);
}
void RTCPeerConnectionHandler::GetStats(
webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track) {
if (!native_peer_connection_->GetStats(observer, track)) {
webrtc::MediaStreamTrackInterface* track,
webrtc::PeerConnectionInterface::StatsOutputLevel level) {
if (!native_peer_connection_->GetStats(observer, track, level)) {
DVLOG(1) << "GetStats failed.";
// TODO(hta): Consider how to get an error back.
std::vector<webrtc::StatsReport> no_reports;
......
......@@ -162,7 +162,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// Calls GetStats on |native_peer_connection_|.
void GetStats(webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track);
webrtc::MediaStreamTrackInterface* track,
webrtc::PeerConnectionInterface::StatsOutputLevel level);
PeerConnectionTracker* peer_connection_tracker();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment