From 5be8c330546687b9723ab8fb5cad81da6dd90903 Mon Sep 17 00:00:00 2001 From: isymchych Date: Thu, 5 Nov 2015 18:53:15 +0200 Subject: [PATCH] report webrtc errors to callstats --- modules/RTC/RTC.js | 4 +- modules/RTC/RTCUtils.js | 6 ++- modules/statistics/CallStats.js | 72 +++++++++++++++++++++++-- modules/statistics/statistics.js | 19 +++++++ modules/xmpp/JingleSessionPC.js | 2 + modules/xmpp/TraceablePeerConnection.js | 12 +++-- service/RTC/RTCEvents.js | 6 +++ 7 files changed, 110 insertions(+), 11 deletions(-) diff --git a/modules/RTC/RTC.js b/modules/RTC/RTC.js index 59e4e1e34..363573e38 100644 --- a/modules/RTC/RTC.js +++ b/modules/RTC/RTC.js @@ -166,7 +166,7 @@ var RTC = { null, null, getMediaStreamUsage()); }; - this.rtcUtils = new RTCUtils(this, onReady); + this.rtcUtils = new RTCUtils(this, eventEmitter, onReady); // Call onReady() if Temasys plugin is not used if (!RTCBrowserType.isTemasysPluginUsed()) { @@ -199,7 +199,7 @@ var RTC = { APP.xmpp.setVideoMute(false, function(mute) { eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute); }); - + callback(); }; } diff --git a/modules/RTC/RTCUtils.js b/modules/RTC/RTCUtils.js index e8448ae7a..28bb566c6 100644 --- a/modules/RTC/RTCUtils.js +++ b/modules/RTC/RTCUtils.js @@ -4,6 +4,7 @@ /* jshint -W101 */ var RTCBrowserType = require("./RTCBrowserType"); var Resolutions = require("../../service/RTC/Resolutions"); +var RTCEvents = require("../../service/RTC/RTCEvents"); var AdapterJS = require("./adapter.screenshare"); var currentResolution = null; @@ -152,10 +153,11 @@ function getConstraints(um, resolution, bandwidth, fps, desktopStream) { } -function RTCUtils(RTCService, onTemasysPluginReady) +function RTCUtils(RTCService, eventEmitter, onTemasysPluginReady) { var self = this; this.service = RTCService; + this.eventEmitter = eventEmitter; if (RTCBrowserType.isFirefox()) { var FFversion = RTCBrowserType.getFirefoxVersion(); if (FFversion >= 40) { @@ -321,12 +323,14 @@ RTCUtils.prototype.getUserMediaWithConstraints = function( self.setAvailableDevices(um, false); console.warn('Failed to get access to local media. Error ', error, constraints); + self.eventEmitter.emit(RTCEvents.GET_USER_MEDIA_FAILED, error); if (failure_callback) { failure_callback(error); } }); } catch (e) { console.error('GUM failed: ', e); + self.eventEmitter.emit(RTCEvents.GET_USER_MEDIA_FAILED, e); if(failure_callback) { failure_callback(e); } diff --git a/modules/statistics/CallStats.js b/modules/statistics/CallStats.js index 957d3bd3f..7abe75420 100644 --- a/modules/statistics/CallStats.js +++ b/modules/statistics/CallStats.js @@ -5,6 +5,11 @@ var jsSHA = require('jssha'); var io = require('socket.io-client'); var callStats = null; +// getUserMedia calls happen before CallStats init +// so if there are any getUserMedia errors, we store them in this array +// and send them to callstats on init +var pendingUserMediaErrors = []; + function initCallback (err, msg) { console.log("Initializing Status: err="+err+" msg="+msg); } @@ -42,17 +47,25 @@ var CallStats = { usage, this.confID, this.pcCallback.bind(this)); + + // notify callstats about getUserMedia failures if there were any + if (pendingUserMediaErrors.length) { + pendingUserMediaErrors.forEach(this.sendGetUserMediaFailed, this); + pendingUserMediaErrors.length = 0; + } }, pcCallback: function (err, msg) { - if (!callStats) + if (!callStats) { return; + } console.log("Monitoring status: "+ err + " msg: " + msg); callStats.sendFabricEvent(this.peerconnection, callStats.fabricEvent.fabricSetup, this.confID); }, sendMuteEvent: function (mute, type) { - if (!callStats) + if (!callStats) { return; + } var event = null; if (type === "video") { event = (mute? callStats.fabricEvent.videoPause : @@ -78,7 +91,8 @@ var CallStats = { callStats.sendFabricEvent(this.peerconnection, callStats.fabricEvent.fabricSetupFailed, this.confID); }, - /** + + /** * Sends the given feedback through CallStats. * * @param overallFeedback an integer between 1 and 5 indicating the @@ -97,6 +111,56 @@ var CallStats = { callStats.sendUserFeedback( this.confID, feedbackJSON); - } + }, + + sendGetUserMediaFailed: function (e) { + if(!callStats) { + pendingUserMediaErrors.push(e); + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.getUserMedia, e); + }, + + sendCreateOfferFailed: function (e) { + if(!callStats) { + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.createOffer, e); + }, + + sendCreateAnswerFailed: function (e) { + if(!callStats) { + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.createAnswer, e); + }, + + sendSetLocalDescFailed: function (e) { + if(!callStats) { + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.setLocalDescription, e); + }, + + sendSetRemoteDescFailed: function (e) { + if(!callStats) { + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.setRemoteDescription, e); + }, + + sendAddIceCandidateFailed: function (e) { + if(!callStats) { + return; + } + callStats.reportError(this.peerconnection, this.confID, + callStats.webRTCFunctions.addIceCandidate, e); + }, + }; module.exports = CallStats; \ No newline at end of file diff --git a/modules/statistics/statistics.js b/modules/statistics/statistics.js index 5685cbd78..1c0c01913 100644 --- a/modules/statistics/statistics.js +++ b/modules/statistics/statistics.js @@ -109,6 +109,25 @@ var statistics = { APP.RTC.addListener(RTCEvents.VIDEO_MUTE, function (mute) { CallStats.sendMuteEvent(mute, "video"); }); + + APP.RTC.addListener(RTCEvents.GET_USER_MEDIA_FAILED, function (e) { + CallStats.sendGetUserMediaFailed(e); + }); + APP.xmpp.addListener(RTCEvents.CREATE_OFFER_FAILED, function (e) { + CallStats.sendCreateOfferFailed(e); + }); + APP.xmpp.addListener(RTCEvents.CREATE_ANSWER_FAILED, function (e) { + CallStats.sendCreateAnswerFailed(e); + }); + APP.xmpp.addListener(RTCEvents.SET_LOCAL_DESCRIPTION_FAILED, function (e) { + CallStats.sendSetLocalDescFailed(e); + }); + APP.xmpp.addListener(RTCEvents.SET_REMOTE_DESCRIPTION_FAILED, function (e) { + CallStats.sendSetRemoteDescFailed(e); + }); + APP.xmpp.addListener(RTCEvents.ADD_ICE_CANDIDATE_FAILED, function (e) { + CallStats.sendAddIceCandidateFailed(e); + }); } }; diff --git a/modules/xmpp/JingleSessionPC.js b/modules/xmpp/JingleSessionPC.js index b5beaeefd..a7857f9f7 100644 --- a/modules/xmpp/JingleSessionPC.js +++ b/modules/xmpp/JingleSessionPC.js @@ -8,6 +8,7 @@ var SDP = require("./SDP"); var async = require("async"); var transform = require("sdp-transform"); var XMPPEvents = require("../../service/xmpp/XMPPEvents"); +var RTCEvents = require("../../service/RTC/RTCEvents"); var RTCBrowserType = require("../RTC/RTCBrowserType"); var SSRCReplacement = require("./LocalSSRCReplacement"); @@ -720,6 +721,7 @@ JingleSessionPC.prototype.addIceCandidate = function (elem) { self.peerconnection.addIceCandidate(candidate); } catch (e) { console.error('addIceCandidate failed', e.toString(), line); + self.eventEmitter.emit(RTCEvents.ADD_ICE_CANDIDATE_FAILED, err); } }); }); diff --git a/modules/xmpp/TraceablePeerConnection.js b/modules/xmpp/TraceablePeerConnection.js index f1486bc66..4e05a2811 100644 --- a/modules/xmpp/TraceablePeerConnection.js +++ b/modules/xmpp/TraceablePeerConnection.js @@ -2,8 +2,8 @@ webkitRTCPeerConnection, RTCSessionDescription */ /* jshint -W101 */ var RTC = require('../RTC/RTC'); -var RTCBrowserType = require("../RTC/RTCBrowserType.js"); -var XMPPEvents = require("../../service/xmpp/XMPPEvents"); +var RTCBrowserType = require("../RTC/RTCBrowserType"); +var RTCEvents = require("../../service/RTC/RTCEvents"); var SSRCReplacement = require("./LocalSSRCReplacement"); function TraceablePeerConnection(ice_config, constraints, session) { @@ -16,6 +16,7 @@ function TraceablePeerConnection(ice_config, constraints, session) { } else { RTCPeerConnectionType = webkitRTCPeerConnection; } + self.eventEmitter = session.eventEmitter; this.peerconnection = new RTCPeerConnectionType(ice_config, constraints); this.updateLog = []; this.stats = {}; @@ -218,7 +219,7 @@ if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { var desc = this.peerconnection.localDescription; desc = SSRCReplacement.mungeLocalVideoSSRC(desc); - + this.trace('getLocalDescription::preTransform', dumpSDP(desc)); // if we're running on FF, transform to Plan B first. @@ -292,6 +293,7 @@ TraceablePeerConnection.prototype.setLocalDescription }, function (err) { self.trace('setLocalDescriptionOnFailure', err); + self.eventEmitter.emit(RTCEvents.SET_LOCAL_DESCRIPTION_FAILED, err); failureCallback(err); } ); @@ -327,6 +329,7 @@ TraceablePeerConnection.prototype.setRemoteDescription }, function (err) { self.trace('setRemoteDescriptionOnFailure', err); + self.eventEmitter.emit(RTCEvents.SET_REMOTE_DESCRIPTION_FAILED, err); failureCallback(err); } ); @@ -372,6 +375,7 @@ TraceablePeerConnection.prototype.createOffer }, function(err) { self.trace('createOfferOnFailure', err); + self.eventEmitter.emit(RTCEvents.CREATE_OFFER_FAILED, err); failureCallback(err); }, constraints @@ -402,6 +406,7 @@ TraceablePeerConnection.prototype.createAnswer }, function(err) { self.trace('createAnswerOnFailure', err); + self.eventEmitter.emit(RTCEvents.CREATE_ANSWER_FAILED, err); failureCallback(err); }, constraints @@ -440,4 +445,3 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) { }; module.exports = TraceablePeerConnection; - diff --git a/service/RTC/RTCEvents.js b/service/RTC/RTCEvents.js index bbcc4d8d4..8f150163e 100644 --- a/service/RTC/RTCEvents.js +++ b/service/RTC/RTCEvents.js @@ -1,6 +1,12 @@ var RTCEvents = { RTC_READY: "rtc.ready", DATA_CHANNEL_OPEN: "rtc.data_channel_open", + CREATE_OFFER_FAILED: "rtc.create_offer_failed", + CREATE_ANSWER_FAILED: "rtc.create_answer_failed", + SET_LOCAL_DESCRIPTION_FAILED: "rtc.set_local_description_failed", + SET_REMOTE_DESCRIPTION_FAILED: "rtc.set_remote_description_failed", + ADD_ICE_CANDIDATE_FAILED: "rtc.add_ice_candidate_failed", + GET_USER_MEDIA_FAILED: "rtc.get_user_media_failed", LASTN_CHANGED: "rtc.lastn_changed", DOMINANTSPEAKER_CHANGED: "rtc.dominantspeaker_changed", LASTN_ENDPOINT_CHANGED: "rtc.lastn_endpoint_changed",