@salesforce/b2c-tooling-sdk 1.18.0 → 1.19.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/dist/esm/clients/index.d.ts +2 -0
- package/dist/esm/clients/index.js +1 -0
- package/dist/esm/clients/index.js.map +1 -1
- package/dist/esm/clients/metrics.d.ts +123 -0
- package/dist/esm/clients/metrics.generated.d.ts +1016 -0
- package/dist/esm/clients/metrics.generated.js +6 -0
- package/dist/esm/clients/metrics.generated.js.map +1 -0
- package/dist/esm/clients/metrics.js +65 -0
- package/dist/esm/clients/metrics.js.map +1 -0
- package/dist/esm/clients/middleware-registry.d.ts +1 -1
- package/dist/esm/clients/middleware-registry.js.map +1 -1
- package/dist/esm/discovery/detector.d.ts +1 -0
- package/dist/esm/discovery/detector.js +3 -1
- package/dist/esm/discovery/detector.js.map +1 -1
- package/dist/esm/discovery/index.d.ts +1 -1
- package/dist/esm/discovery/patterns/cartridges.js +4 -2
- package/dist/esm/discovery/patterns/cartridges.js.map +1 -1
- package/dist/esm/discovery/patterns/sfra.js +10 -5
- package/dist/esm/discovery/patterns/sfra.js.map +1 -1
- package/dist/esm/discovery/types.d.ts +20 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operations/code/cartridges.d.ts +18 -0
- package/dist/esm/operations/code/cartridges.js +31 -20
- package/dist/esm/operations/code/cartridges.js.map +1 -1
- package/dist/esm/operations/logs/filter.d.ts +6 -1
- package/dist/esm/operations/logs/filter.js +7 -2
- package/dist/esm/operations/logs/filter.js.map +1 -1
- package/dist/esm/operations/metrics/index.d.ts +371 -0
- package/dist/esm/operations/metrics/index.js +478 -0
- package/dist/esm/operations/metrics/index.js.map +1 -0
- package/dist/esm/operations/metrics/tags.d.ts +148 -0
- package/dist/esm/operations/metrics/tags.js +235 -0
- package/dist/esm/operations/metrics/tags.js.map +1 -0
- package/package.json +6 -2
- package/specs/metrics-v1.json +1713 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
import { toOrganizationId } from '../../clients/custom-apis.js';
|
|
2
|
+
import { getApiErrorMessage } from '../../clients/error-utils.js';
|
|
3
|
+
import { getLogger } from '../../logging/logger.js';
|
|
4
|
+
import { parseSinceTime, parseRelativeTime } from '../logs/filter.js';
|
|
5
|
+
/**
|
|
6
|
+
* All metric categories exposed by the Metrics API, in a stable, documented order.
|
|
7
|
+
*
|
|
8
|
+
* Values match the API path segments (e.g. `overall` → `/metrics/overall`).
|
|
9
|
+
*/
|
|
10
|
+
export const METRIC_CATEGORIES = [
|
|
11
|
+
'overall',
|
|
12
|
+
'sales',
|
|
13
|
+
'ecdn',
|
|
14
|
+
'third-party',
|
|
15
|
+
'scapi',
|
|
16
|
+
'scapi-hooks',
|
|
17
|
+
'mrt',
|
|
18
|
+
'controller',
|
|
19
|
+
'ocapi',
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* How far back the Metrics API retains data: `from` must be no older than
|
|
23
|
+
* `serverNow - 30 days`, or the API returns 400.
|
|
24
|
+
*/
|
|
25
|
+
export const METRICS_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
26
|
+
/**
|
|
27
|
+
* Default (and maximum) width of a metrics time window: 24 hours.
|
|
28
|
+
*
|
|
29
|
+
* The Metrics API pairs a request that omits `to` with its own `now` and then
|
|
30
|
+
* enforces a maximum window of `to - from ≤ 24h`, rejecting anything wider with a
|
|
31
|
+
* 400. An open-ended `from` older than 24h therefore always fails. To make the
|
|
32
|
+
* behavior predictable, {@link resolveMetricsWindow} fills in a 24-hour window
|
|
33
|
+
* (clamped so `to` never exceeds `now`) for any bound the caller leaves open, and
|
|
34
|
+
* always sends both `from` and `to`. This is only a *default* for derivation — an
|
|
35
|
+
* explicit `from`+`to` range wider than 24h is still sent as-is, letting the API
|
|
36
|
+
* remain authoritative and return its own error.
|
|
37
|
+
*/
|
|
38
|
+
export const METRICS_DEFAULT_WINDOW_MS = 24 * 60 * 60 * 1000;
|
|
39
|
+
/**
|
|
40
|
+
* Safety margin kept *inside* the retention window when clamping `from`. Because
|
|
41
|
+
* the server evaluates retention against its own clock at request time, a `from`
|
|
42
|
+
* computed as exactly "30 days ago" on the client is reliably rejected once
|
|
43
|
+
* request latency and client/server clock skew are added. {@link resolveMetricsWindow}
|
|
44
|
+
* therefore clamps a `from` that lands within this margin of the retention floor
|
|
45
|
+
* up to `now - 30 days + margin`, so edge requests (e.g. `--from 30d`) succeed.
|
|
46
|
+
* 5 minutes comfortably covers latency and typical skew while costing a
|
|
47
|
+
* negligible fraction of the 30-day window.
|
|
48
|
+
*/
|
|
49
|
+
export const METRICS_RETENTION_SAFETY_MARGIN_MS = 5 * 60 * 1000;
|
|
50
|
+
/**
|
|
51
|
+
* Parses a single metrics time bound (`from` or `to`) into a {@link Date}.
|
|
52
|
+
*
|
|
53
|
+
* This is the shared bound parser for the CLI `metrics get` command and the MCP
|
|
54
|
+
* `metrics_get` tool. It resolves a single bound in isolation; deriving the
|
|
55
|
+
* companion bound and applying the 24-hour default window is the job of
|
|
56
|
+
* {@link resolveMetricsWindow}.
|
|
57
|
+
*
|
|
58
|
+
* @param value - The bound: a Date, epoch milliseconds, a relative duration
|
|
59
|
+
* (`5m`/`1h`/`2d`, relative to `now`), or an ISO 8601 timestamp
|
|
60
|
+
* @param now - Reference time for relative durations (defaults to the current
|
|
61
|
+
* time; injectable for deterministic tests)
|
|
62
|
+
* @returns The resolved {@link Date}
|
|
63
|
+
* @throws TypeError if a string value is neither a valid relative duration nor
|
|
64
|
+
* a parseable ISO 8601 timestamp
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const from = parseMetricsBound('2d'); // 2 days ago
|
|
69
|
+
* const to = parseMetricsBound('2026-01-25T12:00:00Z');
|
|
70
|
+
* await getSalesMetrics(client, tenantId, {from, to});
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function parseMetricsBound(value, now = new Date()) {
|
|
74
|
+
if (value instanceof Date)
|
|
75
|
+
return value;
|
|
76
|
+
if (typeof value === 'number')
|
|
77
|
+
return new Date(value);
|
|
78
|
+
return parseSinceTime(value, now);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parses a `--window`/`--for` duration into milliseconds. Accepts a relative
|
|
82
|
+
* string (`1h`, `30m`, `2d`) or a raw number of milliseconds.
|
|
83
|
+
*
|
|
84
|
+
* @throws TypeError if a string is not a valid relative duration
|
|
85
|
+
*/
|
|
86
|
+
function parseWindowMs(window) {
|
|
87
|
+
if (typeof window === 'number')
|
|
88
|
+
return window;
|
|
89
|
+
const ms = parseRelativeTime(window);
|
|
90
|
+
if (ms === null) {
|
|
91
|
+
throw new TypeError(`Invalid window duration: "${window}". Use a relative duration like "30m", "1h", or "2d".`);
|
|
92
|
+
}
|
|
93
|
+
return ms;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolves `from`/`to`/`window` inputs into the concrete bounds to send to the
|
|
97
|
+
* Metrics API. This is the shared resolver for the CLI `metrics get` command and
|
|
98
|
+
* the MCP `metrics_get` tool, so both share identical, tested semantics.
|
|
99
|
+
*
|
|
100
|
+
* The resolver always produces an explicit `from`+`to` pair. The Metrics API
|
|
101
|
+
* pairs a request that omits `to` with its own `now` and enforces a 24-hour
|
|
102
|
+
* maximum window, so an open-ended `from` older than 24 hours always fails; to
|
|
103
|
+
* make the behavior predictable, any bound the caller leaves open is filled from
|
|
104
|
+
* the 24-hour default window (see {@link METRICS_DEFAULT_WINDOW_MS}) rather than
|
|
105
|
+
* relying on the server's implicit end.
|
|
106
|
+
*
|
|
107
|
+
* The `window` duration makes fixed-width lookbacks easy without hand-computing
|
|
108
|
+
* a second timestamp — e.g. "a 1-hour window starting 7 days ago" is
|
|
109
|
+
* `{from: '7d', window: '1h'}`. Resolution rules:
|
|
110
|
+
*
|
|
111
|
+
* - `from` + `to` — used as given; `window` must NOT also be set. An explicit
|
|
112
|
+
* range wider than the 24-hour maximum is still sent as-is, leaving the API to
|
|
113
|
+
* return its own error.
|
|
114
|
+
* - `from` + `window` — `to = from + window`.
|
|
115
|
+
* - `to` + `window` — `from = to - window`.
|
|
116
|
+
* - `window` only — the last `window`: `to = now`, `from = now - window`.
|
|
117
|
+
* - `from` only — a 24-hour window forward from `from`: `to = min(from + 24h, now)`.
|
|
118
|
+
* - `to` only — a 24-hour window back from `to`: `from = to - 24h`.
|
|
119
|
+
* - nothing — the last 24 hours: `to = now`, `from = now - 24h`.
|
|
120
|
+
*
|
|
121
|
+
* Bounds filled from the 24-hour default (the last three rules) set
|
|
122
|
+
* {@link ResolvedMetricsWindow.defaultedWindow}. Validation is structural
|
|
123
|
+
* (over-specification and `from` after `to`). Additionally, a `from` that lands
|
|
124
|
+
* at or beyond the 30-day retention floor is clamped *forward* to
|
|
125
|
+
* `now - 30 days + margin` (see {@link METRICS_RETENTION_SAFETY_MARGIN_MS}) so
|
|
126
|
+
* requests like `--from 30d` are not rejected by the server's own slightly-later
|
|
127
|
+
* clock; the clamp is applied before deriving the companion bound so the window
|
|
128
|
+
* width is preserved, only ever moves `from` toward `now`, and is reported via
|
|
129
|
+
* {@link ResolvedMetricsWindow.clampedFrom}.
|
|
130
|
+
*
|
|
131
|
+
* @param input - The raw `from`/`to`/`window` inputs
|
|
132
|
+
* @param now - Reference time for relative bounds, default/window modes, and the
|
|
133
|
+
* retention clamp (defaults to the current time; injectable for deterministic tests)
|
|
134
|
+
* @returns The resolved bounds plus ISO/epoch-second echoes and clamp/default flags
|
|
135
|
+
* @throws TypeError if a bound or the window string is unparseable
|
|
136
|
+
* @throws RangeError if all three are supplied, or the resolved `from` is after `to`
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // A 1-hour window starting 7 days ago:
|
|
141
|
+
* const w = resolveMetricsWindow({from: '7d', window: '1h'});
|
|
142
|
+
* await getScapiMetrics(client, tenantId, {from: w.from, to: w.to});
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export function resolveMetricsWindow(input = {}, now = new Date()) {
|
|
146
|
+
const hasFrom = input.from !== undefined && input.from !== '';
|
|
147
|
+
const hasTo = input.to !== undefined && input.to !== '';
|
|
148
|
+
const hasWindow = input.window !== undefined && input.window !== '';
|
|
149
|
+
if (hasFrom && hasTo && hasWindow) {
|
|
150
|
+
throw new RangeError('Specify at most two of from, to, and window — not all three.');
|
|
151
|
+
}
|
|
152
|
+
// Clamp a `from` forward if it predates the retention floor, to survive the
|
|
153
|
+
// server evaluating retention against its own (slightly later) clock. Only
|
|
154
|
+
// ever moves `from` toward `now`, never fetches out-of-range data.
|
|
155
|
+
const earliestSafe = now.getTime() - METRICS_RETENTION_MS + METRICS_RETENTION_SAFETY_MARGIN_MS;
|
|
156
|
+
let clampedFrom = false;
|
|
157
|
+
const clampFrom = (d) => {
|
|
158
|
+
if (d.getTime() < earliestSafe) {
|
|
159
|
+
clampedFrom = true;
|
|
160
|
+
return new Date(earliestSafe);
|
|
161
|
+
}
|
|
162
|
+
return d;
|
|
163
|
+
};
|
|
164
|
+
// Clamp a provided `from` up front so a window derived from it stays inside
|
|
165
|
+
// retention (and a full-width window fits).
|
|
166
|
+
let from = hasFrom ? clampFrom(parseMetricsBound(input.from, now)) : undefined;
|
|
167
|
+
let to = hasTo ? parseMetricsBound(input.to, now) : undefined;
|
|
168
|
+
let defaultedWindow = false;
|
|
169
|
+
if (hasWindow) {
|
|
170
|
+
const windowMs = parseWindowMs(input.window);
|
|
171
|
+
if (from && !to) {
|
|
172
|
+
to = new Date(from.getTime() + windowMs);
|
|
173
|
+
}
|
|
174
|
+
else if (to && !from) {
|
|
175
|
+
from = new Date(to.getTime() - windowMs);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// window alone → the last {window}
|
|
179
|
+
to = now;
|
|
180
|
+
from = new Date(now.getTime() - windowMs);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (!(from && to)) {
|
|
184
|
+
// No explicit window and at least one bound open → fill it from the 24-hour
|
|
185
|
+
// default window, sending an explicit range instead of relying on the
|
|
186
|
+
// server's implicit `to = now` + 24h-maximum behavior.
|
|
187
|
+
defaultedWindow = true;
|
|
188
|
+
if (from && !to) {
|
|
189
|
+
// A window forward from `from`, but never past `now` (no future data).
|
|
190
|
+
to = new Date(Math.min(from.getTime() + METRICS_DEFAULT_WINDOW_MS, now.getTime()));
|
|
191
|
+
}
|
|
192
|
+
else if (to && !from) {
|
|
193
|
+
from = new Date(to.getTime() - METRICS_DEFAULT_WINDOW_MS);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Nothing supplied → the last 24 hours.
|
|
197
|
+
to = now;
|
|
198
|
+
from = new Date(now.getTime() - METRICS_DEFAULT_WINDOW_MS);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// A `from` derived from `to` (via window or the default) may itself predate
|
|
202
|
+
// retention; clamp it forward too. Idempotent for an already-clamped bound.
|
|
203
|
+
from = clampFrom(from);
|
|
204
|
+
if (from.getTime() > to.getTime()) {
|
|
205
|
+
throw new RangeError(`Invalid time window: from (${from.toISOString()}) must be before to (${to.toISOString()}).`);
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
from: from,
|
|
209
|
+
to: to,
|
|
210
|
+
fromIso: from.toISOString(),
|
|
211
|
+
toIso: to.toISOString(),
|
|
212
|
+
fromEpochSeconds: toEpochSeconds(from),
|
|
213
|
+
toEpochSeconds: toEpochSeconds(to),
|
|
214
|
+
clampedFrom,
|
|
215
|
+
defaultedWindow,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Converts a millisecond time input ({@link Date} or epoch ms) to the epoch
|
|
220
|
+
* **seconds** the Metrics API expects on the wire.
|
|
221
|
+
*/
|
|
222
|
+
function toEpochSeconds(value) {
|
|
223
|
+
const ms = value instanceof Date ? value.getTime() : value;
|
|
224
|
+
return Math.floor(ms / 1000);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Normalizes an optional time-window into the query object openapi-fetch expects.
|
|
228
|
+
* Converts millisecond inputs to epoch seconds and drops undefined values so they
|
|
229
|
+
* are not serialized.
|
|
230
|
+
*/
|
|
231
|
+
function timeWindowQuery(options) {
|
|
232
|
+
const query = {};
|
|
233
|
+
if (options?.from !== undefined)
|
|
234
|
+
query.from = toEpochSeconds(options.from);
|
|
235
|
+
if (options?.to !== undefined)
|
|
236
|
+
query.to = toEpochSeconds(options.to);
|
|
237
|
+
return query;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Normalizes a successful metrics response for JS consumers: rewrites every data
|
|
241
|
+
* point timestamp from the API's epoch **seconds** to epoch **milliseconds** so
|
|
242
|
+
* that `new Date(point.timestamp)` yields the correct instant. Returns a new
|
|
243
|
+
* response object; the input is not mutated.
|
|
244
|
+
*/
|
|
245
|
+
function normalizeResponse(data) {
|
|
246
|
+
return {
|
|
247
|
+
...data,
|
|
248
|
+
data: (data.data ?? []).map((metric) => ({
|
|
249
|
+
...metric,
|
|
250
|
+
dataSeries: (metric.dataSeries ?? []).map((series) => ({
|
|
251
|
+
...series,
|
|
252
|
+
data: (series.data ?? []).map((point) => ({ ...point, timestamp: point.timestamp * 1000 })),
|
|
253
|
+
})),
|
|
254
|
+
})),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Wraps a failed metrics request in a descriptive Error.
|
|
259
|
+
*/
|
|
260
|
+
function metricsError(category, error, response) {
|
|
261
|
+
return new Error(`Failed to get ${category} metrics: ${getApiErrorMessage(error, response)}`, { cause: error });
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Retrieves overall application metrics for an organization.
|
|
265
|
+
*
|
|
266
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
267
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
268
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
269
|
+
* @returns The metrics data response
|
|
270
|
+
* @throws Error if the request fails
|
|
271
|
+
*/
|
|
272
|
+
export async function getOverallMetrics(client, tenantId, options) {
|
|
273
|
+
getLogger().debug({ tenantId, options }, 'Fetching overall metrics');
|
|
274
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/overall', {
|
|
275
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
276
|
+
});
|
|
277
|
+
if (error || !data)
|
|
278
|
+
throw metricsError('overall', error, response);
|
|
279
|
+
return normalizeResponse(data);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Retrieves sales metrics for an organization.
|
|
283
|
+
*
|
|
284
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
285
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
286
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
287
|
+
* @returns The metrics data response
|
|
288
|
+
* @throws Error if the request fails
|
|
289
|
+
*/
|
|
290
|
+
export async function getSalesMetrics(client, tenantId, options) {
|
|
291
|
+
getLogger().debug({ tenantId, options }, 'Fetching sales metrics');
|
|
292
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/sales', {
|
|
293
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
294
|
+
});
|
|
295
|
+
if (error || !data)
|
|
296
|
+
throw metricsError('sales', error, response);
|
|
297
|
+
return normalizeResponse(data);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Retrieves embedded CDN (eCDN) metrics for an organization.
|
|
301
|
+
*
|
|
302
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
303
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
304
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
305
|
+
* @returns The metrics data response
|
|
306
|
+
* @throws Error if the request fails
|
|
307
|
+
*/
|
|
308
|
+
export async function getEcdnMetrics(client, tenantId, options) {
|
|
309
|
+
getLogger().debug({ tenantId, options }, 'Fetching ecdn metrics');
|
|
310
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/ecdn', {
|
|
311
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
312
|
+
});
|
|
313
|
+
if (error || !data)
|
|
314
|
+
throw metricsError('ecdn', error, response);
|
|
315
|
+
return normalizeResponse(data);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Retrieves third-party service call metrics for an organization.
|
|
319
|
+
*
|
|
320
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
321
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
322
|
+
* @param options - Optional time window and `thirdPartyServiceId` filter
|
|
323
|
+
* @returns The metrics data response
|
|
324
|
+
* @throws Error if the request fails
|
|
325
|
+
*/
|
|
326
|
+
export async function getThirdPartyMetrics(client, tenantId, options) {
|
|
327
|
+
getLogger().debug({ tenantId, options }, 'Fetching third-party metrics');
|
|
328
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/third-party', {
|
|
329
|
+
params: {
|
|
330
|
+
path: { organizationId: toOrganizationId(tenantId) },
|
|
331
|
+
query: { ...timeWindowQuery(options), thirdPartyServiceId: options?.thirdPartyServiceId },
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
if (error || !data)
|
|
335
|
+
throw metricsError('third-party', error, response);
|
|
336
|
+
return normalizeResponse(data);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Retrieves SCAPI request metrics for an organization.
|
|
340
|
+
*
|
|
341
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
342
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
343
|
+
* @param options - Optional time window and `apiFamily`/`apiName` filters
|
|
344
|
+
* @returns The metrics data response
|
|
345
|
+
* @throws Error if the request fails
|
|
346
|
+
*/
|
|
347
|
+
export async function getScapiMetrics(client, tenantId, options) {
|
|
348
|
+
getLogger().debug({ tenantId, options }, 'Fetching scapi metrics');
|
|
349
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/scapi', {
|
|
350
|
+
params: {
|
|
351
|
+
path: { organizationId: toOrganizationId(tenantId) },
|
|
352
|
+
query: { ...timeWindowQuery(options), apiFamily: options?.apiFamily, apiName: options?.apiName },
|
|
353
|
+
},
|
|
354
|
+
});
|
|
355
|
+
if (error || !data)
|
|
356
|
+
throw metricsError('scapi', error, response);
|
|
357
|
+
return normalizeResponse(data);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Retrieves SCAPI hook execution metrics for an organization.
|
|
361
|
+
*
|
|
362
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
363
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
364
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
365
|
+
* @returns The metrics data response
|
|
366
|
+
* @throws Error if the request fails
|
|
367
|
+
*/
|
|
368
|
+
export async function getScapiHooksMetrics(client, tenantId, options) {
|
|
369
|
+
getLogger().debug({ tenantId, options }, 'Fetching scapi-hooks metrics');
|
|
370
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/scapi-hooks', {
|
|
371
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
372
|
+
});
|
|
373
|
+
if (error || !data)
|
|
374
|
+
throw metricsError('scapi-hooks', error, response);
|
|
375
|
+
return normalizeResponse(data);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Retrieves Managed Runtime (MRT) metrics for an organization.
|
|
379
|
+
*
|
|
380
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
381
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
382
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
383
|
+
* @returns The metrics data response
|
|
384
|
+
* @throws Error if the request fails
|
|
385
|
+
*/
|
|
386
|
+
export async function getMrtMetrics(client, tenantId, options) {
|
|
387
|
+
getLogger().debug({ tenantId, options }, 'Fetching mrt metrics');
|
|
388
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/mrt', {
|
|
389
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
390
|
+
});
|
|
391
|
+
if (error || !data)
|
|
392
|
+
throw metricsError('mrt', error, response);
|
|
393
|
+
return normalizeResponse(data);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Retrieves controller/pipeline metrics for an organization.
|
|
397
|
+
*
|
|
398
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
399
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
400
|
+
* @param options - Optional time window (epoch milliseconds)
|
|
401
|
+
* @returns The metrics data response
|
|
402
|
+
* @throws Error if the request fails
|
|
403
|
+
*/
|
|
404
|
+
export async function getControllerMetrics(client, tenantId, options) {
|
|
405
|
+
getLogger().debug({ tenantId, options }, 'Fetching controller metrics');
|
|
406
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/controller', {
|
|
407
|
+
params: { path: { organizationId: toOrganizationId(tenantId) }, query: timeWindowQuery(options) },
|
|
408
|
+
});
|
|
409
|
+
if (error || !data)
|
|
410
|
+
throw metricsError('controller', error, response);
|
|
411
|
+
return normalizeResponse(data);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Retrieves OCAPI request metrics for an organization.
|
|
415
|
+
*
|
|
416
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
417
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
418
|
+
* @param options - Optional time window and `ocapiCategory`/`ocapiApi` filters
|
|
419
|
+
* @returns The metrics data response
|
|
420
|
+
* @throws Error if the request fails
|
|
421
|
+
*/
|
|
422
|
+
export async function getOcapiMetrics(client, tenantId, options) {
|
|
423
|
+
getLogger().debug({ tenantId, options }, 'Fetching ocapi metrics');
|
|
424
|
+
const { data, error, response } = await client.GET('/organizations/{organizationId}/metrics/ocapi', {
|
|
425
|
+
params: {
|
|
426
|
+
path: { organizationId: toOrganizationId(tenantId) },
|
|
427
|
+
query: { ...timeWindowQuery(options), ocapiCategory: options?.ocapiCategory, ocapiApi: options?.ocapiApi },
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
if (error || !data)
|
|
431
|
+
throw metricsError('ocapi', error, response);
|
|
432
|
+
return normalizeResponse(data);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Retrieves metrics for a category by name, dispatching to the category-specific
|
|
436
|
+
* function. Category-specific filters (`thirdPartyServiceId`, `apiFamily`,
|
|
437
|
+
* `apiName`, `ocapiCategory`, `ocapiApi`) are applied only for the categories
|
|
438
|
+
* that support them and ignored otherwise.
|
|
439
|
+
*
|
|
440
|
+
* @param client - Metrics API client from {@link createMetricsClient}
|
|
441
|
+
* @param tenantId - Tenant ID (with or without the `f_ecom_` prefix)
|
|
442
|
+
* @param category - One of {@link METRIC_CATEGORIES}
|
|
443
|
+
* @param options - Optional time window and category-specific filters
|
|
444
|
+
* @returns The metrics data response
|
|
445
|
+
* @throws Error if the request fails or the category is unknown
|
|
446
|
+
*/
|
|
447
|
+
export async function getMetricsByCategory(client, tenantId, category, options) {
|
|
448
|
+
switch (category) {
|
|
449
|
+
case 'overall':
|
|
450
|
+
return getOverallMetrics(client, tenantId, options);
|
|
451
|
+
case 'sales':
|
|
452
|
+
return getSalesMetrics(client, tenantId, options);
|
|
453
|
+
case 'ecdn':
|
|
454
|
+
return getEcdnMetrics(client, tenantId, options);
|
|
455
|
+
case 'third-party':
|
|
456
|
+
return getThirdPartyMetrics(client, tenantId, options);
|
|
457
|
+
case 'scapi':
|
|
458
|
+
return getScapiMetrics(client, tenantId, options);
|
|
459
|
+
case 'scapi-hooks':
|
|
460
|
+
return getScapiHooksMetrics(client, tenantId, options);
|
|
461
|
+
case 'mrt':
|
|
462
|
+
return getMrtMetrics(client, tenantId, options);
|
|
463
|
+
case 'controller':
|
|
464
|
+
return getControllerMetrics(client, tenantId, options);
|
|
465
|
+
case 'ocapi':
|
|
466
|
+
return getOcapiMetrics(client, tenantId, options);
|
|
467
|
+
default: {
|
|
468
|
+
// Exhaustiveness guard: if a new category is added to METRIC_CATEGORIES
|
|
469
|
+
// without a case here, this line fails to compile.
|
|
470
|
+
const exhaustive = category;
|
|
471
|
+
throw new Error(`Unknown metric category: ${String(exhaustive)}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
// Client-side dimension/tag extraction for series (interim until the API
|
|
476
|
+
// exposes structured tags server-side). See ./tags.ts.
|
|
477
|
+
export { parseSeriesTags, enrichMetricsTags } from './tags.js';
|
|
478
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/operations/metrics/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side dimension extraction for Metrics API series.
|
|
3
|
+
*
|
|
4
|
+
* The Metrics API returns each series as `{id, name, data}`, where `id`/`name`
|
|
5
|
+
* pack every identifying dimension into a single display string using
|
|
6
|
+
* inconsistent delimiters — e.g. `bdpx.product` (realm `.` apiFamily),
|
|
7
|
+
* `bdpx.product HIT` (realm `.` family ` ` cacheStatus), `2xx bdpx.host` (status
|
|
8
|
+
* class *before* the realm), or `bdpx.host.socketReadTimeout` (realm `.` host —
|
|
9
|
+
* whose own dots are ambiguous — `.` exceptionType). This makes the strings
|
|
10
|
+
* effectively unparseable in general and awkward to chart, group, or merge
|
|
11
|
+
* across realms.
|
|
12
|
+
*
|
|
13
|
+
* This module derives a structured, InfluxDB/Prometheus-style `tags` map for
|
|
14
|
+
* each series so consumers (dashboards, a Grafana plugin, ad-hoc analysis) can
|
|
15
|
+
* group and filter by dimension instead of regexing display strings. Two design
|
|
16
|
+
* rules keep it robust:
|
|
17
|
+
*
|
|
18
|
+
* 1. **Identity comes from the request, not the string.** `realm` and
|
|
19
|
+
* `environment` are derived from the tenant/organization the request targeted
|
|
20
|
+
* (`f_ecom_bdpx_prd` → `realm=bdpx`, `environment=prd`), never scraped from
|
|
21
|
+
* the packed id. This is reliable regardless of the id's delimiter soup and
|
|
22
|
+
* correctly distinguishes the *org's* environment from, say, eCDN hosts that
|
|
23
|
+
* span dev/stg/prod within a single prod request.
|
|
24
|
+
* 2. **Never throw, never drop data.** An id that matches no known pattern still
|
|
25
|
+
* gets `{realm, environment}` plus the unrecognized remainder under `series`,
|
|
26
|
+
* so enrichment only ever adds information.
|
|
27
|
+
*
|
|
28
|
+
* This is an interim client-side convenience. The intent is for the Metrics API
|
|
29
|
+
* to expose a `tags` object on each series server-side; when it does, this layer
|
|
30
|
+
* becomes a thin fallback (or is retired).
|
|
31
|
+
*
|
|
32
|
+
* @module operations/metrics/tags
|
|
33
|
+
*/
|
|
34
|
+
import type { MetricsDataResponse } from '../../clients/metrics.js';
|
|
35
|
+
import type { MetricCategory } from './index.js';
|
|
36
|
+
/**
|
|
37
|
+
* A flat map of a series' identifying dimensions (string → string), following
|
|
38
|
+
* the InfluxDB/Prometheus/CloudWatch "tag"/"label"/"dimension" convention.
|
|
39
|
+
*
|
|
40
|
+
* Always contains `realm` and `environment` (derived from the request context).
|
|
41
|
+
* Category-specific keys (`apiFamily`, `host`, `cacheStatus`, `statusClass`,
|
|
42
|
+
* `ocapiCategory`, `controller`, `exceptionType`) are added when recognized. A
|
|
43
|
+
* rollup/aggregation series carries `aggregation` (a *statistic*, not a
|
|
44
|
+
* dimension — kept distinct so consumers can separate "how it was computed" from
|
|
45
|
+
* "what it describes"). An unrecognized remainder is preserved under `series`.
|
|
46
|
+
*/
|
|
47
|
+
export type MetricSeriesTags = Record<string, string>;
|
|
48
|
+
/**
|
|
49
|
+
* The request identity and applied filters used to derive authoritative tags.
|
|
50
|
+
*
|
|
51
|
+
* `realm`/`environment` are parsed from `tenantId`. The optional filter fields
|
|
52
|
+
* mirror the Metrics API's category filters; when a filter was sent, that
|
|
53
|
+
* dimension is *known from the request* and is stamped onto every series as an
|
|
54
|
+
* authoritative tag — rather than being (mis)parsed from a drilled-down series
|
|
55
|
+
* id. For example, requesting `apiFamily=shopper` makes the server return
|
|
56
|
+
* finer-grained ids like `bdpx.shopper.auth.v1`; folding the filter in yields the
|
|
57
|
+
* correct `apiFamily: "shopper"` instead of the string-parser's wrong
|
|
58
|
+
* `apiFamily: "shopper.auth.v1"`.
|
|
59
|
+
*/
|
|
60
|
+
export interface MetricsTagContext {
|
|
61
|
+
/** Tenant or organization id the request targeted (with or without `f_ecom_`). */
|
|
62
|
+
tenantId: string;
|
|
63
|
+
/** The `apiFamily` filter sent with a scapi request, if any. */
|
|
64
|
+
apiFamily?: string;
|
|
65
|
+
/** The `apiName` filter sent with a scapi request, if any. */
|
|
66
|
+
apiName?: string;
|
|
67
|
+
/** The `ocapiCategory` filter sent with an ocapi request, if any. */
|
|
68
|
+
ocapiCategory?: string;
|
|
69
|
+
/** The `ocapiApi` filter sent with an ocapi request, if any. */
|
|
70
|
+
ocapiApi?: string;
|
|
71
|
+
/** The `thirdPartyServiceId` filter sent with a third-party request, if any. */
|
|
72
|
+
thirdPartyServiceId?: string;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Extracts the dimension tags for a single series id.
|
|
76
|
+
*
|
|
77
|
+
* Combines three tiers, most-authoritative last:
|
|
78
|
+
* 1. **Request identity** — `realm`/`environment` from the tenant id (never parsed
|
|
79
|
+
* from the series string).
|
|
80
|
+
* 2. **String heuristics** — category/metric-specific dimensions parsed from the
|
|
81
|
+
* packed id (`apiFamily`, `host`, `cacheStatus`, …), or the raw remainder under
|
|
82
|
+
* `series` when no rule matches.
|
|
83
|
+
* 3. **Applied filters** — any filter that was sent with the request
|
|
84
|
+
* ({@link MetricsTagContext}) is stamped last, overriding a heuristic guess.
|
|
85
|
+
* This corrects drill-down ids: with `apiFamily=shopper` the server returns
|
|
86
|
+
* `bdpx.shopper.auth.v1`, which heuristics would mis-tag as
|
|
87
|
+
* `apiFamily: "shopper.auth.v1"`; the filter restores `apiFamily: "shopper"`.
|
|
88
|
+
*
|
|
89
|
+
* The result is always a superset of the request context and never throws.
|
|
90
|
+
*
|
|
91
|
+
* @param params - The series' category, metric id, series id, and request context
|
|
92
|
+
* @returns The extracted {@link MetricSeriesTags}
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* parseSeriesTags({
|
|
97
|
+
* category: 'scapi', metricId: 'cacheHitRate',
|
|
98
|
+
* seriesId: 'bdpx.product HIT', context: {tenantId: 'f_ecom_bdpx_prd'},
|
|
99
|
+
* });
|
|
100
|
+
* // → { realm: 'bdpx', environment: 'prd', apiFamily: 'product', cacheStatus: 'HIT' }
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare function parseSeriesTags(params: {
|
|
104
|
+
category: MetricCategory;
|
|
105
|
+
metricId: string;
|
|
106
|
+
seriesId: string;
|
|
107
|
+
context: MetricsTagContext;
|
|
108
|
+
}): MetricSeriesTags;
|
|
109
|
+
/**
|
|
110
|
+
* Enriches a metrics response by adding a structured `tags` map to every series,
|
|
111
|
+
* in place-safe fashion (returns a new response; the input is not mutated).
|
|
112
|
+
*
|
|
113
|
+
* This is the batch counterpart to {@link parseSeriesTags}: it walks every
|
|
114
|
+
* metric and series and attaches `series.tags` derived from the series id, the
|
|
115
|
+
* metric id, the category, and the request context. Existing fields (`id`,
|
|
116
|
+
* `name`, `data`) are preserved exactly, so the enriched response is a
|
|
117
|
+
* structural superset — consumers that ignore `tags` are unaffected. The
|
|
118
|
+
* category must be supplied because a {@link MetricsDataResponse} does not carry
|
|
119
|
+
* it (it is implied by the endpoint that produced the response).
|
|
120
|
+
*
|
|
121
|
+
* @param response - The metrics response to enrich
|
|
122
|
+
* @param category - The metric category the response was fetched for
|
|
123
|
+
* @param context - The request identity used to derive `realm`/`environment`
|
|
124
|
+
* @returns A new response with `tags` added to each series
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* const raw = await getScapiMetrics(client, tenantId);
|
|
129
|
+
* const enriched = enrichMetricsTags(raw, 'scapi', {tenantId});
|
|
130
|
+
* for (const metric of enriched.data) {
|
|
131
|
+
* for (const series of metric.dataSeries) {
|
|
132
|
+
* console.log(series.tags, series.data);
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
export declare function enrichMetricsTags(response: MetricsDataResponse, category: MetricCategory, context: MetricsTagContext): MetricsTaggedResponse;
|
|
138
|
+
/**
|
|
139
|
+
* A metrics response whose series carry the structured {@link MetricSeriesTags}.
|
|
140
|
+
* Structurally a superset of {@link MetricsDataResponse}.
|
|
141
|
+
*/
|
|
142
|
+
export interface MetricsTaggedResponse extends MetricsDataResponse {
|
|
143
|
+
data: Array<MetricsDataResponse['data'][number] & {
|
|
144
|
+
dataSeries: Array<MetricsDataResponse['data'][number]['dataSeries'][number] & {
|
|
145
|
+
tags: MetricSeriesTags;
|
|
146
|
+
}>;
|
|
147
|
+
}>;
|
|
148
|
+
}
|