diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index 72f3ded759..b32d1757cf 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -190,10 +190,10 @@ export interface IConfig { obfuscateRoomName?: boolean; rtcstatsEnabled?: boolean; rtcstatsEndpoint?: string; + rtcstatsLogFlushSizeBytes?: number; rtcstatsPollInterval?: number; rtcstatsSendSdp?: boolean; rtcstatsStoreLogs?: boolean; - rtcstatsUseLegacy?: boolean; scriptURLs?: Array; watchRTCEnabled?: boolean; whiteListedEvents?: string[]; diff --git a/react/features/base/config/functions.native.ts b/react/features/base/config/functions.native.ts index 282282a897..3a9a131b28 100644 --- a/react/features/base/config/functions.native.ts +++ b/react/features/base/config/functions.native.ts @@ -24,7 +24,6 @@ export function _cleanupConfig(config: IConfig) { delete config.analytics?.rtcstatsEndpoint; delete config.analytics?.rtcstatsPollInterval; delete config.analytics?.rtcstatsSendSdp; - delete config.analytics?.rtcstatsUseLegacy; delete config.analytics?.obfuscateRoomName; delete config.analytics?.watchRTCEnabled; delete config.watchRTCConfigParams; diff --git a/react/features/base/logging/JitsiMeetLogStorage.ts b/react/features/base/logging/JitsiMeetLogStorage.ts index 1cf5c4b6f2..ac7fb5bb39 100644 --- a/react/features/base/logging/JitsiMeetLogStorage.ts +++ b/react/features/base/logging/JitsiMeetLogStorage.ts @@ -1,12 +1,13 @@ import { IStore } from '../../app/types'; +import JitsiMeetJS from '../../base/lib-jitsi-meet'; import RTCStats from '../../rtcstats/RTCStats'; import { isRTCStatsEnabled } from '../../rtcstats/functions'; /** - * Implements log storage interface from the @jitsi/logger lib. + * Implements log storage interface from the @jitsi/logger lib, as it stands + * now it only sends logs to the rtcstats server in case it is enabled. */ export default class JitsiMeetLogStorage { - counter: number; getState: IStore['getState']; /** @@ -15,12 +16,6 @@ export default class JitsiMeetLogStorage { * @param {Function} getState - The Redux store's {@code getState} method. */ constructor(getState: IStore['getState']) { - /** - * Counts each log entry, increases on every batch log entry stored. - * - * @type {number} - */ - this.counter = 1; /** * The Redux store's {@code getState} method. @@ -31,18 +26,14 @@ export default class JitsiMeetLogStorage { } /** - * The JitsiMeetLogStorage is ready when the conference has been joined. - * A conference is considered joined when the 'conference' field is defined - * in the base/conference state. + * The JitsiMeetLogStorage is ready we can use the rtcstats trace to send logs + * to the rtcstats server. * * @returns {boolean} true when this storage is ready or * false otherwise. */ isReady() { - const { conference, error: conferenceError } = this.getState()['features/base/conference']; - const { error: connectionError } = this.getState()['features/base/connection']; - - return Boolean(conference || conferenceError || connectionError); + return JitsiMeetJS.rtcstats.isTraceAvailable(); } /** @@ -55,9 +46,9 @@ export default class JitsiMeetLogStorage { const config = this.getState()['features/base/config']; - // Saving the logs in RTCStats is a new feature and so there is no prior behavior that needs to be maintained. - // That said, this is still experimental and needs to be rolled out gradually so we want this to be off by - // default. + // RTCStats can run without sending app logs to the server. + // Be mindful that there exists another LogStorage instance withing lib-jitsi-meet, + // that is used to send logs generated there. return config?.analytics?.rtcstatsStoreLogs && isRTCStatsEnabled(this.getState()); } diff --git a/react/features/base/logging/middleware.ts b/react/features/base/logging/middleware.ts index aca18cbf93..e7aa5bbafc 100644 --- a/react/features/base/logging/middleware.ts +++ b/react/features/base/logging/middleware.ts @@ -107,9 +107,6 @@ function _conferenceJoined({ getState }: IStore, next: Function, action: AnyActi const { logCollector } = getState()['features/base/logging']; if (logCollector && conference === getCurrentConference(getState())) { - // Start the LogCollector's periodic "store logs" task - logCollector.start(); - // Make an attempt to flush in case a lot of logs have been cached, // before the collector was started. logCollector.flush(); @@ -150,12 +147,21 @@ function _initLogging({ dispatch, getState }: IStore, // Create the LogCollector and register it as the global log transport. It // is done early to capture as much logs as possible. Captured logs will be - // cached, before the JitsiMeetLogStorage gets ready (statistics module is - // initialized). + // cached, before the JitsiMeetLogStorage gets ready (RTCStats trace is + // available). if (!logCollector && !loggingConfig.disableLogCollector) { - const _logCollector = new Logger.LogCollector(new JitsiMeetLogStorage(getState)); + const { apiLogLevels, analytics: { rtcstatsLogFlushSizeBytes } = {} } = getState()['features/base/config']; - const { apiLogLevels } = getState()['features/base/config']; + // The smaller the flush size the smaller the chance of losing logs, but + // the more often the logs will be sent to the server, by default the LogCollector + // will set once the logs reach 10KB or 30 seconds have passed since the last flush, + // this means if something happens between that interval and the logs don't get flushed + // they will be lost, for instance the meeting tab is closed, the browser crashes, + // an uncaught exception happens, etc. + // If undefined is passed the default values will be used, + const _logCollector = new Logger.LogCollector(new JitsiMeetLogStorage(getState), { + maxEntryLength: rtcstatsLogFlushSizeBytes + }); if (apiLogLevels && Array.isArray(apiLogLevels) && typeof APP === 'object') { const transport = buildExternalApiLogTransport(apiLogLevels); @@ -165,6 +171,9 @@ function _initLogging({ dispatch, getState }: IStore, } Logger.addGlobalTransport(_logCollector); + + _logCollector.start(); + dispatch(setLogCollector(_logCollector)); // The JitsiMeetInMemoryLogStorage can not be accessed on mobile through