diff --git a/packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.ts b/packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.ts index 7ae50cb572d..2ee5f18b6d7 100644 --- a/packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.ts +++ b/packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.ts @@ -290,10 +290,12 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin { } = options; const identifiers: Event['event']['identifiers'] = { correlationId: 'unknown', + sessionCorrelationId: 'unknown', }; if (meeting) { identifiers.correlationId = meeting.correlationId; + identifiers.sessionCorrelationId = meeting.sessionCorrelationId; } if (sessionCorrelationId) { diff --git a/packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts b/packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts index 521a1222e29..64a9313aa86 100644 --- a/packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +++ b/packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts @@ -30,6 +30,7 @@ describe('internal-plugin-metrics', () => { const fakeMeeting = { id: '1', correlationId: 'correlationId', + sessionCorrelationId: undefined, callStateForMetrics: {}, environment: 'meeting_evn', locusUrl: 'locus/url', @@ -354,6 +355,36 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: undefined, + deviceId: 'deviceUrl', + locusId: 'url', + locusStartTime: 'lastActive', + locusUrl: 'locus/url', + machineId: 'installationId', + mediaAgentAlias: 'mediaAgentAlias', + mediaAgentGroupId: 'mediaAgentGroupId', + orgId: 'orgId', + userId: 'userId', + }); + }); + + it('should build identifiers correctly', () => { + cd.device = { + ...cd.device, + config: {installationId: 'installationId'}, + }; + + const res = cd.getIdentifiers({ + mediaConnections: [ + {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'}, + ], + meeting: fakeMeeting, + sessionCorrelationId: 'sessionCorrelationId', + }); + + assert.deepEqual(res, { + correlationId: 'correlationId', + sessionCorrelationId: 'sessionCorrelationId', deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -419,6 +450,7 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: undefined, webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1', deviceId: 'deviceUrl', @@ -452,6 +484,43 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: undefined, + webexConferenceIdStr: 'webexConferenceIdStr1', + globalMeetingId: 'globalMeetingId1', + deviceId: 'deviceUrl', + locusId: 'url', + locusStartTime: 'lastActive', + locusUrl: 'locus/url', + mediaAgentAlias: 'mediaAgentAlias', + mediaAgentGroupId: 'mediaAgentGroupId', + orgId: 'orgId', + userId: 'userId', + webexSiteName: 'siteName1', + }); + }); + + it('should build identifiers correctly with a meeting that has sessionCorrelationId', () => { + const res = cd.getIdentifiers({ + mediaConnections: [ + {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'}, + ], + webexConferenceIdStr: 'webexConferenceIdStr', + globalMeetingId: 'globalMeetingId', + meeting: { + ...fakeMeeting, + sessionCorrelationId: 'sessionCorrelationId1', + meetingInfo: { + ...fakeMeeting.meetingInfo, + confIdStr: 'webexConferenceIdStr1', + meetingId: 'globalMeetingId1', + siteName: 'siteName1', + }, + }, + }); + + assert.deepEqual(res, { + correlationId: 'correlationId', + sessionCorrelationId: 'sessionCorrelationId1', webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1', deviceId: 'deviceUrl', @@ -474,6 +543,7 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', webexConferenceIdStr: 'webexConferenceIdStr1', deviceId: 'deviceUrl', locusUrl: 'locus-url', @@ -490,6 +560,7 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', globalMeetingId: 'globalMeetingId1', deviceId: 'deviceUrl', locusUrl: 'locus-url', @@ -505,6 +576,23 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', + deviceId: 'deviceUrl', + locusUrl: 'locus-url', + orgId: 'orgId', + userId: 'userId', + }); + }); + + it('should build identifiers correctly given sessionCorrelationId', () => { + const res = cd.getIdentifiers({ + correlationId: 'correlationId', + sessionCorrelationId: 'sessionCorrelationId', + }); + + assert.deepEqual(res, { + correlationId: 'correlationId', + sessionCorrelationId: 'sessionCorrelationId', deviceId: 'deviceUrl', locusUrl: 'locus-url', orgId: 'orgId', @@ -533,6 +621,7 @@ describe('internal-plugin-metrics', () => { assert.deepEqual(res, { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', locusUrl: 'locus-url', deviceId: 'deviceUrl', orgId: 'orgId', @@ -623,6 +712,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -648,6 +738,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -684,6 +775,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -960,6 +1052,58 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId2', + sessionCorrelationId: undefined, + deviceId: 'deviceUrl', + locusId: 'url', + locusStartTime: 'lastActive', + locusUrl: 'locus/url', + mediaAgentAlias: 'alias', + mediaAgentGroupId: '1', + orgId: 'orgId', + userId: 'userId', + }, + loginType: 'fakeLoginType', + name: 'client.alert.displayed', + userType: 'host', + isConvergedArchitectureEnabled: undefined, + webexSubServiceType: undefined, + }, + eventId: 'my-fake-id', + origin: { + origin: 'fake-origin', + }, + originTime: { + sent: 'not_defined_yet', + triggered: now.toISOString(), + }, + senderCountryCode: 'UK', + version: 1, + }); + }); + + it('should use meeting loginType if present and meetingId provided, with sessionCorrelationId', () => { + const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics'); + sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'}); + const options = { + meetingId: fakeMeeting2.id, + mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}], + sessionCorrelationId: 'sessionCorrelationId1' + }; + + cd.submitClientEvent({ + name: 'client.alert.displayed', + options, + }); + + assert.calledWith(submitToCallDiagnosticsSpy, { + event: { + canProceed: true, + eventData: { + webClientDomain: 'whatever', + }, + identifiers: { + correlationId: 'correlationId2', + sessionCorrelationId: 'sessionCorrelationId1', deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -1017,6 +1161,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1', deviceId: 'deviceUrl', @@ -1095,6 +1240,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -1170,6 +1316,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', deviceId: 'deviceUrl', locusUrl: 'locus-url', orgId: 'orgId', @@ -1243,6 +1390,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: 'unknown', deviceId: 'deviceUrl', locusUrl: 'locus-url', orgId: 'orgId', @@ -1322,6 +1470,7 @@ describe('internal-plugin-metrics', () => { }, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, deviceId: 'deviceUrl', locusId: 'url', locusStartTime: 'lastActive', @@ -1454,6 +1603,7 @@ describe('internal-plugin-metrics', () => { canProceed: true, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1', userId: 'userId', @@ -1493,6 +1643,7 @@ describe('internal-plugin-metrics', () => { canProceed: true, identifiers: { correlationId: 'correlationId', + sessionCorrelationId: undefined, webexConferenceIdStr: 'webexConferenceIdStr1', globalMeetingId: 'globalMeetingId1', userId: 'userId', @@ -1538,6 +1689,7 @@ describe('internal-plugin-metrics', () => { locusUrl: 'locus/url', locusId: 'url', locusStartTime: 'lastActive', + sessionCorrelationId: undefined, }, eventData: {webClientDomain: 'whatever'}, intervals: [{}], @@ -2291,6 +2443,7 @@ describe('internal-plugin-metrics', () => { locusUrl: 'locus/url', orgId: 'orgId', userId: 'userId', + sessionCorrelationId: undefined, }, loginType: 'login-ci', name: 'client.exit.app', diff --git a/packages/@webex/plugin-meetings/src/meeting/index.ts b/packages/@webex/plugin-meetings/src/meeting/index.ts index 650f5cb193e..5b2d1cab5a5 100644 --- a/packages/@webex/plugin-meetings/src/meeting/index.ts +++ b/packages/@webex/plugin-meetings/src/meeting/index.ts @@ -227,6 +227,7 @@ export type AddMediaOptions = { export type CallStateForMetrics = { correlationId?: string; + sessionCorrelationId?: string; joinTrigger?: string; loginType?: string; }; @@ -742,12 +743,29 @@ export default class Meeting extends StatelessWebexPlugin { */ this.callStateForMetrics = attrs.callStateForMetrics || {}; const correlationId = attrs.correlationId || attrs.callStateForMetrics?.correlationId; + const sessionCorrelationId = + attrs.sessionCorrelationId || attrs.callStateForMetrics?.sessionCorrelationId; + if (sessionCorrelationId) { + LoggerProxy.logger.log( + `Meetings:index#constructor --> Initializing the meeting object with session correlation id from app ${correlationId}` + ); + this.callStateForMetrics.sessionCorrelationId = sessionCorrelationId; + } else { + LoggerProxy.logger.log( + `Meetings:index#constructor --> No session correlation id supplied. None will be generated and this field will remain blank` + ); + // TODO: supply a session from the meetings instance + this.callStateForMetrics.sessionCorrelationId = ''; + } if (correlationId) { LoggerProxy.logger.log( `Meetings:index#constructor --> Initializing the meeting object with correlation id from app ${correlationId}` ); this.callStateForMetrics.correlationId = correlationId; } else { + LoggerProxy.logger.log( + `Meetings:index#constructor --> Initializing the meeting object with generated correlation id from sdk ${this.id}` + ); this.callStateForMetrics.correlationId = this.id; } /** @@ -1581,6 +1599,22 @@ export default class Meeting extends StatelessWebexPlugin { this.callStateForMetrics.correlationId = correlationId; } + /** + * Getter - Returns callStateForMetrics.sessionCorrelationId + * @returns {string} + */ + get sessionCorrelationId() { + return this.callStateForMetrics.correlationId; + } + + /** + * Setter - sets callStateForMetrics.sessionCorrelationId + * @param {string} sessionCorrelationId + */ + set sessionCorrelationId(sessionCorrelationId: string) { + this.callStateForMetrics.sessionCorrelationId = sessionCorrelationId; + } + /** * Getter - Returns isoLocalClientMeetingJoinTime * This will be set once on meeting join, and not updated again diff --git a/packages/@webex/plugin-meetings/src/meetings/index.ts b/packages/@webex/plugin-meetings/src/meetings/index.ts index ccbf479842d..a9b79c52364 100644 --- a/packages/@webex/plugin-meetings/src/meetings/index.ts +++ b/packages/@webex/plugin-meetings/src/meetings/index.ts @@ -1081,6 +1081,7 @@ export default class Meetings extends WebexPlugin { * @param {CallStateForMetrics} callStateForMetrics - information about call state for metrics * @param {Object} [meetingInfo] - Pre-fetched complete meeting info * @param {String} [meetingLookupUrl] - meeting info prefetch url + * @param {string} sessionCorrelationId - the optional specified sessionCorrelationId (callStateForMetrics.sessionCorrelationId) can be provided instead * @returns {Promise} A new Meeting. * @public * @memberof Meetings @@ -1094,7 +1095,8 @@ export default class Meetings extends WebexPlugin { failOnMissingMeetingInfo = false, callStateForMetrics: CallStateForMetrics = undefined, meetingInfo = undefined, - meetingLookupUrl = undefined + meetingLookupUrl = undefined, + sessionCorrelationId: string = undefined ) { // Validate meeting information based on the provided destination and // type. This must be performed prior to determining if the meeting is @@ -1105,6 +1107,10 @@ export default class Meetings extends WebexPlugin { callStateForMetrics = {...(callStateForMetrics || {}), correlationId}; } + if (sessionCorrelationId) { + callStateForMetrics = {...(callStateForMetrics || {}), sessionCorrelationId}; + } + return ( this.meetingInfo .fetchInfoOptions(destination, type) diff --git a/packages/@webex/plugin-meetings/test/unit/spec/meeting/index.js b/packages/@webex/plugin-meetings/test/unit/spec/meeting/index.js index 2b947cfbdb6..dd234046488 100644 --- a/packages/@webex/plugin-meetings/test/unit/spec/meeting/index.js +++ b/packages/@webex/plugin-meetings/test/unit/spec/meeting/index.js @@ -307,7 +307,7 @@ describe('plugin-meetings', () => { assert.equal(meeting.resource, uuid2); assert.equal(meeting.deviceUrl, uuid3); assert.equal(meeting.correlationId, correlationId); - assert.deepEqual(meeting.callStateForMetrics, {correlationId}); + assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''}); assert.deepEqual(meeting.meetingInfo, {}); assert.instanceOf(meeting.members, Members); assert.calledOnceWithExactly( @@ -376,7 +376,7 @@ describe('plugin-meetings', () => { } ); assert.equal(newMeeting.correlationId, newMeeting.id); - assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id}); + assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id, sessionCorrelationId: ''}); }); it('correlationId can be provided in callStateForMetrics', () => { @@ -403,6 +403,36 @@ describe('plugin-meetings', () => { correlationId: uuid4, joinTrigger: 'fake-join-trigger', loginType: 'fake-login-type', + sessionCorrelationId: '', + }); + }); + + it('sessionCorrelationId can be provided in callStateForMetrics', () => { + const newMeeting = new Meeting( + { + userId: uuid1, + resource: uuid2, + deviceUrl: uuid3, + locus: {url: url1}, + destination: testDestination, + destinationType: DESTINATION_TYPE.MEETING_ID, + callStateForMetrics: { + correlationId: uuid4, + sessionCorrelationId: uuid1, + joinTrigger: 'fake-join-trigger', + loginType: 'fake-login-type', + }, + }, + { + parent: webex, + } + ); + assert.exists(newMeeting.sessionCorrelationId); + assert.deepEqual(newMeeting.callStateForMetrics, { + correlationId: uuid4, + sessionCorrelationId: uuid1, + joinTrigger: 'fake-join-trigger', + loginType: 'fake-login-type', }); }); @@ -6927,33 +6957,36 @@ describe('plugin-meetings', () => { describe('#setCorrelationId', () => { it('should set the correlationId and return undefined', () => { assert.equal(meeting.correlationId, correlationId); - assert.deepEqual(meeting.callStateForMetrics, {correlationId}); + assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''}); meeting.setCorrelationId(uuid1); assert.equal(meeting.correlationId, uuid1); - assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1}); + assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, sessionCorrelationId: ''}); }); }); describe('#updateCallStateForMetrics', () => { it('should update the callState, overriding existing values', () => { - assert.deepEqual(meeting.callStateForMetrics, {correlationId}); + assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''}); meeting.updateCallStateForMetrics({ correlationId: uuid1, + sessionCorrelationId: uuid3, joinTrigger: 'jt', loginType: 'lt', }); assert.deepEqual(meeting.callStateForMetrics, { correlationId: uuid1, + sessionCorrelationId: uuid3, joinTrigger: 'jt', loginType: 'lt', }); }); it('should update the callState, keeping non-supplied values', () => { - assert.deepEqual(meeting.callStateForMetrics, {correlationId}); + assert.deepEqual(meeting.callStateForMetrics, {correlationId, sessionCorrelationId: ''}); meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'}); assert.deepEqual(meeting.callStateForMetrics, { correlationId, + sessionCorrelationId: '', joinTrigger: 'jt', loginType: 'lt', }); diff --git a/packages/@webex/plugin-meetings/test/unit/spec/meetings/index.js b/packages/@webex/plugin-meetings/test/unit/spec/meetings/index.js index 937fa1fba73..21629c5f398 100644 --- a/packages/@webex/plugin-meetings/test/unit/spec/meetings/index.js +++ b/packages/@webex/plugin-meetings/test/unit/spec/meetings/index.js @@ -753,7 +753,9 @@ describe('plugin-meetings', () => { const FAKE_USE_RANDOM_DELAY = true; const correlationId = 'my-correlationId'; + const sessionCorrelationId = 'my-session-correlationId'; const callStateForMetrics = { + sessionCorrelationId: 'my-session-correlationId2', correlationId: 'my-correlationId2', joinTrigger: 'my-join-trigger', loginType: 'my-login-type', @@ -769,11 +771,15 @@ describe('plugin-meetings', () => { {}, correlationId, true, - callStateForMetrics + callStateForMetrics, + undefined, + undefined, + sessionCorrelationId ); assert.calledOnceWithExactly(fakeMeeting.setCallStateForMetrics, { ...callStateForMetrics, correlationId, + sessionCorrelationId, }); }); @@ -814,13 +820,14 @@ describe('plugin-meetings', () => { undefined, meetingInfo, 'meetingLookupURL', + sessionCorrelationId ], [ test1, test2, FAKE_USE_RANDOM_DELAY, {}, - {correlationId}, + {correlationId, sessionCorrelationId}, true, meetingInfo, 'meetingLookupURL', @@ -1719,6 +1726,7 @@ describe('plugin-meetings', () => { const expectedMeetingData = { correlationId: 'my-correlationId', callStateForMetrics: { + sessionCorrelationId: '', correlationId: 'my-correlationId', joinTrigger: 'my-join-trigger', loginType: 'my-login-type',