diff --git a/react/features/analytics/AnalyticsEvents.js b/react/features/analytics/AnalyticsEvents.js index 715764959..93f6e7232 100644 --- a/react/features/analytics/AnalyticsEvents.js +++ b/react/features/analytics/AnalyticsEvents.js @@ -350,6 +350,27 @@ export function createRecordingDialogEvent(dialogName, buttonName) { }; } +/** + * Creates an event which indicates that an action related to recording has + * occured. + * + * @param {string} action - The action (e.g. 'start' or 'stop'). + * @param {string} type - The recording type (e.g. 'file' or 'live'). + * @param {number} value - The duration of the recording in seconds (for stop + * action). + * @returns {Object} The event in a format suitable for sending via + * sendAnalytics. + */ +export function createRecordingEvent(action, type, value) { + return { + action, + actionSubject: `recording.${type}`, + attributes: { + value + } + }; +} + /** * Creates an event which specifies that the "confirm" button on the remote * mute dialog has been clicked. diff --git a/react/features/recording/actions.js b/react/features/recording/actions.js index aa4143488..d937ec0d3 100644 --- a/react/features/recording/actions.js +++ b/react/features/recording/actions.js @@ -1,7 +1,6 @@ // @flow -import JitsiMeetJS from '../base/lib-jitsi-meet'; - +import JitsiMeetJS, { JitsiRecordingConstants } from '../base/lib-jitsi-meet'; import { hideNotification, showErrorNotification, @@ -138,6 +137,12 @@ export function showStoppedRecordingNotification(streamType: string) { * }} */ export function updateRecordingSessionData(session: Object) { + const status = session.getStatus(); + const timestamp + = status === JitsiRecordingConstants.status.ON + ? Date.now() / 1000 + : undefined; + return { type: RECORDING_SESSION_UPDATED, sessionData: { @@ -145,7 +150,8 @@ export function updateRecordingSessionData(session: Object) { id: session.getID(), liveStreamViewURL: session.getLiveStreamViewURL(), mode: session.getMode(), - status: session.getStatus() + status, + timestamp } }; } diff --git a/react/features/recording/middleware.js b/react/features/recording/middleware.js index b2c40527e..fe797e57a 100644 --- a/react/features/recording/middleware.js +++ b/react/features/recording/middleware.js @@ -1,5 +1,10 @@ /* @flow */ + +import { + createRecordingEvent, + sendAnalytics +} from '../analytics'; import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app'; import { CONFERENCE_WILL_JOIN, getCurrentConference } from '../base/conference'; import JitsiMeetJS, { @@ -117,6 +122,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { && (!oldSessionData || oldSessionData.status !== ON) && updatedSessionData.mode === JitsiRecordingConstants.mode.FILE) { + sendAnalytics(createRecordingEvent('start', 'file')); dispatch(playSound(RECORDING_ON_SOUND_ID)); } else if (updatedSessionData.status === OFF && (!oldSessionData || oldSessionData.status !== OFF)) { @@ -126,6 +132,15 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { if (updatedSessionData.mode === JitsiRecordingConstants.mode.FILE) { + let duration = 0; + + // eslint-disable-next-line max-depth + if (oldSessionData && oldSessionData.timestamp) { + duration + = (Date.now() / 1000) - oldSessionData.timestamp; + } + sendAnalytics( + createRecordingEvent('stop', 'file', duration)); dispatch(stopSound(RECORDING_ON_SOUND_ID)); dispatch(playSound(RECORDING_OFF_SOUND_ID)); }