@webex/internal-plugin-metrics 3.12.0-webex-services-ready.4 → 3.13.0
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/.repo-context.json +466 -0
- package/.sdd/manifest.json +626 -0
- package/AGENTS.md +208 -0
- package/README.md +274 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +155 -94
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/config.js +3 -1
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +118 -5
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/network-telemetry.js +610 -0
- package/dist/network-telemetry.js.map +1 -0
- package/dist/new-metrics.js +47 -11
- package/dist/new-metrics.js.map +1 -1
- package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
- package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/index.js +143 -0
- package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/types.js +7 -0
- package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
- package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +12 -3
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/config.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/metrics.types.d.ts +7 -3
- package/dist/types/network-telemetry.d.ts +108 -0
- package/dist/types/new-metrics.d.ts +13 -1
- package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
- package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
- package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
- package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
- package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
- package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
- package/dist/unhandled-exception-telemetry/index.js +331 -0
- package/dist/unhandled-exception-telemetry/index.js.map +1 -0
- package/dist/unhandled-exception-telemetry/utils.js +105 -0
- package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
- package/docs/adr/index.md +27 -0
- package/docs/architecture.md +437 -0
- package/docs/getting-started.md +131 -0
- package/docs/index.md +52 -0
- package/docs/specs/README.md +88 -0
- package/package.json +11 -11
- package/schemas/repo-context.schema.json +796 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +100 -30
- package/src/call-diagnostic/config.ts +2 -0
- package/src/call-diagnostic/docs/README.md +535 -0
- package/src/config.js +7 -0
- package/src/docs/README.md +703 -0
- package/src/index.ts +11 -0
- package/src/metrics.js +123 -5
- package/src/metrics.types.ts +13 -3
- package/src/network-telemetry.ts +757 -0
- package/src/new-metrics.ts +44 -2
- package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
- package/src/privacy-and-security-permission-enricher/docs/README.md +356 -0
- package/src/privacy-and-security-permission-enricher/index.ts +142 -0
- package/src/privacy-and-security-permission-enricher/types.ts +21 -0
- package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
- package/src/rtcMetrics/docs/README.md +447 -0
- package/src/unhandled-exception-telemetry/docs/README.md +536 -0
- package/src/unhandled-exception-telemetry/index.ts +404 -0
- package/src/unhandled-exception-telemetry/utils.ts +101 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +485 -21
- package/test/unit/spec/metrics.js +14 -5
- package/test/unit/spec/network-telemetry.ts +610 -0
- package/test/unit/spec/new-metrics.ts +190 -48
- package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
- package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
- package/test/unit/spec/unhandled-exception-telemetry.ts +689 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<!-- sdd-generated-metadata
|
|
2
|
+
doc_kind: agent-entry
|
|
3
|
+
generated_from: agents@0.3.0
|
|
4
|
+
generated_by: claude-code
|
|
5
|
+
approved_by: rarajes2@cisco.com
|
|
6
|
+
updated_at: 2026-10-07T04:50:31Z
|
|
7
|
+
validation_status: pass
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# AI Agent Instructions
|
|
11
|
+
|
|
12
|
+
Agent entry for the `@webex/internal-plugin-metrics` package inside the `webex-js-sdk` monorepo.
|
|
13
|
+
Commands in this file are run from the monorepo root unless stated otherwise.
|
|
14
|
+
|
|
15
|
+
## Working Method
|
|
16
|
+
|
|
17
|
+
- Read the relevant repository files before editing. Do not edit blind.
|
|
18
|
+
- Understand the task and affected surfaces before writing code.
|
|
19
|
+
- Prefer focused edits over rewriting whole files.
|
|
20
|
+
- Do not invent commands, paths, exports, or behavior. Verify them from repository-local source.
|
|
21
|
+
- Test or validate before declaring done.
|
|
22
|
+
- Keep output concise. If something is uncertain, say so instead of guessing.
|
|
23
|
+
|
|
24
|
+
## Canonical Repository Documentation
|
|
25
|
+
|
|
26
|
+
Before changing code or documentation, start with:
|
|
27
|
+
|
|
28
|
+
- `docs/index.md` for repository documentation navigation;
|
|
29
|
+
- `docs/architecture.md` for repository boundaries and interactions;
|
|
30
|
+
- `docs/specs/README.md` for the manifest-backed module and contract registry;
|
|
31
|
+
- the affected module's manifest-routed `<module-path>/docs/README.md`; and
|
|
32
|
+
- `docs/adr/index.md` plus applicable concrete ADRs for durable decisions.
|
|
33
|
+
|
|
34
|
+
Follow `.sdd/manifest.json` for each contract's publication state and canonical source. Published
|
|
35
|
+
repository-owned HTTP APIs use their linked OpenAPI document; internal HTTP surfaces may link route
|
|
36
|
+
code, and published SDKs use their ecosystem-native API artifact. The manifest remains authoritative
|
|
37
|
+
for canonical paths and artifact decisions.
|
|
38
|
+
|
|
39
|
+
This package owns no HTTP surface. Every HTTP contract it touches belongs to the upstream Webex
|
|
40
|
+
metrics or unified telemetry service, and its own published surface is the SDK export declared in
|
|
41
|
+
`package.json` and `src/index.ts`.
|
|
42
|
+
|
|
43
|
+
## 1. Commands (Run First)
|
|
44
|
+
|
|
45
|
+
Use only documented commands. Do not invent alternatives when a command is missing.
|
|
46
|
+
|
|
47
|
+
| Task | Command |
|
|
48
|
+
| ---------------------- | --------------------------------------------------------------------------------- |
|
|
49
|
+
| Install dependencies | `yarn install` (monorepo root) |
|
|
50
|
+
| Start dev environment | Not applicable — this package is a library plugin with no runnable dev server |
|
|
51
|
+
| Run tests | `yarn workspace @webex/internal-plugin-metrics test:unit` |
|
|
52
|
+
| Run linters | `yarn workspace @webex/internal-plugin-metrics test:style` |
|
|
53
|
+
| Build/release artifact | `yarn workspace @webex/internal-plugin-metrics build:src` |
|
|
54
|
+
| Format code | No dedicated command; `test:style` runs `eslint ./src/**/*.*` without `--fix` |
|
|
55
|
+
|
|
56
|
+
Run a single unit spec with `--targets` relative to `test/unit/spec/`, for example
|
|
57
|
+
`yarn workspace @webex/internal-plugin-metrics test:unit --targets network-telemetry.ts`.
|
|
58
|
+
|
|
59
|
+
There is no runnable full build-with-tests command. The `test` script in `package.json` chains
|
|
60
|
+
`test:integration` and `test:browser`, which this package does not define, and no `test/integration`
|
|
61
|
+
directory exists. `.sdd/manifest.json` records `commands.build` as an unresolved owner decision for that
|
|
62
|
+
reason. Do not treat `test` as a working gate and do not substitute another command for it.
|
|
63
|
+
|
|
64
|
+
If a required command is unknown, stop and ask for the exact command.
|
|
65
|
+
|
|
66
|
+
## 2. Agent Persona and Scope
|
|
67
|
+
|
|
68
|
+
You are the Webex JS SDK telemetry engineering assistant for `@webex/internal-plugin-metrics`.
|
|
69
|
+
|
|
70
|
+
Primary outcomes:
|
|
71
|
+
|
|
72
|
+
- Deliver production-safe changes with passing tests.
|
|
73
|
+
- Preserve existing behavior unless a change request explicitly requires a behavior change.
|
|
74
|
+
- Keep docs and configuration aligned with code changes.
|
|
75
|
+
|
|
76
|
+
Definition of done:
|
|
77
|
+
|
|
78
|
+
1. Requested change is implemented.
|
|
79
|
+
2. Relevant tests/lint/build checks pass locally.
|
|
80
|
+
3. Updated docs/config cover new behavior.
|
|
81
|
+
4. PR summary includes risks and rollback notes.
|
|
82
|
+
|
|
83
|
+
## 3. Repository Knowledge
|
|
84
|
+
|
|
85
|
+
### Tech Stack
|
|
86
|
+
|
|
87
|
+
Document concrete versions so assistants choose compatible APIs.
|
|
88
|
+
|
|
89
|
+
| Area | Tooling | Version |
|
|
90
|
+
| ---------------- | ------------------------------------------------------------ | ------------------------------ |
|
|
91
|
+
| Language runtime | Node.js; `engines` in `package.json` sets the consumer floor, and the owner-declared manifest `toolchain` sets the build and test version | `22.14` to build and test; `>=18` floor |
|
|
92
|
+
| Build tool | `@webex/legacy-tools` plus `tsc`, per `package.json` scripts | workspace package |
|
|
93
|
+
| Test framework | Mocha, selected by `webex-legacy-tools test --runner mocha` | workspace runner |
|
|
94
|
+
| Lint/format | ESLint with `@webex/eslint-config-legacy`, per `.eslintrc.js` | `eslint ^8.24.0`, `prettier ^2.7.1` |
|
|
95
|
+
|
|
96
|
+
### Project Map
|
|
97
|
+
|
|
98
|
+
- `src/index.ts`: package entry point; registers the `metrics` and `newMetrics` internal plugins and defines the export surface.
|
|
99
|
+
- `src/metrics.js`: the legacy `webex.internal.metrics` plugin, its three Batcher children and the network-telemetry wiring.
|
|
100
|
+
- `src/new-metrics.ts`: the `webex.internal.newMetrics` façade over every current event family.
|
|
101
|
+
- `src/network-telemetry.ts`: the SDK request-outcome collector and its summary payload.
|
|
102
|
+
- `src/call-diagnostic/`: Call Analyzer client, feature and media-quality events, the latency ledger and error-code mapping.
|
|
103
|
+
- `src/privacy-and-security-permission-enricher/`: permission-change enrichment policy for client events.
|
|
104
|
+
- `src/rtcMetrics/`: WebRTC stats reporting to the unified telemetry service.
|
|
105
|
+
- `src/unhandled-exception-telemetry/`: browser uncaught-error and rejection reporter.
|
|
106
|
+
- `test/unit/spec/`: the unit suite; its subtree mirrors `src/`.
|
|
107
|
+
|
|
108
|
+
### Critical Constraints
|
|
109
|
+
|
|
110
|
+
- The Call Analyzer event schema is owned externally by `@webex/event-dictionary-ts`, pinned in `package.json`. Do not hand-declare event names or payload fields in `src/metrics.types.ts`; derive them from that package.
|
|
111
|
+
- Telemetry must never affect the requests it observes. Requests to the `metrics` and `unifiedTelemetry` services are excluded centrally in `src/network-telemetry.ts`, and every submission failure is caught and logged rather than propagated.
|
|
112
|
+
- Personal data must not reach telemetry. IP addresses are anonymized in `src/call-diagnostic/call-diagnostic-metrics.util.ts`, URL credentials and query data are stripped in `src/unhandled-exception-telemetry/utils.ts`, and endpoint path segments are redacted in `src/network-telemetry.ts`.
|
|
113
|
+
- `webex.internal.metrics` and `webex.internal.newMetrics` are consumed by sibling workspace packages, including `packages/@webex/plugin-meetings` and `packages/@webex/internal-plugin-device`. Treat both surfaces as stable and additive.
|
|
114
|
+
- `src/metrics.js` must tolerate being constructed standalone and before `webex.config` is populated. Its deferred `change:config` initialization in `initialize` exists for that reason; do not collapse it into a direct call.
|
|
115
|
+
|
|
116
|
+
## 4. Testing Workflow
|
|
117
|
+
|
|
118
|
+
Run checks in this order:
|
|
119
|
+
|
|
120
|
+
1. `yarn workspace @webex/internal-plugin-metrics test:unit`
|
|
121
|
+
2. `yarn workspace @webex/internal-plugin-metrics test:style`
|
|
122
|
+
3. Not applicable — this package defines no integration or end-to-end tier.
|
|
123
|
+
|
|
124
|
+
Testing rules:
|
|
125
|
+
|
|
126
|
+
- Add or update tests for every behavior change.
|
|
127
|
+
- Cover failure paths and edge cases, not only happy paths.
|
|
128
|
+
- Do not remove tests to make CI pass.
|
|
129
|
+
- Use `sinon` for stubs and `assert` from `@webex/test-helper-chai` for assertions, matching the existing specs.
|
|
130
|
+
- Control time with `sinon.useFakeTimers()`; the telemetry collectors are interval and timeout driven.
|
|
131
|
+
|
|
132
|
+
## 5. Code Style and Patterns
|
|
133
|
+
|
|
134
|
+
Coding expectations:
|
|
135
|
+
|
|
136
|
+
- Follow repository style rules and static analysis output.
|
|
137
|
+
- Prefer small, composable functions over large procedural blocks.
|
|
138
|
+
- Make error handling explicit at system boundaries.
|
|
139
|
+
- Keep public interfaces stable unless a breaking change is requested.
|
|
140
|
+
- Before adding a literal path, filename, command, workflow identifier, status,
|
|
141
|
+
or other policy value, search the repository for exact and semantically
|
|
142
|
+
equivalent uses. When repeated production values represent one shared
|
|
143
|
+
contract, move them to the narrowest owning shared module or catalog as one
|
|
144
|
+
canonical named constant, enum, or type and update consumers. Keep incidental
|
|
145
|
+
similarities, one-off implementation details, and independent test fixtures
|
|
146
|
+
local.
|
|
147
|
+
- Do not import a default, named, object, or namespace binding and immediately
|
|
148
|
+
re-export it. Consumers should import from the owning module; package barrels
|
|
149
|
+
should use direct named re-exports.
|
|
150
|
+
- Do not write inline runtime `typeof` checks outside descriptively named guard
|
|
151
|
+
implementations. Import and reuse the owning guard instead; TypeScript
|
|
152
|
+
type-position `typeof` queries remain allowed.
|
|
153
|
+
|
|
154
|
+
Pattern example:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
Preferred:
|
|
158
|
+
- Validate external input close to the boundary.
|
|
159
|
+
- Return typed/structured results.
|
|
160
|
+
- Include actionable error messages.
|
|
161
|
+
|
|
162
|
+
Avoid:
|
|
163
|
+
- Passing unvalidated payloads deep into the system.
|
|
164
|
+
- Swallowing exceptions or returning ambiguous null values.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
New code in this package is TypeScript. `src/metrics.js`, `src/batcher.js`,
|
|
168
|
+
`src/client-metrics-batcher.js` and `src/config.js` remain JavaScript because they extend the
|
|
169
|
+
Ampersand-based `WebexPlugin` and `Batcher` classes from `@webex/webex-core`; keep edits there
|
|
170
|
+
in-style rather than converting the file as a side effect.
|
|
171
|
+
|
|
172
|
+
## 6. Git Workflow
|
|
173
|
+
|
|
174
|
+
- Branch naming: `[feature|fix|chore]/[short-description]`
|
|
175
|
+
- Commit format: conventional commits (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`)
|
|
176
|
+
- Keep commits focused and reversible.
|
|
177
|
+
- Rebase on the target branch before opening PR.
|
|
178
|
+
|
|
179
|
+
PR checklist:
|
|
180
|
+
|
|
181
|
+
- What changed and why.
|
|
182
|
+
- Tests run and results.
|
|
183
|
+
- Risk/impact areas.
|
|
184
|
+
- Rollback approach.
|
|
185
|
+
|
|
186
|
+
## 7. Boundaries and Escalation
|
|
187
|
+
|
|
188
|
+
### Always
|
|
189
|
+
|
|
190
|
+
- Prefer existing patterns over introducing new architecture.
|
|
191
|
+
- Keep changes minimal for the requested scope.
|
|
192
|
+
- Call out assumptions and unknowns explicitly.
|
|
193
|
+
|
|
194
|
+
### Ask First
|
|
195
|
+
|
|
196
|
+
- Adding new dependencies or external services.
|
|
197
|
+
- Large refactors or schema migrations.
|
|
198
|
+
- Security-sensitive changes (auth, encryption, secrets handling).
|
|
199
|
+
- Any destructive data or infrastructure operation.
|
|
200
|
+
- Changing a submitted payload shape, metric name or event name, because downstream ingestion and dashboards depend on them.
|
|
201
|
+
|
|
202
|
+
### Never
|
|
203
|
+
|
|
204
|
+
- Commit secrets, keys, or credentials.
|
|
205
|
+
- Bypass required checks by disabling tests or linters.
|
|
206
|
+
- Rewrite history on shared branches.
|
|
207
|
+
- Change unrelated files "while here" without clear need.
|
|
208
|
+
- Add personally identifiable information, credentials or raw IP addresses to any telemetry payload.
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ This is an internal Cisco Webex plugin. As such, it does not strictly adhere to
|
|
|
8
8
|
|
|
9
9
|
- [Install](#install)
|
|
10
10
|
- [Usage](#usage)
|
|
11
|
+
- [Unhandled exception telemetry](#unhandled-exception-telemetry)
|
|
12
|
+
- [Network request telemetry](#network-request-telemetry)
|
|
11
13
|
- [Contribute](#contribute)
|
|
12
14
|
- [Maintainers](#maintainers)
|
|
13
15
|
- [License](#license)
|
|
@@ -29,6 +31,278 @@ const webex = new WebexCore();
|
|
|
29
31
|
webex.internal.metrics.WHATEVER;
|
|
30
32
|
```
|
|
31
33
|
|
|
34
|
+
## Unhandled exception telemetry
|
|
35
|
+
|
|
36
|
+
Unhandled exception telemetry is currently supported only in browser environments. It starts after
|
|
37
|
+
the Webex SDK emits `ready`. It does not install a standalone collector, capture errors before SDK
|
|
38
|
+
initialization, persist events, or retry failed telemetry submissions.
|
|
39
|
+
|
|
40
|
+
The reporter captures uncaught errors, unhandled promise rejections, and resource load failures.
|
|
41
|
+
Matching failures captured in the same one-second in-memory window are submitted once with an
|
|
42
|
+
`occurrenceCount`. Non-HTTP(S) URLs are redacted; URL credentials, query parameters, and fragments
|
|
43
|
+
are stripped; and error names, messages, and stacks are truncated before submission.
|
|
44
|
+
|
|
45
|
+
Telemetry is disabled by default. Enable it with
|
|
46
|
+
`metrics.unhandledExceptionTelemetry.enabled: true`. Applications may provide a synchronous
|
|
47
|
+
`getMetadata` callback in the same configuration object. It must return an object whose fields can
|
|
48
|
+
include application context such as `orgId` and `dataCenter`. Metadata must not contain personally
|
|
49
|
+
identifiable information or credentials.
|
|
50
|
+
|
|
51
|
+
````js
|
|
52
|
+
import Webex from 'webex';
|
|
53
|
+
|
|
54
|
+
const webex = Webex.init({
|
|
55
|
+
config: {
|
|
56
|
+
metrics: {
|
|
57
|
+
unhandledExceptionTelemetry: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
getMetadata: () => ({
|
|
60
|
+
orgId: 'your-organization-id',
|
|
61
|
+
dataCenter: 'your-data-center',
|
|
62
|
+
}),
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
## Network request telemetry
|
|
68
|
+
|
|
69
|
+
Network request telemetry is disabled by default. Enable it with
|
|
70
|
+
`metrics.networkTelemetry.enabled: true`. When enabled, the metrics plugin summarizes requests
|
|
71
|
+
made through the Webex SDK request pipeline. The reporting interval is configurable with
|
|
72
|
+
`metrics.networkTelemetry.intervalMs` and defaults to ten minutes. It listens to the SDK-wide `request:start`,
|
|
73
|
+
`request:success`, and `request:failure` events, so individual plugins do not need to wrap or
|
|
74
|
+
replace `webex.request()`.
|
|
75
|
+
|
|
76
|
+
For example, to collect one-minute windows:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
const webex = Webex.init({
|
|
80
|
+
config: {
|
|
81
|
+
metrics: {
|
|
82
|
+
networkTelemetry: {
|
|
83
|
+
enabled: true,
|
|
84
|
+
intervalMs: 60 * 1_000,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The listeners are installed once for each Webex instance when `webex.internal.metrics` is
|
|
92
|
+
constructed and the feature is enabled. The metrics package must be imported before constructing
|
|
93
|
+
the Webex instance. Standard Webex SDK bundles already import and register the metrics plugin.
|
|
94
|
+
|
|
95
|
+
### Scope
|
|
96
|
+
|
|
97
|
+
The collector counts request and response outcomes that pass through `webex.request()` and its interceptors. For failures, it also records aggregated error details covering:
|
|
98
|
+
|
|
99
|
+
- HTTP responses rejected by the SDK, such as `4xx` and `5xx` responses.
|
|
100
|
+
- Network or CORS failures where no HTTP response is available.
|
|
101
|
+
- Aborted and timed-out SDK requests when the error exposes that information.
|
|
102
|
+
- Request preparation failures that emit `request:failure`.
|
|
103
|
+
|
|
104
|
+
It does not monitor arbitrary application `fetch()`, `XMLHttpRequest`, WebSocket, or other traffic outside the SDK request pipeline. It also does not use `PerformanceObserver` or browser-wide request interception.
|
|
105
|
+
|
|
106
|
+
### Event flow
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
webex.request()
|
|
110
|
+
-> SDK request interceptors
|
|
111
|
+
-> request:start(options)
|
|
112
|
+
-> request:success(options, response) or request:failure(options, reason)
|
|
113
|
+
-> metrics request outcome listeners
|
|
114
|
+
-> aggregate host, endpoint, response, and error counts
|
|
115
|
+
-> every configured interval, submit JS_SDK_NETWORK_REQUEST_SUMMARY
|
|
116
|
+
````
|
|
117
|
+
|
|
118
|
+
The listeners and ten-minute accumulator are registered during metrics plugin initialization:
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
initialize(...args) {
|
|
122
|
+
WebexPlugin.prototype.initialize.call(this, ...args);
|
|
123
|
+
if (this.webex.config.metrics.networkTelemetry.enabled !== true) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
this.networkTelemetry = createNetworkTelemetryCollector(/* submission callbacks */);
|
|
127
|
+
this.listenTo(this.webex, 'request:start', this.recordNetworkRequestStart);
|
|
128
|
+
this.listenTo(this.webex, 'request:success', this.recordNetworkRequestSuccess);
|
|
129
|
+
this.listenTo(this.webex, 'request:failure', this.recordNetworkRequestFailure);
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The metrics plugin exposes `flushNetworkTelemetry()` for callers that need to submit the current
|
|
134
|
+
non-empty window immediately, such as after an early call failure. When the metrics plugin is
|
|
135
|
+
stopped, any non-empty partial window is submitted once before the collector is disposed. Empty
|
|
136
|
+
windows are not submitted during shutdown, and the shutdown hook waits for the submission attempt
|
|
137
|
+
to settle.
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
await webex.internal.metrics.flushNetworkTelemetry();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Metric schema
|
|
144
|
+
|
|
145
|
+
One operational client metric named `JS_SDK_NETWORK_REQUEST_SUMMARY` is submitted at the configured
|
|
146
|
+
interval. Its `eventPayload` has this shape:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
type NetworkTelemetry = {
|
|
150
|
+
metricsSummary: {
|
|
151
|
+
totalSendRequest: number;
|
|
152
|
+
totalFailedRequest: number;
|
|
153
|
+
totalRecvdResponse: number;
|
|
154
|
+
totalFailedResponse: number;
|
|
155
|
+
};
|
|
156
|
+
metrics: Array<{
|
|
157
|
+
host: string;
|
|
158
|
+
endPoint: string;
|
|
159
|
+
countSendRequest: number;
|
|
160
|
+
countFailedRequest: number;
|
|
161
|
+
countRecvdResponse: number;
|
|
162
|
+
countFailedResponse: number;
|
|
163
|
+
averageNetworkDurationMs: number;
|
|
164
|
+
maxNetworkDurationP90Ms: number;
|
|
165
|
+
maxNetworkDurationP99Ms: number;
|
|
166
|
+
}>;
|
|
167
|
+
errorMetrics: Array<{
|
|
168
|
+
host: string;
|
|
169
|
+
endPoint: string;
|
|
170
|
+
statusCode: number;
|
|
171
|
+
errorCode: string;
|
|
172
|
+
method: string;
|
|
173
|
+
errorType: string;
|
|
174
|
+
errorMessage: string;
|
|
175
|
+
trackingIds: string[];
|
|
176
|
+
countError: number;
|
|
177
|
+
}>;
|
|
178
|
+
errorMetricsSummary: Record<string, {count: number}>;
|
|
179
|
+
};
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The SDK adds application metadata to the outer client metric when it wraps this `eventPayload`:
|
|
183
|
+
|
|
184
|
+
| Property | Source |
|
|
185
|
+
| -------------------- | --------------------------------------------------------------------------- |
|
|
186
|
+
| `tags.app_name` | `webex.config.appName`, or `unknown` |
|
|
187
|
+
| `tags.app_version` | `webex.config.appVersion`, or `unknown` |
|
|
188
|
+
| `tags.app_url` | Browser origin without path/query data, hostname fallback, or `non-browser` |
|
|
189
|
+
| `fields.sdk_version` | `webex.version` |
|
|
190
|
+
|
|
191
|
+
Counter mapping:
|
|
192
|
+
|
|
193
|
+
| Event or outcome | Summary and endpoint counters |
|
|
194
|
+
| --------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
195
|
+
| `request:start` | `totalSendRequest`, `countSendRequest` |
|
|
196
|
+
| `request:success` | `totalRecvdResponse`, `countRecvdResponse` |
|
|
197
|
+
| `request:failure` without an HTTP response | `totalFailedRequest`, `countFailedRequest` |
|
|
198
|
+
| `request:failure` with an HTTP status (`4xx`/`5xx`) | Received-response counters plus `totalFailedResponse`/`countFailedResponse` |
|
|
199
|
+
|
|
200
|
+
The `metrics` array is grouped by `host` and `endPoint`. For service-based SDK requests, `host` is the normalized logical service name. Direct-URI requests use the URI host. `endPoint` is a sanitized resource or URI path. `averageNetworkDurationMs` is the average measured network duration for completed requests in the group, while `maxNetworkDurationP90Ms` and `maxNetworkDurationP99Ms` are the maximum durations at the nearest-rank 90th and 99th percentiles. All values are in milliseconds.
|
|
201
|
+
|
|
202
|
+
The `errorMetrics` array groups identical failures by host, endpoint, status code, error code, method, error type, and error message. `countError` records the number of occurrences, while `trackingIds` retains at most ten unique identifiers. `errorMetricsSummary` counts errors by status code; status `0` means no HTTP response was available.
|
|
203
|
+
|
|
204
|
+
Example:
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
{
|
|
208
|
+
metricName: 'JS_SDK_NETWORK_REQUEST_SUMMARY',
|
|
209
|
+
type: 'operational',
|
|
210
|
+
fields: {
|
|
211
|
+
totalSendRequest: 14,
|
|
212
|
+
totalFailedRequest: 1,
|
|
213
|
+
totalRecvdResponse: 13,
|
|
214
|
+
totalFailedResponse: 1
|
|
215
|
+
},
|
|
216
|
+
eventPayload: {
|
|
217
|
+
metricsSummary: {
|
|
218
|
+
totalSendRequest: 14,
|
|
219
|
+
totalFailedRequest: 1,
|
|
220
|
+
totalRecvdResponse: 13,
|
|
221
|
+
totalFailedResponse: 1
|
|
222
|
+
},
|
|
223
|
+
metrics: [{
|
|
224
|
+
host: 'hydra',
|
|
225
|
+
endPoint: 'rooms/:id/messages',
|
|
226
|
+
countSendRequest: 2,
|
|
227
|
+
countFailedRequest: 0,
|
|
228
|
+
countRecvdResponse: 2,
|
|
229
|
+
countFailedResponse: 1,
|
|
230
|
+
averageNetworkDurationMs: 410,
|
|
231
|
+
maxNetworkDurationP90Ms: 510,
|
|
232
|
+
maxNetworkDurationP99Ms: 640
|
|
233
|
+
}],
|
|
234
|
+
errorMetrics: [{
|
|
235
|
+
host: 'hydra',
|
|
236
|
+
endPoint: 'rooms/:id/messages',
|
|
237
|
+
statusCode: 503,
|
|
238
|
+
errorCode: 'SERVICE_UNAVAILABLE',
|
|
239
|
+
method: 'POST',
|
|
240
|
+
errorType: 'server_error',
|
|
241
|
+
errorMessage: 'Service unavailable',
|
|
242
|
+
trackingIds: ['example-tracking-id'],
|
|
243
|
+
countError: 1
|
|
244
|
+
}],
|
|
245
|
+
errorMetricsSummary: {
|
|
246
|
+
503: {count: 1}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Failure classification
|
|
253
|
+
|
|
254
|
+
Classification is evaluated in the following order:
|
|
255
|
+
|
|
256
|
+
| Condition | `errorType` |
|
|
257
|
+
| --------------------------------------------------------------------------------------------------------- | --------------- |
|
|
258
|
+
| Error name is `AbortError` | `aborted` |
|
|
259
|
+
| Status is `408` or `504`, timeout appears in the error details, or the configured request timeout elapsed | `timeout` |
|
|
260
|
+
| Status is `429` | `rate_limited` |
|
|
261
|
+
| Status is `5xx` | `server_error` |
|
|
262
|
+
| Status is `4xx` | `client_error` |
|
|
263
|
+
| No response status is available, or the error name contains `network` | `network_error` |
|
|
264
|
+
| Any other SDK request failure | `request_error` |
|
|
265
|
+
|
|
266
|
+
### Telemetry request exclusion
|
|
267
|
+
|
|
268
|
+
Requests to the `metrics` and `unifiedTelemetry` services are excluded from both success and failure collection. The exclusion also covers the legacy `api: 'metrics'` request option. This prevents a telemetry upload from affecting its own summary.
|
|
269
|
+
|
|
270
|
+
The exclusion is centralized in the collector; telemetry request call sites do not require special flags.
|
|
271
|
+
|
|
272
|
+
### Endpoint normalization and cardinality
|
|
273
|
+
|
|
274
|
+
The `endPoint` value is derived from `options.resource`, or from the URI path for a direct-URI request:
|
|
275
|
+
|
|
276
|
+
- Query parameters and fragments are removed.
|
|
277
|
+
- Numeric, percent-encoded, uppercase, and otherwise non-route-looking segments are replaced with `:id`.
|
|
278
|
+
|
|
279
|
+
For example:
|
|
280
|
+
|
|
281
|
+
```text
|
|
282
|
+
rooms/Y2lzY29zcGFyazovL3VzL1JPT00/messages?personId=secret
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
becomes:
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
rooms/:id/messages
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Endpoint normalization is heuristic. A short lowercase alphabetic identifier can resemble a static route segment. Do not place sensitive values directly in a resource path; use normal SDK resource identifiers and avoid embedding credentials or personal data in route names. Error messages are included because they are part of the requested error aggregate schema; callers should not put credentials or personal data in thrown error messages.
|
|
292
|
+
|
|
293
|
+
### Submission behavior
|
|
294
|
+
|
|
295
|
+
Each ten-minute summary uses the existing `submitClientMetrics()` batching and transport path. The accumulator resets at the reporting boundary before asynchronous submission, so requests received while a summary is being sent belong to the next window. A telemetry submission failure is caught and logged.
|
|
296
|
+
|
|
297
|
+
### Tests
|
|
298
|
+
|
|
299
|
+
Run the focused unit tests with Node.js 22.14:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
nvm use 22.14
|
|
303
|
+
yarn workspace @webex/internal-plugin-metrics test:unit --targets network-telemetry.ts
|
|
304
|
+
```
|
|
305
|
+
|
|
32
306
|
## Maintainers
|
|
33
307
|
|
|
34
308
|
This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/).
|