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