From a60dfac633a7a7a0d44a8417933f156ca2da27c7 Mon Sep 17 00:00:00 2001 From: cmcgarry Date: Wed, 5 Nov 2025 12:03:21 +0000 Subject: [PATCH 1/2] feat(metrics): add prelogin metrics interface to new-metrics --- .../src/new-metrics.ts | 21 +++++++ .../src/prelogin-metrics.ts | 62 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts diff --git a/packages/@webex/internal-plugin-metrics/src/new-metrics.ts b/packages/@webex/internal-plugin-metrics/src/new-metrics.ts index e771fc9cddb..0bc82176a34 100644 --- a/packages/@webex/internal-plugin-metrics/src/new-metrics.ts +++ b/packages/@webex/internal-plugin-metrics/src/new-metrics.ts @@ -9,6 +9,7 @@ import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics'; import BehavioralMetrics from './behavioral-metrics'; import OperationalMetrics from './operational-metrics'; import BusinessMetrics from './business-metrics'; +import PreLoginMetrics from './prelogin-metrics'; import { RecursivePartial, MetricEventProduct, @@ -45,6 +46,7 @@ class Metrics extends WebexPlugin { behavioralMetrics: BehavioralMetrics; operationalMetrics: OperationalMetrics; businessMetrics: BusinessMetrics; + preLoginMetrics: PreLoginMetrics; isReady = false; /** @@ -87,6 +89,8 @@ class Metrics extends WebexPlugin { this.webex.once('ready', () => { // @ts-ignore this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex}); + // @ts-ignore + this.preLoginMetrics = new PreLoginMetrics({}, {parent: this.webex}); this.isReady = true; this.setDelaySubmitClientEvents({ shouldDelay: this.delaySubmitClientEvents, @@ -251,6 +255,23 @@ class Metrics extends WebexPlugin { return this.businessMetrics.submitBusinessEvent({name, payload, table, metadata}); } + /** + * Call Analyzer: Pre-Login Event + * @param args + */ + submitPreLoginEvent(preLoginId: string, name: string, payload: EventPayload): Promise { + if (!this.isReady) { + // @ts-ignore + this.webex.logger.log( + `NewMetrics: @submitPreLoginEvent. Attempted to submit before webex.ready: ${name}` + ); + + return Promise.resolve(); + } + + return this.preLoginMetrics.submitPreLoginEvent(preLoginId, name, payload); + } + /** * Call Analyzer: Media Quality Event * @param args diff --git a/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts b/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts new file mode 100644 index 00000000000..e466610b593 --- /dev/null +++ b/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts @@ -0,0 +1,62 @@ +import GenericMetrics from './generic-metrics'; +import {EventPayload} from './metrics.types'; +import PreLoginMetricsBatcher from './prelogin-metrics-batcher'; + +/** + * @param {string} name - Metric name + * @param {EventPayload} payload - Metric payload + * @returns {object} Metrics Payload + */ +function buildEvent(name: string, payload: EventPayload) { + return { + type: ['business'], + eventPayload: { + key: name, + client_timestamp: new Date().toISOString(), + // ...metadata, + value: payload, + }, + }; +} + +/** + * @description Util class to handle PreLogin Metrics + * @export + * @class PreLoginMetrics + */ +export default class PreLoginMetrics extends GenericMetrics { + // @ts-ignore + private preLoginMetricsBatcher: PreLoginMetricsBatcher; + + /** + * Constructor + * @param {any[]} args - Constructor arguments + * @constructor + */ + constructor(...args) { + super(...args); + // @ts-ignore + this.logger = this.webex.logger; + // @ts-ignore + this.preLoginMetricsBatcher = new PreLoginMetricsBatcher({}, {parent: this.webex}); + } + + /** + * @param {string} preLoginId - A string representing the pre-login user ID + * @param {string} name - Metric name + * @param {EventPayload} payload - Metric payload + * @returns {Promise} Metrics Payload + */ + public submitPreLoginEvent( + preLoginId: string, + name: string, + payload: EventPayload + ): Promise { + // build metrics-a event type + const finalEvent = buildEvent(name, payload); + + this.preLoginMetricsBatcher.savePreLoginId(preLoginId); + + return this.preLoginMetricsBatcher.request(finalEvent); + } +} From d7cbf19e1b45977005787765cc0de2fec5c9a9ca Mon Sep 17 00:00:00 2001 From: cmcgarry Date: Thu, 6 Nov 2025 15:40:50 +0000 Subject: [PATCH 2/2] feat(metrics): add prelogin metrics interface to new-metrics - update api --- .../src/new-metrics.ts | 19 +++++- .../src/prelogin-metrics.ts | 62 ++++++++++++++----- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/packages/@webex/internal-plugin-metrics/src/new-metrics.ts b/packages/@webex/internal-plugin-metrics/src/new-metrics.ts index 0bc82176a34..2e58834516a 100644 --- a/packages/@webex/internal-plugin-metrics/src/new-metrics.ts +++ b/packages/@webex/internal-plugin-metrics/src/new-metrics.ts @@ -259,7 +259,17 @@ class Metrics extends WebexPlugin { * Call Analyzer: Pre-Login Event * @param args */ - submitPreLoginEvent(preLoginId: string, name: string, payload: EventPayload): Promise { + SubmitPreLoginEvent({ + name, + preLoginId, + payload, + metadata, + }: { + name: string; + preLoginId: string; + payload: EventPayload; + metadata?: EventPayload; + }): Promise { if (!this.isReady) { // @ts-ignore this.webex.logger.log( @@ -269,7 +279,12 @@ class Metrics extends WebexPlugin { return Promise.resolve(); } - return this.preLoginMetrics.submitPreLoginEvent(preLoginId, name, payload); + return this.preLoginMetrics.submitPreLoginEvent({ + name, + preLoginId, + payload, + metadata, + }); } /** diff --git a/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts b/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts index e466610b593..05da0577800 100644 --- a/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts +++ b/packages/@webex/internal-plugin-metrics/src/prelogin-metrics.ts @@ -1,20 +1,31 @@ import GenericMetrics from './generic-metrics'; -import {EventPayload} from './metrics.types'; +import {EventPayload, Table} from './metrics.types'; import PreLoginMetricsBatcher from './prelogin-metrics-batcher'; /** + * Builds a formatted event object for metrics submission. * @param {string} name - Metric name - * @param {EventPayload} payload - Metric payload - * @returns {object} Metrics Payload + * @param {string} preLoginId - Pre-login user identifier + * @param {EventPayload} payload - Metric payload data + * @param {EventPayload} metadata - Additional metadata to include in the event + * @returns {object} Formatted metrics event object with type, eventPayload, and timestamp */ -function buildEvent(name: string, payload: EventPayload) { +function buildEvent( + name: string, + preLoginId: string, + payload: EventPayload, + metadata: EventPayload +) { + const payloadWithPreLoginId = {...payload, preLoginId}; + return { type: ['business'], eventPayload: { key: name, client_timestamp: new Date().toISOString(), - // ...metadata, - value: payload, + preLoginId, + ...metadata, + value: payloadWithPreLoginId, }, }; } @@ -42,18 +53,35 @@ export default class PreLoginMetrics extends GenericMetrics { } /** - * @param {string} preLoginId - A string representing the pre-login user ID - * @param {string} name - Metric name - * @param {EventPayload} payload - Metric payload - * @returns {Promise} Metrics Payload + * Submit a business metric to our metrics endpoint. + * Routes to the correct table with the correct schema payload by table. + * @see https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA + * @param {Object} options - The options object + * @param {string} options.name - Name of the metric + * @param {string} options.preLoginId - ID to identify pre-login user + * @param {EventPayload} options.payload - User payload of the metric + * @param {EventPayload} [options.metadata] - Optional metadata to include outside of eventPayload.value + * @returns {Promise} Promise that resolves when the metric is submitted */ - public submitPreLoginEvent( - preLoginId: string, - name: string, - payload: EventPayload - ): Promise { - // build metrics-a event type - const finalEvent = buildEvent(name, payload); + public submitPreLoginEvent({ + name, + preLoginId, + payload, + metadata, + }: { + name: string; + preLoginId: string; + payload: EventPayload; + metadata?: EventPayload; + }): Promise { + if (!metadata) { + metadata = {}; + } + if (!metadata.appType) { + metadata.appType = 'Web Client'; + } + + const finalEvent = buildEvent(name, preLoginId, payload, metadata); this.preLoginMetricsBatcher.savePreLoginId(preLoginId);