@autter/otlp-ingester 1.3.3 → 1.3.4

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/memory.d.ts CHANGED
@@ -24,15 +24,15 @@ export declare const platformEventSchema: z.ZodObject<{
24
24
  service: string;
25
25
  environment: string;
26
26
  release: string;
27
+ kind: "oom_kill" | "restart";
27
28
  instanceId: string;
28
29
  platform: "ecs" | "kubernetes" | "other";
29
- kind: "oom_kill" | "restart";
30
30
  occurredAt: string;
31
31
  }, {
32
32
  service: string;
33
+ kind: "oom_kill" | "restart";
33
34
  instanceId: string;
34
35
  platform: "ecs" | "kubernetes" | "other";
35
- kind: "oom_kill" | "restart";
36
36
  occurredAt: string;
37
37
  environment?: string | undefined;
38
38
  release?: string | undefined;
@@ -8,7 +8,7 @@ export declare const browserPayloadSchema: z.ZodObject<{
8
8
  release: z.ZodOptional<z.ZodString>;
9
9
  events: z.ZodArray<z.ZodObject<{
10
10
  id: z.ZodOptional<z.ZodString>;
11
- type: z.ZodEnum<["exception", "unhandled_rejection", "message", "session_start", "track_event", "outcome", "request_failure", "timing"]>;
11
+ type: z.ZodEnum<["exception", "unhandled_rejection", "message", "session_start", "track_event", "outcome", "request_failure", "csp_violation", "timing"]>;
12
12
  timestamp: z.ZodString;
13
13
  /** exception/message events: signal level. Defaults per type. */
14
14
  severity: z.ZodOptional<z.ZodEnum<["fatal", "error", "warning", "info"]>>;
@@ -25,10 +25,11 @@ export declare const browserPayloadSchema: z.ZodObject<{
25
25
  route: z.ZodOptional<z.ZodString>;
26
26
  context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
27
27
  }, "strip", z.ZodTypeAny, {
28
- type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "timing";
28
+ type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "csp_violation" | "timing";
29
29
  message: string;
30
30
  timestamp: string;
31
31
  durationMs?: number | undefined;
32
+ route?: string | undefined;
32
33
  filename?: string | undefined;
33
34
  id?: string | undefined;
34
35
  severity?: "fatal" | "error" | "warning" | "info" | undefined;
@@ -37,12 +38,12 @@ export declare const browserPayloadSchema: z.ZodObject<{
37
38
  errorType?: string | undefined;
38
39
  line?: number | undefined;
39
40
  column?: number | undefined;
40
- route?: string | undefined;
41
41
  context?: Record<string, unknown> | undefined;
42
42
  }, {
43
- type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "timing";
43
+ type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "csp_violation" | "timing";
44
44
  timestamp: string;
45
45
  durationMs?: number | undefined;
46
+ route?: string | undefined;
46
47
  message?: string | undefined;
47
48
  filename?: string | undefined;
48
49
  id?: string | undefined;
@@ -52,7 +53,6 @@ export declare const browserPayloadSchema: z.ZodObject<{
52
53
  errorType?: string | undefined;
53
54
  line?: number | undefined;
54
55
  column?: number | undefined;
55
- route?: string | undefined;
56
56
  context?: Record<string, unknown> | undefined;
57
57
  }>, "many">;
58
58
  }, "strip", z.ZodTypeAny, {
@@ -60,10 +60,11 @@ export declare const browserPayloadSchema: z.ZodObject<{
60
60
  environment: string;
61
61
  version: 1;
62
62
  events: {
63
- type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "timing";
63
+ type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "csp_violation" | "timing";
64
64
  message: string;
65
65
  timestamp: string;
66
66
  durationMs?: number | undefined;
67
+ route?: string | undefined;
67
68
  filename?: string | undefined;
68
69
  id?: string | undefined;
69
70
  severity?: "fatal" | "error" | "warning" | "info" | undefined;
@@ -72,7 +73,6 @@ export declare const browserPayloadSchema: z.ZodObject<{
72
73
  errorType?: string | undefined;
73
74
  line?: number | undefined;
74
75
  column?: number | undefined;
75
- route?: string | undefined;
76
76
  context?: Record<string, unknown> | undefined;
77
77
  }[];
78
78
  release?: string | undefined;
@@ -82,9 +82,10 @@ export declare const browserPayloadSchema: z.ZodObject<{
82
82
  environment: string;
83
83
  version: 1;
84
84
  events: {
85
- type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "timing";
85
+ type: "exception" | "message" | "unhandled_rejection" | "session_start" | "track_event" | "outcome" | "request_failure" | "csp_violation" | "timing";
86
86
  timestamp: string;
87
87
  durationMs?: number | undefined;
88
+ route?: string | undefined;
88
89
  message?: string | undefined;
89
90
  filename?: string | undefined;
90
91
  id?: string | undefined;
@@ -94,7 +95,6 @@ export declare const browserPayloadSchema: z.ZodObject<{
94
95
  errorType?: string | undefined;
95
96
  line?: number | undefined;
96
97
  column?: number | undefined;
97
- route?: string | undefined;
98
98
  context?: Record<string, unknown> | undefined;
99
99
  }[];
100
100
  release?: string | undefined;
@@ -17,6 +17,7 @@ const browserEventSchema = z.object({
17
17
  "track_event",
18
18
  "outcome",
19
19
  "request_failure",
20
+ "csp_violation",
20
21
  "timing",
21
22
  ]),
22
23
  timestamp: z.string().datetime(),
@@ -49,6 +50,7 @@ const TYPE_TO_ERROR_TYPE = {
49
50
  message: "Message",
50
51
  outcome: "OutcomeFailure",
51
52
  request_failure: "HttpRequestError",
53
+ csp_violation: "CspViolation",
52
54
  };
53
55
  // Content-level gate for the free-form `context` bag. The schema whitelist
54
56
  // above is structural; this masks obvious PII/secrets inside whatever a
@@ -78,6 +80,7 @@ const TYPE_TO_SEVERITY = {
78
80
  message: "warning",
79
81
  outcome: "error",
80
82
  request_failure: "error",
83
+ csp_violation: "error",
81
84
  };
82
85
  export function normalizeBrowserPayload(payload) {
83
86
  const occurrences = [];
@@ -96,6 +96,7 @@ function severityOf(eventAttrs, spanAttrs) {
96
96
  const MAX_SPANS_PER_REQUEST = 5000;
97
97
  export function normalizeTraces(request) {
98
98
  const occurrences = [];
99
+ const occurrenceSpanIds = [];
99
100
  const spans = [];
100
101
  const llmCalls = [];
101
102
  const rollups = new Map();
@@ -143,6 +144,7 @@ export function normalizeTraces(request) {
143
144
  for (const event of exceptionEvents) {
144
145
  const eventAttrs = attrMap(event.attributes);
145
146
  const handled = eventAttrs.get("autter.handled") === "true";
147
+ occurrenceSpanIds.push(span.spanId ?? "");
146
148
  occurrences.push({
147
149
  source: "server",
148
150
  severity: severityOf(eventAttrs, attrs),
@@ -175,6 +177,7 @@ export function normalizeTraces(request) {
175
177
  for (const event of failedOutcomes) {
176
178
  const outcome = attrMap(event.attributes);
177
179
  const name = (outcome.get("autter.outcome.name") ?? "operation").replace(EMAIL_VALUE_RE, "[redacted]").slice(0, 200);
180
+ occurrenceSpanIds.push(span.spanId ?? "");
178
181
  occurrences.push({
179
182
  source: "server", severity: "error", service: resource.service,
180
183
  environment: resource.environment, release: resource.release,
@@ -186,6 +189,7 @@ export function normalizeTraces(request) {
186
189
  });
187
190
  }
188
191
  if (exceptionEvents.length === 0 && failedOutcomes.length === 0 && isError) {
192
+ occurrenceSpanIds.push(span.spanId ?? "");
189
193
  occurrences.push({
190
194
  source: "server",
191
195
  severity: severityOf(new Map(), attrs),
@@ -270,6 +274,7 @@ export function normalizeTraces(request) {
270
274
  }
271
275
  }
272
276
  }
277
+ inheritHttpFromParent(occurrences, occurrenceSpanIds, spans);
273
278
  return {
274
279
  occurrences,
275
280
  spans,
@@ -278,6 +283,62 @@ export function normalizeTraces(request) {
278
283
  spanCount,
279
284
  };
280
285
  }
286
+ /**
287
+ * Exception spans are often children named "Error" with no HTTP attributes.
288
+ * Copy method, route, status, and duration from the server span in the same
289
+ * trace so the issue can name the API that failed.
290
+ */
291
+ function inheritHttpFromParent(occurrences, occurrenceSpanIds, spans) {
292
+ const byId = new Map();
293
+ for (const span of spans) {
294
+ if (span.spanId)
295
+ byId.set(span.spanId, span);
296
+ }
297
+ for (let i = 0; i < occurrences.length; i++) {
298
+ const occurrence = occurrences[i];
299
+ const spanId = occurrenceSpanIds[i];
300
+ if (!occurrence || !spanId)
301
+ continue;
302
+ const http = httpServerAncestor(byId, spanId);
303
+ if (!http)
304
+ continue;
305
+ if (!occurrence.route && http.route)
306
+ occurrence.route = http.route;
307
+ const method = methodFromSpan(http);
308
+ if (!occurrence.method && method)
309
+ occurrence.method = method;
310
+ if ((occurrence.statusCode == null || occurrence.statusCode === 0) &&
311
+ http.statusCode != null &&
312
+ http.statusCode > 0) {
313
+ occurrence.statusCode = http.statusCode;
314
+ }
315
+ if (http.durationMs > 0) {
316
+ const attributes = { ...(occurrence.attributes ?? {}) };
317
+ if (attributes["http.server.duration_ms"] == null) {
318
+ attributes["http.server.duration_ms"] = Math.round(http.durationMs);
319
+ occurrence.attributes = attributes;
320
+ }
321
+ }
322
+ }
323
+ }
324
+ function httpServerAncestor(byId, spanId) {
325
+ let current = byId.get(spanId) ?? null;
326
+ const seen = new Set();
327
+ while (current && current.spanId && !seen.has(current.spanId)) {
328
+ seen.add(current.spanId);
329
+ if (current.kind === "server")
330
+ return current;
331
+ const parentId = current.parentSpanId;
332
+ if (!parentId)
333
+ return null;
334
+ current = byId.get(parentId) ?? null;
335
+ }
336
+ return null;
337
+ }
338
+ function methodFromSpan(span) {
339
+ const raw = span.attributes?.["http.request.method"];
340
+ return typeof raw === "string" && raw.trim() ? raw.trim().toUpperCase().slice(0, 16) : null;
341
+ }
281
342
  function minuteBucket(date) {
282
343
  return new Date(Math.floor(date.getTime() / 60_000) * 60_000);
283
344
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autter/otlp-ingester",
3
- "version": "1.3.3",
3
+ "version": "1.3.4",
4
4
  "description": "Self-hostable OTLP + browser-error ingest service for Autter Runtime: normalises telemetry into a per-repo ClickHouse data model",
5
5
  "license": "MIT",
6
6
  "type": "module",