@autter/otlp-ingester 1.6.0 → 1.7.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/README.md +15 -3
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +15 -3
- package/dist/clickhouse.js +12 -1
- package/dist/compat-manifest.json +16 -0
- package/dist/config.d.ts +26 -5
- package/dist/config.js +33 -8
- package/dist/normalize-browser.d.ts +26 -26
- package/dist/normalize-otlp.d.ts +6 -0
- package/dist/normalize-otlp.js +131 -84
- package/dist/server.d.ts +7 -0
- package/dist/server.js +78 -30
- package/dist/source-map-mappings.d.ts +57 -0
- package/dist/source-map-mappings.js +245 -0
- package/dist/source-map-scopes.d.ts +71 -0
- package/dist/source-map-scopes.js +190 -0
- package/dist/source-maps-lookup.d.ts +6 -3
- package/dist/source-maps-lookup.js +35 -13
- package/dist/source-maps.d.ts +16 -3
- package/dist/source-maps.js +27 -7
- package/dist/symbolicate.d.ts +46 -8
- package/dist/symbolicate.js +138 -32
- package/dist/trace-dedupe.d.ts +98 -0
- package/dist/trace-dedupe.js +385 -0
- package/dist/types.d.ts +5 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,6 +31,16 @@ works with its default exporter settings.
|
|
|
31
31
|
| --- | --- | --- | --- |
|
|
32
32
|
| `server` (default) | `autter_rt_…` (secret) | all endpoints | 300 req/min |
|
|
33
33
|
| `client` | `autter_rtc_…` (publishable, safe in frontend bundles) | `/v1/browser` only | origin allow-list, 120 req/min |
|
|
34
|
+
| `upload` (1.7.0+) | `autter_rtu_…` (secret, for CI) | `/v1/sourcemaps` and `/v1/sourcemaps/check` only | 300 req/min |
|
|
35
|
+
|
|
36
|
+
An upload key gets `403 {"error":"upload_key_not_allowed","detail":"autter_rtu_ keys can only upload source maps …"}`
|
|
37
|
+
on every other route, so a CI secret that leaks can upload source maps for
|
|
38
|
+
one repository and nothing else. A static entry without `scope` is an upload
|
|
39
|
+
key when its key starts with `autter_rtu_`, else a server key; an entry (or a
|
|
40
|
+
validator answer) with any other `scope` is ignored rather than treated as a
|
|
41
|
+
server key. Ingesters before 1.7.0 treat every scope but `client` as
|
|
42
|
+
`server`, so a validator must not answer `"scope": "upload"` to them: from
|
|
43
|
+
1.7.0 every validator request carries `x-autter-ingester-version`.
|
|
34
44
|
|
|
35
45
|
`/v1/browser` answers CORS preflights permissively; real enforcement (key +
|
|
36
46
|
origin allow-list) happens on the POST. Cross-origin browsers send
|
|
@@ -41,12 +51,14 @@ route parses as JSON.
|
|
|
41
51
|
AUTTER_INGEST_KEYS='[
|
|
42
52
|
{"key":"autter_rt_…","orgId":"org1","repositoryId":"repo1"},
|
|
43
53
|
{"key":"autter_rtc_…","orgId":"org1","repositoryId":"repo1",
|
|
44
|
-
"scope":"client","allowedOrigins":["https://app.example.com"]}
|
|
54
|
+
"scope":"client","allowedOrigins":["https://app.example.com"]},
|
|
55
|
+
{"key":"autter_rtu_…","orgId":"org1","repositoryId":"repo1","scope":"upload"}
|
|
45
56
|
]'
|
|
46
57
|
```
|
|
47
58
|
|
|
48
59
|
The validator webhook may return the same extra fields:
|
|
49
|
-
`{ orgId, repositoryId, scope?, allowedOrigins? }
|
|
60
|
+
`{ orgId, repositoryId, scope?, allowedOrigins? }`, with `scope` one of
|
|
61
|
+
`server`, `client`, `upload`.
|
|
50
62
|
|
|
51
63
|
### Version compatibility
|
|
52
64
|
|
|
@@ -75,7 +87,7 @@ the Autter dashboard reads both. See [docs/COMPATIBILITY.md](../../docs/COMPATIB
|
|
|
75
87
|
| `SINK_MAX_ATTEMPTS` | `12` | Delivery attempts per batch (1–60 s backoff) |
|
|
76
88
|
| `SINK_MAX_BUFFERED_BATCHES` | `1000` | Retry buffer cap; oldest drops are logged |
|
|
77
89
|
| `SINK_MAX_BUFFERED_MB` | `64` | Sink retry buffer cap (memory) |
|
|
78
|
-
| `SOURCE_MAP_CACHE_MB` | `64` | Memory budget (
|
|
90
|
+
| `SOURCE_MAP_CACHE_MB` | `64` | Memory budget (decoded size, function scope tables included) for parsed source maps used to symbolicate browser frames at ingest; least recently used maps are evicted, and a map that needs more than half of it is used without being kept |
|
|
79
91
|
| `MAX_BODY_BYTES` | `1048576` | Request body cap |
|
|
80
92
|
| `RATE_LIMIT_PER_MINUTE` | `300` | Per-key fixed window (server keys) |
|
|
81
93
|
| `CLIENT_RATE_LIMIT_PER_MINUTE` | `120` | Per-key fixed window (client keys) |
|
package/dist/auth.d.ts
CHANGED
package/dist/auth.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { INGESTER_VERSION_HEADER } from "./compat.js";
|
|
2
|
+
import { defaultScopeFor, isIngestKeyScope } from "./config.js";
|
|
3
|
+
import { ingesterVersion } from "./sdk-versions.js";
|
|
1
4
|
const VALIDATOR_CACHE_TTL_MS = 60_000;
|
|
2
5
|
export class KeyResolver {
|
|
3
6
|
config;
|
|
@@ -6,10 +9,13 @@ export class KeyResolver {
|
|
|
6
9
|
constructor(config) {
|
|
7
10
|
this.config = config;
|
|
8
11
|
for (const entry of config.ingestKeys) {
|
|
12
|
+
const scope = entry.scope ?? defaultScopeFor(entry.key);
|
|
13
|
+
if (!isIngestKeyScope(scope))
|
|
14
|
+
continue;
|
|
9
15
|
this.staticKeys.set(entry.key, {
|
|
10
16
|
orgId: entry.orgId,
|
|
11
17
|
repositoryId: entry.repositoryId,
|
|
12
|
-
scope
|
|
18
|
+
scope,
|
|
13
19
|
allowedOrigins: entry.allowedOrigins ?? [],
|
|
14
20
|
});
|
|
15
21
|
}
|
|
@@ -44,6 +50,11 @@ export class KeyResolver {
|
|
|
44
50
|
method: "POST",
|
|
45
51
|
headers: {
|
|
46
52
|
"content-type": "application/json",
|
|
53
|
+
// Lets the validator tell which scopes this ingester enforces:
|
|
54
|
+
// before 1.7.0 any scope but "client" meant a server key, so an
|
|
55
|
+
// upload key must not be answered as "upload" to an ingester
|
|
56
|
+
// that doesn't send this header (or sends an older version).
|
|
57
|
+
[INGESTER_VERSION_HEADER]: ingesterVersion(),
|
|
47
58
|
...(this.config.keyValidatorToken
|
|
48
59
|
? { authorization: `Bearer ${this.config.keyValidatorToken}` }
|
|
49
60
|
: {}),
|
|
@@ -53,11 +64,12 @@ export class KeyResolver {
|
|
|
53
64
|
});
|
|
54
65
|
if (response.ok) {
|
|
55
66
|
const body = (await response.json());
|
|
56
|
-
|
|
67
|
+
const scope = body.scope === undefined || body.scope === null ? defaultScopeFor(key) : body.scope;
|
|
68
|
+
if (body.orgId && body.repositoryId && isIngestKeyScope(scope)) {
|
|
57
69
|
ctx = {
|
|
58
70
|
orgId: body.orgId,
|
|
59
71
|
repositoryId: body.repositoryId,
|
|
60
|
-
scope
|
|
72
|
+
scope,
|
|
61
73
|
allowedOrigins: body.allowedOrigins ?? [],
|
|
62
74
|
};
|
|
63
75
|
}
|
package/dist/clickhouse.js
CHANGED
|
@@ -19,6 +19,9 @@ const INSERT_SETTINGS = {
|
|
|
19
19
|
async_insert: 1,
|
|
20
20
|
wait_for_async_insert: 1,
|
|
21
21
|
};
|
|
22
|
+
/** Source maps above this go in with a plain insert (below ClickHouse's
|
|
23
|
+
* default async_insert_max_data_size of 10 MiB). */
|
|
24
|
+
const ASYNC_INSERT_MAX_MAP_CHARS = 8 * 1024 * 1024;
|
|
22
25
|
/** "YYYY-MM-DD hh:mm:ss.sss" (UTC) — the DateTime64 query-parameter form. */
|
|
23
26
|
function chDateTime(date) {
|
|
24
27
|
return date.toISOString().replace("T", " ").replace("Z", "");
|
|
@@ -474,7 +477,15 @@ export class ClickHouseStore {
|
|
|
474
477
|
await this.ensureSchema();
|
|
475
478
|
await this.getClient().insert({
|
|
476
479
|
table: this.table("runtime_source_maps"), format: "JSONEachRow",
|
|
477
|
-
|
|
480
|
+
// One row of up to 32 MiB. Parallel parsing cuts input into
|
|
481
|
+
// 10 MiB chunks, refuses single JSON rows far past that, and gains
|
|
482
|
+
// nothing on one row. A map past the async-insert buffer (10 MiB
|
|
483
|
+
// by default) is inserted directly rather than buffered.
|
|
484
|
+
clickhouse_settings: {
|
|
485
|
+
...INSERT_SETTINGS,
|
|
486
|
+
input_format_parallel_parsing: 0,
|
|
487
|
+
...(sourceMap.map.length > ASYNC_INSERT_MAX_MAP_CHARS ? { async_insert: 0 } : {}),
|
|
488
|
+
},
|
|
478
489
|
values: [{ org_id: ctx.orgId, repository_id: ctx.repositoryId, release: sourceMap.release,
|
|
479
490
|
filename: sourceMap.filename, map: sourceMap.map, debug_id: sourceMap.debugId,
|
|
480
491
|
content_hash: sourceMap.contentHash }],
|
|
@@ -118,6 +118,22 @@
|
|
|
118
118
|
"ingester": "1.6.0",
|
|
119
119
|
"migrations": [],
|
|
120
120
|
"sdks": { "@autter/runtime-browser": "1.6.0", "@autter/runtime-next": "1.6.0", "@autter/runtime-node": "1.6.0" }
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "sourcemap_upload_keys",
|
|
124
|
+
"title": "Upload-only keys for source maps (autter_rtu_)",
|
|
125
|
+
"ingester": "1.7.0",
|
|
126
|
+
"migrations": [],
|
|
127
|
+
"route": "/v1/sourcemaps",
|
|
128
|
+
"sdks": {}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"id": "source_map_verify",
|
|
132
|
+
"title": "Source map check by debug id (autter-runtime sourcemaps verify)",
|
|
133
|
+
"ingester": "1.7.0",
|
|
134
|
+
"migrations": ["0017-source-maps-debug-id"],
|
|
135
|
+
"route": "/v1/sourcemaps/check",
|
|
136
|
+
"sdks": {}
|
|
121
137
|
}
|
|
122
138
|
]
|
|
123
139
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
import type { IngestKeyScope } from "./types.js";
|
|
2
|
+
export declare const INGEST_KEY_SCOPES: readonly IngestKeyScope[];
|
|
3
|
+
/** Prefix of upload-only keys (`autter_rtu_…`): source map uploads from CI. */
|
|
4
|
+
export declare const UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
5
|
+
export declare function isIngestKeyScope(value: unknown): value is IngestKeyScope;
|
|
6
|
+
/**
|
|
7
|
+
* The scope of a key whose static entry or validator answer names none:
|
|
8
|
+
* "upload" for an `autter_rtu_…` key (its prefix promises no more than
|
|
9
|
+
* that), else "server" as before 1.7.0.
|
|
10
|
+
*/
|
|
11
|
+
export declare function defaultScopeFor(key: string): IngestKeyScope;
|
|
1
12
|
export interface StaticIngestKey {
|
|
2
13
|
key: string;
|
|
3
14
|
orgId: string;
|
|
4
15
|
repositoryId: string;
|
|
5
|
-
/**
|
|
6
|
-
|
|
16
|
+
/**
|
|
17
|
+
* "server" = secret backend key, every route; "client" = publishable
|
|
18
|
+
* browser key, `/v1/browser` only; "upload" = CI key, `/v1/sourcemaps`
|
|
19
|
+
* and `/v1/sourcemaps/check` only. Default: "upload" for an
|
|
20
|
+
* `autter_rtu_…` key, else "server". An entry with any other value is
|
|
21
|
+
* ignored (never treated as a server key).
|
|
22
|
+
*/
|
|
23
|
+
scope?: IngestKeyScope;
|
|
7
24
|
/** client keys: exact origins allowed to send (e.g. https://app.example.com). */
|
|
8
25
|
allowedOrigins?: string[];
|
|
9
26
|
}
|
|
@@ -55,10 +72,14 @@ export interface IngesterConfig {
|
|
|
55
72
|
redactValuePatterns?: string[];
|
|
56
73
|
redactKeyPatterns?: string[];
|
|
57
74
|
/**
|
|
58
|
-
* In-memory budget (MiB,
|
|
59
|
-
*
|
|
60
|
-
*
|
|
75
|
+
* In-memory budget (MiB, decoded size) for parsed source maps used to
|
|
76
|
+
* symbolicate browser frames at ingest (SOURCE_MAP_CACHE_MB, default 64).
|
|
77
|
+
* A map that needs more than half of it is used without being kept.
|
|
61
78
|
*/
|
|
62
79
|
sourceMapCacheMb?: number;
|
|
63
80
|
}
|
|
81
|
+
/** Parse AUTTER_INGEST_KEYS. Entries without a string key, orgId and
|
|
82
|
+
* repositoryId, or with an unknown scope, are dropped (a typo in `scope`
|
|
83
|
+
* must not turn a restricted key into a server key). */
|
|
84
|
+
export declare function parseIngestKeys(raw: string | undefined): StaticIngestKey[];
|
|
64
85
|
export declare function loadConfig(): IngesterConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export const INGEST_KEY_SCOPES = ["server", "client", "upload"];
|
|
2
|
+
/** Prefix of upload-only keys (`autter_rtu_…`): source map uploads from CI. */
|
|
3
|
+
export const UPLOAD_KEY_PREFIX = "autter_rtu_";
|
|
4
|
+
export function isIngestKeyScope(value) {
|
|
5
|
+
return typeof value === "string" && INGEST_KEY_SCOPES.includes(value);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The scope of a key whose static entry or validator answer names none:
|
|
9
|
+
* "upload" for an `autter_rtu_…` key (its prefix promises no more than
|
|
10
|
+
* that), else "server" as before 1.7.0.
|
|
11
|
+
*/
|
|
12
|
+
export function defaultScopeFor(key) {
|
|
13
|
+
return key.startsWith(UPLOAD_KEY_PREFIX) ? "upload" : "server";
|
|
14
|
+
}
|
|
1
15
|
function intEnv(name, fallback) {
|
|
2
16
|
const raw = process.env[name];
|
|
3
17
|
if (!raw)
|
|
@@ -19,22 +33,33 @@ function patternListEnv(name) {
|
|
|
19
33
|
new RegExp(source);
|
|
20
34
|
return parsed;
|
|
21
35
|
}
|
|
22
|
-
|
|
36
|
+
/** Parse AUTTER_INGEST_KEYS. Entries without a string key, orgId and
|
|
37
|
+
* repositoryId, or with an unknown scope, are dropped (a typo in `scope`
|
|
38
|
+
* must not turn a restricted key into a server key). */
|
|
39
|
+
export function parseIngestKeys(raw) {
|
|
23
40
|
if (!raw)
|
|
24
41
|
return [];
|
|
42
|
+
let parsed;
|
|
25
43
|
try {
|
|
26
|
-
|
|
27
|
-
if (!Array.isArray(parsed))
|
|
28
|
-
return [];
|
|
29
|
-
return parsed.filter((entry) => entry &&
|
|
30
|
-
typeof entry.key === "string" &&
|
|
31
|
-
typeof entry.orgId === "string" &&
|
|
32
|
-
typeof entry.repositoryId === "string");
|
|
44
|
+
parsed = JSON.parse(raw);
|
|
33
45
|
}
|
|
34
46
|
catch {
|
|
35
47
|
console.error("AUTTER_INGEST_KEYS is not valid JSON — ignoring");
|
|
36
48
|
return [];
|
|
37
49
|
}
|
|
50
|
+
if (!Array.isArray(parsed))
|
|
51
|
+
return [];
|
|
52
|
+
const keys = [];
|
|
53
|
+
parsed.forEach((entry, index) => {
|
|
54
|
+
if (!entry || typeof entry.key !== "string" || typeof entry.orgId !== "string" || typeof entry.repositoryId !== "string")
|
|
55
|
+
return;
|
|
56
|
+
if (entry.scope !== undefined && !isIngestKeyScope(entry.scope)) {
|
|
57
|
+
console.error(`AUTTER_INGEST_KEYS[${index}] has scope ${JSON.stringify(entry.scope)}; expected one of ${INGEST_KEY_SCOPES.join(", ")} — ignoring this key`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
keys.push({ ...entry, scope: entry.scope ?? defaultScopeFor(entry.key) });
|
|
61
|
+
});
|
|
62
|
+
return keys;
|
|
38
63
|
}
|
|
39
64
|
export function loadConfig() {
|
|
40
65
|
const config = {
|
|
@@ -52,65 +52,65 @@ export declare const browserPayloadSchema: z.ZodObject<{
|
|
|
52
52
|
*/
|
|
53
53
|
traceId: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
54
54
|
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
type: "request_failure" | "timing" | "outcome" | "csp_violation" | "message" | "exception" | "unhandled_rejection" | "session_start" | "track_event";
|
|
55
56
|
message: string;
|
|
56
|
-
type: "message" | "exception" | "request_failure" | "timing" | "outcome" | "csp_violation" | "unhandled_rejection" | "session_start" | "track_event";
|
|
57
57
|
timestamp: string;
|
|
58
|
+
breadcrumbs?: unknown[] | undefined;
|
|
59
|
+
route?: string | undefined;
|
|
58
60
|
severity?: "info" | "warning" | "error" | "fatal" | undefined;
|
|
59
61
|
errorType?: string | undefined;
|
|
60
62
|
stack?: string | undefined;
|
|
61
|
-
route?: string | undefined;
|
|
62
63
|
traceId?: string | undefined;
|
|
63
|
-
breadcrumbs?: unknown[] | undefined;
|
|
64
64
|
debugIds?: Record<string, unknown> | undefined;
|
|
65
65
|
durationMs?: number | undefined;
|
|
66
66
|
filename?: string | undefined;
|
|
67
|
-
id?: string | undefined;
|
|
68
|
-
name?: string | undefined;
|
|
69
|
-
line?: number | undefined;
|
|
70
67
|
column?: number | undefined;
|
|
68
|
+
line?: number | undefined;
|
|
69
|
+
name?: string | undefined;
|
|
70
|
+
id?: string | undefined;
|
|
71
71
|
context?: Record<string, unknown> | undefined;
|
|
72
72
|
fingerprint?: string | string[] | undefined;
|
|
73
73
|
}, {
|
|
74
|
-
type: "
|
|
74
|
+
type: "request_failure" | "timing" | "outcome" | "csp_violation" | "message" | "exception" | "unhandled_rejection" | "session_start" | "track_event";
|
|
75
75
|
timestamp: string;
|
|
76
|
+
breadcrumbs?: unknown;
|
|
77
|
+
route?: string | undefined;
|
|
76
78
|
message?: string | undefined;
|
|
77
79
|
severity?: "info" | "warning" | "error" | "fatal" | undefined;
|
|
78
80
|
errorType?: string | undefined;
|
|
79
81
|
stack?: string | undefined;
|
|
80
|
-
route?: string | undefined;
|
|
81
82
|
traceId?: unknown;
|
|
82
|
-
breadcrumbs?: unknown;
|
|
83
83
|
debugIds?: unknown;
|
|
84
84
|
durationMs?: number | undefined;
|
|
85
85
|
filename?: string | undefined;
|
|
86
|
-
id?: string | undefined;
|
|
87
|
-
name?: string | undefined;
|
|
88
|
-
line?: number | undefined;
|
|
89
86
|
column?: number | undefined;
|
|
87
|
+
line?: number | undefined;
|
|
88
|
+
name?: string | undefined;
|
|
89
|
+
id?: string | undefined;
|
|
90
90
|
context?: Record<string, unknown> | undefined;
|
|
91
91
|
fingerprint?: unknown;
|
|
92
92
|
}>, "many">;
|
|
93
93
|
}, "strip", z.ZodTypeAny, {
|
|
94
|
+
version: 1;
|
|
94
95
|
service: string;
|
|
95
96
|
environment: string;
|
|
96
|
-
version: 1;
|
|
97
97
|
events: {
|
|
98
|
+
type: "request_failure" | "timing" | "outcome" | "csp_violation" | "message" | "exception" | "unhandled_rejection" | "session_start" | "track_event";
|
|
98
99
|
message: string;
|
|
99
|
-
type: "message" | "exception" | "request_failure" | "timing" | "outcome" | "csp_violation" | "unhandled_rejection" | "session_start" | "track_event";
|
|
100
100
|
timestamp: string;
|
|
101
|
+
breadcrumbs?: unknown[] | undefined;
|
|
102
|
+
route?: string | undefined;
|
|
101
103
|
severity?: "info" | "warning" | "error" | "fatal" | undefined;
|
|
102
104
|
errorType?: string | undefined;
|
|
103
105
|
stack?: string | undefined;
|
|
104
|
-
route?: string | undefined;
|
|
105
106
|
traceId?: string | undefined;
|
|
106
|
-
breadcrumbs?: unknown[] | undefined;
|
|
107
107
|
debugIds?: Record<string, unknown> | undefined;
|
|
108
108
|
durationMs?: number | undefined;
|
|
109
109
|
filename?: string | undefined;
|
|
110
|
-
id?: string | undefined;
|
|
111
|
-
name?: string | undefined;
|
|
112
|
-
line?: number | undefined;
|
|
113
110
|
column?: number | undefined;
|
|
111
|
+
line?: number | undefined;
|
|
112
|
+
name?: string | undefined;
|
|
113
|
+
id?: string | undefined;
|
|
114
114
|
context?: Record<string, unknown> | undefined;
|
|
115
115
|
fingerprint?: string | string[] | undefined;
|
|
116
116
|
}[];
|
|
@@ -118,26 +118,26 @@ export declare const browserPayloadSchema: z.ZodObject<{
|
|
|
118
118
|
sessionId?: string | undefined;
|
|
119
119
|
sdk?: string | undefined;
|
|
120
120
|
}, {
|
|
121
|
+
version: 1;
|
|
121
122
|
service: string;
|
|
122
123
|
environment: string;
|
|
123
|
-
version: 1;
|
|
124
124
|
events: {
|
|
125
|
-
type: "
|
|
125
|
+
type: "request_failure" | "timing" | "outcome" | "csp_violation" | "message" | "exception" | "unhandled_rejection" | "session_start" | "track_event";
|
|
126
126
|
timestamp: string;
|
|
127
|
+
breadcrumbs?: unknown;
|
|
128
|
+
route?: string | undefined;
|
|
127
129
|
message?: string | undefined;
|
|
128
130
|
severity?: "info" | "warning" | "error" | "fatal" | undefined;
|
|
129
131
|
errorType?: string | undefined;
|
|
130
132
|
stack?: string | undefined;
|
|
131
|
-
route?: string | undefined;
|
|
132
133
|
traceId?: unknown;
|
|
133
|
-
breadcrumbs?: unknown;
|
|
134
134
|
debugIds?: unknown;
|
|
135
135
|
durationMs?: number | undefined;
|
|
136
136
|
filename?: string | undefined;
|
|
137
|
-
id?: string | undefined;
|
|
138
|
-
name?: string | undefined;
|
|
139
|
-
line?: number | undefined;
|
|
140
137
|
column?: number | undefined;
|
|
138
|
+
line?: number | undefined;
|
|
139
|
+
name?: string | undefined;
|
|
140
|
+
id?: string | undefined;
|
|
141
141
|
context?: Record<string, unknown> | undefined;
|
|
142
142
|
fingerprint?: unknown;
|
|
143
143
|
}[];
|
package/dist/normalize-otlp.d.ts
CHANGED
|
@@ -78,7 +78,13 @@ export interface OtlpMetricsRequest {
|
|
|
78
78
|
}>;
|
|
79
79
|
}
|
|
80
80
|
export interface NormalizedTraces {
|
|
81
|
+
/** One per thrown error: duplicate recordings across a trace's spans are
|
|
82
|
+
* merged and redundant status-only occurrences dropped (trace-dedupe.ts). */
|
|
81
83
|
occurrences: RuntimeOccurrenceInput[];
|
|
84
|
+
/** Each occurrence's position among every signal the batch recorded,
|
|
85
|
+
* before deduplication: the batch index its deterministic id is derived
|
|
86
|
+
* from, so a merge or a drop never shifts another occurrence's id. */
|
|
87
|
+
occurrenceBatchIndexes: number[];
|
|
82
88
|
spans: RuntimeSpanRow[];
|
|
83
89
|
metricPoints: RuntimeMetricPoint[];
|
|
84
90
|
llmCalls: RuntimeLlmCall[];
|