@webex/contact-center 3.12.0-next.9 → 3.12.0-task-refactor.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +438 -0
- package/ai-docs/README.md +131 -0
- package/ai-docs/RULES.md +455 -0
- package/ai-docs/patterns/event-driven-patterns.md +485 -0
- package/ai-docs/patterns/testing-patterns.md +480 -0
- package/ai-docs/patterns/typescript-patterns.md +365 -0
- package/ai-docs/templates/README.md +102 -0
- package/ai-docs/templates/documentation/create-agents-md.md +240 -0
- package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
- package/ai-docs/templates/existing-service/bug-fix.md +254 -0
- package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
- package/ai-docs/templates/new-method/00-master.md +80 -0
- package/ai-docs/templates/new-method/01-requirements.md +232 -0
- package/ai-docs/templates/new-method/02-implementation.md +295 -0
- package/ai-docs/templates/new-method/03-tests.md +201 -0
- package/ai-docs/templates/new-method/04-validation.md +141 -0
- package/ai-docs/templates/new-service/00-master.md +109 -0
- package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
- package/ai-docs/templates/new-service/02-code-generation.md +346 -0
- package/ai-docs/templates/new-service/03-integration.md +178 -0
- package/ai-docs/templates/new-service/04-test-generation.md +205 -0
- package/ai-docs/templates/new-service/05-validation.md +145 -0
- package/dist/cc.js +65 -123
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +13 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +26 -13
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +7 -6
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +0 -3
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/Util.js +2 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/types.js +16 -14
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +0 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +79 -55
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +17 -92
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +5 -25
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +1 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +644 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +45 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +556 -532
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +132 -28
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +7 -6
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +0 -51
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +77 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +366 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +139 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +256 -0
- package/dist/services/task/state-machine/guards.js.map +1 -0
- package/dist/services/task/state-machine/index.js +53 -0
- package/dist/services/task/state-machine/index.js.map +1 -0
- package/dist/services/task/state-machine/types.js +54 -0
- package/dist/services/task/state-machine/types.js.map +1 -0
- package/dist/services/task/state-machine/uiControlsComputer.js +369 -0
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
- package/dist/services/task/taskDataNormalizer.js +99 -0
- package/dist/services/task/taskDataNormalizer.js.map +1 -0
- package/dist/services/task/types.js +157 -18
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1031 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +149 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/types/cc.d.ts +4 -33
- package/dist/types/constants.d.ts +13 -2
- package/dist/types/index.d.ts +11 -5
- package/dist/types/metrics/constants.d.ts +5 -3
- package/dist/types/services/ApiAiAssistant.d.ts +1 -1
- package/dist/types/services/config/types.d.ts +97 -25
- package/dist/types/services/core/Err.d.ts +0 -2
- package/dist/types/services/core/Utils.d.ts +25 -23
- package/dist/types/services/core/aqm-reqs.d.ts +0 -49
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
- package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
- package/dist/types/services/core/websocket/types.d.ts +1 -1
- package/dist/types/services/index.d.ts +1 -1
- package/dist/types/services/task/Task.d.ts +146 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskUtils.d.ts +39 -8
- package/dist/types/services/task/constants.d.ts +5 -4
- package/dist/types/services/task/dialer.d.ts +0 -15
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
- package/dist/types/services/task/state-machine/actions.d.ts +8 -0
- package/dist/types/services/task/state-machine/constants.d.ts +91 -0
- package/dist/types/services/task/state-machine/guards.d.ts +78 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +256 -0
- package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
- package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
- package/dist/types/services/task/types.d.ts +539 -88
- package/dist/types/services/task/voice/Voice.d.ts +183 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +68 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +70 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +14 -11
- package/src/cc.ts +91 -177
- package/src/constants.ts +13 -2
- package/src/index.ts +14 -5
- package/src/metrics/ai-docs/AGENTS.md +348 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
- package/src/metrics/behavioral-events.ts +28 -14
- package/src/metrics/constants.ts +7 -8
- package/src/services/ApiAiAssistant.ts +2 -4
- package/src/services/agent/ai-docs/AGENTS.md +238 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
- package/src/services/ai-docs/AGENTS.md +384 -0
- package/src/services/config/Util.ts +2 -3
- package/src/services/config/ai-docs/AGENTS.md +253 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
- package/src/services/config/types.ts +108 -20
- package/src/services/constants.ts +0 -1
- package/src/services/core/Err.ts +0 -1
- package/src/services/core/Utils.ts +90 -67
- package/src/services/core/ai-docs/AGENTS.md +379 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
- package/src/services/core/aqm-reqs.ts +22 -100
- package/src/services/core/websocket/WebSocketManager.ts +4 -23
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -2
- package/src/services/task/Task.ts +785 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +567 -633
- package/src/services/task/TaskUtils.ts +175 -31
- package/src/services/task/ai-docs/AGENTS.md +448 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
- package/src/services/task/constants.ts +5 -4
- package/src/services/task/dialer.ts +1 -56
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
- package/src/services/task/state-machine/actions.ts +409 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
- package/src/services/task/state-machine/constants.ts +150 -0
- package/src/services/task/state-machine/guards.ts +295 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +228 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +529 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +641 -95
- package/src/services/task/voice/Voice.ts +1255 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +88 -5
- package/src/utils/AGENTS.md +276 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +59 -142
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
- package/test/unit/spec/services/config/index.ts +26 -55
- package/test/unit/spec/services/core/Utils.ts +103 -52
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
- package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +416 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +781 -1735
- package/test/unit/spec/services/task/TaskUtils.ts +125 -0
- package/test/unit/spec/services/task/dialer.ts +112 -198
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +587 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +242 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
- package/dist/services/task/index.js +0 -1525
- package/dist/services/task/index.js.map +0 -1
- package/dist/types/services/task/index.d.ts +0 -650
- package/src/services/task/index.ts +0 -1801
- package/test/unit/spec/services/task/index.ts +0 -2184
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# Metrics Module - AI Agent Guide
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Track behavioral, operational, and business metrics for Contact Center SDK operations using a singleton `MetricsManager`. Provides event timing, payload preparation, batching, and submission to the Webex metrics backend.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import MetricsManager from '../metrics/MetricsManager';
|
|
11
|
+
import {METRIC_EVENT_NAMES} from '../metrics/constants';
|
|
12
|
+
|
|
13
|
+
// Get the singleton instance (webex is set during cc.register())
|
|
14
|
+
const metrics = MetricsManager.getInstance();
|
|
15
|
+
|
|
16
|
+
// Time an operation, then track its result
|
|
17
|
+
metrics.timeEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS);
|
|
18
|
+
// ... perform the operation ...
|
|
19
|
+
metrics.trackEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, {agentId: '123'});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Key Capabilities
|
|
25
|
+
|
|
26
|
+
- **Singleton Pattern**: Single `MetricsManager` instance shared across the entire SDK
|
|
27
|
+
- **Three Metric Types**: Behavioral (user actions), operational (system events), business (business-level analytics)
|
|
28
|
+
- **Event Timing**: `timeEvent` + `trackEvent` pattern automatically calculates `duration_ms`
|
|
29
|
+
- **Queued Submission**: Events are queued until the Webex SDK is ready, then submitted in order
|
|
30
|
+
- **Behavioral Taxonomy**: Structured `product.agent.target.verb` naming convention for behavioral events
|
|
31
|
+
- **Payload Preparation**: Automatic cleanup of empty fields, space-to-underscore conversion, and `tabHidden` metadata
|
|
32
|
+
- **AQM Response Helpers**: Static methods to extract common tracking fields from AQM responses
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## API Reference
|
|
37
|
+
|
|
38
|
+
### Methods
|
|
39
|
+
|
|
40
|
+
#### `MetricsManager.getInstance(options?)`
|
|
41
|
+
|
|
42
|
+
Returns the singleton instance. On first call with `{webex}`, binds to the Webex SDK and begins listening for the `ready` event.
|
|
43
|
+
|
|
44
|
+
**Parameters**:
|
|
45
|
+
- `options` (object, optional): `{webex: WebexSDK}` - The Webex SDK instance
|
|
46
|
+
|
|
47
|
+
**Returns**: `MetricsManager`
|
|
48
|
+
|
|
49
|
+
**Example**:
|
|
50
|
+
```typescript
|
|
51
|
+
// During initialization (called internally by cc.register())
|
|
52
|
+
const metrics = MetricsManager.getInstance({webex});
|
|
53
|
+
|
|
54
|
+
// Subsequent calls (no webex needed)
|
|
55
|
+
const metrics = MetricsManager.getInstance();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
#### `metrics.timeEvent(keys)`
|
|
61
|
+
|
|
62
|
+
Starts a timer for one or more event keys. When a matching `trackEvent` / `trackBehavioralEvent` / `trackOperationalEvent` / `trackBusinessEvent` is called, `duration_ms` is automatically added to the payload.
|
|
63
|
+
|
|
64
|
+
**Parameters**:
|
|
65
|
+
- `keys` (string | string[]): One or more `METRIC_EVENT_NAMES` values. The first key is the tracking key; all keys in the array will resolve the same timer.
|
|
66
|
+
|
|
67
|
+
**Returns**: `void`
|
|
68
|
+
|
|
69
|
+
**Example**:
|
|
70
|
+
```typescript
|
|
71
|
+
// Single key
|
|
72
|
+
metrics.timeEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS);
|
|
73
|
+
|
|
74
|
+
// Multiple keys (success/failure share one timer)
|
|
75
|
+
metrics.timeEvent([
|
|
76
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
77
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
78
|
+
]);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
#### `metrics.trackEvent(name, payload?, metricServices?)`
|
|
84
|
+
|
|
85
|
+
Tracks an event across one or more metric services.
|
|
86
|
+
|
|
87
|
+
**Parameters**:
|
|
88
|
+
- `name` (METRIC_EVENT_NAMES): The event name constant
|
|
89
|
+
- `payload` (EventPayload, optional): Key-value pairs of event data
|
|
90
|
+
- `metricServices` (MetricsType[], optional): Array of `'behavioral'` | `'operational'` | `'business'` (default: `['behavioral']`)
|
|
91
|
+
|
|
92
|
+
**Returns**: `void`
|
|
93
|
+
|
|
94
|
+
**Example**:
|
|
95
|
+
```typescript
|
|
96
|
+
// Behavioral only (default)
|
|
97
|
+
metrics.trackEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, {agentId: '123'});
|
|
98
|
+
|
|
99
|
+
// Multiple services
|
|
100
|
+
metrics.trackEvent(
|
|
101
|
+
METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS,
|
|
102
|
+
{interactionId: 'abc'},
|
|
103
|
+
['behavioral', 'operational']
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
#### `metrics.trackBehavioralEvent(name, options?)`
|
|
110
|
+
|
|
111
|
+
Tracks a single behavioral event. Looks up the event taxonomy from `behavioral-events.ts` and submits via `webex.internal.newMetrics.submitBehavioralEvent`.
|
|
112
|
+
|
|
113
|
+
**Parameters**:
|
|
114
|
+
- `name` (METRIC_EVENT_NAMES): The event name
|
|
115
|
+
- `options` (EventPayload, optional): Additional payload data
|
|
116
|
+
|
|
117
|
+
**Returns**: `void`
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
#### `metrics.trackOperationalEvent(name, options?)`
|
|
122
|
+
|
|
123
|
+
Tracks a single operational event. Prefixes the event name with `WXCC_SDK_` and submits via `webex.internal.newMetrics.submitOperationalEvent`.
|
|
124
|
+
|
|
125
|
+
**Parameters**:
|
|
126
|
+
- `name` (METRIC_EVENT_NAMES): The event name
|
|
127
|
+
- `options` (EventPayload, optional): Additional payload data
|
|
128
|
+
|
|
129
|
+
**Returns**: `void`
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
#### `metrics.trackBusinessEvent(name, options?)`
|
|
134
|
+
|
|
135
|
+
Tracks a single business event. Prefixes the event name with `WXCC_SDK_` and submits via `webex.internal.newMetrics.submitBusinessEvent` with `appType: 'wxcc_sdk'`.
|
|
136
|
+
|
|
137
|
+
**Parameters**:
|
|
138
|
+
- `name` (METRIC_EVENT_NAMES): The event name
|
|
139
|
+
- `options` (EventPayload, optional): Additional payload data
|
|
140
|
+
|
|
141
|
+
**Returns**: `void`
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
#### `metrics.setMetricsDisabled(disabled)`
|
|
146
|
+
|
|
147
|
+
Enables or disables metrics collection. When disabled, all pending events are cleared and new events are dropped.
|
|
148
|
+
|
|
149
|
+
**Parameters**:
|
|
150
|
+
- `disabled` (boolean): `true` to disable, `false` to enable
|
|
151
|
+
|
|
152
|
+
**Returns**: `void`
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
#### `MetricsManager.getCommonTrackingFieldForAQMResponse(response)`
|
|
157
|
+
|
|
158
|
+
Static helper that extracts common tracking fields from an AQM success response.
|
|
159
|
+
|
|
160
|
+
**Parameters**:
|
|
161
|
+
- `response` (any): The AQM response object
|
|
162
|
+
|
|
163
|
+
**Returns**: `Record<string, any>` with fields: `agentId`, `agentSessionId`, `teamId`, `siteId`, `orgId`, `eventType`, `trackingId`, `notifTrackingId`
|
|
164
|
+
|
|
165
|
+
**Example**:
|
|
166
|
+
```typescript
|
|
167
|
+
const fields = MetricsManager.getCommonTrackingFieldForAQMResponse(aqmResponse);
|
|
168
|
+
metrics.trackEvent(METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS, {
|
|
169
|
+
...fields,
|
|
170
|
+
interactionId: task.interactionId,
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
#### `MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failureResponse)`
|
|
177
|
+
|
|
178
|
+
Static helper that extracts common tracking fields from an AQM failure response.
|
|
179
|
+
|
|
180
|
+
**Parameters**:
|
|
181
|
+
- `failureResponse` (Failure): The AQM failure response object
|
|
182
|
+
|
|
183
|
+
**Returns**: `Record<string, any>` with fields: `agentId`, `trackingId`, `notifTrackingId`, `orgId`, `failureType`, `failureReason`, `reasonCode`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
#### `MetricsManager.resetInstance()`
|
|
188
|
+
|
|
189
|
+
Resets the singleton instance. Used for testing only.
|
|
190
|
+
|
|
191
|
+
**Returns**: `void`
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Metric Event Names
|
|
196
|
+
|
|
197
|
+
All event names are defined in `METRIC_EVENT_NAMES` (`constants.ts`). Events follow a `<Category> <Action> <Result>` pattern.
|
|
198
|
+
|
|
199
|
+
### Agent Events
|
|
200
|
+
|
|
201
|
+
| Constant | Value | Description |
|
|
202
|
+
|----------|-------|-------------|
|
|
203
|
+
| `STATION_LOGIN_SUCCESS` | `'Station Login Success'` | Agent station login succeeded |
|
|
204
|
+
| `STATION_LOGIN_FAILED` | `'Station Login Failed'` | Agent station login failed |
|
|
205
|
+
| `STATION_LOGOUT_SUCCESS` | `'Station Logout Success'` | Agent station logout succeeded |
|
|
206
|
+
| `STATION_LOGOUT_FAILED` | `'Station Logout Failed'` | Agent station logout failed |
|
|
207
|
+
| `STATION_RELOGIN_SUCCESS` | `'Station Relogin Success'` | Silent relogin succeeded |
|
|
208
|
+
| `STATION_RELOGIN_FAILED` | `'Station Relogin Failed'` | Silent relogin failed |
|
|
209
|
+
| `AGENT_STATE_CHANGE_SUCCESS` | `'Agent State Change Success'` | State change succeeded |
|
|
210
|
+
| `AGENT_STATE_CHANGE_FAILED` | `'Agent State Change Failed'` | State change failed |
|
|
211
|
+
| `FETCH_BUDDY_AGENTS_SUCCESS` | `'Fetch Buddy Agents Success'` | Buddy agents fetch succeeded |
|
|
212
|
+
| `FETCH_BUDDY_AGENTS_FAILED` | `'Fetch Buddy Agents Failed'` | Buddy agents fetch failed |
|
|
213
|
+
| `AGENT_RONA` | `'Agent RONA'` | Agent Ring-On-No-Answer triggered |
|
|
214
|
+
| `AGENT_CONTACT_ASSIGN_FAILED` | `'Agent Contact Assign Failed'` | Contact assignment failed |
|
|
215
|
+
| `AGENT_INVITE_FAILED` | `'Agent Invite Failed'` | Agent invite failed |
|
|
216
|
+
| `AGENT_DEVICE_TYPE_UPDATE_SUCCESS` | `'Agent Device Type Update Success'` | Device type update succeeded |
|
|
217
|
+
| `AGENT_DEVICE_TYPE_UPDATE_FAILED` | `'Agent Device Type Update Failed'` | Device type update failed |
|
|
218
|
+
|
|
219
|
+
### Task Events
|
|
220
|
+
|
|
221
|
+
| Constant | Value | Description |
|
|
222
|
+
|----------|-------|-------------|
|
|
223
|
+
| `TASK_ACCEPT_SUCCESS` / `FAILED` | `'Task Accept ...'` | Task accept result |
|
|
224
|
+
| `TASK_DECLINE_SUCCESS` / `FAILED` | `'Task Decline ...'` | Task decline result |
|
|
225
|
+
| `TASK_END_SUCCESS` / `FAILED` | `'Task End ...'` | Task end result |
|
|
226
|
+
| `TASK_WRAPUP_SUCCESS` / `FAILED` | `'Task Wrapup ...'` | Task wrapup result |
|
|
227
|
+
| `TASK_HOLD_SUCCESS` / `FAILED` | `'Task Hold ...'` | Task hold result |
|
|
228
|
+
| `TASK_RESUME_SUCCESS` / `FAILED` | `'Task Resume ...'` | Task resume result |
|
|
229
|
+
| `TASK_CONSULT_START_SUCCESS` / `FAILED` | `'Task Consult Start ...'` | Consult start result |
|
|
230
|
+
| `TASK_CONSULT_END_SUCCESS` / `FAILED` | `'Task Consult End ...'` | Consult end result |
|
|
231
|
+
| `TASK_TRANSFER_SUCCESS` / `FAILED` | `'Task Transfer ...'` | Transfer result |
|
|
232
|
+
| `TASK_PAUSE_RECORDING_SUCCESS` / `FAILED` | `'Task Pause Recording ...'` | Pause recording result |
|
|
233
|
+
| `TASK_RESUME_RECORDING_SUCCESS` / `FAILED` | `'Task Resume Recording ...'` | Resume recording result |
|
|
234
|
+
| `TASK_ACCEPT_CONSULT_SUCCESS` / `FAILED` | `'Task Accept Consult ...'` | Accept consult result |
|
|
235
|
+
| `TASK_AUTO_ANSWER_SUCCESS` / `FAILED` | `'Task Auto Answer ...'` | Auto-answer result |
|
|
236
|
+
| `TASK_OUTDIAL_SUCCESS` / `FAILED` | `'Task Outdial ...'` | Outdial result |
|
|
237
|
+
|
|
238
|
+
### Conference Events
|
|
239
|
+
|
|
240
|
+
| Constant | Value | Description |
|
|
241
|
+
|----------|-------|-------------|
|
|
242
|
+
| `TASK_CONFERENCE_START_SUCCESS` / `FAILED` | `'Task Conference Start ...'` | Conference start result |
|
|
243
|
+
| `TASK_CONFERENCE_END_SUCCESS` / `FAILED` | `'Task Conference End ...'` | Conference end result |
|
|
244
|
+
| `TASK_CONFERENCE_TRANSFER_SUCCESS` / `FAILED` | `'Task Conference Transfer ...'` | Conference transfer result |
|
|
245
|
+
| `TASK_CONFERENCE_EXIT_SUCCESS` / `FAILED` | `'Task Conference Exit ...'` | Conference exit result |
|
|
246
|
+
| `TASK_SWITCH_CALL_SUCCESS` / `FAILED` | `'Task Switch Call ...'` | Switch call result |
|
|
247
|
+
|
|
248
|
+
### System Events
|
|
249
|
+
|
|
250
|
+
| Constant | Value | Description |
|
|
251
|
+
|----------|-------|-------------|
|
|
252
|
+
| `WEBSOCKET_REGISTER_SUCCESS` / `FAILED` | `'Websocket Register ...'` | WebSocket registration result |
|
|
253
|
+
| `WEBSOCKET_DEREGISTER_SUCCESS` / `FAIL` | `'Websocket Deregister ...'` | WebSocket deregistration result |
|
|
254
|
+
| `WEBSOCKET_EVENT_RECEIVED` | `'Websocket Event Received'` | WebSocket event received |
|
|
255
|
+
| `UPLOAD_LOGS_SUCCESS` / `FAILED` | `'Upload Logs ...'` | Log upload result |
|
|
256
|
+
|
|
257
|
+
### Data Fetch Events
|
|
258
|
+
|
|
259
|
+
| Constant | Value | Description |
|
|
260
|
+
|----------|-------|-------------|
|
|
261
|
+
| `ENTRYPOINT_FETCH_SUCCESS` / `FAILED` | `'Entrypoint Fetch ...'` | Entry point fetch result |
|
|
262
|
+
| `ADDRESSBOOK_FETCH_SUCCESS` / `FAILED` | `'AddressBook Fetch ...'` | Address book fetch result |
|
|
263
|
+
| `QUEUE_FETCH_SUCCESS` / `FAILED` | `'Queue Fetch ...'` | Queue fetch result |
|
|
264
|
+
| `OUTDIAL_ANI_EP_FETCH_SUCCESS` / `FAILED` | `'Outdial ANI Entries Fetch ...'` | Outdial ANI entries fetch result |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Behavioral Event Taxonomy
|
|
269
|
+
|
|
270
|
+
Each behavioral event maps to a structured taxonomy in `behavioral-events.ts`:
|
|
271
|
+
|
|
272
|
+
```
|
|
273
|
+
{product}.{agent}.{target}.{verb}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
- **product**: Always `'wxcc_sdk'` (from `PRODUCT_NAME`)
|
|
277
|
+
- **agent**: `'user'` for user-initiated actions, `'service'` for system-generated events
|
|
278
|
+
- **target**: Snake_case description of the action (e.g., `'station_login'`, `'task_accept'`)
|
|
279
|
+
- **verb**: `'complete'` for success, `'fail'` for failure, `'set'` for RONA events
|
|
280
|
+
|
|
281
|
+
**Example**: `STATION_LOGIN_SUCCESS` maps to `wxcc_sdk.user.station_login.complete`
|
|
282
|
+
|
|
283
|
+
> **Note**: The following events do **not** have behavioral taxonomy mappings in `behavioral-events.ts`:
|
|
284
|
+
> - `WEBSOCKET_DEREGISTER_SUCCESS`
|
|
285
|
+
> - `WEBSOCKET_DEREGISTER_FAIL`
|
|
286
|
+
> - `WEBSOCKET_EVENT_RECEIVED`
|
|
287
|
+
>
|
|
288
|
+
> Calling `trackBehavioralEvent` with these event names will push an event with an `undefined` taxonomy.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Usage Pattern (timeEvent + trackEvent)
|
|
293
|
+
|
|
294
|
+
The standard pattern used throughout the Contact Center SDK:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const metrics = MetricsManager.getInstance();
|
|
298
|
+
|
|
299
|
+
// 1. Start timing before the operation
|
|
300
|
+
metrics.timeEvent([
|
|
301
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
302
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
const response = await performLogin(params);
|
|
307
|
+
|
|
308
|
+
// 2a. Track success (duration_ms auto-added)
|
|
309
|
+
metrics.trackEvent(METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, {
|
|
310
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
311
|
+
});
|
|
312
|
+
} catch (error) {
|
|
313
|
+
// 2b. Track failure (duration_ms auto-added)
|
|
314
|
+
metrics.trackEvent(METRIC_EVENT_NAMES.STATION_LOGIN_FAILED, {
|
|
315
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error),
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Error Handling
|
|
323
|
+
|
|
324
|
+
MetricsManager is designed to be non-blocking. Metric failures do not propagate to callers:
|
|
325
|
+
|
|
326
|
+
- If `webex` is not yet ready, events are queued in `pendingBehavioralEvents`, `pendingOperationalEvents`, or `pendingBusinessEvents`
|
|
327
|
+
- Once `webex.ready` fires, all pending events are flushed
|
|
328
|
+
- If metrics are disabled via `setMetricsDisabled(true)`, all track methods silently return
|
|
329
|
+
- Invalid metric types log an error via `LoggerProxy` but do not throw
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Dependencies
|
|
334
|
+
|
|
335
|
+
- **`@webex/internal-plugin-metrics`**: Provides `webex.internal.newMetrics` for actual metric submission (`submitBehavioralEvent`, `submitOperationalEvent`, `submitBusinessEvent`)
|
|
336
|
+
- **`LoggerProxy`**: Used for error logging within the metrics module
|
|
337
|
+
- **`Failure` type** (from `services/core/GlobalTypes`): Used in `getCommonTrackingFieldForAQMResponseFailed`
|
|
338
|
+
- **`PRODUCT_NAME`** (from `constants.ts`): Set to `'wxcc_sdk'`, used as the product identifier in behavioral taxonomy and as prefix for operational/business event names
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Related
|
|
343
|
+
|
|
344
|
+
- [`MetricsManager.ts`](../MetricsManager.ts) - Singleton metrics manager implementation
|
|
345
|
+
- [`behavioral-events.ts`](../behavioral-events.ts) - Event taxonomy mapping
|
|
346
|
+
- [`constants.ts`](../constants.ts) - `METRIC_EVENT_NAMES` definitions
|
|
347
|
+
- [`../../constants.ts`](../../constants.ts) - `PRODUCT_NAME` constant
|
|
348
|
+
- [`services/core/GlobalTypes.ts`](../../services/core/GlobalTypes.ts) - `Failure` type definition
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Metrics Module - Architecture
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Technical documentation for the metrics collection, batching, and submission system within the Contact Center SDK.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Overview
|
|
8
|
+
|
|
9
|
+
| Component | File | Responsibility |
|
|
10
|
+
| ------------------------ | ----------------------- | ------------------------------------------------------------------------------ |
|
|
11
|
+
| `MetricsManager` | `MetricsManager.ts` | Singleton that manages event queuing, timing, payload preparation, and submission |
|
|
12
|
+
| `BehavioralEventTaxonomy`| `behavioral-events.ts` | Maps metric event names to structured taxonomy for behavioral analytics |
|
|
13
|
+
| `METRIC_EVENT_NAMES` | `constants.ts` | Canonical constant object of all tracked metric event names |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## File Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
src/metrics/
|
|
21
|
+
├── MetricsManager.ts # Singleton metrics manager
|
|
22
|
+
├── behavioral-events.ts # Behavioral event taxonomy mapping
|
|
23
|
+
├── constants.ts # METRIC_EVENT_NAMES constants
|
|
24
|
+
└── ai-docs/
|
|
25
|
+
├── AGENTS.md # Usage documentation (see PR #4762)
|
|
26
|
+
└── ARCHITECTURE.md # This file
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Singleton Pattern
|
|
32
|
+
|
|
33
|
+
`MetricsManager` uses a private constructor with a static `getInstance` factory:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// MetricsManager.ts
|
|
37
|
+
export default class MetricsManager {
|
|
38
|
+
private static instance: MetricsManager;
|
|
39
|
+
private constructor() {}
|
|
40
|
+
|
|
41
|
+
public static getInstance(options?: {webex: WebexSDK}): MetricsManager {
|
|
42
|
+
if (!MetricsManager.instance) {
|
|
43
|
+
MetricsManager.instance = new MetricsManager();
|
|
44
|
+
}
|
|
45
|
+
if (!MetricsManager.instance.webex && options?.webex) {
|
|
46
|
+
MetricsManager.instance.setWebex(options.webex);
|
|
47
|
+
}
|
|
48
|
+
return MetricsManager.instance;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static resetInstance() {
|
|
52
|
+
MetricsManager.instance = undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- The Webex SDK instance is set once via `setWebex()`, which listens for the `ready` event before flushing pending queues.
|
|
58
|
+
- `resetInstance()` sets the singleton to `undefined`, allowing a fresh instance to be created. Primarily used in tests.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Data Flow
|
|
63
|
+
|
|
64
|
+
### Event Submission Flow
|
|
65
|
+
|
|
66
|
+
```mermaid
|
|
67
|
+
flowchart TD
|
|
68
|
+
A[cc.ts calls metricsManager.timeEvent] --> B[Store startTime + keys in runningEvents]
|
|
69
|
+
B --> C[Operation executes]
|
|
70
|
+
C --> D{Success or Failure?}
|
|
71
|
+
D -->|Success| E[cc.ts calls metricsManager.trackEvent with success name]
|
|
72
|
+
D -->|Failure| F[cc.ts calls metricsManager.trackEvent with failure name]
|
|
73
|
+
E --> G[addDurationIfTimed attaches duration_ms]
|
|
74
|
+
F --> G
|
|
75
|
+
G --> H[preparePayload cleans and enriches]
|
|
76
|
+
H --> I{Metric type?}
|
|
77
|
+
I -->|behavioral| J[Push to pendingBehavioralEvents]
|
|
78
|
+
I -->|operational| K[Push to pendingOperationalEvents]
|
|
79
|
+
I -->|business| L[Push to pendingBusinessEvents]
|
|
80
|
+
J --> M[submitPendingBehavioralEvents]
|
|
81
|
+
K --> N[submitPendingOperationalEvents]
|
|
82
|
+
L --> O[submitPendingBusinessEvents]
|
|
83
|
+
M --> P[webex.internal.newMetrics.submitBehavioralEvent]
|
|
84
|
+
N --> Q[webex.internal.newMetrics.submitOperationalEvent]
|
|
85
|
+
O --> R[webex.internal.newMetrics.submitBusinessEvent]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Sequence Diagrams
|
|
91
|
+
|
|
92
|
+
### Track Event with Timing
|
|
93
|
+
|
|
94
|
+
```mermaid
|
|
95
|
+
sequenceDiagram
|
|
96
|
+
participant CC as ContactCenter (cc.ts)
|
|
97
|
+
participant MM as MetricsManager
|
|
98
|
+
participant NM as webex.internal.newMetrics
|
|
99
|
+
|
|
100
|
+
CC->>MM: timeEvent([SUCCESS_KEY, FAILURE_KEY])
|
|
101
|
+
Note over MM: Store startTime + key set in runningEvents
|
|
102
|
+
CC->>CC: Execute operation (e.g., stationLogin)
|
|
103
|
+
Note over MM: trackEvent defaults to ['behavioral'] only if no metricServices specified
|
|
104
|
+
alt Success
|
|
105
|
+
CC->>MM: trackEvent(SUCCESS_KEY, payload, ['behavioral', 'operational', 'business'])
|
|
106
|
+
else Failure
|
|
107
|
+
CC->>MM: trackEvent(FAILURE_KEY, payload, ['behavioral', 'operational', 'business'])
|
|
108
|
+
end
|
|
109
|
+
MM->>MM: addDurationIfTimed → attach duration_ms
|
|
110
|
+
MM->>MM: preparePayload → clean empty fields, add tabHidden
|
|
111
|
+
loop For each metric type
|
|
112
|
+
MM->>MM: Push to pending queue
|
|
113
|
+
alt readyToSubmitEvents
|
|
114
|
+
MM->>NM: submit[Behavioral|Operational|Business]Event
|
|
115
|
+
else not ready
|
|
116
|
+
Note over MM: Events stay queued until SDK ready
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Initialization and Readiness
|
|
122
|
+
|
|
123
|
+
```mermaid
|
|
124
|
+
sequenceDiagram
|
|
125
|
+
participant CC as ContactCenter
|
|
126
|
+
participant MM as MetricsManager
|
|
127
|
+
participant Webex as WebexSDK
|
|
128
|
+
|
|
129
|
+
CC->>MM: getInstance({webex})
|
|
130
|
+
MM->>MM: Create singleton (if needed)
|
|
131
|
+
MM->>MM: setWebex(webex)
|
|
132
|
+
opt webex.ready === true
|
|
133
|
+
MM->>MM: setReadyToSubmitEvents()
|
|
134
|
+
MM->>MM: submitPendingEvents()
|
|
135
|
+
end
|
|
136
|
+
MM->>Webex: webex.once('ready', callback)
|
|
137
|
+
Note over MM: 'ready' listener is always registered
|
|
138
|
+
Webex-->>MM: 'ready' event fires
|
|
139
|
+
MM->>MM: setReadyToSubmitEvents()
|
|
140
|
+
MM->>MM: submitPendingEvents()
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Behavioral Event Taxonomy
|
|
146
|
+
|
|
147
|
+
Each metric event name maps to a `BehavioralEventTaxonomy` with four fields:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
type BehavioralEventTaxonomy = {
|
|
151
|
+
product: MetricEventProduct; // Always PRODUCT_NAME ('wxcc_sdk')
|
|
152
|
+
agent: MetricEventAgent; // 'user' or 'service'
|
|
153
|
+
target: string; // e.g., 'station_login', 'task_accept'
|
|
154
|
+
verb: MetricEventVerb; // 'complete' for success, 'fail' for failure
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The final behavioral event name is constructed as: `{product}.{agent}.{target}.{verb}`
|
|
159
|
+
|
|
160
|
+
Example: `wxcc_sdk.user.station_login.complete`
|
|
161
|
+
|
|
162
|
+
The mapping is defined in `behavioral-events.ts` via `eventTaxonomyMap` and accessed through `getEventTaxonomy(name)`.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Event Queuing and Submission
|
|
167
|
+
|
|
168
|
+
### Three Parallel Queues
|
|
169
|
+
|
|
170
|
+
MetricsManager maintains three independent pending event queues:
|
|
171
|
+
|
|
172
|
+
| Queue | Type | Submitted Via | Name Transform | Extra Metadata |
|
|
173
|
+
| --------------------------- | ------------ | -------------------------------------------------- | ----------------------------------------------- | -------------------------------- |
|
|
174
|
+
| `pendingBehavioralEvents` | behavioral | `webex.internal.newMetrics.submitBehavioralEvent` | Taxonomy-based (`{product}.{agent}.{target}.{verb}`) | None |
|
|
175
|
+
| `pendingOperationalEvents` | operational | `webex.internal.newMetrics.submitOperationalEvent` | `WXCC_SDK_` prefix + uppercase (e.g. `WXCC_SDK_STATION_LOGIN_SUCCESS`) | None |
|
|
176
|
+
| `pendingBusinessEvents` | business | `webex.internal.newMetrics.submitBusinessEvent` | `WXCC_SDK_` prefix + uppercase (same as operational) | `metadata: {appType: 'wxcc_sdk'}` |
|
|
177
|
+
|
|
178
|
+
### Submission Guards
|
|
179
|
+
|
|
180
|
+
- **readyToSubmitEvents**: Set to `true` only after `webex.once('ready')` fires. Events queue until then.
|
|
181
|
+
- **submittingEvents**: Lock flag to prevent concurrent `submitPendingEvents()` calls.
|
|
182
|
+
- **metricsDisabled**: When `true`, all `track*` methods return early and `clearPendingEvents()` empties all queues.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Timing Pattern (`timeEvent` / `trackEvent`)
|
|
187
|
+
|
|
188
|
+
```mermaid
|
|
189
|
+
flowchart LR
|
|
190
|
+
A[timeEvent keys] --> B[runningEvents stores startTime + key Set]
|
|
191
|
+
B --> C[trackEvent called with one of the keys]
|
|
192
|
+
C --> D[addDurationIfTimed matches key]
|
|
193
|
+
D --> E[Calculates duration_ms = now - startTime]
|
|
194
|
+
E --> F[Removes all keys for that operation]
|
|
195
|
+
F --> G[Attaches duration_ms to payload]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Usage pattern from `cc.ts`:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Before operation
|
|
202
|
+
this.metricsManager.timeEvent([
|
|
203
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
204
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
205
|
+
]);
|
|
206
|
+
|
|
207
|
+
// On success
|
|
208
|
+
this.metricsManager.trackEvent(
|
|
209
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
210
|
+
{ ...MetricsManager.getCommonTrackingFieldForAQMResponse(resp) },
|
|
211
|
+
['behavioral', 'operational', 'business']
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// On failure
|
|
215
|
+
this.metricsManager.trackEvent(
|
|
216
|
+
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
217
|
+
{ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure) },
|
|
218
|
+
['behavioral', 'operational', 'business']
|
|
219
|
+
);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Payload Preparation
|
|
225
|
+
|
|
226
|
+
`preparePayload()` processes every event payload before submission:
|
|
227
|
+
|
|
228
|
+
1. **Removes empty/null/undefined fields** — strips keys with `undefined`, `null`, `''`, any arrays, or empty objects
|
|
229
|
+
2. **Converts spaces to underscores** — `spacesToUnderscore()` applied to all key names
|
|
230
|
+
3. **Adds common metadata** — appends `tabHidden: document.hidden` in browser environments
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Error Handling Strategy
|
|
235
|
+
|
|
236
|
+
MetricsManager does not throw errors to callers. Instead:
|
|
237
|
+
|
|
238
|
+
- Invalid metric types are logged via `LoggerProxy.error`
|
|
239
|
+
- Empty `timeEvent` key arrays are logged and ignored
|
|
240
|
+
- Disabled state (`metricsDisabled`) silently drops events
|
|
241
|
+
- The `submittingEvents` lock prevents race conditions during concurrent submissions
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Common Tracking Field Extraction
|
|
246
|
+
|
|
247
|
+
Two static helpers extract standardized fields from AQM responses for metric payloads:
|
|
248
|
+
|
|
249
|
+
### `getCommonTrackingFieldForAQMResponse(response)`
|
|
250
|
+
|
|
251
|
+
Extracts: `agentId`, `agentSessionId`, `teamId`, `siteId`, `orgId`, `eventType`, `trackingId`, `notifTrackingId`
|
|
252
|
+
|
|
253
|
+
### `getCommonTrackingFieldForAQMResponseFailed(failureResponse)`
|
|
254
|
+
|
|
255
|
+
Extracts: `agentId`, `trackingId`, `notifTrackingId`, `orgId`, `failureType`, `failureReason`, `reasonCode`
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Metric Event Names
|
|
260
|
+
|
|
261
|
+
All event names are defined in `constants.ts` as `METRIC_EVENT_NAMES`. Events follow a `{Domain} {Action} {Success|Failed}` naming convention:
|
|
262
|
+
|
|
263
|
+
| Category | Success Event | Failure Event |
|
|
264
|
+
| ---------------------- | -------------------------------------- | -------------------------------------- |
|
|
265
|
+
| Station Login | `STATION_LOGIN_SUCCESS` | `STATION_LOGIN_FAILED` |
|
|
266
|
+
| Station Logout | `STATION_LOGOUT_SUCCESS` | `STATION_LOGOUT_FAILED` |
|
|
267
|
+
| Station Relogin | `STATION_RELOGIN_SUCCESS` | `STATION_RELOGIN_FAILED` |
|
|
268
|
+
| State Change | `AGENT_STATE_CHANGE_SUCCESS` | `AGENT_STATE_CHANGE_FAILED` |
|
|
269
|
+
| Buddy Agents | `FETCH_BUDDY_AGENTS_SUCCESS` | `FETCH_BUDDY_AGENTS_FAILED` |
|
|
270
|
+
| WebSocket Register | `WEBSOCKET_REGISTER_SUCCESS` | `WEBSOCKET_REGISTER_FAILED` |
|
|
271
|
+
| Task Accept | `TASK_ACCEPT_SUCCESS` | `TASK_ACCEPT_FAILED` |
|
|
272
|
+
| Task Decline | `TASK_DECLINE_SUCCESS` | `TASK_DECLINE_FAILED` |
|
|
273
|
+
| Task End | `TASK_END_SUCCESS` | `TASK_END_FAILED` |
|
|
274
|
+
| Task Wrapup | `TASK_WRAPUP_SUCCESS` | `TASK_WRAPUP_FAILED` |
|
|
275
|
+
| Task Hold | `TASK_HOLD_SUCCESS` | `TASK_HOLD_FAILED` |
|
|
276
|
+
| Task Resume | `TASK_RESUME_SUCCESS` | `TASK_RESUME_FAILED` |
|
|
277
|
+
| Task Consult Start | `TASK_CONSULT_START_SUCCESS` | `TASK_CONSULT_START_FAILED` |
|
|
278
|
+
| Task Consult End | `TASK_CONSULT_END_SUCCESS` | `TASK_CONSULT_END_FAILED` |
|
|
279
|
+
| Task Transfer | `TASK_TRANSFER_SUCCESS` | `TASK_TRANSFER_FAILED` |
|
|
280
|
+
| Task Resume Recording | `TASK_RESUME_RECORDING_SUCCESS` | `TASK_RESUME_RECORDING_FAILED` |
|
|
281
|
+
| Task Pause Recording | `TASK_PAUSE_RECORDING_SUCCESS` | `TASK_PAUSE_RECORDING_FAILED` |
|
|
282
|
+
| Task Accept Consult | `TASK_ACCEPT_CONSULT_SUCCESS` | `TASK_ACCEPT_CONSULT_FAILED` |
|
|
283
|
+
| Task Auto Answer | `TASK_AUTO_ANSWER_SUCCESS` | `TASK_AUTO_ANSWER_FAILED` |
|
|
284
|
+
| Conference Start | `TASK_CONFERENCE_START_SUCCESS` | `TASK_CONFERENCE_START_FAILED` |
|
|
285
|
+
| Conference End | `TASK_CONFERENCE_END_SUCCESS` | `TASK_CONFERENCE_END_FAILED` |
|
|
286
|
+
| Conference Transfer | `TASK_CONFERENCE_TRANSFER_SUCCESS` | `TASK_CONFERENCE_TRANSFER_FAILED` |
|
|
287
|
+
| Conference Exit | `TASK_CONFERENCE_EXIT_SUCCESS` | `TASK_CONFERENCE_EXIT_FAILED` |
|
|
288
|
+
| Switch Call | `TASK_SWITCH_CALL_SUCCESS` | `TASK_SWITCH_CALL_FAILED` |
|
|
289
|
+
| Outdial | `TASK_OUTDIAL_SUCCESS` | `TASK_OUTDIAL_FAILED` |
|
|
290
|
+
| Upload Logs | `UPLOAD_LOGS_SUCCESS` | `UPLOAD_LOGS_FAILED` |
|
|
291
|
+
| WebSocket Deregister | `WEBSOCKET_DEREGISTER_SUCCESS` | `WEBSOCKET_DEREGISTER_FAIL` |
|
|
292
|
+
| Device Type Update | `AGENT_DEVICE_TYPE_UPDATE_SUCCESS` | `AGENT_DEVICE_TYPE_UPDATE_FAILED` |
|
|
293
|
+
| EntryPoint | `ENTRYPOINT_FETCH_SUCCESS` | `ENTRYPOINT_FETCH_FAILED` |
|
|
294
|
+
| AddressBook | `ADDRESSBOOK_FETCH_SUCCESS` | `ADDRESSBOOK_FETCH_FAILED` |
|
|
295
|
+
| Queue | `QUEUE_FETCH_SUCCESS` | `QUEUE_FETCH_FAILED` |
|
|
296
|
+
| Outdial ANI Entries | `OUTDIAL_ANI_EP_FETCH_SUCCESS` | `OUTDIAL_ANI_EP_FETCH_FAILED` |
|
|
297
|
+
|
|
298
|
+
Special events (no success/failure pair):
|
|
299
|
+
- `AGENT_RONA` — has behavioral taxonomy (`service.agent_rona.set`)
|
|
300
|
+
- `AGENT_CONTACT_ASSIGN_FAILED` — has behavioral taxonomy (`service.agent_contact_assign.fail`)
|
|
301
|
+
- `AGENT_INVITE_FAILED` — has behavioral taxonomy (`service.agent_invite.fail`)
|
|
302
|
+
- `WEBSOCKET_EVENT_RECEIVED` — **no** behavioral taxonomy (not in `eventTaxonomyMap`)
|
|
303
|
+
|
|
304
|
+
Events **without** behavioral taxonomy (not in `eventTaxonomyMap`): `WEBSOCKET_DEREGISTER_SUCCESS`, `WEBSOCKET_DEREGISTER_FAIL`, `WEBSOCKET_EVENT_RECEIVED`
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Troubleshooting
|
|
309
|
+
|
|
310
|
+
### Issue: Metrics not being submitted
|
|
311
|
+
|
|
312
|
+
**Cause**: Webex SDK not yet ready when `trackEvent` is called
|
|
313
|
+
|
|
314
|
+
**Solution**: Events are automatically queued in `pending*Events` arrays and flushed once `webex.once('ready')` fires. Verify the SDK is initializing correctly.
|
|
315
|
+
|
|
316
|
+
### Issue: Duration not attached to metric
|
|
317
|
+
|
|
318
|
+
**Cause**: `timeEvent` was not called before `trackEvent`, or the event name does not match any key in `runningEvents`
|
|
319
|
+
|
|
320
|
+
**Solution**: Ensure `timeEvent([SUCCESS_KEY, FAILURE_KEY])` is called before the operation, and that the exact `METRIC_EVENT_NAMES` constant is used in both calls.
|
|
321
|
+
|
|
322
|
+
### Issue: Metrics silently dropped
|
|
323
|
+
|
|
324
|
+
**Cause**: `metricsDisabled` is set to `true`
|
|
325
|
+
|
|
326
|
+
**Solution**: Check if `setMetricsDisabled(true)` was called. This clears all pending queues and causes all `track*` methods to return early.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Related Files
|
|
331
|
+
|
|
332
|
+
- [MetricsManager.ts](../MetricsManager.ts) — Singleton metrics manager
|
|
333
|
+
- [behavioral-events.ts](../behavioral-events.ts) — Event taxonomy mapping
|
|
334
|
+
- [constants.ts](../constants.ts) — METRIC_EVENT_NAMES definitions
|
|
335
|
+
- [cc.ts](../../cc.ts) — Main plugin class (primary consumer)
|
|
336
|
+
- [constants.ts](../../constants.ts) — PRODUCT_NAME used in event prefixing
|