@kortyx/usage-telemetry 0.3.0 → 0.4.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/CHANGELOG.md +8 -0
- package/README.md +86 -4
- package/dist/browser-node.d.ts +11 -3
- package/dist/browser-node.js +432 -23
- package/dist/browser-node.js.map +1 -1
- package/dist/{client-rVwo4XAO.d.ts → client-BPjAx5oh.d.ts} +8 -5
- package/dist/index.d.ts +12 -3
- package/dist/index.js +426 -23
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +10 -4
- package/dist/node.js +445 -24
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
package/dist/browser-node.js
CHANGED
|
@@ -23,8 +23,10 @@ __export(browser_node_exports, {
|
|
|
23
23
|
configureUsageTelemetry: () => configureUsageTelemetry,
|
|
24
24
|
createNodeUsageTelemetry: () => createNodeUsageTelemetry,
|
|
25
25
|
createUsageTelemetry: () => createUsageTelemetry,
|
|
26
|
+
flushUsageTelemetry: () => flushUsageTelemetry,
|
|
26
27
|
getUsageTelemetry: () => getUsageTelemetry,
|
|
27
28
|
publicUsageConfiguration: () => publicUsageConfiguration,
|
|
29
|
+
runtimeUsageContext: () => runtimeUsageContext,
|
|
28
30
|
scale: () => scale,
|
|
29
31
|
usageDisabled: () => usageDisabled
|
|
30
32
|
});
|
|
@@ -72,6 +74,10 @@ var operations = [
|
|
|
72
74
|
"studio.settings",
|
|
73
75
|
"studio.update",
|
|
74
76
|
"studio.ingest",
|
|
77
|
+
"cli.command",
|
|
78
|
+
"studio.eval.execution",
|
|
79
|
+
"studio.diagnostic",
|
|
80
|
+
"studio.table.layout",
|
|
75
81
|
"cli.topology",
|
|
76
82
|
"cli.eval"
|
|
77
83
|
];
|
|
@@ -86,9 +92,143 @@ var outcomes = [
|
|
|
86
92
|
"ungraded"
|
|
87
93
|
];
|
|
88
94
|
var publicCatalog = {
|
|
89
|
-
products: ["sdk", "oss_studio"],
|
|
95
|
+
products: ["sdk", "oss_studio", "cli"],
|
|
90
96
|
operations,
|
|
91
97
|
properties: {
|
|
98
|
+
measurement_version: ["2"],
|
|
99
|
+
measurement_kind: [
|
|
100
|
+
"invocation",
|
|
101
|
+
"stage",
|
|
102
|
+
"execution",
|
|
103
|
+
"attempt",
|
|
104
|
+
"chunk",
|
|
105
|
+
"output",
|
|
106
|
+
"update",
|
|
107
|
+
"poll",
|
|
108
|
+
"request",
|
|
109
|
+
"call",
|
|
110
|
+
"feature",
|
|
111
|
+
"observation"
|
|
112
|
+
],
|
|
113
|
+
traffic_source: ["internal", "synthetic", "external", "unknown"],
|
|
114
|
+
layout_action: [
|
|
115
|
+
"visibility",
|
|
116
|
+
"show_all",
|
|
117
|
+
"reset",
|
|
118
|
+
"apply",
|
|
119
|
+
"reset_width",
|
|
120
|
+
"pin",
|
|
121
|
+
"unpin",
|
|
122
|
+
"resize",
|
|
123
|
+
"reorder"
|
|
124
|
+
],
|
|
125
|
+
eval_phase: [
|
|
126
|
+
"params",
|
|
127
|
+
"setup",
|
|
128
|
+
"execute",
|
|
129
|
+
"responder",
|
|
130
|
+
"reference",
|
|
131
|
+
"grading",
|
|
132
|
+
"verification",
|
|
133
|
+
"cleanup",
|
|
134
|
+
"reporting"
|
|
135
|
+
],
|
|
136
|
+
cli_resource: ["evals.runs", "evals.suites"],
|
|
137
|
+
retryable: "boolean",
|
|
138
|
+
retried: "boolean",
|
|
139
|
+
recovered: "boolean",
|
|
140
|
+
retry_attempt: ["1", "2-5", "6-20", "21-100", "101+"],
|
|
141
|
+
batch_size: ["1", "2-5", "6-20", "21-100", "101+"],
|
|
142
|
+
http_status_class: ["1xx", "2xx", "3xx", "4xx", "5xx"],
|
|
143
|
+
cause_category: [
|
|
144
|
+
"configuration",
|
|
145
|
+
"provider",
|
|
146
|
+
"validation",
|
|
147
|
+
"domain",
|
|
148
|
+
"workflow",
|
|
149
|
+
"persistence",
|
|
150
|
+
"request",
|
|
151
|
+
"transport",
|
|
152
|
+
"internal",
|
|
153
|
+
"unknown"
|
|
154
|
+
],
|
|
155
|
+
cli_command: [
|
|
156
|
+
"studio.start",
|
|
157
|
+
"studio.stop",
|
|
158
|
+
"studio.restart",
|
|
159
|
+
"studio.status",
|
|
160
|
+
"studio.logs",
|
|
161
|
+
"studio.credentials",
|
|
162
|
+
"studio.reset",
|
|
163
|
+
"studio.prompts",
|
|
164
|
+
"studio.evals",
|
|
165
|
+
"studio.runs",
|
|
166
|
+
"studio.sessions",
|
|
167
|
+
"studio.interrupts",
|
|
168
|
+
"studio.workflows",
|
|
169
|
+
"studio.diagnostics",
|
|
170
|
+
"studio.inspect",
|
|
171
|
+
"studio.doctor",
|
|
172
|
+
"studio.catalogs",
|
|
173
|
+
"connections",
|
|
174
|
+
"evals.run",
|
|
175
|
+
"evals.list",
|
|
176
|
+
"topology.push",
|
|
177
|
+
"help",
|
|
178
|
+
"unknown"
|
|
179
|
+
],
|
|
180
|
+
cli_action: [
|
|
181
|
+
"start",
|
|
182
|
+
"stop",
|
|
183
|
+
"restart",
|
|
184
|
+
"status",
|
|
185
|
+
"logs",
|
|
186
|
+
"credentials",
|
|
187
|
+
"reset",
|
|
188
|
+
"run",
|
|
189
|
+
"list",
|
|
190
|
+
"get",
|
|
191
|
+
"show",
|
|
192
|
+
"inspect",
|
|
193
|
+
"analyze",
|
|
194
|
+
"download",
|
|
195
|
+
"doctor",
|
|
196
|
+
"cancel",
|
|
197
|
+
"compare",
|
|
198
|
+
"create",
|
|
199
|
+
"update",
|
|
200
|
+
"delete",
|
|
201
|
+
"import",
|
|
202
|
+
"export",
|
|
203
|
+
"pull",
|
|
204
|
+
"push",
|
|
205
|
+
"add",
|
|
206
|
+
"remove",
|
|
207
|
+
"use",
|
|
208
|
+
"verify",
|
|
209
|
+
"versions",
|
|
210
|
+
"diff",
|
|
211
|
+
"validate",
|
|
212
|
+
"action",
|
|
213
|
+
"tag",
|
|
214
|
+
"untag",
|
|
215
|
+
"rollback",
|
|
216
|
+
"promote",
|
|
217
|
+
"archive",
|
|
218
|
+
"restore",
|
|
219
|
+
"test",
|
|
220
|
+
"copy",
|
|
221
|
+
"apply",
|
|
222
|
+
"wait",
|
|
223
|
+
"catalogs",
|
|
224
|
+
"help",
|
|
225
|
+
"unknown"
|
|
226
|
+
],
|
|
227
|
+
dry_run: "boolean",
|
|
228
|
+
json_output: "boolean",
|
|
229
|
+
settings_override: "boolean",
|
|
230
|
+
case_timeout_override: "boolean",
|
|
231
|
+
run_timeout_override: "boolean",
|
|
92
232
|
phase: [
|
|
93
233
|
"admission",
|
|
94
234
|
"execution",
|
|
@@ -233,6 +373,7 @@ var publicCatalog = {
|
|
|
233
373
|
"pending",
|
|
234
374
|
"expired"
|
|
235
375
|
],
|
|
376
|
+
match: ["all", "any"],
|
|
236
377
|
filter: [
|
|
237
378
|
"search",
|
|
238
379
|
"status",
|
|
@@ -265,6 +406,7 @@ var publicCatalog = {
|
|
|
265
406
|
"401",
|
|
266
407
|
"403",
|
|
267
408
|
"404",
|
|
409
|
+
"408",
|
|
268
410
|
"409",
|
|
269
411
|
"413",
|
|
270
412
|
"422",
|
|
@@ -288,6 +430,47 @@ var publicCatalog = {
|
|
|
288
430
|
},
|
|
289
431
|
// Built-in contracts only; application codes and provider response text are excluded.
|
|
290
432
|
errorCodes: [
|
|
433
|
+
"UNCLASSIFIED_FAILURE",
|
|
434
|
+
"HTTP_UNAUTHORIZED",
|
|
435
|
+
"HTTP_FORBIDDEN",
|
|
436
|
+
"HTTP_NOT_FOUND",
|
|
437
|
+
"HTTP_TIMEOUT",
|
|
438
|
+
"HTTP_CONFLICT",
|
|
439
|
+
"HTTP_TOO_LARGE",
|
|
440
|
+
"HTTP_RATE_LIMITED",
|
|
441
|
+
"HTTP_SERVER_ERROR",
|
|
442
|
+
"HTTP_INVALID_REQUEST",
|
|
443
|
+
"NETWORK_DNS_FAILED",
|
|
444
|
+
"NETWORK_CONNECTION_REFUSED",
|
|
445
|
+
"NETWORK_CONNECTION_RESET",
|
|
446
|
+
"NETWORK_TIMEOUT",
|
|
447
|
+
"NETWORK_TLS_FAILED",
|
|
448
|
+
"CLI_ARGUMENT_INVALID",
|
|
449
|
+
"CLI_EXIT_FAILED",
|
|
450
|
+
"STUDIO_NOT_CONFIGURED",
|
|
451
|
+
"STUDIO_RESPONSE_INVALID",
|
|
452
|
+
"EVAL_CONCURRENCY_CHANGED",
|
|
453
|
+
"EVAL_CONSUMER_FAILED",
|
|
454
|
+
"EVAL_CONTRACT_CHANGED",
|
|
455
|
+
"EVAL_DISCOVERY_REJECTED",
|
|
456
|
+
"EVAL_EXECUTION_CONFLICT",
|
|
457
|
+
"EVAL_EXECUTION_STORE_CHANGED",
|
|
458
|
+
"EVAL_EXECUTION_UNKNOWN",
|
|
459
|
+
"EVAL_EXECUTOR_BUSY",
|
|
460
|
+
"EVAL_EXECUTOR_FAILED",
|
|
461
|
+
"EVAL_EXECUTOR_REJECTED",
|
|
462
|
+
"EVAL_EXECUTOR_UNAUTHORIZED",
|
|
463
|
+
"EVAL_GRADING_FAILED",
|
|
464
|
+
"EVAL_GRADING_TIMEOUT",
|
|
465
|
+
"EVAL_JUDGE_UNAVAILABLE",
|
|
466
|
+
"EVAL_LEASE_LOST",
|
|
467
|
+
"EVAL_RETRY_DELAY_EXCEEDED",
|
|
468
|
+
"EVAL_SETUP_TIMEOUT",
|
|
469
|
+
"EVAL_TRANSPORT_UNAVAILABLE",
|
|
470
|
+
"EVAL_VERIFICATION_TIMEOUT",
|
|
471
|
+
"EVAL_RESULT_INVALID",
|
|
472
|
+
"EVAL_RUN_TIMEOUT",
|
|
473
|
+
"EVAL_SETTINGS_INVALID",
|
|
291
474
|
"EXECUTION_FAILED",
|
|
292
475
|
"INVALID_REQUEST",
|
|
293
476
|
"INVALID_RESUME",
|
|
@@ -355,8 +538,8 @@ function scale(value) {
|
|
|
355
538
|
return value <= 1 ? "1" : value <= 5 ? "2-5" : value <= 20 ? "6-20" : value <= 100 ? "21-100" : "101+";
|
|
356
539
|
}
|
|
357
540
|
|
|
358
|
-
// src/
|
|
359
|
-
function
|
|
541
|
+
// src/failure.ts
|
|
542
|
+
function usageErrorProperty(value, key) {
|
|
360
543
|
try {
|
|
361
544
|
if (!value || typeof value !== "object") return void 0;
|
|
362
545
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
@@ -365,40 +548,201 @@ function property(value, key) {
|
|
|
365
548
|
return void 0;
|
|
366
549
|
}
|
|
367
550
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
551
|
+
var networkCodes = {
|
|
552
|
+
ENOTFOUND: "NETWORK_DNS_FAILED",
|
|
553
|
+
EAI_AGAIN: "NETWORK_DNS_FAILED",
|
|
554
|
+
ECONNREFUSED: "NETWORK_CONNECTION_REFUSED",
|
|
555
|
+
ECONNRESET: "NETWORK_CONNECTION_RESET",
|
|
556
|
+
EPIPE: "NETWORK_CONNECTION_RESET",
|
|
557
|
+
ETIMEDOUT: "NETWORK_TIMEOUT",
|
|
558
|
+
UND_ERR_CONNECT_TIMEOUT: "NETWORK_TIMEOUT",
|
|
559
|
+
UND_ERR_HEADERS_TIMEOUT: "NETWORK_TIMEOUT",
|
|
560
|
+
UND_ERR_BODY_TIMEOUT: "NETWORK_TIMEOUT",
|
|
561
|
+
CERT_HAS_EXPIRED: "NETWORK_TLS_FAILED",
|
|
562
|
+
DEPTH_ZERO_SELF_SIGNED_CERT: "NETWORK_TLS_FAILED",
|
|
563
|
+
UNABLE_TO_VERIFY_LEAF_SIGNATURE: "NETWORK_TLS_FAILED"
|
|
564
|
+
};
|
|
565
|
+
function classifyUsageHttpStatus(status) {
|
|
566
|
+
if (!Number.isInteger(status) || status < 100 || status > 599)
|
|
567
|
+
return {
|
|
568
|
+
outcome: "failed",
|
|
569
|
+
properties: {
|
|
570
|
+
error_code: "UNCLASSIFIED_FAILURE",
|
|
571
|
+
error_category: "unknown"
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
if (status < 400)
|
|
575
|
+
return {
|
|
576
|
+
outcome: "success",
|
|
577
|
+
properties: { http_status_class: `${Math.floor(status / 100)}xx` }
|
|
578
|
+
};
|
|
579
|
+
const code = status === 401 ? "HTTP_UNAUTHORIZED" : status === 403 ? "HTTP_FORBIDDEN" : status === 404 ? "HTTP_NOT_FOUND" : status === 408 || status === 504 ? "HTTP_TIMEOUT" : status === 409 ? "HTTP_CONFLICT" : status === 413 ? "HTTP_TOO_LARGE" : status === 429 ? "HTTP_RATE_LIMITED" : status >= 500 ? "HTTP_SERVER_ERROR" : "HTTP_INVALID_REQUEST";
|
|
580
|
+
return {
|
|
581
|
+
outcome: "failed",
|
|
582
|
+
properties: {
|
|
583
|
+
error_code: code,
|
|
584
|
+
error_category: status >= 500 || status === 408 ? "transport" : "request",
|
|
585
|
+
http_status: String(status),
|
|
586
|
+
http_status_class: `${Math.floor(status / 100)}xx`,
|
|
587
|
+
retryable: status === 408 || status === 429 || status >= 500
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
function nativeExceptionName(value) {
|
|
592
|
+
try {
|
|
593
|
+
if (typeof DOMException !== "undefined")
|
|
594
|
+
return Object.getOwnPropertyDescriptor(
|
|
595
|
+
DOMException.prototype,
|
|
596
|
+
"name"
|
|
597
|
+
)?.get?.call(value);
|
|
598
|
+
} catch {
|
|
599
|
+
}
|
|
600
|
+
return void 0;
|
|
601
|
+
}
|
|
602
|
+
function classifyOne(error, catalog) {
|
|
603
|
+
const read = (key) => usageErrorProperty(error, key);
|
|
604
|
+
let name = read("name") ?? nativeExceptionName(error);
|
|
605
|
+
try {
|
|
606
|
+
if (name === void 0 && error instanceof SyntaxError)
|
|
607
|
+
name = "SyntaxError";
|
|
608
|
+
} catch {
|
|
609
|
+
}
|
|
610
|
+
const code = read("code");
|
|
611
|
+
if (name === "AbortError" || code === "EXECUTION_CANCELLED" || code === "ABORT_ERR")
|
|
372
612
|
return { outcome: "cancelled", properties: {} };
|
|
373
613
|
if (code === "EXECUTION_LIMIT_REACHED" || name === "ExecutionLimitReached")
|
|
374
614
|
return { outcome: "limit_reached", properties: {} };
|
|
375
|
-
if (
|
|
615
|
+
if (typeof name === "string" && [
|
|
616
|
+
"GraphInterrupt",
|
|
617
|
+
"NodeInterrupt",
|
|
618
|
+
"Interrupt",
|
|
619
|
+
"ParallelChildWaiting"
|
|
620
|
+
].includes(name))
|
|
376
621
|
return { outcome: "suspended", properties: {} };
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
622
|
+
if (name === "EvalConfigurationError")
|
|
623
|
+
return {
|
|
624
|
+
outcome: "failed",
|
|
625
|
+
properties: {
|
|
626
|
+
error_code: "EVAL_SETTINGS_INVALID",
|
|
627
|
+
error_category: "configuration",
|
|
628
|
+
retryable: false
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
if (name === "TimeoutError")
|
|
632
|
+
return {
|
|
633
|
+
outcome: "failed",
|
|
634
|
+
properties: {
|
|
635
|
+
error_code: "NETWORK_TIMEOUT",
|
|
636
|
+
error_category: "transport",
|
|
637
|
+
retryable: true
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
if (typeof code === "string" && Object.hasOwn(networkCodes, code))
|
|
641
|
+
return {
|
|
642
|
+
outcome: "failed",
|
|
643
|
+
properties: {
|
|
644
|
+
error_code: networkCodes[code] ?? "UNCLASSIFIED_FAILURE",
|
|
645
|
+
error_category: "transport",
|
|
646
|
+
retryable: true
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
if (typeof code === "string" && catalog.errorCodes.includes(code)) {
|
|
650
|
+
const failure = usageErrorProperty(error, "failure");
|
|
651
|
+
const category = read("category") ?? usageErrorProperty(failure, "category");
|
|
652
|
+
const retryable = read("retryable") ?? usageErrorProperty(failure, "retryable");
|
|
653
|
+
const status2 = read("status") ?? usageErrorProperty(failure, "status");
|
|
654
|
+
return {
|
|
655
|
+
outcome: "failed",
|
|
656
|
+
properties: {
|
|
657
|
+
...typeof status2 === "number" ? classifyUsageHttpStatus(status2).properties : {},
|
|
658
|
+
// The framework code is more specific than its HTTP projection.
|
|
659
|
+
error_code: code,
|
|
660
|
+
error_category: code !== "EXECUTION_FAILED" && typeof category === "string" && Array.isArray(catalog.properties.error_category) && catalog.properties.error_category.includes(category) ? category : "unknown",
|
|
661
|
+
...typeof retryable === "boolean" ? { retryable } : {}
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
const status = read("status") ?? read("statusCode");
|
|
666
|
+
if (typeof status === "number" && Number.isInteger(status) && status >= 400 && status <= 599)
|
|
667
|
+
return classifyUsageHttpStatus(status);
|
|
668
|
+
if (name === "ZodError" || name === "SyntaxError")
|
|
669
|
+
return {
|
|
670
|
+
outcome: "failed",
|
|
671
|
+
properties: {
|
|
672
|
+
error_code: "SCHEMA_VALIDATION",
|
|
673
|
+
error_category: "validation"
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
return void 0;
|
|
677
|
+
}
|
|
678
|
+
function classifyUsageError(error, catalog = publicCatalog) {
|
|
679
|
+
const seen = /* @__PURE__ */ new Set();
|
|
680
|
+
const pending = [{ value: error, depth: 0 }];
|
|
681
|
+
let result;
|
|
682
|
+
while (pending.length && seen.size < 8) {
|
|
683
|
+
const current = pending.shift();
|
|
684
|
+
if (!current || seen.has(current.value)) continue;
|
|
685
|
+
seen.add(current.value);
|
|
686
|
+
const found = classifyOne(current.value, catalog);
|
|
687
|
+
if (found) {
|
|
688
|
+
if (!result) result = found;
|
|
689
|
+
else if (found.properties.error_code && found.outcome === "failed" && found.properties.error_code !== result.properties.error_code) {
|
|
690
|
+
result.properties.cause_code = found.properties.error_code;
|
|
691
|
+
result.properties.cause_category = found.properties.error_category ?? "unknown";
|
|
692
|
+
if (result.properties.retryable === void 0 && typeof found.properties.retryable === "boolean")
|
|
693
|
+
result.properties.retryable = found.properties.retryable;
|
|
694
|
+
break;
|
|
695
|
+
}
|
|
696
|
+
if (result === found && found.outcome !== "failed") return found;
|
|
386
697
|
}
|
|
698
|
+
if (current.depth < 3)
|
|
699
|
+
for (const key of ["failure", "cause", "error"]) {
|
|
700
|
+
const value = usageErrorProperty(current.value, key);
|
|
701
|
+
if (value && typeof value === "object")
|
|
702
|
+
pending.push({ value, depth: current.depth + 1 });
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return result ?? {
|
|
706
|
+
outcome: "failed",
|
|
707
|
+
properties: { error_code: "other", error_category: "unknown" }
|
|
387
708
|
};
|
|
388
709
|
}
|
|
710
|
+
|
|
711
|
+
// src/measurement.ts
|
|
712
|
+
function usageMeasurement(event, operation, input) {
|
|
713
|
+
if (event === "usage.feature")
|
|
714
|
+
return usageErrorProperty(input, "origin") === "background" || usageErrorProperty(input, "origin") === "server" ? "observation" : "feature";
|
|
715
|
+
if (operation === "cli.command" || operation === "sdk.eval")
|
|
716
|
+
return "invocation";
|
|
717
|
+
if (operation === "studio.setup") return "stage";
|
|
718
|
+
if (operation === "sdk.execution" || operation === "studio.eval.execution")
|
|
719
|
+
return "execution";
|
|
720
|
+
if (operation === "sdk.export" || operation === "sdk.model") return "attempt";
|
|
721
|
+
if (operation === "sdk.structured") {
|
|
722
|
+
const format = usageErrorProperty(input, "format");
|
|
723
|
+
return format === "text-delta" ? "chunk" : format === "final" ? "output" : "update";
|
|
724
|
+
}
|
|
725
|
+
if (usageErrorProperty(input, "origin") === "background") return "poll";
|
|
726
|
+
if (operation.startsWith("studio.")) return "request";
|
|
727
|
+
return "call";
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/client.ts
|
|
389
731
|
function sanitizeProperties(input, catalog = publicCatalog) {
|
|
390
732
|
const safe = {};
|
|
391
733
|
for (const [key, rule] of Object.entries(catalog.properties)) {
|
|
392
|
-
const value =
|
|
734
|
+
const value = usageErrorProperty(input, key);
|
|
393
735
|
if (value === void 0) continue;
|
|
394
736
|
if (rule === "boolean") {
|
|
395
737
|
if (typeof value === "boolean") safe[key] = value;
|
|
396
738
|
} else if (typeof value === "string")
|
|
397
739
|
safe[key] = rule.includes(value) ? value : "other";
|
|
398
740
|
}
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
741
|
+
for (const key of ["error_code", "cause_code"]) {
|
|
742
|
+
const code = usageErrorProperty(input, key);
|
|
743
|
+
if (typeof code === "string")
|
|
744
|
+
safe[key] = catalog.errorCodes.includes(code) ? code : "other";
|
|
745
|
+
}
|
|
402
746
|
return safe;
|
|
403
747
|
}
|
|
404
748
|
var durationBounds = [10, 100, 1e3, 1e4, 6e4];
|
|
@@ -419,6 +763,16 @@ function createUsageTelemetry(options) {
|
|
|
419
763
|
let disposed = false;
|
|
420
764
|
let dropped = 0;
|
|
421
765
|
let delivered = 0;
|
|
766
|
+
let lostObservations = 0;
|
|
767
|
+
let failedBatches = 0;
|
|
768
|
+
let reportedLoss = 0;
|
|
769
|
+
let reportedFailures = 0;
|
|
770
|
+
const lose = (count) => {
|
|
771
|
+
lostObservations = Math.min(
|
|
772
|
+
Number.MAX_SAFE_INTEGER,
|
|
773
|
+
lostObservations + count
|
|
774
|
+
);
|
|
775
|
+
};
|
|
422
776
|
let hour = Math.floor(now() / 36e5);
|
|
423
777
|
let sent = 0;
|
|
424
778
|
const active = () => {
|
|
@@ -454,6 +808,10 @@ function createUsageTelemetry(options) {
|
|
|
454
808
|
pending.clear();
|
|
455
809
|
if (!records.length) return;
|
|
456
810
|
let attempted = records.length;
|
|
811
|
+
let attemptedObservations = records.reduce(
|
|
812
|
+
(total, record2) => total + record2.count,
|
|
813
|
+
0
|
|
814
|
+
);
|
|
457
815
|
flight = (async () => {
|
|
458
816
|
try {
|
|
459
817
|
if (options.debug?.()) {
|
|
@@ -471,7 +829,14 @@ function createUsageTelemetry(options) {
|
|
|
471
829
|
);
|
|
472
830
|
const batch = records.slice(0, allowance);
|
|
473
831
|
dropped += records.length - batch.length;
|
|
832
|
+
lose(
|
|
833
|
+
records.slice(allowance).reduce((total, record2) => total + record2.count, 0)
|
|
834
|
+
);
|
|
474
835
|
attempted = batch.length;
|
|
836
|
+
attemptedObservations = batch.reduce(
|
|
837
|
+
(total, record2) => total + record2.count,
|
|
838
|
+
0
|
|
839
|
+
);
|
|
475
840
|
if (!batch.length || !active()) return;
|
|
476
841
|
const identified = await options.identity();
|
|
477
842
|
const identity = typeof identified === "string" ? identified : identified.id;
|
|
@@ -482,13 +847,25 @@ function createUsageTelemetry(options) {
|
|
|
482
847
|
identity
|
|
483
848
|
)) {
|
|
484
849
|
dropped += batch.length;
|
|
850
|
+
lose(attemptedObservations);
|
|
485
851
|
return;
|
|
486
852
|
}
|
|
487
853
|
sent += batch.length;
|
|
854
|
+
const lossSnapshot = lostObservations;
|
|
855
|
+
const failureSnapshot = failedBatches;
|
|
856
|
+
if (batch[0] && (lossSnapshot > reportedLoss || failureSnapshot > reportedFailures))
|
|
857
|
+
batch[0].delivery_health = {
|
|
858
|
+
dropped_observations: lossSnapshot - reportedLoss,
|
|
859
|
+
failed_batches: failureSnapshot - reportedFailures
|
|
860
|
+
};
|
|
488
861
|
await options.transport(batch, identity);
|
|
862
|
+
reportedLoss = lossSnapshot;
|
|
863
|
+
reportedFailures = failureSnapshot;
|
|
489
864
|
delivered += batch.length;
|
|
490
865
|
} catch {
|
|
491
866
|
dropped += attempted;
|
|
867
|
+
lose(attemptedObservations);
|
|
868
|
+
failedBatches = Math.min(Number.MAX_SAFE_INTEGER, failedBatches + 1);
|
|
492
869
|
}
|
|
493
870
|
})().finally(() => {
|
|
494
871
|
flight = void 0;
|
|
@@ -512,12 +889,29 @@ function createUsageTelemetry(options) {
|
|
|
512
889
|
}
|
|
513
890
|
if (!configured || !catalog.operations.includes(operation) || !outcomes.includes(outcome))
|
|
514
891
|
return;
|
|
515
|
-
const
|
|
892
|
+
const failed = outcome === "failed";
|
|
893
|
+
const status = usageErrorProperty(input, "http_status");
|
|
894
|
+
const http = typeof status === "string" && /^\d{3}$/.test(status) ? classifyUsageHttpStatus(Number(status)).properties : {};
|
|
895
|
+
const properties = sanitizeProperties(
|
|
896
|
+
{
|
|
897
|
+
measurement_version: "2",
|
|
898
|
+
measurement_kind: usageMeasurement(event, operation, input),
|
|
899
|
+
...failed ? {
|
|
900
|
+
error_code: "UNCLASSIFIED_FAILURE",
|
|
901
|
+
error_category: "unknown",
|
|
902
|
+
...http
|
|
903
|
+
} : {},
|
|
904
|
+
...sanitizeProperties(input, catalog),
|
|
905
|
+
traffic_source: options.context.trafficSource ?? "unknown"
|
|
906
|
+
},
|
|
907
|
+
catalog
|
|
908
|
+
);
|
|
516
909
|
const key = JSON.stringify([event, operation, outcome, properties]);
|
|
517
910
|
let existing = pending.get(key);
|
|
518
911
|
if (!existing) {
|
|
519
912
|
if (pending.size >= (options.maxGroups ?? 64)) {
|
|
520
913
|
dropped++;
|
|
914
|
+
lose(1);
|
|
521
915
|
return;
|
|
522
916
|
}
|
|
523
917
|
existing = {
|
|
@@ -529,7 +923,9 @@ function createUsageTelemetry(options) {
|
|
|
529
923
|
component: options.context.component,
|
|
530
924
|
version: options.context.version,
|
|
531
925
|
analytics_environment: options.context.environment ?? "production",
|
|
532
|
-
runtime_mode:
|
|
926
|
+
runtime_mode: ["development", "production", "ci"].includes(
|
|
927
|
+
options.context.runtimeMode ?? ""
|
|
928
|
+
) ? options.context.runtimeMode ?? "unknown" : "unknown",
|
|
533
929
|
identity_scope: options.context.identityScope ?? "installation",
|
|
534
930
|
operation,
|
|
535
931
|
outcome,
|
|
@@ -574,8 +970,11 @@ function createUsageTelemetry(options) {
|
|
|
574
970
|
if (ended) return;
|
|
575
971
|
ended = true;
|
|
576
972
|
try {
|
|
973
|
+
const status = usageErrorProperty(extra, "http_status");
|
|
974
|
+
const http = outcome === "failed" && typeof status === "string" && /^\d{3}$/.test(status) ? classifyUsageHttpStatus(Number(status)).properties : {};
|
|
577
975
|
record("usage.operation", operation, outcome, now() - began, {
|
|
578
976
|
...initial,
|
|
977
|
+
...http,
|
|
579
978
|
...sanitizeProperties(extra, catalog)
|
|
580
979
|
});
|
|
581
980
|
} catch {
|
|
@@ -629,6 +1028,9 @@ function createUsageTelemetry(options) {
|
|
|
629
1028
|
|
|
630
1029
|
// src/browser-node.ts
|
|
631
1030
|
var clients = /* @__PURE__ */ new Map();
|
|
1031
|
+
async function flushUsageTelemetry() {
|
|
1032
|
+
await Promise.all([...clients.values()].map((client) => client.flush()));
|
|
1033
|
+
}
|
|
632
1034
|
function createNodeUsageTelemetry(options) {
|
|
633
1035
|
return createUsageTelemetry({
|
|
634
1036
|
...options,
|
|
@@ -656,9 +1058,14 @@ function getUsageTelemetry(component, version = "unknown", product = "sdk") {
|
|
|
656
1058
|
function usageDisabled() {
|
|
657
1059
|
return true;
|
|
658
1060
|
}
|
|
1061
|
+
function runtimeUsageContext() {
|
|
1062
|
+
return { runtimeMode: "unknown", trafficSource: "unknown" };
|
|
1063
|
+
}
|
|
659
1064
|
function publicUsageConfiguration() {
|
|
660
1065
|
return {
|
|
661
1066
|
enabled: false,
|
|
1067
|
+
runtimeMode: "unknown",
|
|
1068
|
+
trafficSource: "unknown",
|
|
662
1069
|
debug: false,
|
|
663
1070
|
environment: "production",
|
|
664
1071
|
key: "",
|
|
@@ -670,8 +1077,10 @@ function publicUsageConfiguration() {
|
|
|
670
1077
|
configureUsageTelemetry,
|
|
671
1078
|
createNodeUsageTelemetry,
|
|
672
1079
|
createUsageTelemetry,
|
|
1080
|
+
flushUsageTelemetry,
|
|
673
1081
|
getUsageTelemetry,
|
|
674
1082
|
publicUsageConfiguration,
|
|
1083
|
+
runtimeUsageContext,
|
|
675
1084
|
scale,
|
|
676
1085
|
usageDisabled
|
|
677
1086
|
});
|