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}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onConferenceJoined() {
|
_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.UI.initConference();
|
||||||
|
|
||||||
APP.keyboardshortcut.init();
|
APP.keyboardshortcut.init();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Implements in memory logs storage, used for testing/debugging.
|
* Implements in memory logs storage, used for testing/debugging.
|
||||||
|
*
|
||||||
|
* FIXME: move to base/logging
|
||||||
*/
|
*/
|
||||||
export default class JitsiMeetInMemoryLogStorage {
|
export default class JitsiMeetInMemoryLogStorage {
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,45 @@
|
||||||
/* global APP */
|
import { getCurrentConference } from '../../react/features/base/conference';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements logs storage through the CallStats.
|
* Implements logs storage through the CallStats.
|
||||||
|
*
|
||||||
|
* FIXME: move to base/logging
|
||||||
*/
|
*/
|
||||||
export default class JitsiMeetLogStorage {
|
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.
|
* Counts each log entry, increases on every batch log entry stored.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.counter = 1;
|
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
|
* @return {boolean} <tt>true</tt> when this storage is ready or
|
||||||
* <tt>false</tt> otherwise.
|
* <tt>false</tt> otherwise.
|
||||||
*/
|
*/
|
||||||
isReady() {
|
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.
|
* representing log lines or aggregated lines objects.
|
||||||
*/
|
*/
|
||||||
storeLogs(logEntries) {
|
storeLogs(logEntries) {
|
||||||
|
const conference = getCurrentConference(this.getState());
|
||||||
|
|
||||||
if (!APP.conference.isCallstatsEnabled()) {
|
if (!conference || !conference.isCallstatsEnabled()) {
|
||||||
// Discard the logs if CallStats is not enabled.
|
// Discard the logs if CallStats is not enabled.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -58,8 +77,9 @@ export default class JitsiMeetLogStorage {
|
||||||
// on the way that could be uninitialized if the storeLogs
|
// on the way that could be uninitialized if the storeLogs
|
||||||
// attempt would be made very early (which is unlikely)
|
// attempt would be made very early (which is unlikely)
|
||||||
try {
|
try {
|
||||||
APP.conference._room.sendApplicationLog(logMessage);
|
conference.sendApplicationLog(logMessage);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// FIXME whole objects logged
|
||||||
// NOTE console is intentional here
|
// NOTE console is intentional here
|
||||||
console.error(
|
console.error(
|
||||||
'Failed to store the logs: ', logMessage, 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
|
* The type of redux action which sets the configuration of the feature
|
||||||
* base/logging.
|
* base/logging.
|
||||||
|
|
|
@ -1,6 +1,24 @@
|
||||||
/* @flow */
|
/* @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.
|
* Sets the configuration of the feature base/logging.
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
import Logger from 'jitsi-meet-logger';
|
import Logger from 'jitsi-meet-logger';
|
||||||
|
|
||||||
import { APP_WILL_MOUNT } from '../app';
|
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 { MiddlewareRegistry } from '../redux';
|
||||||
|
|
||||||
import JitsiMeetInMemoryLogStorage
|
import JitsiMeetInMemoryLogStorage
|
||||||
|
@ -12,6 +16,7 @@ import JitsiMeetLogStorage from '../../../../modules/util/JitsiMeetLogStorage';
|
||||||
|
|
||||||
import { isTestModeEnabled } from '../testing';
|
import { isTestModeEnabled } from '../testing';
|
||||||
|
|
||||||
|
import { setLogCollector } from './actions';
|
||||||
import { SET_LOGGING_CONFIG } from './actionTypes';
|
import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||||
|
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
|
@ -28,6 +33,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case APP_WILL_MOUNT:
|
case APP_WILL_MOUNT:
|
||||||
return _appWillMount(store, next, action);
|
return _appWillMount(store, next, action);
|
||||||
|
|
||||||
|
case CONFERENCE_JOINED:
|
||||||
|
return _conferenceJoined(store, next, action);
|
||||||
|
|
||||||
case LIB_WILL_INIT:
|
case LIB_WILL_INIT:
|
||||||
return _libWillInit(store, next, action);
|
return _libWillInit(store, next, action);
|
||||||
|
|
||||||
|
@ -66,28 +74,83 @@ function _appWillMount({ getState }, next, action) {
|
||||||
return 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.
|
* 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
|
* @param {Object} loggingConfig - The configuration with which logging is to be
|
||||||
* initialized.
|
* initialized.
|
||||||
* @param {boolean} isTestingEnabled - Is debug logging enabled.
|
* @param {boolean} isTestingEnabled - Is debug logging enabled.
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @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
|
// 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
|
// is done early to capture as much logs as possible. Captured logs will be
|
||||||
// cached, before the JitsiMeetLogStorage gets ready (statistics module is
|
// cached, before the JitsiMeetLogStorage gets ready (statistics module is
|
||||||
// initialized).
|
// initialized).
|
||||||
if (typeof APP === 'object'
|
if (!logCollector && !loggingConfig.disableLogCollector) {
|
||||||
&& !APP.logCollector
|
const _logCollector
|
||||||
&& !loggingConfig.disableLogCollector) {
|
= new Logger.LogCollector(new JitsiMeetLogStorage(getState));
|
||||||
APP.logCollector = new Logger.LogCollector(new JitsiMeetLogStorage());
|
|
||||||
Logger.addGlobalTransport(APP.logCollector);
|
|
||||||
JitsiMeetJS.addGlobalLogTransport(APP.logCollector);
|
|
||||||
|
|
||||||
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();
|
APP.debugLogs = new JitsiMeetInMemoryLogStorage();
|
||||||
const debugLogCollector = new Logger.LogCollector(
|
const debugLogCollector = new Logger.LogCollector(
|
||||||
APP.debugLogs, { storeInterval: 1000 });
|
APP.debugLogs, { storeInterval: 1000 });
|
||||||
|
@ -96,6 +159,11 @@ function _initLogging(loggingConfig, isTestingEnabled) {
|
||||||
JitsiMeetJS.addGlobalLogTransport(debugLogCollector);
|
JitsiMeetJS.addGlobalLogTransport(debugLogCollector);
|
||||||
debugLogCollector.start();
|
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
|
* @returns {Object} The new state that is the result of the reduction of the
|
||||||
* specified {@code action}.
|
* specified {@code action}.
|
||||||
*/
|
*/
|
||||||
function _setLoggingConfig({ getState }, next, action) {
|
function _setLoggingConfig({ dispatch, getState }, next, action) {
|
||||||
const result = next(action);
|
const result = next(action);
|
||||||
const newValue = getState()['features/base/logging'].config;
|
const newValue = getState()['features/base/logging'].config;
|
||||||
const isTestingEnabled = isTestModeEnabled(getState());
|
const isTestingEnabled = isTestModeEnabled(getState());
|
||||||
|
@ -151,7 +219,10 @@ function _setLoggingConfig({ getState }, next, action) {
|
||||||
_setLogLevels(Logger, newValue);
|
_setLogLevels(Logger, newValue);
|
||||||
_setLogLevels(JitsiMeetJS, newValue);
|
_setLogLevels(JitsiMeetJS, newValue);
|
||||||
|
|
||||||
_initLogging(newValue, isTestingEnabled);
|
_initLogging({
|
||||||
|
dispatch,
|
||||||
|
getState
|
||||||
|
}, newValue, isTestingEnabled);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
// @flow
|
// @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.
|
* The default/initial redux state of the feature base/logging.
|
||||||
|
@ -12,7 +12,12 @@ import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
config: require('../../../../logging_config.js')
|
config: require('../../../../logging_config.js'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The log collector.
|
||||||
|
*/
|
||||||
|
logCollector: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
ReducerRegistry.register(
|
ReducerRegistry.register(
|
||||||
|
@ -21,6 +26,9 @@ ReducerRegistry.register(
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_LOGGING_CONFIG:
|
case SET_LOGGING_CONFIG:
|
||||||
return _setLoggingConfig(state, action);
|
return _setLoggingConfig(state, action);
|
||||||
|
case SET_LOG_COLLECTOR: {
|
||||||
|
return _setLogCollector(state, action);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
|
@ -54,3 +62,17 @@ function _setLoggingConfig(state, action) {
|
||||||
config
|
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