diff --git a/JitsiConference.js b/JitsiConference.js
index c7ca319c17..c0259818b4 100644
--- a/JitsiConference.js
+++ b/JitsiConference.js
@@ -472,13 +472,8 @@ JitsiConference.prototype._init = function(options = {}) {
userName: config.statisticsDisplayName ? config.statisticsDisplayName : this.myUserId(),
confID: config.confID || `${this.connection.options.hosts.domain}/${this.options.name}`,
siteID: config.siteID,
- customScriptUrl: config.callStatsCustomScriptUrl,
- callStatsID: config.callStatsID,
- callStatsSecret: config.callStatsSecret,
- callStatsApplicationLogsDisabled: config.callStatsApplicationLogsDisabled,
roomName: this.options.name,
- applicationName: config.applicationName,
- configParams: config.callStatsConfigParams
+ applicationName: config.applicationName
});
Statistics.analytics.addPermanentProperties({
'callstats_name': this._statsCurrentId
@@ -1237,13 +1232,6 @@ JitsiConference.prototype.onLocalTrackRemoved = function(track) {
track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);
}
- // send event for stopping screen sharing
- // FIXME: we assume we have only one screen sharing track
- // if we change this we need to fix this check
- if (track.isVideoTrack() && track.videoType === VideoType.DESKTOP) {
- this.statistics.sendScreenSharingEvent(false);
- }
-
this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
};
@@ -1381,17 +1369,6 @@ JitsiConference.prototype._removeLocalSourceOnReject = function(jingleSession, e
JitsiConference.prototype._setupNewTrack = function(newTrack) {
const mediaType = newTrack.getType();
- if (newTrack.isAudioTrack() || (newTrack.isVideoTrack() && newTrack.videoType !== VideoType.DESKTOP)) {
- // Report active device to statistics
- const devices = RTC.getCurrentlyAvailableMediaDevices();
- const device = devices
- .find(d => d.kind === `${newTrack.getTrack().kind}input` && d.label === newTrack.getTrack().label);
-
- if (device) {
- Statistics.sendActiveDeviceListEvent(RTC.getEventDataForActiveDevice(device));
- }
- }
-
// Create a source name for this track if it doesn't exist.
if (!newTrack.getSourceName()) {
const sourceName = getSourceNameForJitsiTrack(
@@ -2256,14 +2233,6 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(jingleSession, jingl
this._desktopSharingFrameRate
&& jingleSession.peerconnection.setDesktopSharingFrameRate(this._desktopSharingFrameRate);
- // Start callstats as soon as peerconnection is initialized,
- // do not wait for XMPPEvents.PEERCONNECTION_READY, as it may never
- // happen in case if user doesn't have or denied permission to
- // both camera and microphone.
- logger.info('Starting CallStats for JVB connection...');
- this.statistics.startCallStats(
- this.jvbJingleSession.peerconnection,
- 'jitsi' /* Remote user ID for JVB is 'jitsi' */);
this.statistics.startRemoteStats(this.jvbJingleSession.peerconnection);
} catch (e) {
GlobalOnErrorHandler.callErrorHandler(e);
@@ -2377,11 +2346,7 @@ JitsiConference.prototype.onCallEnded = function(jingleSession, reasonCondition,
// Stop the stats
if (this.statistics) {
- this.statistics.stopRemoteStats(
- this.jvbJingleSession.peerconnection);
- logger.info('Stopping JVB CallStats');
- this.statistics.stopCallStats(
- this.jvbJingleSession.peerconnection);
+ this.statistics.stopRemoteStats(this.jvbJingleSession.peerconnection);
}
// Current JVB JingleSession is no longer valid, so set it to null
@@ -2694,7 +2659,7 @@ JitsiConference.prototype.getLocalParticipantProperty = function(name) {
};
/**
- * Sends the given feedback through CallStats if enabled.
+ * Sends the given feedback if enabled.
*
* @param overallFeedback an integer between 1 and 5 indicating the
* user feedback
@@ -2706,14 +2671,13 @@ JitsiConference.prototype.sendFeedback = function(overallFeedback, detailedFeedb
};
/**
- * Returns true if the callstats integration is enabled, otherwise returns
- * false.
- *
- * @returns true if the callstats integration is enabled, otherwise returns
- * false.
+ * @returns false, since callstats in not supported anymore.
+ * @deprecated
*/
JitsiConference.prototype.isCallstatsEnabled = function() {
- return this.statistics.isCallstatsEnabled();
+ logger.warn('Callstats is no longer supported');
+
+ return false;
};
/**
@@ -2727,52 +2691,10 @@ JitsiConference.prototype.getSsrcByTrack = function(track) {
};
/**
- * Handles track attached to container (Calls associateStreamWithVideoTag method
- * from statistics module)
- * @param {JitsiLocalTrack|JitsiRemoteTrack} track the track
- * @param container the container
+ * This is a no-op since callstats is no longer supported.
*/
-JitsiConference.prototype._onTrackAttach = function(track, container) {
- const isLocal = track.isLocal();
- let ssrc = null;
- const isP2P = track.isP2P;
- const remoteUserId = isP2P ? track.getParticipantId() : 'jitsi';
- const peerConnection
- = isP2P
- ? this.p2pJingleSession && this.p2pJingleSession.peerconnection
- : this.jvbJingleSession && this.jvbJingleSession.peerconnection;
-
- if (isLocal) {
- // Local tracks have SSRC stored on per peer connection basis.
- if (peerConnection) {
- ssrc = peerConnection.getLocalSSRC(track);
- }
- } else {
- ssrc = track.getSSRC();
- }
- if (!container.id || !ssrc || !peerConnection) {
- return;
- }
-
- this.statistics.associateStreamWithVideoTag(
- peerConnection,
- ssrc,
- isLocal,
- remoteUserId,
- track.getUsageLabel(),
- container.id);
-};
-
-/**
- * Logs an "application log" message.
- * @param message {string} The message to log. Note that while this can be a
- * generic string, the convention used by lib-jitsi-meet and jitsi-meet is to
- * log valid JSON strings, with an "id" field used for distinguishing between
- * message types. E.g.: {id: "recorder_status", status: "off"}
- */
-JitsiConference.prototype.sendApplicationLog = function(message) {
- Statistics.sendLog(message);
-};
+// eslint-disable-next-line no-empty-function
+JitsiConference.prototype.sendApplicationLog = function() { };
/**
* Checks if the user identified by given mucJid is the conference focus.
@@ -2996,20 +2918,6 @@ JitsiConference.prototype._acceptP2PIncomingCall = function(jingleSession, jingl
enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()
});
- logger.info('Starting CallStats for P2P connection...');
-
- let remoteID = Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid);
-
- const participant = this.participants.get(remoteID);
-
- if (participant) {
- remoteID = participant.getStatsID() || remoteID;
- }
-
- this.statistics.startCallStats(
- this.p2pJingleSession.peerconnection,
- remoteID);
-
const localTracks = this._getInitialLocalTracks();
this.p2pJingleSession.acceptOffer(
@@ -3295,12 +3203,6 @@ JitsiConference.prototype._setP2PStatus = function(newStatus) {
logger.info('Peer to peer connection closed!');
}
- // Put the JVB connection on hold/resume
- if (this.jvbJingleSession) {
- this.statistics.sendConnectionResumeOrHoldEvent(
- this.jvbJingleSession.peerconnection, !newStatus);
- }
-
// Clear dtmfManager, so that it can be recreated with new connection
this.dtmfManager = null;
@@ -3353,20 +3255,6 @@ JitsiConference.prototype._startP2PSession = function(remoteJid) {
enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()
});
- logger.info('Starting CallStats for P2P connection...');
-
- let remoteID = Strophe.getResourceFromJid(this.p2pJingleSession.remoteJid);
-
- const participant = this.participants.get(remoteID);
-
- if (participant) {
- remoteID = participant.getStatsID() || remoteID;
- }
-
- this.statistics.startCallStats(
- this.p2pJingleSession.peerconnection,
- remoteID);
-
const localTracks = this.getLocalTracks();
this.p2pJingleSession.invite(localTracks);
@@ -3520,8 +3408,6 @@ JitsiConference.prototype._stopP2PSession = function(options = {}) {
// Stop P2P stats
logger.info('Stopping remote stats for P2P connection');
this.statistics.stopRemoteStats(this.p2pJingleSession.peerconnection);
- logger.info('Stopping CallStats for P2P connection');
- this.statistics.stopCallStats(this.p2pJingleSession.peerconnection);
this.p2pJingleSession.terminate(
() => {
diff --git a/JitsiConferenceEventManager.js b/JitsiConferenceEventManager.js
index ba9be2528b..144e3cc1bb 100644
--- a/JitsiConferenceEventManager.js
+++ b/JitsiConferenceEventManager.js
@@ -9,7 +9,6 @@ import Statistics from './modules/statistics/statistics';
import EventEmitterForwarder from './modules/util/EventEmitterForwarder';
import { MediaType } from './service/RTC/MediaType';
import RTCEvents from './service/RTC/RTCEvents';
-import { VideoType } from './service/RTC/VideoType';
import AuthenticationEvents
from './service/authentication/AuthenticationEvents';
import {
@@ -31,26 +30,6 @@ const logger = getLogger(__filename);
export default function JitsiConferenceEventManager(conference) {
this.conference = conference;
this.xmppListeners = {};
-
- // Listeners related to the conference only
- conference.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED,
- track => {
- if (!track.isLocal() || !conference.statistics) {
- return;
- }
- const session
- = track.isP2P
- ? conference.p2pJingleSession : conference.jvbJingleSession;
-
- // TPC will be null, before the conference starts, but the event
- // still should be queued
- const tpc = (session && session.peerconnection) || null;
-
- conference.statistics.sendMuteEvent(
- tpc,
- track.isMuted(),
- track.getType());
- });
}
/**
@@ -360,20 +339,6 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
chatRoom.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, role => {
conference.onLocalRoleChanged(role);
-
- // log all events for the recorder operated by the moderator
- if (conference.statistics && conference.isModerator()) {
- conference.on(JitsiConferenceEvents.RECORDER_STATE_CHANGED,
- recorderSession => {
- const logObject = {
- error: recorderSession.getError(),
- id: 'recorder_status',
- status: recorderSession.getStatus()
- };
-
- Statistics.sendLog(JSON.stringify(logObject));
- });
- }
});
chatRoom.addListener(XMPPEvents.MUC_ROLE_CHANGED,
@@ -475,21 +440,6 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
}
});
- if (conference.statistics) {
- // FIXME ICE related events should end up in RTCEvents eventually
- chatRoom.addListener(XMPPEvents.CONNECTION_ICE_FAILED,
- session => {
- conference.statistics.sendIceConnectionFailedEvent(
- session.peerconnection);
- });
-
- // FIXME XMPPEvents.ADD_ICE_CANDIDATE_FAILED is never emitted
- chatRoom.addListener(XMPPEvents.ADD_ICE_CANDIDATE_FAILED,
- (e, pc) => {
- conference.statistics.sendAddIceCandidateFailed(e, pc);
- });
- }
-
// Breakout rooms.
this.chatRoomForwarder.forward(XMPPEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM,
JitsiConferenceEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM);
@@ -526,7 +476,7 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED, dominant, previous, silence);
if (conference.statistics && conference.myUserId() === dominant) {
// We are the new dominant speaker.
- conference.statistics.sendDominantSpeakerEvent(conference.room.roomjid, silence);
+ conference.xmpp.sendDominantSpeakerEvent(conference.room.roomjid, silence);
}
if (conference.lastDominantSpeaker !== dominant) {
if (previous && previous.length) {
@@ -603,30 +553,8 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
}
});
- rtc.addListener(RTCEvents.LOCAL_UFRAG_CHANGED,
- (tpc, ufrag) => {
- if (!tpc.isP2P) {
- Statistics.sendLog(
- JSON.stringify({
- id: 'local_ufrag',
- value: ufrag
- }));
- }
- });
- rtc.addListener(RTCEvents.REMOTE_UFRAG_CHANGED,
- (tpc, ufrag) => {
- if (!tpc.isP2P) {
- Statistics.sendLog(
- JSON.stringify({
- id: 'remote_ufrag',
- value: ufrag
- }));
- }
- });
-
rtc.addListener(RTCEvents.CREATE_ANSWER_FAILED,
(e, tpc) => {
- conference.statistics.sendCreateAnswerFailed(e, tpc);
if (!tpc.isP2P) {
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);
@@ -635,7 +563,6 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
rtc.addListener(RTCEvents.CREATE_OFFER_FAILED,
(e, tpc) => {
- conference.statistics.sendCreateOfferFailed(e, tpc);
if (!tpc.isP2P) {
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);
@@ -644,7 +571,6 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
rtc.addListener(RTCEvents.SET_LOCAL_DESCRIPTION_FAILED,
(e, tpc) => {
- conference.statistics.sendSetLocalDescFailed(e, tpc);
if (!tpc.isP2P) {
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);
@@ -653,23 +579,11 @@ JitsiConferenceEventManager.prototype.setupRTCListeners = function() {
rtc.addListener(RTCEvents.SET_REMOTE_DESCRIPTION_FAILED,
(e, tpc) => {
- conference.statistics.sendSetRemoteDescFailed(e, tpc);
if (!tpc.isP2P) {
conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED,
JitsiConferenceErrors.OFFER_ANSWER_FAILED, e);
}
});
-
- rtc.addListener(RTCEvents.LOCAL_TRACK_SSRC_UPDATED,
- (track, ssrc) => {
- // when starting screen sharing, the track is created and when
- // we do set local description and we process the ssrc we
- // will be notified for it and we will report it with the event
- // for screen sharing
- if (track.isVideoTrack() && track.videoType === VideoType.DESKTOP) {
- conference.statistics.sendScreenSharingEvent(true, ssrc);
- }
- });
};
/**
diff --git a/JitsiConferenceEvents.ts b/JitsiConferenceEvents.ts
index 29d542ccd9..b02b29d3ca 100644
--- a/JitsiConferenceEvents.ts
+++ b/JitsiConferenceEvents.ts
@@ -22,8 +22,7 @@ export enum JitsiConferenceEvents {
/**
* Fired just before the statistics module is disposed and it's the last chance
- * to submit some logs to the statistics service (ex. CallStats if enabled),
- * before it's disconnected.
+ * to submit some logs to the statistics service before it's disconnected.
*/
BEFORE_STATISTICS_DISPOSED = 'conference.beforeStatisticsDisposed',
diff --git a/JitsiConnection.js b/JitsiConnection.js
index 1835a1625b..95b417b9ef 100644
--- a/JitsiConnection.js
+++ b/JitsiConnection.js
@@ -43,12 +43,6 @@ export default function JitsiConnection(appID, token, options) {
ANALYTICS_CONNECTION_DISCONNECTED,
{ message: msg });
}
- Statistics.sendLog(
- JSON.stringify(
- {
- id: ANALYTICS_CONNECTION_DISCONNECTED,
- msg
- }));
});
}
diff --git a/JitsiMediaDevices.js b/JitsiMediaDevices.js
index 59cbb7646e..577d68c15c 100644
--- a/JitsiMediaDevices.js
+++ b/JitsiMediaDevices.js
@@ -3,7 +3,6 @@ import EventEmitter from 'events';
import * as JitsiMediaDevicesEvents from './JitsiMediaDevicesEvents';
import RTC from './modules/RTC/RTC';
import browser from './modules/browser';
-import Statistics from './modules/statistics/statistics';
import { MediaType } from './service/RTC/MediaType';
import RTCEvents from './service/RTC/RTCEvents';
@@ -29,12 +28,6 @@ class JitsiMediaDevices {
this._eventEmitter.emit(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
devices));
- RTC.addListener(
- RTCEvents.DEVICE_LIST_AVAILABLE,
- devices =>
- this._logOutputDevice(
- this.getAudioOutputDevice(),
- devices));
// We would still want to update the permissions cache in case the permissions API is not supported.
RTC.addListener(
@@ -146,22 +139,6 @@ class JitsiMediaDevices {
}
}
- /**
- * Gathers data and sends it to statistics.
- * @param deviceID the device id to log
- * @param devices list of devices
- */
- _logOutputDevice(deviceID, devices) {
- const device
- = devices.find(
- d => d.kind === 'audiooutput' && d.deviceId === deviceID);
-
- if (device) {
- Statistics.sendActiveDeviceListEvent(
- RTC.getEventDataForActiveDevice(device));
- }
- }
-
/**
* Executes callback with list of media devices connected.
* @param {function} callback
@@ -286,16 +263,6 @@ class JitsiMediaDevices {
* otherwise
*/
setAudioOutputDevice(deviceId) {
- const availableDevices = RTC.getCurrentlyAvailableMediaDevices();
-
- if (availableDevices.length > 0) {
- // if we have devices info report device to stats
- // normally this will not happen on startup as this method is called
- // too early. This will happen only on user selection of new device
- this._logOutputDevice(
- deviceId, RTC.getCurrentlyAvailableMediaDevices());
- }
-
return RTC.setAudioOutputDevice(deviceId);
}
diff --git a/JitsiMeetJS.ts b/JitsiMeetJS.ts
index 23b616e367..c825a358f5 100644
--- a/JitsiMeetJS.ts
+++ b/JitsiMeetJS.ts
@@ -25,7 +25,6 @@ import ProxyConnectionService
import recordingConstants from './modules/recording/recordingConstants';
import Settings from './modules/settings/Settings';
import LocalStatsCollector from './modules/statistics/LocalStatsCollector';
-import precallTest from './modules/statistics/PrecallTest';
import Statistics from './modules/statistics/statistics';
import GlobalOnErrorHandler from './modules/util/GlobalOnErrorHandler';
import ScriptUtil from './modules/util/ScriptUtil';
@@ -158,16 +157,6 @@ export default {
this.getGlobalOnErrorHandler.bind(this));
}
- if (this.version) {
- const logObject = {
- id: 'component_version',
- component: 'lib-jitsi-meet',
- version: this.version
- };
-
- Statistics.sendLog(JSON.stringify(logObject));
- }
-
return RTC.init(options);
},
@@ -379,16 +368,6 @@ export default {
promiseFulfilled = true;
if (error.name === JitsiTrackErrors.SCREENSHARING_USER_CANCELED) {
- // User cancelled action is not really an error, so only
- // log it as an event to avoid having conference classified
- // as partially failed
- const logObject = {
- id: 'screensharing_user_canceled',
- message: error.message
- };
-
- Statistics.sendLog(JSON.stringify(logObject));
-
Statistics.sendAnalytics(
createGetUserMediaEvent(
'warning',
@@ -396,14 +375,6 @@ export default {
reason: 'extension install user canceled'
}));
} else if (error.name === JitsiTrackErrors.NOT_FOUND) {
- // logs not found devices with just application log to cs
- const logObject = {
- id: 'usermedia_missing_device',
- status: error.gum.devices
- };
-
- Statistics.sendLog(JSON.stringify(logObject));
-
const attributes
= getAnalyticsAttributesFromOptions(options);
@@ -412,9 +383,6 @@ export default {
Statistics.sendAnalytics(
createGetUserMediaEvent('error', attributes));
} else {
- // Report gUM failed to the stats
- Statistics.sendGetUserMediaFailed(error);
-
const attributes
= getAnalyticsAttributesFromOptions(options);
@@ -547,8 +515,8 @@ export default {
`Line: ${lineno}`,
`Column: ${colno}`,
'StackTrace: ', error);
- Statistics.reportGlobalError(error);
},
+ /* eslint-enable max-params */
/**
* Informs lib-jitsi-meet about the current network status.
@@ -561,10 +529,6 @@ export default {
NetworkInfo.updateNetworkInfo({ isOnline });
},
- precallTest,
-
- /* eslint-enable max-params */
-
/**
* Represents a hub/namespace for utility functionality which may be of
* interest to lib-jitsi-meet clients.
diff --git a/modules/RTC/JitsiLocalTrack.js b/modules/RTC/JitsiLocalTrack.js
index 76c1be105b..cc4caf705e 100644
--- a/modules/RTC/JitsiLocalTrack.js
+++ b/modules/RTC/JitsiLocalTrack.js
@@ -233,7 +233,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
}
/**
- * Fires NO_DATA_FROM_SOURCE event and logs it to analytics and callstats.
+ * Fires NO_DATA_FROM_SOURCE event and logs it to analytics
*
* @private
* @returns {void}
@@ -247,10 +247,6 @@ export default class JitsiLocalTrack extends JitsiTrack {
// FIXME: Should we report all of those events
Statistics.sendAnalytics(createNoDataFromSourceEvent(this.getType(), value));
- Statistics.sendLog(JSON.stringify({
- name: NO_DATA_FROM_SOURCE,
- log: value
- }));
}
/**
@@ -817,14 +813,6 @@ export default class JitsiLocalTrack extends JitsiTrack {
*/
setConference(conference) {
this.conference = conference;
-
- // We want to keep up with postponed events which should have been fired
- // on "attach" call, but for local track we not always have the
- // conference before attaching. However this may result in duplicated
- // events if they have been triggered on "attach" already.
- for (let i = 0; i < this.containers.length; i++) {
- this._maybeFireTrackAttached(this.containers[i]);
- }
}
/**
diff --git a/modules/RTC/JitsiTrack.js b/modules/RTC/JitsiTrack.js
index 54d398991f..0e7b553dee 100644
--- a/modules/RTC/JitsiTrack.js
+++ b/modules/RTC/JitsiTrack.js
@@ -107,18 +107,6 @@ export default class JitsiTrack extends EventEmitter {
// Should be defined by the classes that are extending JitsiTrack
}
- /**
- * Eventually will trigger RTCEvents.TRACK_ATTACHED event.
- * @param container the video/audio container to which this stream is
- * attached and for which event will be fired.
- * @private
- */
- _maybeFireTrackAttached(container) {
- if (this.conference && container) {
- this.conference._onTrackAttach(this, container);
- }
- }
-
/**
* Called when the track has been attached to a new container.
*
@@ -235,7 +223,6 @@ export default class JitsiTrack extends EventEmitter {
result = RTCUtils.attachMediaStream(container, this.stream);
}
this.containers.push(container);
- this._maybeFireTrackAttached(container);
this._attachTTFMTracker(container);
return result;
diff --git a/modules/RTCStats/RTCStats.ts b/modules/RTCStats/RTCStats.ts
index 7449a7e0e1..a6a8764c6c 100644
--- a/modules/RTCStats/RTCStats.ts
+++ b/modules/RTCStats/RTCStats.ts
@@ -15,20 +15,6 @@ import { RTC_STATS_PC_EVENT, RTC_STATS_WC_DISCONNECTED } from './RTCStatsEvents'
const logger = getLogger(__filename);
-/**
- * Filter out RTCPeerConnection that are created by callstats.io.
- *
- * @param {*} config - Config object sent to the PC c'tor.
- * @returns {boolean}
- */
-function connectionFilter(config) {
- for(const iceUrl of (config?.iceServers ?? [])[0]?.urls ?? []) {
- if (iceUrl.includes('callstats.io')) {
- return true;
- }
- }
-}
-
/**
* RTCStats Singleton that is initialized only once for the lifetime of the app, subsequent calls to init will be ignored.
* Config and conference changes are handled by the start method.
@@ -63,8 +49,7 @@ class RTCStats {
rtcstatsInit(
{ statsEntry: this.sendStatsEntry.bind(this) },
- { connectionFilter,
- pollInterval,
+ { pollInterval,
useLegacy,
sendSdp,
eventCallback: (event) => this.events.emit(RTC_STATS_PC_EVENT, event)}
diff --git a/modules/connectivity/TrackStreamingStatus.ts b/modules/connectivity/TrackStreamingStatus.ts
index 193a83db75..61c0509440 100644
--- a/modules/connectivity/TrackStreamingStatus.ts
+++ b/modules/connectivity/TrackStreamingStatus.ts
@@ -329,14 +329,6 @@ export class TrackStreamingStatusImpl {
logger.debug(`Emit track streaming status(${Date.now()}) ${sourceName}: ${newStatus}`);
- // Log the event on CallStats
- Statistics.sendLog(
- JSON.stringify({
- id: 'track.streaming.status',
- track: sourceName,
- status: newStatus
- }));
-
// It's common for the event listeners to access the JitsiRemoteTrack. Thus pass it as a parameter here.
this.track.emit(JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED, this.track, newStatus);
}
diff --git a/modules/settings/Settings.js b/modules/settings/Settings.js
index b2fef5116e..6f0d6ffa7a 100644
--- a/modules/settings/Settings.js
+++ b/modules/settings/Settings.js
@@ -30,14 +30,14 @@ export default {
},
/**
- * Returns fake username for callstats
+ * Returns the ID to use for the purposes of stats, saved in localstorage as "callStatsUserName".
* @returns {string} fake username for callstats
*/
get callStatsUserName() {
if (!_callStatsUserName) {
_callStatsUserName = this._storage.getItem('callStatsUserName');
if (!_callStatsUserName) {
- _callStatsUserName = generateCallStatsUserName();
+ _callStatsUserName = _generateStatsId();
this._storage.setItem('callStatsUserName', _callStatsUserName);
}
}
@@ -90,13 +90,13 @@ export default {
};
/**
- * Generate fake username for callstats.
- * @returns {string} fake random username
+ * Generate a random ID to be used for statistics.
+ * @returns {string} the random ID
*/
-function generateCallStatsUserName() {
+function _generateStatsId() {
const username = UsernameGenerator.generateUsername();
- logger.log('generated callstats uid', username);
+ logger.log('generated stats id', username);
return username;
}
diff --git a/modules/statistics/AnalyticsAdapter.js b/modules/statistics/AnalyticsAdapter.js
index 54c2e0dbb1..61271c2fb2 100644
--- a/modules/statistics/AnalyticsAdapter.js
+++ b/modules/statistics/AnalyticsAdapter.js
@@ -10,7 +10,6 @@ import browser from '../browser';
const MAX_CACHE_SIZE = 100;
-// eslist-disable-line no-undef
const logger = getLogger(__filename);
/**
diff --git a/modules/statistics/CallStats.js b/modules/statistics/CallStats.js
deleted file mode 100644
index 35a08bed4c..0000000000
--- a/modules/statistics/CallStats.js
+++ /dev/null
@@ -1,787 +0,0 @@
-/* global callstats */
-
-import browser from '../browser';
-import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
-
-const logger = require('@jitsi/logger').getLogger(__filename);
-
-/**
- * We define enumeration of wrtcFuncNames as we need them before
- * callstats is initialized to queue events.
- * @const
- * @see http://www.callstats.io/api/#enumeration-of-wrtcfuncnames
- */
-const wrtcFuncNames = {
- createOffer: 'createOffer',
- createAnswer: 'createAnswer',
- setLocalDescription: 'setLocalDescription',
- setRemoteDescription: 'setRemoteDescription',
- addIceCandidate: 'addIceCandidate',
- getUserMedia: 'getUserMedia',
- iceConnectionFailure: 'iceConnectionFailure',
- signalingError: 'signalingError',
- applicationLog: 'applicationLog'
-};
-
-/**
- * We define enumeration of fabricEvent as we need them before
- * callstats is initialized to queue events.
- * @const
- * @see http://www.callstats.io/api/#enumeration-of-fabricevent
- */
-const fabricEvent = {
- fabricHold: 'fabricHold',
- fabricResume: 'fabricResume',
- audioMute: 'audioMute',
- audioUnmute: 'audioUnmute',
- videoPause: 'videoPause',
- videoResume: 'videoResume',
- fabricUsageEvent: 'fabricUsageEvent',
- fabricStats: 'fabricStats',
- fabricTerminated: 'fabricTerminated',
- screenShareStart: 'screenShareStart',
- screenShareStop: 'screenShareStop',
- dominantSpeaker: 'dominantSpeaker',
- activeDeviceList: 'activeDeviceList'
-};
-
-/**
- * The user id to report to callstats as destination.
- * @type {string}
- */
-const DEFAULT_REMOTE_USER = 'jitsi';
-
-/**
- * Type of pending reports, can be event or an error.
- * @type {{ERROR: string, EVENT: string}}
- */
-const reportType = {
- ERROR: 'error',
- EVENT: 'event',
- MST_WITH_USERID: 'mstWithUserID'
-};
-
-/**
- * Set of currently existing {@link CallStats} instances.
- * @type {Set}
- */
-let _fabrics;
-
-/**
- * An instance of this class is a wrapper for the CallStats API fabric. A fabric
- * reports one peer connection to the CallStats backend and is allocated with
- * {@link callstats.addNewFabric}. It has a bunch of instance methods for
- * reporting various events. A fabric is considered disposed when
- * {@link CallStats.sendTerminateEvent} is executed.
- *
- * Currently only one backend instance can be created ever and it's done using
- * {@link CallStats.initBackend}. At the time of this writing there is no way to
- * explicitly shutdown the backend, but it's supposed to close it's connection
- * automatically, after all fabrics have been terminated.
- */
-export default class CallStats {
- /**
- * A callback passed to {@link callstats.addNewFabric}.
- * @param {string} error 'success' means ok
- * @param {string} msg some more details
- * @private
- */
- static _addNewFabricCallback(error, msg) {
- if (CallStats.backend && error !== 'success') {
- logger.error(`Monitoring status: ${error} msg: ${msg}`);
- }
- }
-
- /**
- * Callback passed to {@link callstats.initialize} (backend initialization)
- * @param {string} error 'success' means ok
- * @param {String} msg
- * @private
- */
- static _initCallback(error, msg) {
- logger.log(`CallStats Status: err=${error} msg=${msg}`);
-
- // there is no lib, nothing to report to
- if (error !== 'success') {
- return;
- }
-
- CallStats.backendInitialized = true;
-
- // I hate that
- let atLeastOneFabric = false;
- let defaultInstance = null;
-
- for (const callStatsInstance of CallStats.fabrics.values()) {
- if (!callStatsInstance.hasFabric) {
- logger.debug('addNewFabric - initCallback');
- if (callStatsInstance._addNewFabric()) {
- atLeastOneFabric = true;
- if (!defaultInstance) {
- defaultInstance = callStatsInstance;
- }
- }
- }
- }
-
- if (!atLeastOneFabric) {
- return;
- }
-
- CallStats._emptyReportQueue(defaultInstance);
- }
-
- /**
- * Empties report queue.
- *
- * @param {CallStats} csInstance - The callstats instance.
- * @private
- */
- static _emptyReportQueue(csInstance) {
- // There is no conference ID nor a PeerConnection available when some of
- // the events are scheduled on the reportsQueue, so those will be
- // reported on the first initialized fabric.
- const defaultConfID = csInstance.confID;
- const defaultPC = csInstance.peerconnection;
-
- // notify callstats about failures if there were any
- for (const report of CallStats.reportsQueue) {
- if (report.type === reportType.ERROR) {
- const errorData = report.data;
-
- CallStats._reportError(
- csInstance,
- errorData.type,
- errorData.error,
- errorData.pc || defaultPC);
- } else if (report.type === reportType.EVENT) {
- // if we have and event to report and we failed to add
- // fabric this event will not be reported anyway, returning
- // an error
- const eventData = report.data;
-
- CallStats.backend.sendFabricEvent(
- report.pc || defaultPC,
- eventData.event,
- defaultConfID,
- eventData.eventData);
- } else if (report.type === reportType.MST_WITH_USERID) {
- const data = report.data;
-
- CallStats.backend.associateMstWithUserID(
- report.pc || defaultPC,
- data.callStatsId,
- defaultConfID,
- data.ssrc,
- data.usageLabel,
- data.containerId
- );
- }
- }
- CallStats.reportsQueue.length = 0;
- }
-
- /* eslint-disable max-params */
- /**
- * Reports an error to callstats.
- *
- * @param {CallStats} [cs]
- * @param type the type of the error, which will be one of the wrtcFuncNames
- * @param error the error
- * @param pc the peerconnection
- * @private
- */
- static _reportError(cs, type, error, pc) {
- let _error = error;
-
- if (!_error) {
- logger.warn('No error is passed!');
- _error = new Error('Unknown error');
- }
- if (CallStats.backendInitialized && cs) {
- CallStats.backend.reportError(pc, cs.confID, type, _error);
- } else {
- CallStats.reportsQueue.push({
- type: reportType.ERROR,
- data: {
- error: _error,
- pc,
- type
- }
- });
- }
-
- // else just ignore it
- }
-
- /* eslint-enable max-params */
-
- /**
- * Reports an error to callstats.
- *
- * @param {CallStats} cs
- * @param event the type of the event, which will be one of the fabricEvent
- * @param eventData additional data to pass to event
- * @private
- */
- static _reportEvent(cs, event, eventData) {
- const pc = cs && cs.peerconnection;
- const confID = cs && cs.confID;
-
- if (CallStats.backendInitialized && cs) {
- CallStats.backend.sendFabricEvent(pc, event, confID, eventData);
- } else {
- CallStats.reportsQueue.push({
- confID,
- pc,
- type: reportType.EVENT,
- data: { event,
- eventData }
- });
- }
- }
-
- /**
- * Wraps some of the CallStats API method and logs their calls with
- * arguments on the debug logging level. Also wraps some of the backend
- * methods execution into try catch blocks to not crash the app in case
- * there is a problem with the backend itself.
- * @param {callstats} theBackend
- * @private
- */
- static _traceAndCatchBackendCalls(theBackend) {
- const tryCatchMethods = [
- 'associateMstWithUserID',
- 'sendFabricEvent',
- 'sendUserFeedback'
-
- // 'reportError', - this one needs special handling - see code below
- ];
-
- for (const methodName of tryCatchMethods) {
- const originalMethod = theBackend[methodName];
-
- theBackend[methodName] = function(...theArguments) {
- try {
- return originalMethod.apply(theBackend, theArguments);
- } catch (e) {
- GlobalOnErrorHandler.callErrorHandler(e);
- }
- };
- }
- const debugMethods = [
- 'associateMstWithUserID',
- 'sendFabricEvent',
- 'sendUserFeedback'
-
- // 'reportError', - this one needs special handling - see code below
- ];
-
- for (const methodName of debugMethods) {
- const originalMethod = theBackend[methodName];
-
- theBackend[methodName] = function(...theArguments) {
- logger.debug(methodName, theArguments);
- originalMethod.apply(theBackend, theArguments);
- };
- }
- const originalReportError = theBackend.reportError;
-
- /* eslint-disable max-params */
- theBackend.reportError = function(pc, cs, type, ...args) {
- // Logs from the logger are submitted on the applicationLog event
- // "type". Logging the arguments on the logger will create endless
- // loop, because it will put all the logs to the logger queue again.
- if (type === wrtcFuncNames.applicationLog) {
- // NOTE otherArguments are not logged to the console on purpose
- // to not log the whole log batch
- // FIXME check the current logging level (currently not exposed
- // by the logger implementation)
- // NOTE it is not safe to log whole objects on react-native as
- // those contain too many circular references and may crash
- // the app.
- if (!browser.isReactNative()) {
- console && console.debug('reportError', pc, cs, type);
- }
- } else {
- logger.debug('reportError', pc, cs, type, ...args);
- }
- try {
- originalReportError.call(theBackend, pc, cs, type, ...args);
- } catch (exception) {
- if (type === wrtcFuncNames.applicationLog) {
- console && console.error('reportError', exception);
- } else {
- GlobalOnErrorHandler.callErrorHandler(exception);
- }
- }
- };
-
- /* eslint-enable max-params */
- }
-
- /**
- * Returns the Set with the currently existing {@link CallStats} instances.
- * Lazily initializes the Set to allow any Set polyfills to be applied.
- * @type {Set}
- */
- static get fabrics() {
- if (!_fabrics) {
- _fabrics = new Set();
- }
-
- return _fabrics;
- }
-
- /**
- * Initializes the CallStats backend. Should be called only if
- * {@link CallStats.isBackendInitialized} returns false.
- * @param {object} options
- * @param {String} options.callStatsID CallStats credentials - ID
- * @param {String} options.callStatsSecret CallStats credentials - secret
- * @param {string} options.aliasName the aliasName part of
- * the userID aka endpoint ID, see CallStats docs for more info.
- * @param {string} options.userName the userName part of
- * the userID aka display name, see CallStats docs for more info.
- * @param {object} options.configParams the set of parameters
- * to enable/disable certain features in the library. See CallStats docs for more info.
- *
- */
- static initBackend(options) {
- if (CallStats.backend) {
- throw new Error('CallStats backend has been initialized already!');
- }
- try {
- const CallStatsBackend = callstats;
-
- CallStats.backend = new CallStatsBackend();
- CallStats._traceAndCatchBackendCalls(CallStats.backend);
- CallStats.userID = {
- aliasName: options.aliasName,
- userName: options.userName
- };
- CallStats.callStatsID = options.callStatsID;
- CallStats.callStatsSecret = options.callStatsSecret;
-
- const configParams = { ...options.configParams };
-
- if (options.applicationName) {
- configParams.applicationVersion = `${options.applicationName} (${browser.getName()})`;
- }
-
- if (options.confID) {
- // we first check is there a tenant in the confID
- const match = options.confID.match(/.*\/(.*)\/.*/);
-
- // if there is no tenant, we will just set '/'
- configParams.siteID = options.siteID || (match && match[1]) || '/';
- }
-
- // userID is generated or given by the origin server
- CallStats.backend.initialize(
- CallStats.callStatsID,
- CallStats.callStatsSecret,
- CallStats.userID,
- CallStats._initCallback,
- undefined,
- configParams);
-
- return true;
- } catch (e) {
- // The callstats.io API failed to initialize (e.g. because its
- // download did not succeed in general or on time). Further attempts
- // to utilize it cannot possibly succeed.
- GlobalOnErrorHandler.callErrorHandler(e);
- CallStats.backend = null;
- logger.error(e);
-
- return false;
- }
- }
-
- /**
- * Checks if the CallStats backend has been created. It does not mean that
- * it has been initialized, but only that the API instance has been
- * allocated successfully.
- * @return {boolean} true if backend exists or false
- * otherwise
- */
- static isBackendInitialized() {
- return Boolean(CallStats.backend);
- }
-
- /**
- * Notifies CallStats about active device.
- * @param {{deviceList: {String:String}}} devicesData list of devices with
- * their data
- * @param {CallStats} cs callstats instance related to the event
- */
- static sendActiveDeviceListEvent(devicesData, cs) {
- CallStats._reportEvent(cs, fabricEvent.activeDeviceList, devicesData);
- }
-
- /**
- * Notifies CallStats that there is a log we want to report.
- *
- * @param {Error} e error to send or {String} message
- * @param {CallStats} cs callstats instance related to the error (optional)
- */
- static sendApplicationLog(e, cs) {
- try {
- CallStats._reportError(
- cs,
- wrtcFuncNames.applicationLog,
- e,
- cs && cs.peerconnection);
- } catch (error) {
- // If sendApplicationLog fails it should not be printed to
- // the logger, because it will try to push the logs again
- // (through sendApplicationLog) and an endless loop is created.
- if (console && (typeof console.error === 'function')) {
- // FIXME send analytics event as well
- console.error('sendApplicationLog failed', error);
- }
- }
- }
-
- /**
- * Sends the given feedback through CallStats.
- *
- * @param {string} conferenceID the conference ID for which the feedback
- * will be reported.
- * @param overall an integer between 1 and 5 indicating the
- * user feedback
- * @param comment detailed feedback from the user.
- */
- static sendFeedback(conferenceID, overall, comment) {
- return new Promise((resolve, reject) => {
- if (CallStats.backend) {
- CallStats.backend.sendUserFeedback(
- conferenceID,
- {
- userID: CallStats.userID,
- overall,
- comment
- },
- (status, message) => {
- if (status === 'success') {
- resolve(message);
- } else {
- reject(message);
- }
- });
- } else {
- const reason = 'Failed to submit feedback to CallStats - no backend';
-
- logger.error(reason);
- reject(reason);
- }
- });
- }
-
- /**
- * Notifies CallStats that getUserMedia failed.
- *
- * @param {Error} e error to send
- * @param {CallStats} cs callstats instance related to the error (optional)
- */
- static sendGetUserMediaFailed(e, cs) {
- CallStats._reportError(cs, wrtcFuncNames.getUserMedia, e, null);
- }
-
- /**
- * Notifies CallStats for mute events
- * @param mute {boolean} true for muted and false for not muted
- * @param type {String} "audio"/"video"
- * @param {CallStats} cs callstats instance related to the event
- */
- static sendMuteEvent(mute, type, cs) {
- let event;
-
- if (type === 'video') {
- event = mute ? fabricEvent.videoPause : fabricEvent.videoResume;
- } else {
- event = mute ? fabricEvent.audioMute : fabricEvent.audioUnmute;
- }
-
- CallStats._reportEvent(cs, event);
- }
-
- /**
- * Creates new CallStats instance that handles all callstats API calls for
- * given {@link TraceablePeerConnection}. Each instance is meant to handle
- * one CallStats fabric added with 'addFabric' API method for the
- * {@link TraceablePeerConnection} instance passed in the constructor.
- * @param {TraceablePeerConnection} tpc
- * @param {Object} options
- * @param {string} options.confID the conference ID that wil be used to
- * report the session.
- * @param {string} [options.remoteUserID='jitsi'] the remote user ID to
- * which given tpc is connected.
- */
- constructor(tpc, options) {
- this.confID = options.confID;
- this.tpc = tpc;
- this.peerconnection = tpc.peerconnection;
- this.remoteUserID = options.remoteUserID || DEFAULT_REMOTE_USER;
- this.hasFabric = false;
-
- CallStats.fabrics.add(this);
-
- if (CallStats.backendInitialized) {
- this._addNewFabric();
-
- // if this is the first fabric let's try to empty the
- // report queue. Reports all events that we recorded between
- // backend initialization and receiving the first fabric
- if (CallStats.fabrics.size === 1) {
- CallStats._emptyReportQueue(this);
- }
- }
- }
-
- /**
- * Initializes CallStats fabric by calling "addNewFabric" for
- * the peer connection associated with this instance.
- * @return {boolean} true if the call was successful or false otherwise.
- */
- _addNewFabric() {
- logger.info('addNewFabric', this.remoteUserID);
- try {
- const fabricAttributes = {
- remoteEndpointType:
- this.tpc.isP2P
- ? CallStats.backend.endpointType.peer
- : CallStats.backend.endpointType.server
- };
- const ret
- = CallStats.backend.addNewFabric(
- this.peerconnection,
- this.remoteUserID,
- CallStats.backend.fabricUsage.multiplex,
- this.confID,
- fabricAttributes,
- CallStats._addNewFabricCallback);
-
- this.hasFabric = true;
-
- const success = ret.status === 'success';
-
- if (!success) {
- logger.error('callstats fabric not initilized', ret.message);
- }
-
- return success;
-
- } catch (error) {
- GlobalOnErrorHandler.callErrorHandler(error);
-
- return false;
- }
- }
-
- /* eslint-disable max-params */
-
- /**
- * Lets CallStats module know where is given SSRC rendered by providing
- * renderer tag ID.
- * If the lib is not initialized yet queue the call for later, when it's
- * ready.
- * @param {number} ssrc the SSRC of the stream
- * @param {boolean} isLocal indicates whether this the stream is local
- * @param {string|null} streamEndpointId if the stream is not local the it
- * needs to contain the stream owner's ID
- * @param {string} usageLabel meaningful usage label of this stream like
- * 'microphone', 'camera' or 'screen'.
- * @param {string} containerId the id of media 'audio' or 'video' tag which
- * renders the stream.
- */
- associateStreamWithVideoTag(
- ssrc,
- isLocal,
- streamEndpointId,
- usageLabel,
- containerId) {
- if (!CallStats.backend) {
- return;
- }
-
- const callStatsId = isLocal ? CallStats.userID : streamEndpointId;
-
- if (CallStats.backendInitialized) {
- CallStats.backend.associateMstWithUserID(
- this.peerconnection,
- callStatsId,
- this.confID,
- ssrc,
- usageLabel,
- containerId);
- } else {
- CallStats.reportsQueue.push({
- type: reportType.MST_WITH_USERID,
- pc: this.peerconnection,
- data: {
- callStatsId,
- containerId,
- ssrc,
- usageLabel
- }
- });
- }
- }
-
- /* eslint-enable max-params */
-
- /**
- * Notifies CallStats that we are the new dominant speaker in the
- * conference.
- */
- sendDominantSpeakerEvent() {
- CallStats._reportEvent(this, fabricEvent.dominantSpeaker);
- }
-
- /**
- * Notifies CallStats that the fabric for the underlying peerconnection was
- * closed and no evens should be reported, after this call.
- */
- sendTerminateEvent() {
- if (CallStats.backendInitialized) {
- CallStats.backend.sendFabricEvent(
- this.peerconnection,
- CallStats.backend.fabricEvent.fabricTerminated,
- this.confID);
- }
- CallStats.fabrics.delete(this);
- }
-
- /**
- * Notifies CallStats for ice connection failed
- */
- sendIceConnectionFailedEvent() {
- CallStats._reportError(
- this,
- wrtcFuncNames.iceConnectionFailure,
- null,
- this.peerconnection);
- }
-
- /**
- * Notifies CallStats that peer connection failed to create offer.
- *
- * @param {Error} e error to send
- */
- sendCreateOfferFailed(e) {
- CallStats._reportError(
- this, wrtcFuncNames.createOffer, e, this.peerconnection);
- }
-
- /**
- * Notifies CallStats that peer connection failed to create answer.
- *
- * @param {Error} e error to send
- */
- sendCreateAnswerFailed(e) {
- CallStats._reportError(
- this, wrtcFuncNames.createAnswer, e, this.peerconnection);
- }
-
- /**
- * Sends either resume or hold event for the fabric associated with
- * the underlying peerconnection.
- * @param {boolean} isResume true to resume or false to hold
- */
- sendResumeOrHoldEvent(isResume) {
- CallStats._reportEvent(
- this,
- isResume ? fabricEvent.fabricResume : fabricEvent.fabricHold);
- }
-
- /**
- * Notifies CallStats for screen sharing events
- * @param {boolean} start true for starting screen sharing and
- * false for not stopping
- * @param {string|null} ssrc - optional ssrc value, used only when
- * starting screen sharing.
- */
- sendScreenSharingEvent(start, ssrc) {
- let eventData;
-
- if (ssrc) {
- eventData = { ssrc };
- }
-
- CallStats._reportEvent(
- this,
- start ? fabricEvent.screenShareStart : fabricEvent.screenShareStop,
- eventData);
- }
-
- /**
- * Notifies CallStats that peer connection failed to set local description.
- *
- * @param {Error} e error to send
- */
- sendSetLocalDescFailed(e) {
- CallStats._reportError(
- this, wrtcFuncNames.setLocalDescription, e, this.peerconnection);
- }
-
- /**
- * Notifies CallStats that peer connection failed to set remote description.
- *
- * @param {Error} e error to send
- */
- sendSetRemoteDescFailed(e) {
- CallStats._reportError(
- this, wrtcFuncNames.setRemoteDescription, e, this.peerconnection);
- }
-
- /**
- * Notifies CallStats that peer connection failed to add ICE candidate.
- *
- * @param {Error} e error to send
- */
- sendAddIceCandidateFailed(e) {
- CallStats._reportError(
- this, wrtcFuncNames.addIceCandidate, e, this.peerconnection);
- }
-}
-
-/**
- * The CallStats API backend instance
- * @type {callstats}
- */
-CallStats.backend = null;
-
-// some errors/events may happen before CallStats init
-// in this case we accumulate them in this array
-// and send them to callstats on init
-CallStats.reportsQueue = [];
-
-/**
- * Whether the library was successfully initialized(the backend) using its
- * initialize method.
- * @type {boolean}
- */
-CallStats.backendInitialized = false;
-
-/**
- * Part of the CallStats credentials - application ID
- * @type {string}
- */
-CallStats.callStatsID = null;
-
-/**
- * Part of the CallStats credentials - application secret
- * @type {string}
- */
-CallStats.callStatsSecret = null;
-
-/**
- * Local CallStats user ID structure. Can be set only once when
- * {@link backend} is initialized, so it's static for the time being.
- * See CallStats API for more info:
- * https://www.callstats.io/api/#userid
- * @type {object}
- */
-CallStats.userID = null;
diff --git a/modules/statistics/PrecallTest.js b/modules/statistics/PrecallTest.js
deleted file mode 100644
index f5f03a683c..0000000000
--- a/modules/statistics/PrecallTest.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import EventEmitter from 'events';
-
-import browser from '../browser';
-import Settings from '../settings/Settings';
-import ScriptUtil from '../util/ScriptUtil';
-
-import { CALLSTATS_SCRIPT_URL } from './constants';
-
-const PRECALL_TEST_RESULTS = 'preCallTestResults';
-const emitter = new EventEmitter();
-let _initialized = false;
-let api = null;
-
-/**
- * Loads the callstats io script.
- *
- * @returns {Promise}
- */
-function _loadScript(options) {
- if (browser.isReactNative()) {
- return;
- }
-
- return new Promise(resolve => {
- ScriptUtil.loadScript(
- options.callStatsCustomScriptUrl || CALLSTATS_SCRIPT_URL,
- /* async */ true,
- /* prepend */ true,
- /* relativeURL */ undefined,
- /* loadCallback */ resolve);
- });
-}
-
-/**
- * Initializes the callstats lib and registers a callback to be invoked
- * when there are 'preCallTestResults'.
- *
- * @typedef PrecallTestOptions
- * @type {Object}
- * @property {string} callStatsID - Callstats credentials - the id.
- * @property {string} callStatsSecret - Callstats credentials - the secret.
- * @property {string} statisticsId - The user name to use when initializing callstats.
- * @property {string} statisticsDisplayName - The user display name.
- *
- * @param { PrecallTestOptions} options - The init options.
- * @returns {Promise}
- */
-function _initialize(options) {
- return new Promise((resolve, reject) => {
- const appId = options.callStatsID;
- const appSecret = options.callStatsSecret;
- const userId = options.statisticsId || options.statisticsDisplayName || Settings.callStatsUserName;
-
- api.initialize(appId, appSecret, userId, (status, message) => {
- if (status === 'success') {
- api.on(PRECALL_TEST_RESULTS, (...args) => {
- emitter.emit(PRECALL_TEST_RESULTS, ...args);
- });
- _initialized = true;
- resolve();
- } else {
- reject({
- status,
- message
- });
- }
- }, null, { disablePrecalltest: true });
- });
-}
-
-/**
- * Loads the callstats script and initializes the library.
- *
- * @param {Function} onResult - The callback to be invoked when results are received.
- * @returns {Promise}
- */
-export async function init(options) {
- if (_initialized) {
- throw new Error('Precall Test already initialized');
- }
-
- const { callStatsID, callStatsSecret, disableThirdPartyRequests } = options;
-
- if (!callStatsID || !callStatsSecret || disableThirdPartyRequests) {
- throw new Error('Callstats is disabled');
- }
-
- await _loadScript(options);
- // eslint-disable-next-line new-cap
- api = new window.callstats();
-
- return _initialize(options);
-}
-
-/**
- * Executes a pre call test.
- *
- * @typedef PrecallTestResults
- * @type {Object}
- * @property {boolean} mediaConnectivity - If there is media connectivity or not.
- * @property {number} throughput - The average throughput.
- * @property {number} fractionalLoss - The packet loss.
- * @property {number} rtt - The round trip time.
- * @property {string} provider - It is usually 'callstats'.
- *
- * @returns {Promise<{PrecallTestResults}>}
- */
-export function execute() {
- if (!_initialized) {
- return Promise.reject('uninitialized');
- }
-
- return new Promise((resolve, reject) => {
- emitter.on(PRECALL_TEST_RESULTS, (status, payload) => {
- if (status === 'success') {
- resolve(payload);
- } else {
- reject({
- status,
- payload
- });
- }
-
- });
-
- api.makePrecallTest();
- });
-}
-
-export default {
- init,
- execute
-};
diff --git a/modules/statistics/constants.js b/modules/statistics/constants.js
index 386b24eb56..6c321bde4b 100644
--- a/modules/statistics/constants.js
+++ b/modules/statistics/constants.js
@@ -1,5 +1,3 @@
-export const CALLSTATS_SCRIPT_URL = 'https://api.callstats.io/static/callstats-ws.min.js';
-
/**
* The number of remote speakers for which the audio levels will be calculated using
* RTCRtpReceiver#getSynchronizationSources. Limit the number of endpoints to save cpu on the client as this API call
diff --git a/modules/statistics/statistics.js b/modules/statistics/statistics.js
index 8addcaa297..12c5be5ec5 100644
--- a/modules/statistics/statistics.js
+++ b/modules/statistics/statistics.js
@@ -1,21 +1,17 @@
import EventEmitter from 'events';
import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
-import JitsiTrackError from '../../JitsiTrackError';
import { JitsiTrackEvents } from '../../JitsiTrackEvents';
import { FEEDBACK } from '../../service/statistics/AnalyticsEvents';
import * as StatisticsEvents from '../../service/statistics/Events';
import RTCStats from '../RTCStats/RTCStats';
import browser from '../browser';
-import ScriptUtil from '../util/ScriptUtil';
import WatchRTC from '../watchRTC/WatchRTC';
import analytics from './AnalyticsAdapter';
-import CallStats from './CallStats';
import LocalStats from './LocalStatsCollector';
import { PerformanceObserverStats } from './PerformanceObserverStats';
import RTPStats from './RTPStatsCollector';
-import { CALLSTATS_SCRIPT_URL } from './constants';
const logger = require('@jitsi/logger').getLogger(__filename);
@@ -25,91 +21,6 @@ const logger = require('@jitsi/logger').getLogger(__filename);
*/
let _instances;
-/**
- * True if callstats API is loaded
- */
-let isCallstatsLoaded = false;
-
-/**
- * Since callstats.io is a third party, we cannot guarantee the quality of their
- * service. More specifically, their server may take noticeably long time to
- * respond. Consequently, it is in our best interest (in the sense that the
- * intergration of callstats.io is pretty important to us but not enough to
- * allow it to prevent people from joining a conference) to (1) start
- * downloading their API as soon as possible and (2) do the downloading
- * asynchronously.
- *
- * @param {StatisticsOptions} options - Options to use for downloading and
- * initializing callstats backend.
- */
-function loadCallStatsAPI(options) {
- if (!isCallstatsLoaded) {
- ScriptUtil.loadScript(
- options.customScriptUrl || CALLSTATS_SCRIPT_URL,
- /* async */ true,
- /* prepend */ true,
- /* relativeURL */ undefined,
- /* loadCallback */ () => _initCallStatsBackend(options)
- );
- isCallstatsLoaded = true;
- }
-}
-
-/**
- * Initializes Callstats backend.
- *
- * @param {StatisticsOptions} options - The options to use for initializing
- * callstats backend.
- * @private
- */
-function _initCallStatsBackend(options) {
- if (CallStats.isBackendInitialized()) {
- return;
- }
-
- if (!CallStats.initBackend({
- callStatsID: options.callStatsID,
- callStatsSecret: options.callStatsSecret,
- userName: options.userName,
- aliasName: options.aliasName,
- applicationName: options.applicationName,
- confID: options.confID,
- siteID: options.siteID,
- configParams: options.configParams
- })) {
- logger.error('CallStats Backend initialization failed bad');
- }
-}
-
-/**
- * callstats strips any additional fields from Error except for "name", "stack",
- * "message" and "constraintName". So we need to bundle additional information
- * from JitsiTrackError into error passed to callstats to preserve valuable
- * information about error.
- * @param {JitsiTrackError} error
- */
-function formatJitsiTrackErrorForCallStats(error) {
- const err = new Error();
-
- // Just copy original stack from error
- err.stack = error.stack;
-
- // Combine name from error's name plus (possibly) name of original GUM error
- err.name = (error.name || 'Unknown error') + (error.gum && error.gum.error
- && error.gum.error.name ? ` - ${error.gum.error.name}` : '');
-
- // Put all constraints into this field. For constraint failed errors we will
- // still know which exactly constraint failed as it will be a part of
- // message.
- err.constraintName = error.gum && error.gum.constraints
- ? JSON.stringify(error.gum.constraints) : '';
-
- // Just copy error's message.
- err.message = error.message;
-
- return err;
-}
-
/**
* Init statistic options
* @param options
@@ -141,20 +52,8 @@ Statistics.init = function(options) {
/**
* The options to configure Statistics.
* @typedef {Object} StatisticsOptions
- * @property {string} applicationName - The application name to pass to
- * callstats.
- * @property {string} aliasName - The alias name to use when initializing callstats.
- * @property {string} userName - The user name to use when initializing callstats.
- * @property {string} confID - The callstats conference ID to use.
- * @property {string} callStatsID - Callstats credentials - the id.
- * @property {string} callStatsSecret - Callstats credentials - the secret.
- * @property {string} customScriptUrl - A custom lib url to use when downloading
- * callstats library.
+ * @property {string} userName - The user name to use
* @property {string} roomName - The room name we are currently in.
- * @property {string} configParams - The set of parameters
- * to enable/disable certain features in the library. See CallStats docs for more info.
- */
-/**
*
* @param {JitsiConference} conference - The conference instance from which the statistics were initialized.
* @param {StatisticsOptions} options - The options to use creating the
@@ -172,35 +71,6 @@ export default function Statistics(conference, options) {
this.xmpp = conference?.xmpp;
this.options = options || {};
- this.callStatsIntegrationEnabled
- = this.options.callStatsID && this.options.callStatsSecret
-
- // Even though AppID and AppSecret may be specified, the integration
- // of callstats.io may be disabled because of globally-disallowed
- // requests to any third parties.
- && (Statistics.disableThirdPartyRequests !== true);
- if (this.callStatsIntegrationEnabled) {
- this.callStatsApplicationLogsDisabled
- = this.options.callStatsApplicationLogsDisabled;
- if (browser.isReactNative()) {
- _initCallStatsBackend(this.options);
- } else {
- loadCallStatsAPI(this.options);
- }
-
- if (!this.options.confID) {
- logger.warn('"confID" is not defined');
- }
- }
-
- /**
- * Stores {@link CallStats} instances for each
- * {@link TraceablePeerConnection} (one {@link CallStats} instance serves
- * one TPC). The instances are mapped by {@link TraceablePeerConnection.id}.
- * @type {Map}
- */
- this.callsStatsInstances = new Map();
-
Statistics.instances.add(this);
RTCStats.start(this.conference);
@@ -419,19 +289,8 @@ Statistics.prototype.setSpeakerList = function(speakerList) {
Statistics.prototype.dispose = function() {
try {
- // NOTE Before reading this please see the comment in stopCallStats...
- //
- // Here we prevent from emitting the event twice in case it will be
- // triggered from stopCallStats.
- // If the event is triggered from here it means that the logs will not
- // be submitted anyway (because there is no CallStats instance), but
- // we're doing that for the sake of some kind of consistency.
- if (!this.callsStatsInstances.size) {
- this.eventEmitter.emit(StatisticsEvents.BEFORE_DISPOSED);
- }
- for (const callStats of this.callsStatsInstances.values()) {
- this.stopCallStats(callStats.tpc);
- }
+ this.eventEmitter.emit(StatisticsEvents.BEFORE_DISPOSED);
+
for (const tpcId of this.rtpStatsMap.keys()) {
this._stopRemoteStats(tpcId);
}
@@ -482,347 +341,12 @@ Statistics.prototype.stopRemoteStats = function(tpc) {
this._stopRemoteStats(tpc.id);
};
-// CALSTATS METHODS
-
/**
- * Initializes the callstats.io API.
- * @param {TraceablePeerConnection} tpc the {@link TraceablePeerConnection}
- * instance for which CalStats will be started.
- * @param {string} remoteUserID
- */
-Statistics.prototype.startCallStats = function(tpc, remoteUserID) {
- if (!this.callStatsIntegrationEnabled) {
- return;
- } else if (this.callsStatsInstances.has(tpc.id)) {
- logger.error('CallStats instance for ${tpc} exists already');
-
- return;
- }
- let confID = this.options.confID;
-
- // confID - domain/tenant/roomName
- // roomName - meeting name or breakout room ID
- // For breakout rooms we change the conference ID used for callstats to use
- // the room ID instead of the meeting name
- if (!confID.endsWith(this.options.roomName)) {
- confID = `${this.options.confID.slice(0, this.options.confID.lastIndexOf('/'))}/${this.options.roomName}`;
- }
-
- logger.info(`Starting CallStats for ${tpc}...`);
- const newInstance
- = new CallStats(
- tpc,
- {
- confID,
- remoteUserID
- });
-
- this.callsStatsInstances.set(tpc.id, newInstance);
-};
-
-/**
- * Obtains the list of *all* {@link CallStats} instances collected from every
- * valid {@link Statistics} instance.
- * @return {Set}
- * @private
- */
-Statistics._getAllCallStatsInstances = function() {
- const csInstances = new Set();
-
- for (const statistics of Statistics.instances) {
- for (const cs of statistics.callsStatsInstances.values()) {
- csInstances.add(cs);
- }
- }
-
- return csInstances;
-};
-
-/**
- * Removes the callstats.io instances.
- */
-Statistics.prototype.stopCallStats = function(tpc) {
- const callStatsInstance = this.callsStatsInstances.get(tpc.id);
-
- if (callStatsInstance) {
- // FIXME the original purpose of adding BEFORE_DISPOSED event was to be
- // able to submit the last log batch from jitsi-meet to CallStats. After
- // recent changes we dispose the CallStats earlier
- // (before Statistics.dispose), so we need to emit this event here to
- // give this last chance for final log batch submission.
- //
- // Eventually there should be a separate module called "log storage"
- // which should emit proper events when it's underlying
- // CallStats instance is going away.
- if (this.callsStatsInstances.size === 1) {
- this.eventEmitter.emit(StatisticsEvents.BEFORE_DISPOSED);
- }
- this.callsStatsInstances.delete(tpc.id);
-
- // The fabric needs to be terminated when being stopped
- callStatsInstance.sendTerminateEvent();
- }
-};
-
-/**
- * Returns true if the callstats integration is enabled, otherwise returns
- * false.
- *
- * @returns true if the callstats integration is enabled, otherwise returns
- * false.
- */
-Statistics.prototype.isCallstatsEnabled = function() {
- return this.callStatsIntegrationEnabled;
-};
-
-/**
- * Logs either resume or hold event for the given peer connection.
- * @param {TraceablePeerConnection} tpc the connection for which event will be
- * reported
- * @param {boolean} isResume true for resume or false for hold
- */
-Statistics.prototype.sendConnectionResumeOrHoldEvent = function(tpc, isResume) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendResumeOrHoldEvent(isResume);
- }
-};
-
-/**
- * Notifies CallStats and analytics (if present) for ice connection failed
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- */
-Statistics.prototype.sendIceConnectionFailedEvent = function(tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendIceConnectionFailedEvent();
- }
-};
-
-/**
- * Notifies CallStats for mute events
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- * @param {boolean} muted true for muted and false for not muted
- * @param {String} type "audio"/"video"
- */
-Statistics.prototype.sendMuteEvent = function(tpc, muted, type) {
- const instance = tpc && this.callsStatsInstances.get(tpc.id);
-
- CallStats.sendMuteEvent(muted, type, instance);
-};
-
-/**
- * Notifies CallStats for screen sharing events
- * @param start {boolean} true for starting screen sharing and
- * false for not stopping
- * @param {string|null} ssrc - optional ssrc value, used only when
- * starting screen sharing.
- */
-Statistics.prototype.sendScreenSharingEvent
- = function(start, ssrc) {
- for (const cs of this.callsStatsInstances.values()) {
- cs.sendScreenSharingEvent(start, ssrc);
- }
- };
-
-/**
- * Notifies the statistics module that we are now the dominant speaker of the
- * conference.
- * @param {String} roomJid - The room jid where the speaker event occurred.
- * @param {boolean} silence - Whether the dominant speaker is silent or not.
- */
-Statistics.prototype.sendDominantSpeakerEvent = function(roomJid, silence) {
- for (const cs of this.callsStatsInstances.values()) {
- cs.sendDominantSpeakerEvent();
- }
-
- // xmpp send dominant speaker event
- this.xmpp.sendDominantSpeakerEvent(roomJid, silence);
-};
-
-/**
- * Notifies about active device.
- * @param {{deviceList: {String:String}}} devicesData - list of devices with
- * their data
- */
-Statistics.sendActiveDeviceListEvent = function(devicesData) {
- const globalSet = Statistics._getAllCallStatsInstances();
-
- if (globalSet.size) {
- for (const cs of globalSet) {
- CallStats.sendActiveDeviceListEvent(devicesData, cs);
- }
- } else {
- CallStats.sendActiveDeviceListEvent(devicesData, null);
- }
-};
-
-/* eslint-disable max-params */
-
-/**
- * Lets the underlying statistics module know where is given SSRC rendered by
- * providing renderer tag ID.
- * @param {TraceablePeerConnection} tpc the connection to which the stream
- * belongs to
- * @param {number} ssrc the SSRC of the stream
- * @param {boolean} isLocal
- * @param {string} userId
- * @param {string} usageLabel meaningful usage label of this stream like
- * 'microphone', 'camera' or 'screen'.
- * @param {string} containerId the id of media 'audio' or 'video' tag which
- * renders the stream.
- */
-Statistics.prototype.associateStreamWithVideoTag = function(
- tpc,
- ssrc,
- isLocal,
- userId,
- usageLabel,
- containerId) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.associateStreamWithVideoTag(
- ssrc,
- isLocal,
- userId,
- usageLabel,
- containerId);
- }
-};
-
-/* eslint-enable max-params */
-
-/**
- * Notifies CallStats that getUserMedia failed.
- *
- * @param {Error} e error to send
- */
-Statistics.sendGetUserMediaFailed = function(e) {
- const error
- = e instanceof JitsiTrackError
- ? formatJitsiTrackErrorForCallStats(e) : e;
- const globalSet = Statistics._getAllCallStatsInstances();
-
- if (globalSet.size) {
- for (const cs of globalSet) {
- CallStats.sendGetUserMediaFailed(error, cs);
- }
- } else {
- CallStats.sendGetUserMediaFailed(error, null);
- }
-};
-
-/**
- * Notifies CallStats that peer connection failed to create offer.
- *
- * @param {Error} e error to send
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- */
-Statistics.prototype.sendCreateOfferFailed = function(e, tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendCreateOfferFailed(e);
- }
-};
-
-/**
- * Notifies CallStats that peer connection failed to create answer.
- *
- * @param {Error} e error to send
- * @param {TraceablePeerConnection} tpc connection on which failure occured.
- */
-Statistics.prototype.sendCreateAnswerFailed = function(e, tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendCreateAnswerFailed(e);
- }
-};
-
-/**
- * Notifies CallStats that peer connection failed to set local description.
- *
- * @param {Error} e error to send
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- */
-Statistics.prototype.sendSetLocalDescFailed = function(e, tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendSetLocalDescFailed(e);
- }
-};
-
-/**
- * Notifies CallStats that peer connection failed to set remote description.
- *
- * @param {Error} e error to send
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- */
-Statistics.prototype.sendSetRemoteDescFailed = function(e, tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendSetRemoteDescFailed(e);
- }
-};
-
-/**
- * Notifies CallStats that peer connection failed to add ICE candidate.
- *
- * @param {Error} e error to send
- * @param {TraceablePeerConnection} tpc connection on which failure occurred.
- */
-Statistics.prototype.sendAddIceCandidateFailed = function(e, tpc) {
- const instance = this.callsStatsInstances.get(tpc.id);
-
- if (instance) {
- instance.sendAddIceCandidateFailed(e);
- }
-};
-
-/**
- * Adds to CallStats an application log.
- *
- * @param {String} m a log message to send or an {Error} object to be reported
- */
-Statistics.sendLog = function(m) {
- const globalSubSet = new Set();
-
- // FIXME we don't want to duplicate logs over P2P instance, but
- // here we should go over instances and call this method for each
- // unique conference ID rather than selecting the first one.
- // We don't have such use case though, so leaving as is for now.
- for (const stats of Statistics.instances) {
- if (stats.callStatsApplicationLogsDisabled) {
- return;
- }
-
- if (stats.callsStatsInstances.size) {
- globalSubSet.add(stats.callsStatsInstances.values().next().value);
- }
- }
-
- if (globalSubSet.size) {
- for (const csPerStats of globalSubSet) {
- CallStats.sendApplicationLog(m, csPerStats);
- }
- } else {
- CallStats.sendApplicationLog(m, null);
- }
-};
-
-/**
- * Sends the given feedback through CallStats.
+ * Sends the given feedback
*
* @param overall an integer between 1 and 5 indicating the user's rating.
* @param comment the comment from the user.
- * @returns {Promise} Resolves when callstats feedback has been submitted
- * successfully.
+ * @returns {Promise} Resolves immediately.
*/
Statistics.prototype.sendFeedback = function(overall, comment) {
// Statistics.analytics.sendEvent is currently fire and forget, without
@@ -834,31 +358,13 @@ Statistics.prototype.sendFeedback = function(overall, comment) {
comment
});
- if (this.isCallstatsEnabled()) {
- return CallStats.sendFeedback(this.options.confID, overall, comment);
- }
-
return Promise.resolve();
};
Statistics.LOCAL_JID = require('../../service/statistics/constants').LOCAL_JID;
/**
- * Reports global error to CallStats.
- *
- * @param {Error} error
- */
-Statistics.reportGlobalError = function(error) {
- if (error instanceof JitsiTrackError && error.gum) {
- Statistics.sendGetUserMediaFailed(error);
- } else {
- Statistics.sendLog(error);
- }
-};
-
-/**
- * Sends event to analytics and logs a message to the logger/console. Console
- * messages might also be logged to callstats automatically.
+ * Sends event to analytics and logs a message to the logger/console.
*
* @param {string | Object} event the event name, or an object which
* represents the entire event.
diff --git a/modules/version/ComponentsVersions.js b/modules/version/ComponentsVersions.js
index 93d07c0caf..f24c1961da 100644
--- a/modules/version/ComponentsVersions.js
+++ b/modules/version/ComponentsVersions.js
@@ -1,5 +1,3 @@
-import Statistics from '../statistics/statistics';
-
const logger = require('@jitsi/logger').getLogger(__filename);
/**
@@ -29,8 +27,6 @@ ComponentsVersions.prototype.processVersions
return;
}
- const log = [];
-
versions.children.forEach(component => {
const name = component.attributes.name;
@@ -39,19 +35,8 @@ ComponentsVersions.prototype.processVersions
if (this.versions[name] !== version) {
this.versions[name] = version;
logger.info(`Got ${name} version: ${version}`);
-
- log.push({
- id: 'component_version',
- component: name,
- version
- });
}
});
-
- // logs versions to stats
- if (log.length > 0) {
- Statistics.sendLog(JSON.stringify(log));
- }
};
/**
diff --git a/modules/xmpp/xmpp.js b/modules/xmpp/xmpp.js
index 835592d119..ac788e0256 100644
--- a/modules/xmpp/xmpp.js
+++ b/modules/xmpp/xmpp.js
@@ -1125,7 +1125,6 @@ export default class XMPP extends Listenable {
logObject.id = 'deployment_info';
const entry = JSON.stringify(logObject);
- Statistics.sendLog(entry);
logger.info(entry);
}
diff --git a/service/statistics/Events.ts b/service/statistics/Events.ts
index 312ae0cd8b..f23f1137cd 100644
--- a/service/statistics/Events.ts
+++ b/service/statistics/Events.ts
@@ -13,8 +13,7 @@ export enum Events {
/**
* An event fired just before the statistics module gets disposes and it's
- * the last chance to submit some logs that will end up in stats services like
- * CallStats (if enabled).
+ * the last chance to submit logs.
*/
BEFORE_DISPOSED = 'statistics.before_disposed',