feat(RN): enable log collector on mobile
Stores the Logger.LogCollector instance in base/logging state instead of global APP variable and enables it on mobile.
This commit is contained in:
parent
e729f0948c
commit
2305effa5c
|
@ -2234,34 +2234,6 @@ export default {
|
|||
* @returns {void}
|
||||
*/
|
||||
_onConferenceJoined() {
|
||||
if (APP.logCollector) {
|
||||
// Start the LogCollector's periodic "store logs" task
|
||||
APP.logCollector.start();
|
||||
APP.logCollectorStarted = true;
|
||||
|
||||
// Make an attempt to flush in case a lot of logs have been
|
||||
// cached, before the collector was started.
|
||||
APP.logCollector.flush();
|
||||
|
||||
// This event listener will flush the logs, before
|
||||
// the statistics module (CallStats) is stopped.
|
||||
//
|
||||
// NOTE The LogCollector is not stopped, because this event can
|
||||
// be triggered multiple times during single conference
|
||||
// (whenever statistics module is stopped). That includes
|
||||
// the case when Jicofo terminates the single person left in the
|
||||
// room. It will then restart the media session when someone
|
||||
// eventually join the room which will start the stats again.
|
||||
APP.conference.addConferenceListener(
|
||||
JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED,
|
||||
() => {
|
||||
if (APP.logCollector) {
|
||||
APP.logCollector.flush();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
APP.UI.initConference();
|
||||
|
||||
APP.keyboardshortcut.init();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/**
|
||||
* Implements in memory logs storage, used for testing/debugging.
|
||||
*
|
||||
* FIXME: move to base/logging
|
||||
*/
|
||||
export default class JitsiMeetInMemoryLogStorage {
|
||||
|
||||
|
|
|
@ -1,27 +1,45 @@
|
|||
/* global APP */
|
||||
import { getCurrentConference } from '../../react/features/base/conference';
|
||||
|
||||
/**
|
||||
* Implements logs storage through the CallStats.
|
||||
*
|
||||
* FIXME: move to base/logging
|
||||
*/
|
||||
export default class JitsiMeetLogStorage {
|
||||
|
||||
/**
|
||||
* Creates new <tt>JitsiMeetLogStorage</tt>
|
||||
* Creates new <tt>JitsiMeetLogStorage</tt>.
|
||||
*
|
||||
* @param {Function} getState - the Redux store's {@code getState} method.
|
||||
*/
|
||||
constructor() {
|
||||
constructor(getState) {
|
||||
/**
|
||||
* Counts each log entry, increases on every batch log entry stored.
|
||||
* @type {number}
|
||||
*/
|
||||
this.counter = 1;
|
||||
|
||||
/**
|
||||
* The Redux store's {@code getState} method.
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
this.getState = getState;
|
||||
}
|
||||
|
||||
/**
|
||||
* The JitsiMeetLogStorage is ready when the CallStats are started and
|
||||
* before refactoring the code it was after the conference has been joined.
|
||||
* A conference is considered joined when the 'conference' field is defined
|
||||
* in the base/conference state.
|
||||
*
|
||||
* @return {boolean} <tt>true</tt> when this storage is ready or
|
||||
* <tt>false</tt> otherwise.
|
||||
*/
|
||||
isReady() {
|
||||
return Boolean(APP.logCollectorStarted && APP.conference);
|
||||
const { conference } = this.getState()['features/base/conference'];
|
||||
|
||||
return Boolean(conference);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,8 +49,9 @@ export default class JitsiMeetLogStorage {
|
|||
* representing log lines or aggregated lines objects.
|
||||
*/
|
||||
storeLogs(logEntries) {
|
||||
const conference = getCurrentConference(this.getState());
|
||||
|
||||
if (!APP.conference.isCallstatsEnabled()) {
|
||||
if (!conference || !conference.isCallstatsEnabled()) {
|
||||
// Discard the logs if CallStats is not enabled.
|
||||
return;
|
||||
}
|
||||
|
@ -58,8 +77,9 @@ export default class JitsiMeetLogStorage {
|
|||
// on the way that could be uninitialized if the storeLogs
|
||||
// attempt would be made very early (which is unlikely)
|
||||
try {
|
||||
APP.conference._room.sendApplicationLog(logMessage);
|
||||
conference.sendApplicationLog(logMessage);
|
||||
} catch (error) {
|
||||
// FIXME whole objects logged
|
||||
// NOTE console is intentional here
|
||||
console.error(
|
||||
'Failed to store the logs: ', logMessage, error);
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
/**
|
||||
* The type of redux action which stores the log collector that will be
|
||||
* submitting the logs to CallStats.
|
||||
*
|
||||
* {
|
||||
* type: SET_LOG_COLLECTOR,
|
||||
* logCollector: Logger.LogCollector
|
||||
* }
|
||||
*/
|
||||
export const SET_LOG_COLLECTOR = Symbol('SET_LOG_COLLECTOR');
|
||||
|
||||
/**
|
||||
* The type of redux action which sets the configuration of the feature
|
||||
* base/logging.
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
/* @flow */
|
||||
|
||||
import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||
import { SET_LOG_COLLECTOR, SET_LOGGING_CONFIG } from './actionTypes';
|
||||
|
||||
/**
|
||||
* Stores a {@code Logger.LogCollector} instance which will be uploading logs
|
||||
* to CallStats.
|
||||
*
|
||||
* @param {Logger.LogCollector} logCollector - The log collector instance to be
|
||||
* stored in the Redux state of base/logging feature.
|
||||
* @returns {{
|
||||
* type,
|
||||
* logCollector: Object
|
||||
* }}
|
||||
*/
|
||||
export function setLogCollector(logCollector: ?Object) {
|
||||
return {
|
||||
type: SET_LOG_COLLECTOR,
|
||||
logCollector
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the configuration of the feature base/logging.
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
import Logger from 'jitsi-meet-logger';
|
||||
|
||||
import { APP_WILL_MOUNT } from '../app';
|
||||
import JitsiMeetJS, { LIB_WILL_INIT } from '../lib-jitsi-meet';
|
||||
import { CONFERENCE_JOINED, getCurrentConference } from '../conference';
|
||||
import JitsiMeetJS, {
|
||||
LIB_WILL_INIT,
|
||||
JitsiConferenceEvents
|
||||
} from '../lib-jitsi-meet';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
import JitsiMeetInMemoryLogStorage
|
||||
|
@ -12,6 +16,7 @@ import JitsiMeetLogStorage from '../../../../modules/util/JitsiMeetLogStorage';
|
|||
|
||||
import { isTestModeEnabled } from '../testing';
|
||||
|
||||
import { setLogCollector } from './actions';
|
||||
import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||
|
||||
declare var APP: Object;
|
||||
|
@ -28,6 +33,9 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
case APP_WILL_MOUNT:
|
||||
return _appWillMount(store, next, action);
|
||||
|
||||
case CONFERENCE_JOINED:
|
||||
return _conferenceJoined(store, next, action);
|
||||
|
||||
case LIB_WILL_INIT:
|
||||
return _libWillInit(store, next, action);
|
||||
|
||||
|
@ -66,28 +74,83 @@ function _appWillMount({ getState }, next, action) {
|
|||
return next(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the log collector, after {@link CONFERENCE_JOINED} action is reduced.
|
||||
*
|
||||
* @param {Store} store - The Redux store in which the specified {@code action}
|
||||
* is being dispatched.
|
||||
* @param {Dispatch} next - The Redux {@code dispatch} function to dispatch the
|
||||
* specified {@code action} to the specified {@code store}.
|
||||
* @param {Action} action - The Redux action {@code CONFERENCE_JOINED} which is
|
||||
* being dispatched in the specified {@code store}.
|
||||
* @private
|
||||
* @returns {*}
|
||||
*/
|
||||
function _conferenceJoined({ getState }, next, action) {
|
||||
|
||||
// Wait until the joined event is processed, so that the JitsiMeetLogStorage
|
||||
// will be ready.
|
||||
const result = next(action);
|
||||
|
||||
const { conference } = action;
|
||||
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();
|
||||
|
||||
// This event listener will flush the logs, before the statistics module
|
||||
// (CallStats) is stopped.
|
||||
//
|
||||
// NOTE The LogCollector is not stopped, because this event can be
|
||||
// triggered multiple times during single conference (whenever
|
||||
// statistics module is stopped). That includes the case when Jicofo
|
||||
// terminates a single person conference (one person left in the room
|
||||
// waiting for someone to join). It will then restart the media session
|
||||
// when someone eventually joins the room which will start the stats
|
||||
// again.
|
||||
conference.on(
|
||||
JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED,
|
||||
() => logCollector.flush()
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes logging in the app.
|
||||
*
|
||||
* @param {Store} store - The Redux store in which context the logging is to be
|
||||
* initialized.
|
||||
* @param {Object} loggingConfig - The configuration with which logging is to be
|
||||
* initialized.
|
||||
* @param {boolean} isTestingEnabled - Is debug logging enabled.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _initLogging(loggingConfig, isTestingEnabled) {
|
||||
function _initLogging({ dispatch, getState }, loggingConfig, isTestingEnabled) {
|
||||
const { logCollector } = getState()['features/base/logging'];
|
||||
|
||||
// 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).
|
||||
if (typeof APP === 'object'
|
||||
&& !APP.logCollector
|
||||
&& !loggingConfig.disableLogCollector) {
|
||||
APP.logCollector = new Logger.LogCollector(new JitsiMeetLogStorage());
|
||||
Logger.addGlobalTransport(APP.logCollector);
|
||||
JitsiMeetJS.addGlobalLogTransport(APP.logCollector);
|
||||
if (!logCollector && !loggingConfig.disableLogCollector) {
|
||||
const _logCollector
|
||||
= new Logger.LogCollector(new JitsiMeetLogStorage(getState));
|
||||
|
||||
if (isTestingEnabled) {
|
||||
Logger.addGlobalTransport(_logCollector);
|
||||
JitsiMeetJS.addGlobalLogTransport(_logCollector);
|
||||
dispatch(setLogCollector(_logCollector));
|
||||
|
||||
// The JitsiMeetInMemoryLogStorage can not be accessed on mobile through
|
||||
// the 'executeScript' method like it's done in torture tests for WEB.
|
||||
if (isTestingEnabled && typeof APP === 'object') {
|
||||
APP.debugLogs = new JitsiMeetInMemoryLogStorage();
|
||||
const debugLogCollector = new Logger.LogCollector(
|
||||
APP.debugLogs, { storeInterval: 1000 });
|
||||
|
@ -96,6 +159,11 @@ function _initLogging(loggingConfig, isTestingEnabled) {
|
|||
JitsiMeetJS.addGlobalLogTransport(debugLogCollector);
|
||||
debugLogCollector.start();
|
||||
}
|
||||
} else if (logCollector && loggingConfig.disableLogCollector) {
|
||||
Logger.removeGlobalTransport(logCollector);
|
||||
JitsiMeetJS.removeGlobalLogTransport(logCollector);
|
||||
logCollector.stop();
|
||||
dispatch(setLogCollector(undefined));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,7 +205,7 @@ function _libWillInit({ getState }, next, action) {
|
|||
* @returns {Object} The new state that is the result of the reduction of the
|
||||
* specified {@code action}.
|
||||
*/
|
||||
function _setLoggingConfig({ getState }, next, action) {
|
||||
function _setLoggingConfig({ dispatch, getState }, next, action) {
|
||||
const result = next(action);
|
||||
const newValue = getState()['features/base/logging'].config;
|
||||
const isTestingEnabled = isTestModeEnabled(getState());
|
||||
|
@ -151,7 +219,10 @@ function _setLoggingConfig({ getState }, next, action) {
|
|||
_setLogLevels(Logger, newValue);
|
||||
_setLogLevels(JitsiMeetJS, newValue);
|
||||
|
||||
_initLogging(newValue, isTestingEnabled);
|
||||
_initLogging({
|
||||
dispatch,
|
||||
getState
|
||||
}, newValue, isTestingEnabled);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// @flow
|
||||
|
||||
import { equals, ReducerRegistry } from '../redux';
|
||||
import { equals, ReducerRegistry, set } from '../redux';
|
||||
|
||||
import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||
import { SET_LOG_COLLECTOR, SET_LOGGING_CONFIG } from './actionTypes';
|
||||
|
||||
/**
|
||||
* The default/initial redux state of the feature base/logging.
|
||||
|
@ -12,7 +12,12 @@ import { SET_LOGGING_CONFIG } from './actionTypes';
|
|||
* }}
|
||||
*/
|
||||
const DEFAULT_STATE = {
|
||||
config: require('../../../../logging_config.js')
|
||||
config: require('../../../../logging_config.js'),
|
||||
|
||||
/**
|
||||
* The log collector.
|
||||
*/
|
||||
logCollector: undefined
|
||||
};
|
||||
|
||||
ReducerRegistry.register(
|
||||
|
@ -21,6 +26,9 @@ ReducerRegistry.register(
|
|||
switch (action.type) {
|
||||
case SET_LOGGING_CONFIG:
|
||||
return _setLoggingConfig(state, action);
|
||||
case SET_LOG_COLLECTOR: {
|
||||
return _setLogCollector(state, action);
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
|
@ -54,3 +62,17 @@ function _setLoggingConfig(state, action) {
|
|||
config
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces a specific Redux action SET_LOG_COLLECTOR of the feature
|
||||
* base/logging.
|
||||
*
|
||||
* @param {Object} state - The Redux state of the feature base/logging.
|
||||
* @param {Action} action - The Redux action SET_LOG_COLLECTOR to reduce.
|
||||
* @private
|
||||
* @returns {Object} The new state of the feature base/logging after the
|
||||
* reduction of the specified action.
|
||||
*/
|
||||
function _setLogCollector(state, action) {
|
||||
return set(state, 'logCollector', action.logCollector);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue