@webex/contact-center 3.12.0-next.9 → 3.12.0-next.90

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