@kortyx/usage-telemetry 0.3.0 → 0.5.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 +17 -0
- package/README.md +126 -4
- package/dist/browser-node.d.ts +11 -3
- package/dist/browser-node.js +549 -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 +543 -23
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +10 -4
- package/dist/node.js +562 -24
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -23,8 +23,10 @@ __export(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
|
});
|
|
@@ -62,6 +64,8 @@ var operations = [
|
|
|
62
64
|
"sdk.checkpoint.rollback",
|
|
63
65
|
"sdk.export",
|
|
64
66
|
"studio.setup",
|
|
67
|
+
"studio.sample",
|
|
68
|
+
"studio.help",
|
|
65
69
|
"studio.connection",
|
|
66
70
|
"studio.read",
|
|
67
71
|
"studio.render",
|
|
@@ -76,6 +80,11 @@ var operations = [
|
|
|
76
80
|
"studio.settings",
|
|
77
81
|
"studio.update",
|
|
78
82
|
"studio.ingest",
|
|
83
|
+
"cli.command",
|
|
84
|
+
"studio.eval.execution",
|
|
85
|
+
"studio.diagnostic",
|
|
86
|
+
"studio.table.layout",
|
|
87
|
+
"studio.help",
|
|
79
88
|
"cli.topology",
|
|
80
89
|
"cli.eval"
|
|
81
90
|
];
|
|
@@ -90,9 +99,256 @@ var outcomes = [
|
|
|
90
99
|
"ungraded"
|
|
91
100
|
];
|
|
92
101
|
var publicCatalog = {
|
|
93
|
-
products: ["sdk", "oss_studio"],
|
|
102
|
+
products: ["sdk", "oss_studio", "cli"],
|
|
94
103
|
operations,
|
|
95
104
|
properties: {
|
|
105
|
+
help_action: [
|
|
106
|
+
"open",
|
|
107
|
+
"documentation",
|
|
108
|
+
"start",
|
|
109
|
+
"step",
|
|
110
|
+
"complete",
|
|
111
|
+
"skip",
|
|
112
|
+
"exit",
|
|
113
|
+
"error",
|
|
114
|
+
"example_request",
|
|
115
|
+
"example_accept",
|
|
116
|
+
"example_cancel"
|
|
117
|
+
],
|
|
118
|
+
help_page: [
|
|
119
|
+
"runs",
|
|
120
|
+
"run",
|
|
121
|
+
"sessions",
|
|
122
|
+
"session",
|
|
123
|
+
"workflows",
|
|
124
|
+
"interrupts",
|
|
125
|
+
"interrupt",
|
|
126
|
+
"prompts",
|
|
127
|
+
"prompt",
|
|
128
|
+
"prompt-groups",
|
|
129
|
+
"prompt-group",
|
|
130
|
+
"evals",
|
|
131
|
+
"eval-suites",
|
|
132
|
+
"eval-suite",
|
|
133
|
+
"evaluation",
|
|
134
|
+
"eval-run",
|
|
135
|
+
"eval-case",
|
|
136
|
+
"eval-comparison",
|
|
137
|
+
"eval-case-comparison",
|
|
138
|
+
"diagnostic",
|
|
139
|
+
"settings",
|
|
140
|
+
"onboarding",
|
|
141
|
+
"other"
|
|
142
|
+
],
|
|
143
|
+
help_context: ["sample", "real"],
|
|
144
|
+
help_step: [
|
|
145
|
+
"overview",
|
|
146
|
+
"controls",
|
|
147
|
+
"records",
|
|
148
|
+
"tabs",
|
|
149
|
+
"content",
|
|
150
|
+
"navigation",
|
|
151
|
+
"state"
|
|
152
|
+
],
|
|
153
|
+
sample_action: [
|
|
154
|
+
"select",
|
|
155
|
+
"view",
|
|
156
|
+
"hide",
|
|
157
|
+
"show",
|
|
158
|
+
"tour_start",
|
|
159
|
+
"tour_complete",
|
|
160
|
+
"tour_skip",
|
|
161
|
+
"tour_error",
|
|
162
|
+
"tour_step",
|
|
163
|
+
"tour_hub",
|
|
164
|
+
"tour_resume",
|
|
165
|
+
"tour_exit",
|
|
166
|
+
"tour_full_start",
|
|
167
|
+
"tour_full_complete",
|
|
168
|
+
"tour_full_partial",
|
|
169
|
+
"tour_reset"
|
|
170
|
+
],
|
|
171
|
+
tour_chapter: [
|
|
172
|
+
"sample-execution",
|
|
173
|
+
"debug-execution",
|
|
174
|
+
"conversation",
|
|
175
|
+
"approvals",
|
|
176
|
+
"prompt-versions",
|
|
177
|
+
"evaluation-results",
|
|
178
|
+
"error-diagnostics",
|
|
179
|
+
"evaluation-progress",
|
|
180
|
+
"personalize"
|
|
181
|
+
],
|
|
182
|
+
tour_step: [
|
|
183
|
+
"project-selector",
|
|
184
|
+
"sample-run",
|
|
185
|
+
"execution-details",
|
|
186
|
+
"find-failed-run",
|
|
187
|
+
"failure-summary",
|
|
188
|
+
"failure-trace",
|
|
189
|
+
"failure-model-io",
|
|
190
|
+
"session-history",
|
|
191
|
+
"session-runs",
|
|
192
|
+
"workflow-topology",
|
|
193
|
+
"workflow-system",
|
|
194
|
+
"approval-decision",
|
|
195
|
+
"approval-timeline",
|
|
196
|
+
"approval-result",
|
|
197
|
+
"prompt-original",
|
|
198
|
+
"prompt-updated",
|
|
199
|
+
"prompt-diff",
|
|
200
|
+
"suite-definition",
|
|
201
|
+
"evaluation-summary",
|
|
202
|
+
"case-evidence",
|
|
203
|
+
"saved-comparison",
|
|
204
|
+
"diagnostic-exception",
|
|
205
|
+
"diagnostic-capture",
|
|
206
|
+
"diagnostic-context",
|
|
207
|
+
"evaluation-progress-summary",
|
|
208
|
+
"evaluation-grading",
|
|
209
|
+
"evaluation-pending-evidence",
|
|
210
|
+
"appearance",
|
|
211
|
+
"sample-visibility"
|
|
212
|
+
],
|
|
213
|
+
tour_failure: ["load", "target", "entry"],
|
|
214
|
+
tour_mode: ["chapter", "full"],
|
|
215
|
+
tour_version: ["1"],
|
|
216
|
+
help_placement: ["card", "button"],
|
|
217
|
+
measurement_version: ["2"],
|
|
218
|
+
measurement_kind: [
|
|
219
|
+
"invocation",
|
|
220
|
+
"stage",
|
|
221
|
+
"execution",
|
|
222
|
+
"attempt",
|
|
223
|
+
"chunk",
|
|
224
|
+
"output",
|
|
225
|
+
"update",
|
|
226
|
+
"poll",
|
|
227
|
+
"request",
|
|
228
|
+
"call",
|
|
229
|
+
"feature",
|
|
230
|
+
"observation"
|
|
231
|
+
],
|
|
232
|
+
traffic_source: ["internal", "synthetic", "external", "unknown"],
|
|
233
|
+
layout_action: [
|
|
234
|
+
"visibility",
|
|
235
|
+
"show_all",
|
|
236
|
+
"reset",
|
|
237
|
+
"apply",
|
|
238
|
+
"reset_width",
|
|
239
|
+
"pin",
|
|
240
|
+
"unpin",
|
|
241
|
+
"resize",
|
|
242
|
+
"reorder"
|
|
243
|
+
],
|
|
244
|
+
eval_phase: [
|
|
245
|
+
"params",
|
|
246
|
+
"setup",
|
|
247
|
+
"execute",
|
|
248
|
+
"responder",
|
|
249
|
+
"reference",
|
|
250
|
+
"grading",
|
|
251
|
+
"verification",
|
|
252
|
+
"cleanup",
|
|
253
|
+
"reporting"
|
|
254
|
+
],
|
|
255
|
+
cli_resource: ["evals.runs", "evals.suites"],
|
|
256
|
+
retryable: "boolean",
|
|
257
|
+
retried: "boolean",
|
|
258
|
+
recovered: "boolean",
|
|
259
|
+
retry_attempt: ["1", "2-5", "6-20", "21-100", "101+"],
|
|
260
|
+
batch_size: ["1", "2-5", "6-20", "21-100", "101+"],
|
|
261
|
+
http_status_class: ["1xx", "2xx", "3xx", "4xx", "5xx"],
|
|
262
|
+
cause_category: [
|
|
263
|
+
"configuration",
|
|
264
|
+
"provider",
|
|
265
|
+
"validation",
|
|
266
|
+
"domain",
|
|
267
|
+
"workflow",
|
|
268
|
+
"persistence",
|
|
269
|
+
"request",
|
|
270
|
+
"transport",
|
|
271
|
+
"internal",
|
|
272
|
+
"unknown"
|
|
273
|
+
],
|
|
274
|
+
cli_command: [
|
|
275
|
+
"studio.start",
|
|
276
|
+
"studio.stop",
|
|
277
|
+
"studio.restart",
|
|
278
|
+
"studio.status",
|
|
279
|
+
"studio.logs",
|
|
280
|
+
"studio.credentials",
|
|
281
|
+
"studio.reset",
|
|
282
|
+
"studio.prompts",
|
|
283
|
+
"studio.evals",
|
|
284
|
+
"studio.runs",
|
|
285
|
+
"studio.sessions",
|
|
286
|
+
"studio.interrupts",
|
|
287
|
+
"studio.workflows",
|
|
288
|
+
"studio.diagnostics",
|
|
289
|
+
"studio.inspect",
|
|
290
|
+
"studio.doctor",
|
|
291
|
+
"studio.catalogs",
|
|
292
|
+
"connections",
|
|
293
|
+
"evals.run",
|
|
294
|
+
"evals.list",
|
|
295
|
+
"topology.push",
|
|
296
|
+
"help",
|
|
297
|
+
"unknown"
|
|
298
|
+
],
|
|
299
|
+
cli_action: [
|
|
300
|
+
"start",
|
|
301
|
+
"stop",
|
|
302
|
+
"restart",
|
|
303
|
+
"status",
|
|
304
|
+
"logs",
|
|
305
|
+
"credentials",
|
|
306
|
+
"reset",
|
|
307
|
+
"run",
|
|
308
|
+
"list",
|
|
309
|
+
"get",
|
|
310
|
+
"show",
|
|
311
|
+
"inspect",
|
|
312
|
+
"analyze",
|
|
313
|
+
"download",
|
|
314
|
+
"doctor",
|
|
315
|
+
"cancel",
|
|
316
|
+
"compare",
|
|
317
|
+
"create",
|
|
318
|
+
"update",
|
|
319
|
+
"delete",
|
|
320
|
+
"import",
|
|
321
|
+
"export",
|
|
322
|
+
"pull",
|
|
323
|
+
"push",
|
|
324
|
+
"add",
|
|
325
|
+
"remove",
|
|
326
|
+
"use",
|
|
327
|
+
"verify",
|
|
328
|
+
"versions",
|
|
329
|
+
"diff",
|
|
330
|
+
"validate",
|
|
331
|
+
"action",
|
|
332
|
+
"tag",
|
|
333
|
+
"untag",
|
|
334
|
+
"rollback",
|
|
335
|
+
"promote",
|
|
336
|
+
"archive",
|
|
337
|
+
"restore",
|
|
338
|
+
"test",
|
|
339
|
+
"copy",
|
|
340
|
+
"apply",
|
|
341
|
+
"wait",
|
|
342
|
+
"catalogs",
|
|
343
|
+
"help",
|
|
344
|
+
"unknown"
|
|
345
|
+
],
|
|
346
|
+
dry_run: "boolean",
|
|
347
|
+
json_output: "boolean",
|
|
348
|
+
topology_strict: "boolean",
|
|
349
|
+
settings_override: "boolean",
|
|
350
|
+
case_timeout_override: "boolean",
|
|
351
|
+
run_timeout_override: "boolean",
|
|
96
352
|
phase: [
|
|
97
353
|
"admission",
|
|
98
354
|
"execution",
|
|
@@ -237,6 +493,7 @@ var publicCatalog = {
|
|
|
237
493
|
"pending",
|
|
238
494
|
"expired"
|
|
239
495
|
],
|
|
496
|
+
match: ["all", "any"],
|
|
240
497
|
filter: [
|
|
241
498
|
"search",
|
|
242
499
|
"status",
|
|
@@ -269,6 +526,7 @@ var publicCatalog = {
|
|
|
269
526
|
"401",
|
|
270
527
|
"403",
|
|
271
528
|
"404",
|
|
529
|
+
"408",
|
|
272
530
|
"409",
|
|
273
531
|
"413",
|
|
274
532
|
"422",
|
|
@@ -292,6 +550,48 @@ var publicCatalog = {
|
|
|
292
550
|
},
|
|
293
551
|
// Built-in contracts only; application codes and provider response text are excluded.
|
|
294
552
|
errorCodes: [
|
|
553
|
+
"UNCLASSIFIED_FAILURE",
|
|
554
|
+
"HTTP_UNAUTHORIZED",
|
|
555
|
+
"HTTP_FORBIDDEN",
|
|
556
|
+
"HTTP_NOT_FOUND",
|
|
557
|
+
"HTTP_TIMEOUT",
|
|
558
|
+
"HTTP_CONFLICT",
|
|
559
|
+
"HTTP_TOO_LARGE",
|
|
560
|
+
"HTTP_RATE_LIMITED",
|
|
561
|
+
"HTTP_SERVER_ERROR",
|
|
562
|
+
"HTTP_INVALID_REQUEST",
|
|
563
|
+
"NETWORK_DNS_FAILED",
|
|
564
|
+
"NETWORK_CONNECTION_REFUSED",
|
|
565
|
+
"NETWORK_CONNECTION_RESET",
|
|
566
|
+
"NETWORK_TIMEOUT",
|
|
567
|
+
"NETWORK_TLS_FAILED",
|
|
568
|
+
"CLI_ARGUMENT_INVALID",
|
|
569
|
+
"CLI_EXIT_FAILED",
|
|
570
|
+
"KTX_TOPOLOGY_INCOMPLETE",
|
|
571
|
+
"STUDIO_NOT_CONFIGURED",
|
|
572
|
+
"STUDIO_RESPONSE_INVALID",
|
|
573
|
+
"EVAL_CONCURRENCY_CHANGED",
|
|
574
|
+
"EVAL_CONSUMER_FAILED",
|
|
575
|
+
"EVAL_CONTRACT_CHANGED",
|
|
576
|
+
"EVAL_DISCOVERY_REJECTED",
|
|
577
|
+
"EVAL_EXECUTION_CONFLICT",
|
|
578
|
+
"EVAL_EXECUTION_STORE_CHANGED",
|
|
579
|
+
"EVAL_EXECUTION_UNKNOWN",
|
|
580
|
+
"EVAL_EXECUTOR_BUSY",
|
|
581
|
+
"EVAL_EXECUTOR_FAILED",
|
|
582
|
+
"EVAL_EXECUTOR_REJECTED",
|
|
583
|
+
"EVAL_EXECUTOR_UNAUTHORIZED",
|
|
584
|
+
"EVAL_GRADING_FAILED",
|
|
585
|
+
"EVAL_GRADING_TIMEOUT",
|
|
586
|
+
"EVAL_JUDGE_UNAVAILABLE",
|
|
587
|
+
"EVAL_LEASE_LOST",
|
|
588
|
+
"EVAL_RETRY_DELAY_EXCEEDED",
|
|
589
|
+
"EVAL_SETUP_TIMEOUT",
|
|
590
|
+
"EVAL_TRANSPORT_UNAVAILABLE",
|
|
591
|
+
"EVAL_VERIFICATION_TIMEOUT",
|
|
592
|
+
"EVAL_RESULT_INVALID",
|
|
593
|
+
"EVAL_RUN_TIMEOUT",
|
|
594
|
+
"EVAL_SETTINGS_INVALID",
|
|
295
595
|
"EXECUTION_FAILED",
|
|
296
596
|
"INVALID_REQUEST",
|
|
297
597
|
"INVALID_RESUME",
|
|
@@ -359,8 +659,8 @@ function scale(value) {
|
|
|
359
659
|
return value <= 1 ? "1" : value <= 5 ? "2-5" : value <= 20 ? "6-20" : value <= 100 ? "21-100" : "101+";
|
|
360
660
|
}
|
|
361
661
|
|
|
362
|
-
// src/
|
|
363
|
-
function
|
|
662
|
+
// src/failure.ts
|
|
663
|
+
function usageErrorProperty(value, key) {
|
|
364
664
|
try {
|
|
365
665
|
if (!value || typeof value !== "object") return void 0;
|
|
366
666
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
@@ -369,40 +669,201 @@ function property(value, key) {
|
|
|
369
669
|
return void 0;
|
|
370
670
|
}
|
|
371
671
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
672
|
+
var networkCodes = {
|
|
673
|
+
ENOTFOUND: "NETWORK_DNS_FAILED",
|
|
674
|
+
EAI_AGAIN: "NETWORK_DNS_FAILED",
|
|
675
|
+
ECONNREFUSED: "NETWORK_CONNECTION_REFUSED",
|
|
676
|
+
ECONNRESET: "NETWORK_CONNECTION_RESET",
|
|
677
|
+
EPIPE: "NETWORK_CONNECTION_RESET",
|
|
678
|
+
ETIMEDOUT: "NETWORK_TIMEOUT",
|
|
679
|
+
UND_ERR_CONNECT_TIMEOUT: "NETWORK_TIMEOUT",
|
|
680
|
+
UND_ERR_HEADERS_TIMEOUT: "NETWORK_TIMEOUT",
|
|
681
|
+
UND_ERR_BODY_TIMEOUT: "NETWORK_TIMEOUT",
|
|
682
|
+
CERT_HAS_EXPIRED: "NETWORK_TLS_FAILED",
|
|
683
|
+
DEPTH_ZERO_SELF_SIGNED_CERT: "NETWORK_TLS_FAILED",
|
|
684
|
+
UNABLE_TO_VERIFY_LEAF_SIGNATURE: "NETWORK_TLS_FAILED"
|
|
685
|
+
};
|
|
686
|
+
function classifyUsageHttpStatus(status) {
|
|
687
|
+
if (!Number.isInteger(status) || status < 100 || status > 599)
|
|
688
|
+
return {
|
|
689
|
+
outcome: "failed",
|
|
690
|
+
properties: {
|
|
691
|
+
error_code: "UNCLASSIFIED_FAILURE",
|
|
692
|
+
error_category: "unknown"
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
if (status < 400)
|
|
696
|
+
return {
|
|
697
|
+
outcome: "success",
|
|
698
|
+
properties: { http_status_class: `${Math.floor(status / 100)}xx` }
|
|
699
|
+
};
|
|
700
|
+
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";
|
|
701
|
+
return {
|
|
702
|
+
outcome: "failed",
|
|
703
|
+
properties: {
|
|
704
|
+
error_code: code,
|
|
705
|
+
error_category: status >= 500 || status === 408 ? "transport" : "request",
|
|
706
|
+
http_status: String(status),
|
|
707
|
+
http_status_class: `${Math.floor(status / 100)}xx`,
|
|
708
|
+
retryable: status === 408 || status === 429 || status >= 500
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
function nativeExceptionName(value) {
|
|
713
|
+
try {
|
|
714
|
+
if (typeof DOMException !== "undefined")
|
|
715
|
+
return Object.getOwnPropertyDescriptor(
|
|
716
|
+
DOMException.prototype,
|
|
717
|
+
"name"
|
|
718
|
+
)?.get?.call(value);
|
|
719
|
+
} catch {
|
|
720
|
+
}
|
|
721
|
+
return void 0;
|
|
722
|
+
}
|
|
723
|
+
function classifyOne(error, catalog) {
|
|
724
|
+
const read = (key) => usageErrorProperty(error, key);
|
|
725
|
+
let name = read("name") ?? nativeExceptionName(error);
|
|
726
|
+
try {
|
|
727
|
+
if (name === void 0 && error instanceof SyntaxError)
|
|
728
|
+
name = "SyntaxError";
|
|
729
|
+
} catch {
|
|
730
|
+
}
|
|
731
|
+
const code = read("code");
|
|
732
|
+
if (name === "AbortError" || code === "EXECUTION_CANCELLED" || code === "ABORT_ERR")
|
|
376
733
|
return { outcome: "cancelled", properties: {} };
|
|
377
734
|
if (code === "EXECUTION_LIMIT_REACHED" || name === "ExecutionLimitReached")
|
|
378
735
|
return { outcome: "limit_reached", properties: {} };
|
|
379
|
-
if (
|
|
736
|
+
if (typeof name === "string" && [
|
|
737
|
+
"GraphInterrupt",
|
|
738
|
+
"NodeInterrupt",
|
|
739
|
+
"Interrupt",
|
|
740
|
+
"ParallelChildWaiting"
|
|
741
|
+
].includes(name))
|
|
380
742
|
return { outcome: "suspended", properties: {} };
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
743
|
+
if (name === "EvalConfigurationError")
|
|
744
|
+
return {
|
|
745
|
+
outcome: "failed",
|
|
746
|
+
properties: {
|
|
747
|
+
error_code: "EVAL_SETTINGS_INVALID",
|
|
748
|
+
error_category: "configuration",
|
|
749
|
+
retryable: false
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
if (name === "TimeoutError")
|
|
753
|
+
return {
|
|
754
|
+
outcome: "failed",
|
|
755
|
+
properties: {
|
|
756
|
+
error_code: "NETWORK_TIMEOUT",
|
|
757
|
+
error_category: "transport",
|
|
758
|
+
retryable: true
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
if (typeof code === "string" && Object.hasOwn(networkCodes, code))
|
|
762
|
+
return {
|
|
763
|
+
outcome: "failed",
|
|
764
|
+
properties: {
|
|
765
|
+
error_code: networkCodes[code] ?? "UNCLASSIFIED_FAILURE",
|
|
766
|
+
error_category: "transport",
|
|
767
|
+
retryable: true
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
if (typeof code === "string" && catalog.errorCodes.includes(code)) {
|
|
771
|
+
const failure = usageErrorProperty(error, "failure");
|
|
772
|
+
const category = read("category") ?? usageErrorProperty(failure, "category");
|
|
773
|
+
const retryable = read("retryable") ?? usageErrorProperty(failure, "retryable");
|
|
774
|
+
const status2 = read("status") ?? usageErrorProperty(failure, "status");
|
|
775
|
+
return {
|
|
776
|
+
outcome: "failed",
|
|
777
|
+
properties: {
|
|
778
|
+
...typeof status2 === "number" ? classifyUsageHttpStatus(status2).properties : {},
|
|
779
|
+
// The framework code is more specific than its HTTP projection.
|
|
780
|
+
error_code: code,
|
|
781
|
+
error_category: code !== "EXECUTION_FAILED" && typeof category === "string" && Array.isArray(catalog.properties.error_category) && catalog.properties.error_category.includes(category) ? category : "unknown",
|
|
782
|
+
...typeof retryable === "boolean" ? { retryable } : {}
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
const status = read("status") ?? read("statusCode");
|
|
787
|
+
if (typeof status === "number" && Number.isInteger(status) && status >= 400 && status <= 599)
|
|
788
|
+
return classifyUsageHttpStatus(status);
|
|
789
|
+
if (name === "ZodError" || name === "SyntaxError")
|
|
790
|
+
return {
|
|
791
|
+
outcome: "failed",
|
|
792
|
+
properties: {
|
|
793
|
+
error_code: "SCHEMA_VALIDATION",
|
|
794
|
+
error_category: "validation"
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
return void 0;
|
|
798
|
+
}
|
|
799
|
+
function classifyUsageError(error, catalog = publicCatalog) {
|
|
800
|
+
const seen = /* @__PURE__ */ new Set();
|
|
801
|
+
const pending = [{ value: error, depth: 0 }];
|
|
802
|
+
let result;
|
|
803
|
+
while (pending.length && seen.size < 8) {
|
|
804
|
+
const current = pending.shift();
|
|
805
|
+
if (!current || seen.has(current.value)) continue;
|
|
806
|
+
seen.add(current.value);
|
|
807
|
+
const found = classifyOne(current.value, catalog);
|
|
808
|
+
if (found) {
|
|
809
|
+
if (!result) result = found;
|
|
810
|
+
else if (found.properties.error_code && found.outcome === "failed" && found.properties.error_code !== result.properties.error_code) {
|
|
811
|
+
result.properties.cause_code = found.properties.error_code;
|
|
812
|
+
result.properties.cause_category = found.properties.error_category ?? "unknown";
|
|
813
|
+
if (result.properties.retryable === void 0 && typeof found.properties.retryable === "boolean")
|
|
814
|
+
result.properties.retryable = found.properties.retryable;
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
if (result === found && found.outcome !== "failed") return found;
|
|
390
818
|
}
|
|
819
|
+
if (current.depth < 3)
|
|
820
|
+
for (const key of ["failure", "cause", "error"]) {
|
|
821
|
+
const value = usageErrorProperty(current.value, key);
|
|
822
|
+
if (value && typeof value === "object")
|
|
823
|
+
pending.push({ value, depth: current.depth + 1 });
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return result ?? {
|
|
827
|
+
outcome: "failed",
|
|
828
|
+
properties: { error_code: "other", error_category: "unknown" }
|
|
391
829
|
};
|
|
392
830
|
}
|
|
831
|
+
|
|
832
|
+
// src/measurement.ts
|
|
833
|
+
function usageMeasurement(event, operation, input) {
|
|
834
|
+
if (event === "usage.feature")
|
|
835
|
+
return usageErrorProperty(input, "origin") === "background" || usageErrorProperty(input, "origin") === "server" ? "observation" : "feature";
|
|
836
|
+
if (operation === "cli.command" || operation === "sdk.eval")
|
|
837
|
+
return "invocation";
|
|
838
|
+
if (operation === "studio.setup") return "stage";
|
|
839
|
+
if (operation === "sdk.execution" || operation === "studio.eval.execution")
|
|
840
|
+
return "execution";
|
|
841
|
+
if (operation === "sdk.export" || operation === "sdk.model") return "attempt";
|
|
842
|
+
if (operation === "sdk.structured") {
|
|
843
|
+
const format = usageErrorProperty(input, "format");
|
|
844
|
+
return format === "text-delta" ? "chunk" : format === "final" ? "output" : "update";
|
|
845
|
+
}
|
|
846
|
+
if (usageErrorProperty(input, "origin") === "background") return "poll";
|
|
847
|
+
if (operation.startsWith("studio.")) return "request";
|
|
848
|
+
return "call";
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// src/client.ts
|
|
393
852
|
function sanitizeProperties(input, catalog = publicCatalog) {
|
|
394
853
|
const safe = {};
|
|
395
854
|
for (const [key, rule] of Object.entries(catalog.properties)) {
|
|
396
|
-
const value =
|
|
855
|
+
const value = usageErrorProperty(input, key);
|
|
397
856
|
if (value === void 0) continue;
|
|
398
857
|
if (rule === "boolean") {
|
|
399
858
|
if (typeof value === "boolean") safe[key] = value;
|
|
400
859
|
} else if (typeof value === "string")
|
|
401
860
|
safe[key] = rule.includes(value) ? value : "other";
|
|
402
861
|
}
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
862
|
+
for (const key of ["error_code", "cause_code"]) {
|
|
863
|
+
const code = usageErrorProperty(input, key);
|
|
864
|
+
if (typeof code === "string")
|
|
865
|
+
safe[key] = catalog.errorCodes.includes(code) ? code : "other";
|
|
866
|
+
}
|
|
406
867
|
return safe;
|
|
407
868
|
}
|
|
408
869
|
var durationBounds = [10, 100, 1e3, 1e4, 6e4];
|
|
@@ -423,6 +884,16 @@ function createUsageTelemetry(options) {
|
|
|
423
884
|
let disposed = false;
|
|
424
885
|
let dropped = 0;
|
|
425
886
|
let delivered = 0;
|
|
887
|
+
let lostObservations = 0;
|
|
888
|
+
let failedBatches = 0;
|
|
889
|
+
let reportedLoss = 0;
|
|
890
|
+
let reportedFailures = 0;
|
|
891
|
+
const lose = (count) => {
|
|
892
|
+
lostObservations = Math.min(
|
|
893
|
+
Number.MAX_SAFE_INTEGER,
|
|
894
|
+
lostObservations + count
|
|
895
|
+
);
|
|
896
|
+
};
|
|
426
897
|
let hour = Math.floor(now() / 36e5);
|
|
427
898
|
let sent = 0;
|
|
428
899
|
const active = () => {
|
|
@@ -458,6 +929,10 @@ function createUsageTelemetry(options) {
|
|
|
458
929
|
pending.clear();
|
|
459
930
|
if (!records.length) return;
|
|
460
931
|
let attempted = records.length;
|
|
932
|
+
let attemptedObservations = records.reduce(
|
|
933
|
+
(total, record2) => total + record2.count,
|
|
934
|
+
0
|
|
935
|
+
);
|
|
461
936
|
flight = (async () => {
|
|
462
937
|
try {
|
|
463
938
|
if (options.debug?.()) {
|
|
@@ -475,7 +950,14 @@ function createUsageTelemetry(options) {
|
|
|
475
950
|
);
|
|
476
951
|
const batch = records.slice(0, allowance);
|
|
477
952
|
dropped += records.length - batch.length;
|
|
953
|
+
lose(
|
|
954
|
+
records.slice(allowance).reduce((total, record2) => total + record2.count, 0)
|
|
955
|
+
);
|
|
478
956
|
attempted = batch.length;
|
|
957
|
+
attemptedObservations = batch.reduce(
|
|
958
|
+
(total, record2) => total + record2.count,
|
|
959
|
+
0
|
|
960
|
+
);
|
|
479
961
|
if (!batch.length || !active()) return;
|
|
480
962
|
const identified = await options.identity();
|
|
481
963
|
const identity2 = typeof identified === "string" ? identified : identified.id;
|
|
@@ -486,13 +968,25 @@ function createUsageTelemetry(options) {
|
|
|
486
968
|
identity2
|
|
487
969
|
)) {
|
|
488
970
|
dropped += batch.length;
|
|
971
|
+
lose(attemptedObservations);
|
|
489
972
|
return;
|
|
490
973
|
}
|
|
491
974
|
sent += batch.length;
|
|
975
|
+
const lossSnapshot = lostObservations;
|
|
976
|
+
const failureSnapshot = failedBatches;
|
|
977
|
+
if (batch[0] && (lossSnapshot > reportedLoss || failureSnapshot > reportedFailures))
|
|
978
|
+
batch[0].delivery_health = {
|
|
979
|
+
dropped_observations: lossSnapshot - reportedLoss,
|
|
980
|
+
failed_batches: failureSnapshot - reportedFailures
|
|
981
|
+
};
|
|
492
982
|
await options.transport(batch, identity2);
|
|
983
|
+
reportedLoss = lossSnapshot;
|
|
984
|
+
reportedFailures = failureSnapshot;
|
|
493
985
|
delivered += batch.length;
|
|
494
986
|
} catch {
|
|
495
987
|
dropped += attempted;
|
|
988
|
+
lose(attemptedObservations);
|
|
989
|
+
failedBatches = Math.min(Number.MAX_SAFE_INTEGER, failedBatches + 1);
|
|
496
990
|
}
|
|
497
991
|
})().finally(() => {
|
|
498
992
|
flight = void 0;
|
|
@@ -516,12 +1010,29 @@ function createUsageTelemetry(options) {
|
|
|
516
1010
|
}
|
|
517
1011
|
if (!configured || !catalog.operations.includes(operation) || !outcomes.includes(outcome))
|
|
518
1012
|
return;
|
|
519
|
-
const
|
|
1013
|
+
const failed = outcome === "failed";
|
|
1014
|
+
const status = usageErrorProperty(input, "http_status");
|
|
1015
|
+
const http = typeof status === "string" && /^\d{3}$/.test(status) ? classifyUsageHttpStatus(Number(status)).properties : {};
|
|
1016
|
+
const properties = sanitizeProperties(
|
|
1017
|
+
{
|
|
1018
|
+
measurement_version: "2",
|
|
1019
|
+
measurement_kind: usageMeasurement(event, operation, input),
|
|
1020
|
+
...failed ? {
|
|
1021
|
+
error_code: "UNCLASSIFIED_FAILURE",
|
|
1022
|
+
error_category: "unknown",
|
|
1023
|
+
...http
|
|
1024
|
+
} : {},
|
|
1025
|
+
...sanitizeProperties(input, catalog),
|
|
1026
|
+
traffic_source: options.context.trafficSource ?? "unknown"
|
|
1027
|
+
},
|
|
1028
|
+
catalog
|
|
1029
|
+
);
|
|
520
1030
|
const key = JSON.stringify([event, operation, outcome, properties]);
|
|
521
1031
|
let existing = pending.get(key);
|
|
522
1032
|
if (!existing) {
|
|
523
1033
|
if (pending.size >= (options.maxGroups ?? 64)) {
|
|
524
1034
|
dropped++;
|
|
1035
|
+
lose(1);
|
|
525
1036
|
return;
|
|
526
1037
|
}
|
|
527
1038
|
existing = {
|
|
@@ -533,7 +1044,9 @@ function createUsageTelemetry(options) {
|
|
|
533
1044
|
component: options.context.component,
|
|
534
1045
|
version: options.context.version,
|
|
535
1046
|
analytics_environment: options.context.environment ?? "production",
|
|
536
|
-
runtime_mode:
|
|
1047
|
+
runtime_mode: ["development", "production", "ci"].includes(
|
|
1048
|
+
options.context.runtimeMode ?? ""
|
|
1049
|
+
) ? options.context.runtimeMode ?? "unknown" : "unknown",
|
|
537
1050
|
identity_scope: options.context.identityScope ?? "installation",
|
|
538
1051
|
operation,
|
|
539
1052
|
outcome,
|
|
@@ -578,8 +1091,11 @@ function createUsageTelemetry(options) {
|
|
|
578
1091
|
if (ended) return;
|
|
579
1092
|
ended = true;
|
|
580
1093
|
try {
|
|
1094
|
+
const status = usageErrorProperty(extra, "http_status");
|
|
1095
|
+
const http = outcome === "failed" && typeof status === "string" && /^\d{3}$/.test(status) ? classifyUsageHttpStatus(Number(status)).properties : {};
|
|
581
1096
|
record("usage.operation", operation, outcome, now() - began, {
|
|
582
1097
|
...initial,
|
|
1098
|
+
...http,
|
|
583
1099
|
...sanitizeProperties(extra, catalog)
|
|
584
1100
|
});
|
|
585
1101
|
} catch {
|
|
@@ -666,6 +1182,10 @@ function createPostHogTransport(options) {
|
|
|
666
1182
|
count: record.count,
|
|
667
1183
|
duration_total_ms: record.duration_total_ms,
|
|
668
1184
|
duration_buckets: record.duration_buckets,
|
|
1185
|
+
...record.delivery_health ? {
|
|
1186
|
+
usage_dropped_observations: record.delivery_health.dropped_observations,
|
|
1187
|
+
usage_failed_batches: record.delivery_health.failed_batches
|
|
1188
|
+
} : {},
|
|
669
1189
|
$process_person_profile: false,
|
|
670
1190
|
$geoip_disable: true,
|
|
671
1191
|
$ip: null
|
|
@@ -761,6 +1281,13 @@ async function installationIdentity() {
|
|
|
761
1281
|
})();
|
|
762
1282
|
return identity;
|
|
763
1283
|
}
|
|
1284
|
+
function runtimeUsageContext() {
|
|
1285
|
+
const traffic = process.env.KORTYX_USAGE_TELEMETRY_TRAFFIC_SOURCE;
|
|
1286
|
+
return {
|
|
1287
|
+
runtimeMode: process.env.CI && !["0", "false"].includes(process.env.CI.toLowerCase()) ? "ci" : process.env.NODE_ENV === "production" ? "production" : process.env.NODE_ENV === "development" ? "development" : "unknown",
|
|
1288
|
+
trafficSource: traffic === "internal" || traffic === "synthetic" || traffic === "external" ? traffic : "unknown"
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
764
1291
|
function usageDisabled() {
|
|
765
1292
|
return ["1", "true"].includes(process.env.KORTYX_USAGE_TELEMETRY_DISABLED ?? "") || process.env.NODE_ENV === "test";
|
|
766
1293
|
}
|
|
@@ -784,6 +1311,11 @@ function createNodeUsageTelemetry(options) {
|
|
|
784
1311
|
}
|
|
785
1312
|
return createUsageTelemetry({
|
|
786
1313
|
...options,
|
|
1314
|
+
context: {
|
|
1315
|
+
...options.context,
|
|
1316
|
+
runtimeMode: options.context.runtimeMode ?? runtimeUsageContext().runtimeMode,
|
|
1317
|
+
trafficSource: options.context.trafficSource ?? runtimeUsageContext().trafficSource
|
|
1318
|
+
},
|
|
787
1319
|
transport,
|
|
788
1320
|
identity: options.identity ?? installationIdentity,
|
|
789
1321
|
enabled: () => valid && !usageDisabled() && (options.enabled?.() ?? true),
|
|
@@ -792,6 +1324,9 @@ function createNodeUsageTelemetry(options) {
|
|
|
792
1324
|
});
|
|
793
1325
|
}
|
|
794
1326
|
var clients = /* @__PURE__ */ new Map();
|
|
1327
|
+
async function flushUsageTelemetry() {
|
|
1328
|
+
await Promise.all([...clients.values()].map((client) => client.flush()));
|
|
1329
|
+
}
|
|
795
1330
|
function configureUsageTelemetry(component, client) {
|
|
796
1331
|
if (clients.get(component) === client) return;
|
|
797
1332
|
clients.get(component)?.dispose();
|
|
@@ -806,7 +1341,7 @@ function getUsageTelemetry(component, version = "unknown", product = "sdk") {
|
|
|
806
1341
|
component,
|
|
807
1342
|
version,
|
|
808
1343
|
environment: process.env.KORTYX_USAGE_TELEMETRY_ENVIRONMENT === "staging" ? "staging" : "production",
|
|
809
|
-
|
|
1344
|
+
...runtimeUsageContext()
|
|
810
1345
|
}
|
|
811
1346
|
});
|
|
812
1347
|
clients.set(component, client);
|
|
@@ -832,6 +1367,7 @@ function publicUsageConfiguration() {
|
|
|
832
1367
|
}
|
|
833
1368
|
return {
|
|
834
1369
|
enabled: valid && !usageDisabled(),
|
|
1370
|
+
...runtimeUsageContext(),
|
|
835
1371
|
debug: process.env.KORTYX_USAGE_TELEMETRY_DEBUG === "1",
|
|
836
1372
|
environment: process.env.KORTYX_USAGE_TELEMETRY_ENVIRONMENT === "staging" ? "staging" : "production",
|
|
837
1373
|
// A mistakenly supplied personal token or credential-bearing URL must never reach HTML.
|
|
@@ -845,8 +1381,10 @@ function publicUsageConfiguration() {
|
|
|
845
1381
|
configureUsageTelemetry,
|
|
846
1382
|
createNodeUsageTelemetry,
|
|
847
1383
|
createUsageTelemetry,
|
|
1384
|
+
flushUsageTelemetry,
|
|
848
1385
|
getUsageTelemetry,
|
|
849
1386
|
publicUsageConfiguration,
|
|
1387
|
+
runtimeUsageContext,
|
|
850
1388
|
scale,
|
|
851
1389
|
usageDisabled
|
|
852
1390
|
});
|