@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.
@@ -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/client.ts
359
- function property(value, key) {
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
- function classifyUsageError(error, catalog = publicCatalog) {
369
- const name = property(error, "name");
370
- const code = property(error, "code") ?? property(property(error, "failure"), "code");
371
- if (name === "AbortError" || code === "EXECUTION_CANCELLED")
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 (name === "GraphInterrupt" || name === "NodeInterrupt" || name === "Interrupt")
615
+ if (typeof name === "string" && [
616
+ "GraphInterrupt",
617
+ "NodeInterrupt",
618
+ "Interrupt",
619
+ "ParallelChildWaiting"
620
+ ].includes(name))
376
621
  return { outcome: "suspended", properties: {} };
377
- const known = typeof code === "string" && catalog.errorCodes.includes(code);
378
- const category = known && code !== "EXECUTION_FAILED" ? property(error, "category") ?? property(property(error, "failure"), "category") ?? "unknown" : "unknown";
379
- const status = property(error, "status") ?? property(property(error, "failure"), "status");
380
- return {
381
- outcome: "failed",
382
- properties: {
383
- error_code: known ? code : "other",
384
- error_category: category,
385
- ...typeof status === "number" ? { http_status: String(status) } : {}
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 = property(input, key);
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 code = property(input, "error_code");
400
- if (typeof code === "string")
401
- safe.error_code = catalog.errorCodes.includes(code) ? code : "other";
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 properties = sanitizeProperties(input, catalog);
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: options.context.runtimeMode ?? "unknown",
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
  });