@autter/runtime-node 1.3.4 → 1.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/README.md +114 -17
- package/dist/chunk-3TJHUCZ6.js +1680 -0
- package/dist/chunk-GI47WGRR.cjs +779 -0
- package/dist/chunk-L6SRL65J.cjs +202 -0
- package/dist/chunk-L7HWKMCZ.js +779 -0
- package/dist/chunk-P4VRTFAV.cjs +1680 -0
- package/dist/chunk-ZS4WQJQR.js +202 -0
- package/dist/cli.cjs +40 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +40 -0
- package/dist/index.cjs +1286 -747
- package/dist/index.d.cts +443 -27
- package/dist/index.d.ts +443 -27
- package/dist/index.js +1112 -543
- package/dist/sinks-RFV76lF1.d.cts +313 -0
- package/dist/sinks-RFV76lF1.d.ts +313 -0
- package/dist/testing.cjs +121 -0
- package/dist/testing.d.cts +57 -0
- package/dist/testing.d.ts +57 -0
- package/dist/testing.js +121 -0
- package/package.json +16 -5
package/dist/index.cjs
CHANGED
|
@@ -1,61 +1,76 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
var _chunkP4VRTFAVcjs = require('./chunk-P4VRTFAV.cjs');
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
var _chunkL6SRL65Jcjs = require('./chunk-L6SRL65J.cjs');
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
var _chunkGI47WGRRcjs = require('./chunk-GI47WGRR.cjs');
|
|
51
66
|
|
|
52
67
|
// src/relay.ts
|
|
53
|
-
var IpWindow = class {
|
|
54
|
-
constructor(limitPerMinute) {
|
|
68
|
+
var IpWindow = (_class = class {
|
|
69
|
+
constructor(limitPerMinute) {;_class.prototype.__init.call(this);
|
|
55
70
|
this.limitPerMinute = limitPerMinute;
|
|
56
71
|
}
|
|
57
|
-
|
|
58
|
-
windows = /* @__PURE__ */ new Map()
|
|
72
|
+
|
|
73
|
+
__init() {this.windows = /* @__PURE__ */ new Map()}
|
|
59
74
|
allow(ip) {
|
|
60
75
|
const start = Math.floor(Date.now() / 6e4) * 6e4;
|
|
61
76
|
const entry = this.windows.get(ip);
|
|
@@ -67,10 +82,10 @@ var IpWindow = class {
|
|
|
67
82
|
entry.count += 1;
|
|
68
83
|
return entry.count <= this.limitPerMinute;
|
|
69
84
|
}
|
|
70
|
-
};
|
|
85
|
+
}, _class);
|
|
71
86
|
function firstForwardedFor(value) {
|
|
72
87
|
const raw = Array.isArray(value) ? value[0] : value;
|
|
73
|
-
return raw ? (raw.split(",")[0]
|
|
88
|
+
return raw ? (_nullishCoalesce(raw.split(",")[0], () => ( ""))).trim() : "";
|
|
74
89
|
}
|
|
75
90
|
var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
76
91
|
var DEFAULT_MAX_BODY = 64 * 1024;
|
|
@@ -87,7 +102,120 @@ var EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
|
87
102
|
"timing"
|
|
88
103
|
]);
|
|
89
104
|
var SEVERITIES = /* @__PURE__ */ new Set(["fatal", "error", "warning", "info"]);
|
|
90
|
-
|
|
105
|
+
var CONTEXT_MAX_DEPTH = 6;
|
|
106
|
+
var CONTEXT_MAX_NODES = 256;
|
|
107
|
+
var CONTEXT_MAX_STRING = 4e3;
|
|
108
|
+
var CONTEXT_MAX_ARRAY = 100;
|
|
109
|
+
var CONTEXT_MAX_KEYS = 100;
|
|
110
|
+
function byteLength(text) {
|
|
111
|
+
return new TextEncoder().encode(text).length;
|
|
112
|
+
}
|
|
113
|
+
function boundContext(value) {
|
|
114
|
+
let nodes = 0;
|
|
115
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
116
|
+
const walk = (v, depth) => {
|
|
117
|
+
if (v === null) return null;
|
|
118
|
+
const t = typeof v;
|
|
119
|
+
if (t === "string") return v.slice(0, CONTEXT_MAX_STRING);
|
|
120
|
+
if (t === "number" || t === "boolean") return v;
|
|
121
|
+
if (t !== "object") return void 0;
|
|
122
|
+
if (depth >= CONTEXT_MAX_DEPTH || nodes >= CONTEXT_MAX_NODES) return void 0;
|
|
123
|
+
const obj = v;
|
|
124
|
+
if (seen.has(obj)) return void 0;
|
|
125
|
+
seen.add(obj);
|
|
126
|
+
let isArr = false;
|
|
127
|
+
try {
|
|
128
|
+
isArr = Array.isArray(v);
|
|
129
|
+
} catch (e2) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
if (isArr) {
|
|
133
|
+
const arr = v;
|
|
134
|
+
const out2 = [];
|
|
135
|
+
let len = 0;
|
|
136
|
+
try {
|
|
137
|
+
len = arr.length;
|
|
138
|
+
} catch (e3) {
|
|
139
|
+
return out2;
|
|
140
|
+
}
|
|
141
|
+
for (let i = 0; i < len && i < CONTEXT_MAX_ARRAY; i++) {
|
|
142
|
+
if (nodes >= CONTEXT_MAX_NODES) break;
|
|
143
|
+
nodes++;
|
|
144
|
+
let el;
|
|
145
|
+
try {
|
|
146
|
+
el = walk(arr[i], depth + 1);
|
|
147
|
+
} catch (e4) {
|
|
148
|
+
el = void 0;
|
|
149
|
+
}
|
|
150
|
+
if (el !== void 0) out2.push(el);
|
|
151
|
+
}
|
|
152
|
+
return out2;
|
|
153
|
+
}
|
|
154
|
+
let keys;
|
|
155
|
+
try {
|
|
156
|
+
keys = Object.keys(obj);
|
|
157
|
+
} catch (e5) {
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
const out = {};
|
|
161
|
+
for (let i = 0; i < keys.length && i < CONTEXT_MAX_KEYS; i++) {
|
|
162
|
+
if (nodes >= CONTEXT_MAX_NODES) break;
|
|
163
|
+
const key = keys[i];
|
|
164
|
+
if (key === void 0) continue;
|
|
165
|
+
nodes++;
|
|
166
|
+
let child;
|
|
167
|
+
try {
|
|
168
|
+
child = walk(obj[key], depth + 1);
|
|
169
|
+
} catch (e6) {
|
|
170
|
+
child = void 0;
|
|
171
|
+
}
|
|
172
|
+
if (child !== void 0) out[key] = child;
|
|
173
|
+
}
|
|
174
|
+
return out;
|
|
175
|
+
};
|
|
176
|
+
let result;
|
|
177
|
+
try {
|
|
178
|
+
result = walk(value, 0);
|
|
179
|
+
} catch (e7) {
|
|
180
|
+
result = void 0;
|
|
181
|
+
}
|
|
182
|
+
return result && typeof result === "object" ? result : {};
|
|
183
|
+
}
|
|
184
|
+
async function readBodyBounded(request, maxBody) {
|
|
185
|
+
const body = request.body;
|
|
186
|
+
if (!body) {
|
|
187
|
+
const text = await request.text();
|
|
188
|
+
return byteLength(text) > maxBody ? { tooLarge: true } : { tooLarge: false, text };
|
|
189
|
+
}
|
|
190
|
+
const reader = body.getReader();
|
|
191
|
+
const chunks = [];
|
|
192
|
+
let total = 0;
|
|
193
|
+
for (; ; ) {
|
|
194
|
+
const { done, value } = await reader.read();
|
|
195
|
+
if (done) break;
|
|
196
|
+
if (!value) continue;
|
|
197
|
+
total += value.byteLength;
|
|
198
|
+
if (total > maxBody) {
|
|
199
|
+
void Promise.resolve().then(() => reader.cancel()).catch(() => {
|
|
200
|
+
});
|
|
201
|
+
return { tooLarge: true };
|
|
202
|
+
}
|
|
203
|
+
chunks.push(value);
|
|
204
|
+
}
|
|
205
|
+
const buf = new Uint8Array(total);
|
|
206
|
+
let offset = 0;
|
|
207
|
+
for (const chunk of chunks) {
|
|
208
|
+
buf.set(chunk, offset);
|
|
209
|
+
offset += chunk.byteLength;
|
|
210
|
+
}
|
|
211
|
+
return { tooLarge: false, text: new TextDecoder().decode(buf) };
|
|
212
|
+
}
|
|
213
|
+
function relayContext(raw, redactor) {
|
|
214
|
+
const bounded = boundContext(raw);
|
|
215
|
+
return Array.isArray(bounded) ? {} : { context: redactor(bounded) };
|
|
216
|
+
}
|
|
217
|
+
var defaultRelayRedactor = _chunkP4VRTFAVcjs.makeRedactor.call(void 0, true);
|
|
218
|
+
function sanitizeBrowserPayload(raw, redactor = defaultRelayRedactor) {
|
|
91
219
|
if (typeof raw !== "object" || raw === null) return null;
|
|
92
220
|
const p = raw;
|
|
93
221
|
if (p.version !== 1) return null;
|
|
@@ -104,16 +232,16 @@ function sanitizeBrowserPayload(raw) {
|
|
|
104
232
|
type: e.type,
|
|
105
233
|
timestamp: e.timestamp,
|
|
106
234
|
...typeof e.severity === "string" && SEVERITIES.has(e.severity) ? { severity: e.severity } : {},
|
|
107
|
-
message: typeof e.message === "string" ? e.message.slice(0, 4e3) : "",
|
|
108
|
-
...typeof e.name === "string" ? { name: e.name.slice(0, 200) } : {},
|
|
235
|
+
message: typeof e.message === "string" ? redactor.text(e.message.slice(0, 4512)).slice(0, 4e3) : "",
|
|
236
|
+
...typeof e.name === "string" ? { name: redactor.text(e.name.slice(0, 712)).slice(0, 200) } : {},
|
|
109
237
|
...typeof e.durationMs === "number" && Number.isFinite(e.durationMs) ? { durationMs: Math.max(0, Math.min(12e4, e.durationMs)) } : {},
|
|
110
|
-
...typeof e.stack === "string" ? { stack: e.stack.slice(0, 32e3) } : {},
|
|
238
|
+
...typeof e.stack === "string" ? { stack: redactor.text(e.stack.slice(0, 32512)).slice(0, 32e3) } : {},
|
|
111
239
|
...typeof e.errorType === "string" ? { errorType: e.errorType.slice(0, 200) } : {},
|
|
112
240
|
...typeof e.filename === "string" ? { filename: e.filename.split("?")[0].slice(0, 1e3) } : {},
|
|
113
241
|
...typeof e.line === "number" ? { line: e.line } : {},
|
|
114
242
|
...typeof e.column === "number" ? { column: e.column } : {},
|
|
115
243
|
...typeof e.route === "string" ? { route: e.route.split("?")[0].slice(0, 1e3) } : {},
|
|
116
|
-
...typeof e.context === "object" && e.context !== null ?
|
|
244
|
+
...typeof e.context === "object" && e.context !== null ? relayContext(e.context, redactor) : {}
|
|
117
245
|
});
|
|
118
246
|
}
|
|
119
247
|
return {
|
|
@@ -122,11 +250,16 @@ function sanitizeBrowserPayload(raw) {
|
|
|
122
250
|
service: p.service.slice(0, 200),
|
|
123
251
|
environment: p.environment.slice(0, 100),
|
|
124
252
|
...typeof p.release === "string" ? { release: p.release.slice(0, 200) } : {},
|
|
253
|
+
// @autter/runtime-browser version, for the ingester's compat records.
|
|
254
|
+
...typeof p.sdk === "string" && /^\d{1,6}\.\d{1,6}\.\d{1,6}[0-9A-Za-z.+-]{0,20}$/.test(p.sdk) ? { sdk: p.sdk } : {},
|
|
125
255
|
events
|
|
126
256
|
};
|
|
127
257
|
}
|
|
128
258
|
function forward(payload, opts) {
|
|
129
|
-
const
|
|
259
|
+
const endpoint = (_nullishCoalesce(opts.endpoint, () => ( DEFAULT_ENDPOINT))).replace(/\/$/, "");
|
|
260
|
+
const url = `${endpoint}/v1/browser`;
|
|
261
|
+
const compat = opts.compatCheck !== false;
|
|
262
|
+
if (compat) _chunkGI47WGRRcjs.ensureCompatConfigured.call(void 0, endpoint);
|
|
130
263
|
void fetch(url, {
|
|
131
264
|
method: "POST",
|
|
132
265
|
headers: {
|
|
@@ -135,15 +268,24 @@ function forward(payload, opts) {
|
|
|
135
268
|
},
|
|
136
269
|
body: JSON.stringify(payload),
|
|
137
270
|
signal: AbortSignal.timeout(1e4)
|
|
271
|
+
}).then((response) => {
|
|
272
|
+
if (!compat) return;
|
|
273
|
+
const types = new Set(
|
|
274
|
+
(_nullishCoalesce(payload.events, () => ( []))).map((e) => String(e.type))
|
|
275
|
+
);
|
|
276
|
+
_chunkGI47WGRRcjs.observeIngesterResponse.call(void 0, { status: response.status, headers: response.headers });
|
|
277
|
+
for (const feature of _chunkGI47WGRRcjs.featuresForBrowserEvents.call(void 0, types)) _chunkGI47WGRRcjs.noteCompatFeature.call(void 0, feature);
|
|
278
|
+
_chunkGI47WGRRcjs.noteRelayRejection.call(void 0, types, response.status, response.headers);
|
|
138
279
|
}).catch((err) => {
|
|
139
|
-
(opts.onError
|
|
280
|
+
(_nullishCoalesce(opts.onError, () => ( ((e) => console.warn("autter relay forward failed:", e)))))(
|
|
140
281
|
err
|
|
141
282
|
);
|
|
142
283
|
});
|
|
143
284
|
}
|
|
144
285
|
function createBrowserRelayFetchHandler(opts) {
|
|
145
|
-
const maxBody = opts.maxBodyBytes
|
|
146
|
-
const
|
|
286
|
+
const maxBody = _nullishCoalesce(opts.maxBodyBytes, () => ( DEFAULT_MAX_BODY));
|
|
287
|
+
const redactor = opts.redact === void 0 || opts.redact === true ? defaultRelayRedactor : _chunkP4VRTFAVcjs.makeRedactor.call(void 0, opts.redact);
|
|
288
|
+
const limiter = opts.perIpRateLimit === false ? null : new IpWindow(_nullishCoalesce(opts.perIpRateLimit, () => ( 120)));
|
|
147
289
|
return async (request) => {
|
|
148
290
|
if (request.method !== "POST") {
|
|
149
291
|
return new Response(null, { status: 405 });
|
|
@@ -156,21 +298,28 @@ function createBrowserRelayFetchHandler(opts) {
|
|
|
156
298
|
});
|
|
157
299
|
}
|
|
158
300
|
}
|
|
159
|
-
|
|
160
|
-
|
|
301
|
+
let bounded;
|
|
302
|
+
try {
|
|
303
|
+
bounded = await readBodyBounded(request, maxBody);
|
|
304
|
+
} catch (e8) {
|
|
305
|
+
return new Response(JSON.stringify({ error: "invalid json" }), {
|
|
306
|
+
status: 400
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (bounded.tooLarge) {
|
|
161
310
|
return new Response(JSON.stringify({ error: "payload too large" }), {
|
|
162
311
|
status: 413
|
|
163
312
|
});
|
|
164
313
|
}
|
|
165
314
|
let raw;
|
|
166
315
|
try {
|
|
167
|
-
raw = JSON.parse(text);
|
|
168
|
-
} catch {
|
|
316
|
+
raw = JSON.parse(bounded.text);
|
|
317
|
+
} catch (e9) {
|
|
169
318
|
return new Response(JSON.stringify({ error: "invalid json" }), {
|
|
170
319
|
status: 400
|
|
171
320
|
});
|
|
172
321
|
}
|
|
173
|
-
const payload = sanitizeBrowserPayload(raw);
|
|
322
|
+
const payload = sanitizeBrowserPayload(raw, redactor);
|
|
174
323
|
if (!payload) {
|
|
175
324
|
return new Response(JSON.stringify({ error: "invalid payload" }), {
|
|
176
325
|
status: 400
|
|
@@ -181,8 +330,9 @@ function createBrowserRelayFetchHandler(opts) {
|
|
|
181
330
|
};
|
|
182
331
|
}
|
|
183
332
|
function createBrowserRelayHandler(opts) {
|
|
184
|
-
const maxBody = opts.maxBodyBytes
|
|
185
|
-
const
|
|
333
|
+
const maxBody = _nullishCoalesce(opts.maxBodyBytes, () => ( DEFAULT_MAX_BODY));
|
|
334
|
+
const redactor = opts.redact === void 0 || opts.redact === true ? defaultRelayRedactor : _chunkP4VRTFAVcjs.makeRedactor.call(void 0, opts.redact);
|
|
335
|
+
const limiter = opts.perIpRateLimit === false ? null : new IpWindow(_nullishCoalesce(opts.perIpRateLimit, () => ( 120)));
|
|
186
336
|
function respond(res, status, body) {
|
|
187
337
|
res.statusCode = status;
|
|
188
338
|
if (body) {
|
|
@@ -193,7 +343,7 @@ function createBrowserRelayHandler(opts) {
|
|
|
193
343
|
}
|
|
194
344
|
}
|
|
195
345
|
function handleParsed(raw, res) {
|
|
196
|
-
const payload = sanitizeBrowserPayload(raw);
|
|
346
|
+
const payload = sanitizeBrowserPayload(raw, redactor);
|
|
197
347
|
if (!payload) {
|
|
198
348
|
respond(res, 400, { error: "invalid payload" });
|
|
199
349
|
return;
|
|
@@ -207,7 +357,7 @@ function createBrowserRelayHandler(opts) {
|
|
|
207
357
|
return;
|
|
208
358
|
}
|
|
209
359
|
if (limiter) {
|
|
210
|
-
const ip = firstForwardedFor(req.headers["x-forwarded-for"]) || req.socket
|
|
360
|
+
const ip = firstForwardedFor(req.headers["x-forwarded-for"]) || _optionalChain([req, 'access', _ => _.socket, 'optionalAccess', _2 => _2.remoteAddress]) || "unknown";
|
|
211
361
|
if (!limiter.allow(ip)) {
|
|
212
362
|
respond(res, 429, { error: "rate limit exceeded" });
|
|
213
363
|
return;
|
|
@@ -218,7 +368,7 @@ function createBrowserRelayHandler(opts) {
|
|
|
218
368
|
if (typeof raw === "string" || Buffer.isBuffer(raw)) {
|
|
219
369
|
try {
|
|
220
370
|
raw = JSON.parse(raw.toString());
|
|
221
|
-
} catch {
|
|
371
|
+
} catch (e10) {
|
|
222
372
|
respond(res, 400, { error: "invalid json" });
|
|
223
373
|
return;
|
|
224
374
|
}
|
|
@@ -243,7 +393,7 @@ function createBrowserRelayHandler(opts) {
|
|
|
243
393
|
if (aborted) return;
|
|
244
394
|
try {
|
|
245
395
|
handleParsed(JSON.parse(Buffer.concat(chunks).toString()), res);
|
|
246
|
-
} catch {
|
|
396
|
+
} catch (e11) {
|
|
247
397
|
respond(res, 400, { error: "invalid json" });
|
|
248
398
|
}
|
|
249
399
|
});
|
|
@@ -254,466 +404,162 @@ function createBrowserRelayHandler(opts) {
|
|
|
254
404
|
}
|
|
255
405
|
|
|
256
406
|
// src/server.ts
|
|
257
|
-
var
|
|
258
|
-
var
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
var
|
|
266
|
-
var
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
var
|
|
272
|
-
var
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
407
|
+
var _http = require('http');
|
|
408
|
+
var _crypto = require('crypto');
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
var _api = require('@opentelemetry/api');
|
|
416
|
+
var _core = require('@opentelemetry/core');
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
var _exportermetricsotlphttp = require('@opentelemetry/exporter-metrics-otlp-http');
|
|
421
|
+
var _exportertraceotlphttp = require('@opentelemetry/exporter-trace-otlp-http');
|
|
422
|
+
var _instrumentationhttp = require('@opentelemetry/instrumentation-http');
|
|
423
|
+
var _resources = require('@opentelemetry/resources');
|
|
424
|
+
var _sdkmetrics = require('@opentelemetry/sdk-metrics');
|
|
425
|
+
var _sdknode = require('@opentelemetry/sdk-node');
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
var _sdktracebase = require('@opentelemetry/sdk-trace-base');
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
var _semanticconventions = require('@opentelemetry/semantic-conventions');
|
|
438
|
+
|
|
439
|
+
// src/redact-exporter.ts
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
var scrubbedResources = /* @__PURE__ */ new WeakMap();
|
|
446
|
+
function redactResource(resource, redactor) {
|
|
447
|
+
const cached = scrubbedResources.get(resource);
|
|
448
|
+
if (cached) return cached;
|
|
449
|
+
const scrubbed = new (0, _resources.Resource)(redactor.exported(resource.attributes));
|
|
450
|
+
scrubbedResources.set(resource, scrubbed);
|
|
451
|
+
return scrubbed;
|
|
452
|
+
}
|
|
453
|
+
function redactSpan(span, redactor) {
|
|
454
|
+
const status = span.status.message ? { ...span.status, message: redactor.text(span.status.message) } : span.status;
|
|
455
|
+
return {
|
|
456
|
+
name: redactor.text(span.name),
|
|
457
|
+
kind: span.kind,
|
|
458
|
+
spanContext: () => span.spanContext(),
|
|
459
|
+
parentSpanId: span.parentSpanId,
|
|
460
|
+
startTime: span.startTime,
|
|
461
|
+
endTime: span.endTime,
|
|
462
|
+
status,
|
|
463
|
+
attributes: redactor.exported(span.attributes),
|
|
464
|
+
links: span.links.map(
|
|
465
|
+
(link) => link.attributes ? { ...link, attributes: redactor.exported(link.attributes) } : link
|
|
466
|
+
),
|
|
467
|
+
events: span.events.map((event) => ({
|
|
468
|
+
...event,
|
|
469
|
+
name: redactor.text(event.name),
|
|
470
|
+
...event.attributes ? { attributes: redactor.exported(event.attributes) } : {}
|
|
471
|
+
})),
|
|
472
|
+
duration: span.duration,
|
|
473
|
+
ended: span.ended,
|
|
474
|
+
resource: redactResource(span.resource, redactor),
|
|
475
|
+
instrumentationLibrary: span.instrumentationLibrary,
|
|
476
|
+
droppedAttributesCount: span.droppedAttributesCount,
|
|
477
|
+
droppedEventsCount: span.droppedEventsCount,
|
|
478
|
+
droppedLinksCount: span.droppedLinksCount
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
var RedactingSpanExporter = class {
|
|
482
|
+
constructor(inner, redactor) {
|
|
304
483
|
this.inner = inner;
|
|
484
|
+
this.redactor = redactor;
|
|
305
485
|
}
|
|
306
|
-
|
|
486
|
+
|
|
487
|
+
|
|
307
488
|
export(spans, resultCallback) {
|
|
308
|
-
this.
|
|
309
|
-
|
|
310
|
-
|
|
489
|
+
const redactor = this.redactor();
|
|
490
|
+
let scrubbed = spans;
|
|
491
|
+
let failed = 0;
|
|
492
|
+
if (redactor.enabled) {
|
|
493
|
+
scrubbed = [];
|
|
494
|
+
for (const span of spans) {
|
|
495
|
+
try {
|
|
496
|
+
scrubbed.push(redactSpan(span, redactor));
|
|
497
|
+
} catch (e12) {
|
|
498
|
+
failed++;
|
|
499
|
+
}
|
|
311
500
|
}
|
|
312
|
-
|
|
313
|
-
|
|
501
|
+
}
|
|
502
|
+
if (!failed) {
|
|
503
|
+
this.inner.export(scrubbed, resultCallback);
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const error = new Error(`autter-runtime: ${failed} span(s) could not be redacted and were not exported`);
|
|
507
|
+
const fail = () => resultCallback({ code: _core.ExportResultCode.FAILED, error });
|
|
508
|
+
if (!scrubbed.length) {
|
|
509
|
+
fail();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
this.inner.export(
|
|
513
|
+
scrubbed,
|
|
514
|
+
(result) => result.code === _core.ExportResultCode.SUCCESS ? fail() : resultCallback(result)
|
|
515
|
+
);
|
|
314
516
|
}
|
|
315
517
|
shutdown() {
|
|
316
518
|
return this.inner.shutdown();
|
|
317
519
|
}
|
|
318
520
|
forceFlush() {
|
|
319
|
-
return this.inner.forceFlush
|
|
521
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _3 => _3.inner, 'access', _4 => _4.forceFlush, 'optionalCall', _5 => _5()]), () => ( Promise.resolve()));
|
|
320
522
|
}
|
|
321
523
|
};
|
|
322
|
-
var
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
var SIGNAL_EXIT_CODES = {
|
|
334
|
-
SIGINT: 130,
|
|
335
|
-
SIGTERM: 143
|
|
336
|
-
};
|
|
337
|
-
function installAutterAutoFlush(options = {}) {
|
|
338
|
-
const logger = options.logger ?? console;
|
|
339
|
-
const log = options.log !== false;
|
|
340
|
-
const warnOnUnflushedExit = options.warnOnUnflushedExit !== false;
|
|
341
|
-
const timeoutMs = Math.max(100, options.timeoutMs ?? 3e3);
|
|
342
|
-
const signals = options.signals ?? DEFAULT_SIGNALS;
|
|
343
|
-
const flushOnUncaughtException = options.flushOnUncaughtException !== false;
|
|
344
|
-
let disposed = false;
|
|
345
|
-
let inFlight = null;
|
|
346
|
-
const doFlush = async () => {
|
|
347
|
-
const targets = options.targets ?? activeFlushTargets();
|
|
348
|
-
if (targets.length === 0) return true;
|
|
349
|
-
let timer;
|
|
350
|
-
const timedOut = new Promise((resolve) => {
|
|
351
|
-
timer = setTimeout(() => resolve(false), timeoutMs);
|
|
352
|
-
});
|
|
353
|
-
const drained = Promise.allSettled(
|
|
354
|
-
targets.map(
|
|
355
|
-
(target) => Promise.resolve().then(() => target.forceFlush())
|
|
356
|
-
)
|
|
357
|
-
).then(
|
|
358
|
-
(results) => results.every((result) => result.status === "fulfilled")
|
|
359
|
-
);
|
|
360
|
-
let ok;
|
|
361
|
-
try {
|
|
362
|
-
ok = await Promise.race([drained, timedOut]);
|
|
363
|
-
} finally {
|
|
364
|
-
clearTimeout(timer);
|
|
365
|
-
}
|
|
366
|
-
if (ok) {
|
|
367
|
-
telemetryStats.markAllFlushed();
|
|
368
|
-
if (log) {
|
|
369
|
-
logger.log("[autter] telemetry flushed");
|
|
370
|
-
}
|
|
371
|
-
} else {
|
|
372
|
-
logger.error(
|
|
373
|
-
`[autter] flush did not finish within ${timeoutMs}ms \u2014 some telemetry may be lost`
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
return ok;
|
|
377
|
-
};
|
|
378
|
-
const flush = (reason = "exit") => {
|
|
379
|
-
if (disposed) return Promise.resolve(false);
|
|
380
|
-
if (!inFlight) {
|
|
381
|
-
inFlight = doFlush().finally(() => {
|
|
382
|
-
inFlight = null;
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
if (isDebugEnabled()) debugLog(`auto-flush requested on ${reason}`);
|
|
386
|
-
return inFlight;
|
|
387
|
-
};
|
|
388
|
-
const signalCounts = /* @__PURE__ */ new Map();
|
|
389
|
-
let handlingUncaughtException = false;
|
|
390
|
-
const onUncaughtException = (error) => {
|
|
391
|
-
if (process.listenerCount("uncaughtException") > 1) return;
|
|
392
|
-
if (handlingUncaughtException) return;
|
|
393
|
-
handlingUncaughtException = true;
|
|
394
|
-
logger.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
|
395
|
-
const keepAlive = setTimeout(() => {
|
|
396
|
-
}, timeoutMs + 50);
|
|
397
|
-
void flush("uncaughtException").finally(() => {
|
|
398
|
-
clearTimeout(keepAlive);
|
|
399
|
-
process.exit(1);
|
|
400
|
-
});
|
|
401
|
-
};
|
|
402
|
-
const onSignal = (signal) => {
|
|
403
|
-
const count = (signalCounts.get(signal) ?? 0) + 1;
|
|
404
|
-
signalCounts.set(signal, count);
|
|
405
|
-
const exitCode = SIGNAL_EXIT_CODES[signal] ?? 1;
|
|
406
|
-
if (count > 1) {
|
|
407
|
-
process.exit(exitCode);
|
|
408
|
-
}
|
|
409
|
-
const otherHandlers = process.listenerCount(signal) - 1;
|
|
410
|
-
if (otherHandlers > 0) {
|
|
411
|
-
void flush(signal);
|
|
524
|
+
var RedactingMetricExporter = class {
|
|
525
|
+
constructor(inner, redactor) {
|
|
526
|
+
this.inner = inner;
|
|
527
|
+
this.redactor = redactor;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
export(metrics2, resultCallback) {
|
|
532
|
+
const redactor = this.redactor();
|
|
533
|
+
if (!redactor.enabled) {
|
|
534
|
+
this.inner.export(metrics2, resultCallback);
|
|
412
535
|
return;
|
|
413
536
|
}
|
|
414
|
-
|
|
415
|
-
process.exit(exitCode);
|
|
416
|
-
});
|
|
417
|
-
};
|
|
418
|
-
const MAX_BEFORE_EXIT_FLUSHES = 10;
|
|
419
|
-
let beforeExitFlushes = 0;
|
|
420
|
-
const onBeforeExit = () => {
|
|
421
|
-
if (disposed) return;
|
|
422
|
-
const targets = options.targets ?? activeFlushTargets();
|
|
423
|
-
const worthIt = beforeExitFlushes === 0 ? targets.length > 0 : telemetryStats.pendingCaptures > 0;
|
|
424
|
-
if (!worthIt || beforeExitFlushes >= MAX_BEFORE_EXIT_FLUSHES) return;
|
|
425
|
-
beforeExitFlushes++;
|
|
426
|
-
const keepAlive = setTimeout(() => {
|
|
427
|
-
}, timeoutMs);
|
|
428
|
-
void flush("beforeExit").finally(() => clearTimeout(keepAlive));
|
|
429
|
-
};
|
|
430
|
-
const onExit = () => {
|
|
431
|
-
if (!warnOnUnflushedExit || disposed) return;
|
|
432
|
-
const pending = telemetryStats.pendingCaptures;
|
|
433
|
-
if (pending > 0) {
|
|
434
|
-
logger.error(
|
|
435
|
-
`[autter] process exiting with ~${pending} captured item(s) never confirmed exported \u2014 await autter.shutdown() on graceful shutdown`
|
|
436
|
-
);
|
|
437
|
-
}
|
|
438
|
-
};
|
|
439
|
-
const signalHandlers = /* @__PURE__ */ new Map();
|
|
440
|
-
process.on("beforeExit", onBeforeExit);
|
|
441
|
-
if (flushOnUncaughtException) {
|
|
442
|
-
process.on("uncaughtException", onUncaughtException);
|
|
443
|
-
}
|
|
444
|
-
for (const signal of signals) {
|
|
445
|
-
const handler = () => onSignal(signal);
|
|
446
|
-
signalHandlers.set(signal, handler);
|
|
447
|
-
process.on(signal, handler);
|
|
448
|
-
}
|
|
449
|
-
process.on("exit", onExit);
|
|
450
|
-
return {
|
|
451
|
-
flush,
|
|
452
|
-
dispose() {
|
|
453
|
-
disposed = true;
|
|
454
|
-
process.removeListener("beforeExit", onBeforeExit);
|
|
455
|
-
process.removeListener("uncaughtException", onUncaughtException);
|
|
456
|
-
process.removeListener("exit", onExit);
|
|
457
|
-
for (const [signal, handler] of signalHandlers) {
|
|
458
|
-
process.removeListener(signal, handler);
|
|
459
|
-
}
|
|
460
|
-
signalHandlers.clear();
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/redact.ts
|
|
466
|
-
var SENSITIVE_KEY_PATTERNS = [
|
|
467
|
-
/e-?mail/,
|
|
468
|
-
/pass(word|wd|phrase)|^pass$/,
|
|
469
|
-
/token/,
|
|
470
|
-
/secret/,
|
|
471
|
-
/credential/,
|
|
472
|
-
/(api|access|secret|private|consumer|client|signing|encryption)-?[_.]?key/,
|
|
473
|
-
/^-?x?-?authorization$|^auth(-|_|$)|bearer/,
|
|
474
|
-
/cookie/,
|
|
475
|
-
/phone|msisdn/,
|
|
476
|
-
/\bssn\b|social[-_ ]?security/,
|
|
477
|
-
/cvv|cvc|card([-_. ]?(number|num|no))?$/,
|
|
478
|
-
/credit[-_.]?card/,
|
|
479
|
-
/connection[-_.]?string/,
|
|
480
|
-
/recovery[-_.]?code|\botp\b|magic[-_.]?link/
|
|
481
|
-
];
|
|
482
|
-
var PRIVATE_KEY_BLOCK_RE = /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?(?:-----END [A-Z ]*PRIVATE KEY-----|$)/g;
|
|
483
|
-
var EMAIL_VALUE_RE = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi;
|
|
484
|
-
var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
485
|
-
var OPENAI_KEY_RE = /\bsk-[A-Za-z0-9]{20,}\b/g;
|
|
486
|
-
var GITHUB_TOKEN_RE = /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g;
|
|
487
|
-
var AWS_KEY_RE = /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g;
|
|
488
|
-
var SLACK_TOKEN_RE = /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g;
|
|
489
|
-
var BEARER_RE = /\bbearer\s+[A-Za-z0-9._~+/=-]{10,}/gi;
|
|
490
|
-
var URL_CREDENTIALS_RE = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/:@]+:[^\s/@]+@/gi;
|
|
491
|
-
function toCaseInsensitive(pattern) {
|
|
492
|
-
return typeof pattern === "string" ? new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i") : new RegExp(pattern.source, pattern.flags.includes("i") ? pattern.flags : `${pattern.flags}i`);
|
|
493
|
-
}
|
|
494
|
-
function compile(options) {
|
|
495
|
-
const keyPatterns = [...SENSITIVE_KEY_PATTERNS];
|
|
496
|
-
const valuePatterns = [
|
|
497
|
-
JWT_RE,
|
|
498
|
-
OPENAI_KEY_RE,
|
|
499
|
-
GITHUB_TOKEN_RE,
|
|
500
|
-
AWS_KEY_RE,
|
|
501
|
-
SLACK_TOKEN_RE,
|
|
502
|
-
BEARER_RE
|
|
503
|
-
];
|
|
504
|
-
if (options?.additionalKeyPatterns) {
|
|
505
|
-
for (const p of options.additionalKeyPatterns) {
|
|
506
|
-
keyPatterns.push(toCaseInsensitive(p));
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
if (options?.additionalValuePatterns) {
|
|
510
|
-
for (const p of options.additionalValuePatterns) {
|
|
511
|
-
if (!valuePatterns.some((existing) => existing.source === (typeof p === "string" ? p : p.source))) {
|
|
512
|
-
valuePatterns.push(typeof p === "string" ? new RegExp(p, "gi") : p);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
return {
|
|
517
|
-
keyPatterns,
|
|
518
|
-
valuePatterns,
|
|
519
|
-
urlCredentials: URL_CREDENTIALS_RE,
|
|
520
|
-
privateKeyBlock: PRIVATE_KEY_BLOCK_RE,
|
|
521
|
-
mask: options?.mask ?? "[redacted]",
|
|
522
|
-
scrubEmailValues: options?.scrubEmailValues !== false
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
function redactString(value, r) {
|
|
526
|
-
let out = value.replace(r.privateKeyBlock, r.mask);
|
|
527
|
-
for (const re of r.valuePatterns) {
|
|
528
|
-
out = out.replace(re, r.mask);
|
|
529
|
-
}
|
|
530
|
-
out = out.replace(r.urlCredentials, "$1" + r.mask + "@");
|
|
531
|
-
if (r.scrubEmailValues) {
|
|
532
|
-
out = out.replace(EMAIL_VALUE_RE, r.mask);
|
|
533
|
-
}
|
|
534
|
-
return out;
|
|
535
|
-
}
|
|
536
|
-
var MAX_REDACTION_DEPTH = 64;
|
|
537
|
-
var MAX_REDACTION_WORK = 1e4;
|
|
538
|
-
var MAX_COLLECTION_ENTRIES = 1e3;
|
|
539
|
-
function canTraverse(depth, state) {
|
|
540
|
-
if (depth > MAX_REDACTION_DEPTH || state.remainingWork <= 0) return false;
|
|
541
|
-
state.remainingWork -= 1;
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
|
-
function redactValue(value, r, state, depth) {
|
|
545
|
-
if (typeof value === "string") return redactString(value, r);
|
|
546
|
-
let isArray = false;
|
|
547
|
-
try {
|
|
548
|
-
isArray = Array.isArray(value);
|
|
549
|
-
} catch {
|
|
550
|
-
return r.mask;
|
|
551
|
-
}
|
|
552
|
-
if (isArray) {
|
|
553
|
-
return redactArray(value, r, state, depth);
|
|
554
|
-
}
|
|
555
|
-
if (typeof value === "object" && value !== null) {
|
|
556
|
-
return redactObject(value, r, state, depth);
|
|
557
|
-
}
|
|
558
|
-
return value;
|
|
559
|
-
}
|
|
560
|
-
function redactArray(value, r, state, depth) {
|
|
561
|
-
const existing = state.ancestors.get(value);
|
|
562
|
-
if (existing) return r.mask;
|
|
563
|
-
if (!canTraverse(depth, state)) return r.mask;
|
|
564
|
-
const out = [];
|
|
565
|
-
state.ancestors.set(value, out);
|
|
566
|
-
let length;
|
|
567
|
-
try {
|
|
568
|
-
length = value.length;
|
|
569
|
-
} catch {
|
|
570
|
-
state.ancestors.delete(value);
|
|
571
|
-
return r.mask;
|
|
572
|
-
}
|
|
573
|
-
const limit = Math.min(length, MAX_COLLECTION_ENTRIES);
|
|
574
|
-
for (let i = 0; i < limit; i += 1) {
|
|
575
|
-
let item;
|
|
537
|
+
let resource;
|
|
576
538
|
try {
|
|
577
|
-
|
|
578
|
-
} catch {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
out.push(redactValue(item, r, state, depth + 1));
|
|
583
|
-
}
|
|
584
|
-
if (length > limit) {
|
|
585
|
-
out.push(r.mask);
|
|
586
|
-
}
|
|
587
|
-
state.ancestors.delete(value);
|
|
588
|
-
return out;
|
|
589
|
-
}
|
|
590
|
-
function redactObject(value, r, state, depth) {
|
|
591
|
-
const existing = state.ancestors.get(value);
|
|
592
|
-
if (existing) return r.mask;
|
|
593
|
-
if (!canTraverse(depth, state)) return r.mask;
|
|
594
|
-
const out = {};
|
|
595
|
-
state.ancestors.set(value, out);
|
|
596
|
-
let count = 0;
|
|
597
|
-
let truncated = false;
|
|
598
|
-
try {
|
|
599
|
-
for (const key in value) {
|
|
600
|
-
if (!Object.prototype.propertyIsEnumerable.call(
|
|
601
|
-
value,
|
|
602
|
-
key
|
|
603
|
-
)) {
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
if (count >= MAX_COLLECTION_ENTRIES) {
|
|
607
|
-
truncated = true;
|
|
608
|
-
break;
|
|
609
|
-
}
|
|
610
|
-
let nestedValue;
|
|
611
|
-
try {
|
|
612
|
-
nestedValue = value[key];
|
|
613
|
-
} catch {
|
|
614
|
-
out[key] = r.mask;
|
|
615
|
-
count += 1;
|
|
616
|
-
continue;
|
|
617
|
-
}
|
|
618
|
-
count += 1;
|
|
619
|
-
out[key] = isSensitiveKey(key, nestedValue, r) ? r.mask : redactValue(
|
|
620
|
-
nestedValue,
|
|
621
|
-
r,
|
|
622
|
-
state,
|
|
623
|
-
depth + 1
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
} catch {
|
|
627
|
-
truncated = true;
|
|
628
|
-
}
|
|
629
|
-
if (truncated) {
|
|
630
|
-
out.__redaction_truncated__ = r.mask;
|
|
631
|
-
}
|
|
632
|
-
state.ancestors.delete(value);
|
|
633
|
-
return out;
|
|
634
|
-
}
|
|
635
|
-
var USAGE_TOKEN_KEYS = /* @__PURE__ */ new Set([
|
|
636
|
-
"input_tokens",
|
|
637
|
-
"output_tokens",
|
|
638
|
-
"prompt_tokens",
|
|
639
|
-
"completion_tokens",
|
|
640
|
-
"total_tokens",
|
|
641
|
-
"token_count",
|
|
642
|
-
"gen_ai.usage.input_tokens",
|
|
643
|
-
"gen_ai.usage.output_tokens",
|
|
644
|
-
"gen_ai.usage.prompt_tokens",
|
|
645
|
-
"gen_ai.usage.completion_tokens",
|
|
646
|
-
"gen_ai.usage.total_tokens",
|
|
647
|
-
"gen_ai.usage.token_count"
|
|
648
|
-
]);
|
|
649
|
-
function isSensitiveKey(key, value, r) {
|
|
650
|
-
const lowered = key.toLowerCase();
|
|
651
|
-
if (USAGE_TOKEN_KEYS.has(lowered)) {
|
|
652
|
-
return !(typeof value === "number" && Number.isFinite(value) && value >= 0);
|
|
653
|
-
}
|
|
654
|
-
return r.keyPatterns.some((re) => re.test(lowered));
|
|
655
|
-
}
|
|
656
|
-
function redactAttributes(attributes, options) {
|
|
657
|
-
const r = compile(options);
|
|
658
|
-
return redactWith(attributes, r);
|
|
659
|
-
}
|
|
660
|
-
function redactWith(attributes, r) {
|
|
661
|
-
const out = {};
|
|
662
|
-
if (!attributes) return out;
|
|
663
|
-
const state = {
|
|
664
|
-
ancestors: /* @__PURE__ */ new WeakMap(),
|
|
665
|
-
remainingWork: MAX_REDACTION_WORK
|
|
666
|
-
};
|
|
667
|
-
let count = 0;
|
|
668
|
-
let truncated = false;
|
|
669
|
-
try {
|
|
670
|
-
for (const key in attributes) {
|
|
671
|
-
if (!Object.prototype.propertyIsEnumerable.call(
|
|
672
|
-
attributes,
|
|
673
|
-
key
|
|
674
|
-
)) {
|
|
675
|
-
continue;
|
|
676
|
-
}
|
|
677
|
-
if (count >= MAX_COLLECTION_ENTRIES || state.remainingWork <= 0) {
|
|
678
|
-
truncated = true;
|
|
679
|
-
break;
|
|
680
|
-
}
|
|
681
|
-
let value;
|
|
682
|
-
try {
|
|
683
|
-
value = attributes[key];
|
|
684
|
-
} catch {
|
|
685
|
-
out[key] = r.mask;
|
|
686
|
-
count += 1;
|
|
687
|
-
state.remainingWork -= 1;
|
|
688
|
-
continue;
|
|
689
|
-
}
|
|
690
|
-
count += 1;
|
|
691
|
-
state.remainingWork -= 1;
|
|
692
|
-
if (value === void 0) continue;
|
|
693
|
-
out[key] = isSensitiveKey(key, value, r) ? r.mask : redactValue(value, r, state, 0);
|
|
539
|
+
resource = redactResource(metrics2.resource, redactor);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
resultCallback({ code: _core.ExportResultCode.FAILED, error });
|
|
542
|
+
return;
|
|
694
543
|
}
|
|
695
|
-
|
|
696
|
-
truncated = true;
|
|
544
|
+
this.inner.export({ ...metrics2, resource }, resultCallback);
|
|
697
545
|
}
|
|
698
|
-
|
|
699
|
-
|
|
546
|
+
forceFlush() {
|
|
547
|
+
return this.inner.forceFlush();
|
|
700
548
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
function makeRedactor(options) {
|
|
704
|
-
if (options === false) {
|
|
705
|
-
return (attributes) => ({ ...attributes ?? {} });
|
|
549
|
+
shutdown() {
|
|
550
|
+
return this.inner.shutdown();
|
|
706
551
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
}
|
|
552
|
+
selectAggregationTemporality(instrumentType) {
|
|
553
|
+
return this.inner.selectAggregationTemporality ? this.inner.selectAggregationTemporality(instrumentType) : _sdkmetrics.AggregationTemporality.CUMULATIVE;
|
|
554
|
+
}
|
|
555
|
+
};
|
|
710
556
|
|
|
711
557
|
// src/memory.ts
|
|
712
|
-
var
|
|
713
|
-
var
|
|
714
|
-
|
|
558
|
+
var _perf_hooks = require('perf_hooks');
|
|
559
|
+
var _v8 = require('v8');
|
|
560
|
+
|
|
715
561
|
function startMemoryMetrics() {
|
|
716
|
-
const meter =
|
|
562
|
+
const meter = _api.metrics.getMeter("autter-process-memory");
|
|
717
563
|
const rss = meter.createObservableGauge("autter.process.memory.rss", { unit: "By" });
|
|
718
564
|
const heapUsed = meter.createObservableGauge("autter.process.memory.heap.used", { unit: "By" });
|
|
719
565
|
const heapLimit = meter.createObservableGauge("autter.process.memory.heap.limit", { unit: "By" });
|
|
@@ -727,9 +573,9 @@ function startMemoryMetrics() {
|
|
|
727
573
|
const callbacks = [
|
|
728
574
|
[rss, (result) => result.observe(process.memoryUsage().rss)],
|
|
729
575
|
[heapUsed, (result) => result.observe(process.memoryUsage().heapUsed)],
|
|
730
|
-
[heapLimit, (result) => result.observe((0,
|
|
576
|
+
[heapLimit, (result) => result.observe(_v8.getHeapStatistics.call(void 0, ).heap_size_limit)],
|
|
731
577
|
[containerLimit, (result) => {
|
|
732
|
-
const constrained = process.constrainedMemory
|
|
578
|
+
const constrained = _nullishCoalesce(_optionalChain([process, 'access', _6 => _6.constrainedMemory, 'optionalCall', _7 => _7()]), () => ( 0));
|
|
733
579
|
if (constrained > 0) result.observe(constrained);
|
|
734
580
|
}],
|
|
735
581
|
[afterGc, (result) => {
|
|
@@ -739,7 +585,7 @@ function startMemoryMetrics() {
|
|
|
739
585
|
[gcDuration, (result) => result.observe(durationMs)]
|
|
740
586
|
];
|
|
741
587
|
for (const [instrument, callback] of callbacks) instrument.addCallback(callback);
|
|
742
|
-
const observer = new
|
|
588
|
+
const observer = new (0, _perf_hooks.PerformanceObserver)((list) => {
|
|
743
589
|
for (const entry of list.getEntries()) {
|
|
744
590
|
collections++;
|
|
745
591
|
durationMs += entry.duration;
|
|
@@ -753,6 +599,383 @@ function startMemoryMetrics() {
|
|
|
753
599
|
};
|
|
754
600
|
}
|
|
755
601
|
|
|
602
|
+
// src/requests.ts
|
|
603
|
+
var _async_hooks = require('async_hooks');
|
|
604
|
+
|
|
605
|
+
var REQUEST_STATE = /* @__PURE__ */ Symbol.for("autter.runtime.request");
|
|
606
|
+
var BOUND = /* @__PURE__ */ Symbol.for("autter.runtime.bound");
|
|
607
|
+
var CAPTURED = /* @__PURE__ */ new WeakSet();
|
|
608
|
+
var capturer = () => {
|
|
609
|
+
};
|
|
610
|
+
function setRequestExceptionCapturer(fn) {
|
|
611
|
+
capturer = fn;
|
|
612
|
+
}
|
|
613
|
+
function markCaptured(error) {
|
|
614
|
+
if (error && typeof error === "object") CAPTURED.add(error);
|
|
615
|
+
}
|
|
616
|
+
function expressRouteOf(req) {
|
|
617
|
+
const props = req;
|
|
618
|
+
const path = _optionalChain([props, 'optionalAccess', _8 => _8.route, 'optionalAccess', _9 => _9.path]);
|
|
619
|
+
if (typeof path !== "string" || path === "") return null;
|
|
620
|
+
const base = typeof _optionalChain([props, 'optionalAccess', _10 => _10.baseUrl]) === "string" ? props.baseUrl : "";
|
|
621
|
+
const route = base + path;
|
|
622
|
+
return route.startsWith("/") ? route : null;
|
|
623
|
+
}
|
|
624
|
+
function defaultShouldCapture(error) {
|
|
625
|
+
return error instanceof _chunkP4VRTFAVcjs.RuntimeError || _chunkP4VRTFAVcjs.errorCodeOf.call(void 0, error) !== void 0 || _chunkP4VRTFAVcjs.responseStatusOf.call(void 0, error) >= 500;
|
|
626
|
+
}
|
|
627
|
+
function captureAtBoundary(error, state, rule = void 0) {
|
|
628
|
+
const wanted = typeof rule === "function" ? rule(error) : rule === void 0 ? defaultShouldCapture(error) : rule;
|
|
629
|
+
if (!wanted) return;
|
|
630
|
+
if (error && typeof error === "object" && CAPTURED.has(error)) return;
|
|
631
|
+
markCaptured(error);
|
|
632
|
+
try {
|
|
633
|
+
if (state && !state.sealed) _chunkP4VRTFAVcjs.local.run(state, () => capturer(error));
|
|
634
|
+
else capturer(error);
|
|
635
|
+
} catch (e13) {
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function bindEmitter(emitter, state) {
|
|
639
|
+
const target = emitter;
|
|
640
|
+
if (!target || typeof target !== "object" || target[BOUND]) return;
|
|
641
|
+
target[BOUND] = true;
|
|
642
|
+
const wrappers = /* @__PURE__ */ new WeakMap();
|
|
643
|
+
const wrap = (listener) => {
|
|
644
|
+
if (typeof listener !== "function") return listener;
|
|
645
|
+
let wrapped = wrappers.get(listener);
|
|
646
|
+
if (!wrapped) {
|
|
647
|
+
wrapped = function(...args) {
|
|
648
|
+
return _chunkP4VRTFAVcjs.local.run(
|
|
649
|
+
state,
|
|
650
|
+
() => listener.apply(this, args)
|
|
651
|
+
);
|
|
652
|
+
};
|
|
653
|
+
wrappers.set(listener, wrapped);
|
|
654
|
+
}
|
|
655
|
+
return wrapped;
|
|
656
|
+
};
|
|
657
|
+
for (const method of [
|
|
658
|
+
"on",
|
|
659
|
+
"addListener",
|
|
660
|
+
"prependListener",
|
|
661
|
+
"once",
|
|
662
|
+
"prependOnceListener"
|
|
663
|
+
]) {
|
|
664
|
+
const original = target[method];
|
|
665
|
+
if (typeof original !== "function") continue;
|
|
666
|
+
target[method] = function(event, listener) {
|
|
667
|
+
return original.call(this, event, wrap(listener));
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
for (const method of ["removeListener", "off"]) {
|
|
671
|
+
const original = target[method];
|
|
672
|
+
if (typeof original !== "function") continue;
|
|
673
|
+
target[method] = function(event, listener) {
|
|
674
|
+
const wrapped = typeof listener === "function" ? _nullishCoalesce(wrappers.get(listener), () => ( listener)) : listener;
|
|
675
|
+
return original.call(this, event, wrapped);
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
function exposeHeaderValue(current, header) {
|
|
680
|
+
const text = Array.isArray(current) ? current.join(", ") : String(_nullishCoalesce(current, () => ( "")));
|
|
681
|
+
const names = text.split(",").map((item) => item.trim().toLowerCase()).filter(Boolean);
|
|
682
|
+
if (names.includes("*") || names.includes(header)) return null;
|
|
683
|
+
return names.length ? `${text}, ${header}` : header;
|
|
684
|
+
}
|
|
685
|
+
function exposeOnCors(res, header) {
|
|
686
|
+
const original = res.writeHead;
|
|
687
|
+
res.writeHead = function(...args) {
|
|
688
|
+
try {
|
|
689
|
+
const inline = args.slice(1).find(
|
|
690
|
+
(arg) => !!arg && typeof arg === "object" && !Array.isArray(arg)
|
|
691
|
+
);
|
|
692
|
+
const inlineKey = (name) => inline ? Object.keys(inline).find((key) => key.toLowerCase() === name) : void 0;
|
|
693
|
+
const cors = res.getHeader("access-control-allow-origin") !== void 0 || inlineKey("access-control-allow-origin") !== void 0;
|
|
694
|
+
if (cors) {
|
|
695
|
+
const key = inlineKey("access-control-expose-headers");
|
|
696
|
+
const value = exposeHeaderValue(
|
|
697
|
+
key && inline ? inline[key] : res.getHeader("access-control-expose-headers"),
|
|
698
|
+
header
|
|
699
|
+
);
|
|
700
|
+
if (value && key && inline) inline[key] = value;
|
|
701
|
+
else if (value) res.setHeader("access-control-expose-headers", value);
|
|
702
|
+
}
|
|
703
|
+
} catch (e14) {
|
|
704
|
+
}
|
|
705
|
+
return original.apply(this, args);
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function pathOf(req) {
|
|
709
|
+
const raw = _nullishCoalesce(_nullishCoalesce(req.originalUrl, () => ( req.url)), () => ( "/"));
|
|
710
|
+
return raw.split(/[?#]/)[0] || "/";
|
|
711
|
+
}
|
|
712
|
+
function finishRequest(state, input) {
|
|
713
|
+
if (state.sealed) return;
|
|
714
|
+
state.name = (_nullishCoalesce(input.name, () => ( `${input.method} ${input.route}`))).slice(0, 200);
|
|
715
|
+
state.outcome = _chunkP4VRTFAVcjs.requestOutcome.call(void 0, {
|
|
716
|
+
...state.explicitOutcome ? { explicit: state.outcome } : {},
|
|
717
|
+
...state.error !== void 0 ? { error: state.error } : {},
|
|
718
|
+
...state.errorThrown ? { thrown: true } : {},
|
|
719
|
+
status: input.status,
|
|
720
|
+
aborted: input.aborted
|
|
721
|
+
});
|
|
722
|
+
const span = _api.trace.getActiveSpan();
|
|
723
|
+
if (_optionalChain([span, 'optionalAccess', _11 => _11.isRecording, 'call', _12 => _12()])) span.setAttribute("autter.operation.outcome", state.outcome);
|
|
724
|
+
if (input.span) {
|
|
725
|
+
const remote = _api.trace.wrapSpanContext(input.span);
|
|
726
|
+
_api.context.with(
|
|
727
|
+
_api.trace.setSpan(_api.context.active(), remote),
|
|
728
|
+
() => _chunkP4VRTFAVcjs.reportExplicitFailure.call(void 0, state)
|
|
729
|
+
);
|
|
730
|
+
} else _chunkP4VRTFAVcjs.reportExplicitFailure.call(void 0, state);
|
|
731
|
+
_chunkP4VRTFAVcjs.emitSummary.call(void 0, state, {
|
|
732
|
+
http: {
|
|
733
|
+
"http.request.method": input.method,
|
|
734
|
+
"http.route": input.route,
|
|
735
|
+
"http.response.status_code": input.status,
|
|
736
|
+
"autter.request.aborted": input.aborted
|
|
737
|
+
},
|
|
738
|
+
...input.span ? { span: input.span } : {}
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
function beginNodeRequest(req, res, options, route) {
|
|
742
|
+
const header = (_nullishCoalesce(options.requestIdHeader, () => ( _chunkP4VRTFAVcjs.DEFAULT_REQUEST_ID_HEADER))).toLowerCase();
|
|
743
|
+
const requestId = _chunkP4VRTFAVcjs.resolveRequestId.call(void 0,
|
|
744
|
+
options.trustRequestId === false ? void 0 : req.headers[header]
|
|
745
|
+
);
|
|
746
|
+
const method = (_nullishCoalesce(req.method, () => ( "GET"))).toUpperCase();
|
|
747
|
+
const path = pathOf(req);
|
|
748
|
+
const state = _chunkP4VRTFAVcjs.createRequestState.call(void 0, {
|
|
749
|
+
name: `${method} ${_chunkP4VRTFAVcjs.normalizeRoutePath.call(void 0, path)}`,
|
|
750
|
+
requestId,
|
|
751
|
+
req,
|
|
752
|
+
res
|
|
753
|
+
});
|
|
754
|
+
req[REQUEST_STATE] = state;
|
|
755
|
+
try {
|
|
756
|
+
if (!res.headersSent) res.setHeader(header, requestId);
|
|
757
|
+
exposeOnCors(res, header);
|
|
758
|
+
} catch (e15) {
|
|
759
|
+
}
|
|
760
|
+
const span = _api.trace.getActiveSpan();
|
|
761
|
+
if (_optionalChain([span, 'optionalAccess', _13 => _13.isRecording, 'call', _14 => _14()]))
|
|
762
|
+
span.setAttributes({
|
|
763
|
+
"autter.request.id": requestId,
|
|
764
|
+
"autter.operation.kind": "request"
|
|
765
|
+
});
|
|
766
|
+
const spanContext = _optionalChain([span, 'optionalAccess', _15 => _15.spanContext, 'call', _16 => _16()]);
|
|
767
|
+
bindEmitter(req, state);
|
|
768
|
+
bindEmitter(res, state);
|
|
769
|
+
let finished = false;
|
|
770
|
+
const done = () => {
|
|
771
|
+
finishRequest(state, {
|
|
772
|
+
method,
|
|
773
|
+
route: _nullishCoalesce(_nullishCoalesce(_optionalChain([route, 'optionalCall', _17 => _17()]), () => ( expressRouteOf(req))), () => ( _chunkP4VRTFAVcjs.normalizeRoutePath.call(void 0, path))),
|
|
774
|
+
status: res.statusCode,
|
|
775
|
+
aborted: !finished,
|
|
776
|
+
...spanContext ? { span: spanContext } : {}
|
|
777
|
+
});
|
|
778
|
+
};
|
|
779
|
+
res.once("finish", () => {
|
|
780
|
+
finished = true;
|
|
781
|
+
done();
|
|
782
|
+
});
|
|
783
|
+
res.once("close", done);
|
|
784
|
+
return state;
|
|
785
|
+
}
|
|
786
|
+
function autterRequests(options = {}) {
|
|
787
|
+
const ignored = _chunkP4VRTFAVcjs.compileIgnore.call(void 0, options.ignore);
|
|
788
|
+
return function autterRequestsMiddleware(req, res, next) {
|
|
789
|
+
if (req[REQUEST_STATE] || ignored(pathOf(req))) {
|
|
790
|
+
next();
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
const state = beginNodeRequest(req, res, options);
|
|
794
|
+
_chunkP4VRTFAVcjs.local.run(state, () => next());
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function autterErrorResponse(options = {}) {
|
|
798
|
+
return function autterErrorResponseMiddleware(error, req, res, next) {
|
|
799
|
+
const state = req[REQUEST_STATE];
|
|
800
|
+
if (state) _chunkP4VRTFAVcjs.noteOperationError.call(void 0, error, true, state);
|
|
801
|
+
captureAtBoundary(error, state, options.capture);
|
|
802
|
+
if (res.headersSent) {
|
|
803
|
+
next(error);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const header = (_nullishCoalesce(options.requestIdHeader, () => ( _chunkP4VRTFAVcjs.DEFAULT_REQUEST_ID_HEADER))).toLowerCase();
|
|
807
|
+
const inbound = _optionalChain([req, 'access', _18 => _18.headers, 'optionalAccess', _19 => _19[header]]);
|
|
808
|
+
const requestId = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _20 => _20.requestId]), () => ( (typeof inbound === "string" ? inbound.slice(0, 128) : void 0)));
|
|
809
|
+
res.statusCode = _chunkP4VRTFAVcjs.responseStatusOf.call(void 0, error);
|
|
810
|
+
res.setHeader("content-type", "application/json; charset=utf-8");
|
|
811
|
+
res.end(JSON.stringify(_chunkP4VRTFAVcjs.toClientError.call(void 0, error, requestId)));
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
var RESOURCE = /* @__PURE__ */ Symbol.for("autter.runtime.resource");
|
|
815
|
+
function autterFastify(fastify, options, done) {
|
|
816
|
+
const opts = _nullishCoalesce(options, () => ( {}));
|
|
817
|
+
const header = (_nullishCoalesce(opts.requestIdHeader, () => ( _chunkP4VRTFAVcjs.DEFAULT_REQUEST_ID_HEADER))).toLowerCase();
|
|
818
|
+
const ignored = _chunkP4VRTFAVcjs.compileIgnore.call(void 0, opts.ignore);
|
|
819
|
+
const stateOf = (request) => request[REQUEST_STATE];
|
|
820
|
+
fastify.addHook("onRequest", ((request, reply, next) => {
|
|
821
|
+
if (ignored(request.url) || request.raw[REQUEST_STATE]) {
|
|
822
|
+
next();
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
const requestId = _chunkP4VRTFAVcjs.resolveRequestId.call(void 0,
|
|
826
|
+
opts.trustRequestId === false ? void 0 : request.headers[header]
|
|
827
|
+
);
|
|
828
|
+
const method = String(_nullishCoalesce(request.method, () => ( "GET"))).toUpperCase();
|
|
829
|
+
const state = _chunkP4VRTFAVcjs.createRequestState.call(void 0, {
|
|
830
|
+
name: `${method} ${_chunkP4VRTFAVcjs.normalizeRoutePath.call(void 0, request.url)}`,
|
|
831
|
+
requestId,
|
|
832
|
+
req: request.raw,
|
|
833
|
+
res: reply.raw
|
|
834
|
+
});
|
|
835
|
+
request[REQUEST_STATE] = state;
|
|
836
|
+
request.raw[REQUEST_STATE] = state;
|
|
837
|
+
reply.header(header, requestId);
|
|
838
|
+
const span = _api.trace.getActiveSpan();
|
|
839
|
+
if (_optionalChain([span, 'optionalAccess', _21 => _21.isRecording, 'call', _22 => _22()]))
|
|
840
|
+
span.setAttributes({
|
|
841
|
+
"autter.request.id": requestId,
|
|
842
|
+
"autter.operation.kind": "request"
|
|
843
|
+
});
|
|
844
|
+
const spanContext = _optionalChain([span, 'optionalAccess', _23 => _23.spanContext, 'call', _24 => _24()]);
|
|
845
|
+
bindEmitter(request.raw, state);
|
|
846
|
+
bindEmitter(reply.raw, state);
|
|
847
|
+
let finished = false;
|
|
848
|
+
const finish = (aborted) => finishRequest(state, {
|
|
849
|
+
method,
|
|
850
|
+
route: _nullishCoalesce(_nullishCoalesce(_optionalChain([request, 'access', _25 => _25.routeOptions, 'optionalAccess', _26 => _26.url]), () => ( request.routerPath)), () => ( _chunkP4VRTFAVcjs.normalizeRoutePath.call(void 0, request.url))),
|
|
851
|
+
status: reply.raw.statusCode || reply.statusCode,
|
|
852
|
+
aborted,
|
|
853
|
+
...spanContext ? { span: spanContext } : {}
|
|
854
|
+
});
|
|
855
|
+
reply.raw.once("finish", () => {
|
|
856
|
+
finished = true;
|
|
857
|
+
finish(false);
|
|
858
|
+
});
|
|
859
|
+
reply.raw.once("close", () => finish(!finished));
|
|
860
|
+
_chunkP4VRTFAVcjs.local.run(state, () => {
|
|
861
|
+
request[RESOURCE] = new (0, _async_hooks.AsyncResource)("autter-request");
|
|
862
|
+
next();
|
|
863
|
+
});
|
|
864
|
+
}));
|
|
865
|
+
fastify.addHook("preHandler", ((request, _reply, next) => {
|
|
866
|
+
const resource = request[RESOURCE];
|
|
867
|
+
if (resource) resource.runInAsyncScope(() => next());
|
|
868
|
+
else next();
|
|
869
|
+
}));
|
|
870
|
+
fastify.addHook("onSend", ((request, reply, payload, next) => {
|
|
871
|
+
try {
|
|
872
|
+
if (stateOf(request) && reply.getHeader("access-control-allow-origin") !== void 0) {
|
|
873
|
+
const value = exposeHeaderValue(reply.getHeader("access-control-expose-headers"), header);
|
|
874
|
+
if (value) reply.header("access-control-expose-headers", value);
|
|
875
|
+
}
|
|
876
|
+
} catch (e16) {
|
|
877
|
+
}
|
|
878
|
+
next(null, payload);
|
|
879
|
+
}));
|
|
880
|
+
fastify.addHook("onError", ((request, _reply, error, next) => {
|
|
881
|
+
const state = stateOf(request);
|
|
882
|
+
if (state) _chunkP4VRTFAVcjs.noteOperationError.call(void 0, error, true, state);
|
|
883
|
+
captureAtBoundary(error, state);
|
|
884
|
+
next();
|
|
885
|
+
}));
|
|
886
|
+
done();
|
|
887
|
+
}
|
|
888
|
+
autterFastify[/* @__PURE__ */ Symbol.for("skip-override")] = true;
|
|
889
|
+
autterFastify[/* @__PURE__ */ Symbol.for("fastify.display-name")] = "autter-runtime";
|
|
890
|
+
function withHeaders(response, header, requestId) {
|
|
891
|
+
const apply = (target) => {
|
|
892
|
+
target.headers.set(header, requestId);
|
|
893
|
+
if (target.headers.get("access-control-allow-origin") !== null) {
|
|
894
|
+
const value = exposeHeaderValue(
|
|
895
|
+
_nullishCoalesce(target.headers.get("access-control-expose-headers"), () => ( "")),
|
|
896
|
+
header
|
|
897
|
+
);
|
|
898
|
+
if (value) target.headers.set("access-control-expose-headers", value);
|
|
899
|
+
}
|
|
900
|
+
return target;
|
|
901
|
+
};
|
|
902
|
+
try {
|
|
903
|
+
return apply(response);
|
|
904
|
+
} catch (e17) {
|
|
905
|
+
try {
|
|
906
|
+
return apply(new Response(response.body, response));
|
|
907
|
+
} catch (e18) {
|
|
908
|
+
return response;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
function withRuntimeRequest(handler, options = {}) {
|
|
913
|
+
const header = (_nullishCoalesce(options.requestIdHeader, () => ( _chunkP4VRTFAVcjs.DEFAULT_REQUEST_ID_HEADER))).toLowerCase();
|
|
914
|
+
const ignored = _chunkP4VRTFAVcjs.compileIgnore.call(void 0, options.ignore);
|
|
915
|
+
return async (request, ...rest) => {
|
|
916
|
+
let pathname = "/";
|
|
917
|
+
try {
|
|
918
|
+
pathname = new URL(request.url, "http://localhost").pathname;
|
|
919
|
+
} catch (e19) {
|
|
920
|
+
}
|
|
921
|
+
if (ignored(pathname)) return handler(request, ...rest);
|
|
922
|
+
const requestId = _chunkP4VRTFAVcjs.resolveRequestId.call(void 0,
|
|
923
|
+
options.trustRequestId === false ? void 0 : request.headers.get(header)
|
|
924
|
+
);
|
|
925
|
+
const method = String(_nullishCoalesce(request.method, () => ( "GET"))).toUpperCase();
|
|
926
|
+
const route = _nullishCoalesce(options.route, () => ( _chunkP4VRTFAVcjs.normalizeRoutePath.call(void 0, pathname)));
|
|
927
|
+
const state = _chunkP4VRTFAVcjs.createRequestState.call(void 0, {
|
|
928
|
+
name: `${method} ${_nullishCoalesce(options.name, () => ( route))}`,
|
|
929
|
+
requestId,
|
|
930
|
+
req: request
|
|
931
|
+
});
|
|
932
|
+
const span = _api.trace.getActiveSpan();
|
|
933
|
+
if (_optionalChain([span, 'optionalAccess', _27 => _27.isRecording, 'call', _28 => _28()]))
|
|
934
|
+
span.setAttributes({
|
|
935
|
+
"autter.request.id": requestId,
|
|
936
|
+
"autter.operation.kind": "request"
|
|
937
|
+
});
|
|
938
|
+
const spanContext = _optionalChain([span, 'optionalAccess', _29 => _29.spanContext, 'call', _30 => _30()]);
|
|
939
|
+
let status = 500;
|
|
940
|
+
try {
|
|
941
|
+
const response = await _chunkP4VRTFAVcjs.local.run(state, async () => {
|
|
942
|
+
try {
|
|
943
|
+
return await handler(request, ...rest);
|
|
944
|
+
} catch (error) {
|
|
945
|
+
_chunkP4VRTFAVcjs.noteOperationError.call(void 0, error, true, state);
|
|
946
|
+
captureAtBoundary(error, state, true);
|
|
947
|
+
throw error;
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
status = response.status;
|
|
951
|
+
return withHeaders(response, header, requestId);
|
|
952
|
+
} finally {
|
|
953
|
+
const aborted = _optionalChain([request, 'access', _31 => _31.signal, 'optionalAccess', _32 => _32.aborted]) === true;
|
|
954
|
+
finishRequest(state, {
|
|
955
|
+
method,
|
|
956
|
+
route,
|
|
957
|
+
name: `${method} ${_nullishCoalesce(options.name, () => ( route))}`,
|
|
958
|
+
status,
|
|
959
|
+
aborted,
|
|
960
|
+
...spanContext ? { span: spanContext } : {}
|
|
961
|
+
});
|
|
962
|
+
if (options.waitUntil) {
|
|
963
|
+
try {
|
|
964
|
+
options.waitUntil(_chunkP4VRTFAVcjs.flushRuntimeLogs.call(void 0, ).catch(() => {
|
|
965
|
+
}));
|
|
966
|
+
} catch (e20) {
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function startHookRequest(res) {
|
|
973
|
+
const req = res.req;
|
|
974
|
+
if (!req || req[REQUEST_STATE]) return;
|
|
975
|
+
const state = beginNodeRequest(req, res, {});
|
|
976
|
+
_chunkP4VRTFAVcjs.local.enterWith(state);
|
|
977
|
+
}
|
|
978
|
+
|
|
756
979
|
// src/server.ts
|
|
757
980
|
var LLM_MARKER_ATTRIBUTES = [
|
|
758
981
|
"gen_ai.operation.name",
|
|
@@ -769,10 +992,10 @@ var LlmAwareSampler = class {
|
|
|
769
992
|
constructor(delegate) {
|
|
770
993
|
this.delegate = delegate;
|
|
771
994
|
}
|
|
772
|
-
|
|
995
|
+
|
|
773
996
|
shouldSample(ctx, traceId, spanName, spanKind, attributes, links) {
|
|
774
997
|
if (isLlmSpan(spanName, attributes)) {
|
|
775
|
-
return { decision:
|
|
998
|
+
return { decision: _sdktracebase.SamplingDecision.RECORD_AND_SAMPLED };
|
|
776
999
|
}
|
|
777
1000
|
return this.delegate.shouldSample(
|
|
778
1001
|
ctx,
|
|
@@ -791,7 +1014,7 @@ var RecordUnsampledSampler = class {
|
|
|
791
1014
|
constructor(delegate) {
|
|
792
1015
|
this.delegate = delegate;
|
|
793
1016
|
}
|
|
794
|
-
|
|
1017
|
+
|
|
795
1018
|
shouldSample(ctx, traceId, spanName, spanKind, attributes, links) {
|
|
796
1019
|
const result = this.delegate.shouldSample(
|
|
797
1020
|
ctx,
|
|
@@ -801,8 +1024,8 @@ var RecordUnsampledSampler = class {
|
|
|
801
1024
|
attributes,
|
|
802
1025
|
links
|
|
803
1026
|
);
|
|
804
|
-
if (result.decision ===
|
|
805
|
-
return { ...result, decision:
|
|
1027
|
+
if (result.decision === _sdktracebase.SamplingDecision.NOT_RECORD) {
|
|
1028
|
+
return { ...result, decision: _sdktracebase.SamplingDecision.RECORD };
|
|
806
1029
|
}
|
|
807
1030
|
return result;
|
|
808
1031
|
}
|
|
@@ -815,14 +1038,14 @@ var RETENTION_MAX_BUFFERED_SPANS = 5e3;
|
|
|
815
1038
|
var RETENTION_SWEEP_INTERVAL_MS = 1e4;
|
|
816
1039
|
var RETENTION_TRACE_TTL_MS = 3e4;
|
|
817
1040
|
function spanIndicatesError(span) {
|
|
818
|
-
if (span.status.code ===
|
|
1041
|
+
if (span.status.code === _api.SpanStatusCode.ERROR) return true;
|
|
819
1042
|
return span.events.some((event) => event.name === "exception");
|
|
820
1043
|
}
|
|
821
1044
|
var TAIL_RETAINED_ATTR = "autter.tail_retained";
|
|
822
1045
|
function withSampledFlag(span) {
|
|
823
1046
|
const spanContext = {
|
|
824
1047
|
...span.spanContext(),
|
|
825
|
-
traceFlags: span.spanContext().traceFlags |
|
|
1048
|
+
traceFlags: span.spanContext().traceFlags | _api.TraceFlags.SAMPLED
|
|
826
1049
|
};
|
|
827
1050
|
return {
|
|
828
1051
|
name: span.name,
|
|
@@ -844,29 +1067,29 @@ function withSampledFlag(span) {
|
|
|
844
1067
|
droppedLinksCount: span.droppedLinksCount
|
|
845
1068
|
};
|
|
846
1069
|
}
|
|
847
|
-
var ErrorTraceRetentionProcessor = class {
|
|
848
|
-
constructor(inner, retainErrors = true, slowThresholdMs = 0) {
|
|
1070
|
+
var ErrorTraceRetentionProcessor = (_class2 = class {
|
|
1071
|
+
constructor(inner, retainErrors = true, slowThresholdMs = 0) {;_class2.prototype.__init2.call(this);_class2.prototype.__init3.call(this);
|
|
849
1072
|
this.inner = inner;
|
|
850
1073
|
this.retainErrors = retainErrors;
|
|
851
1074
|
this.slowThresholdMs = slowThresholdMs;
|
|
852
1075
|
this.sweeper = setInterval(() => this.sweep(), RETENTION_SWEEP_INTERVAL_MS);
|
|
853
|
-
this.sweeper.unref
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
traces = /* @__PURE__ */ new Map()
|
|
859
|
-
bufferedSpans = 0
|
|
860
|
-
|
|
1076
|
+
_optionalChain([this, 'access', _33 => _33.sweeper, 'access', _34 => _34.unref, 'optionalCall', _35 => _35()]);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
__init2() {this.traces = /* @__PURE__ */ new Map()}
|
|
1082
|
+
__init3() {this.bufferedSpans = 0}
|
|
1083
|
+
|
|
861
1084
|
onStart(_span, _parentContext) {
|
|
862
1085
|
}
|
|
863
1086
|
onEnd(span) {
|
|
864
1087
|
const ctx = span.spanContext();
|
|
865
|
-
if ((ctx.traceFlags &
|
|
1088
|
+
if ((ctx.traceFlags & _api.TraceFlags.SAMPLED) !== 0) return;
|
|
866
1089
|
const entry = this.entryFor(ctx.traceId);
|
|
867
1090
|
if (entry.retained) {
|
|
868
1091
|
this.forward(span);
|
|
869
|
-
} else if (this.retainErrors && spanIndicatesError(span) || this.slowThresholdMs > 0 && span.kind ===
|
|
1092
|
+
} else if (this.retainErrors && spanIndicatesError(span) || this.slowThresholdMs > 0 && span.kind === _api.SpanKind.SERVER && span.duration[0] * 1e3 + span.duration[1] / 1e6 >= this.slowThresholdMs) {
|
|
870
1093
|
entry.retained = true;
|
|
871
1094
|
this.flush(entry);
|
|
872
1095
|
this.forward(span);
|
|
@@ -881,8 +1104,8 @@ var ErrorTraceRetentionProcessor = class {
|
|
|
881
1104
|
}
|
|
882
1105
|
/** Promote the active trace, if any — called on captured errors. */
|
|
883
1106
|
retainActiveTrace() {
|
|
884
|
-
const active2 =
|
|
885
|
-
if (!active2 || (active2.traceFlags &
|
|
1107
|
+
const active2 = _optionalChain([_api.trace, 'access', _36 => _36.getActiveSpan, 'call', _37 => _37(), 'optionalAccess', _38 => _38.spanContext, 'call', _39 => _39()]);
|
|
1108
|
+
if (!active2 || (active2.traceFlags & _api.TraceFlags.SAMPLED) !== 0) return;
|
|
886
1109
|
const entry = this.entryFor(active2.traceId);
|
|
887
1110
|
if (entry.retained) return;
|
|
888
1111
|
entry.retained = true;
|
|
@@ -937,10 +1160,10 @@ var ErrorTraceRetentionProcessor = class {
|
|
|
937
1160
|
if (entry.firstSeenAtMs <= cutoff) this.drop(traceId);
|
|
938
1161
|
}
|
|
939
1162
|
}
|
|
940
|
-
};
|
|
1163
|
+
}, _class2);
|
|
941
1164
|
function llmBaseAttributes(info) {
|
|
942
1165
|
return {
|
|
943
|
-
"gen_ai.operation.name": info.operation
|
|
1166
|
+
"gen_ai.operation.name": _nullishCoalesce(info.operation, () => ( "chat")),
|
|
944
1167
|
// Both keys: gen_ai.system is the pre-1.37 semconv name and what
|
|
945
1168
|
// most tooling still matches on.
|
|
946
1169
|
"gen_ai.provider.name": info.provider,
|
|
@@ -970,97 +1193,106 @@ function usageAttributes(usage) {
|
|
|
970
1193
|
return attrs;
|
|
971
1194
|
}
|
|
972
1195
|
async function runLlmSpan(tracer, info, fn) {
|
|
973
|
-
const span = tracer.startSpan(`${info.operation
|
|
974
|
-
kind:
|
|
1196
|
+
const span = tracer.startSpan(`${_nullishCoalesce(info.operation, () => ( "chat"))} ${info.model}`, {
|
|
1197
|
+
kind: _api.SpanKind.CLIENT,
|
|
975
1198
|
attributes: llmBaseAttributes(info)
|
|
976
1199
|
});
|
|
977
|
-
const
|
|
1200
|
+
const usage = {};
|
|
1201
|
+
let responseModel;
|
|
1202
|
+
const setResponseModel = (model) => {
|
|
1203
|
+
responseModel = model;
|
|
1204
|
+
span.setAttribute("gen_ai.response.model", model);
|
|
1205
|
+
};
|
|
978
1206
|
const handle = {
|
|
979
|
-
setUsage: (
|
|
980
|
-
|
|
1207
|
+
setUsage: (next) => {
|
|
1208
|
+
Object.assign(usage, next);
|
|
1209
|
+
span.setAttributes(usageAttributes(next));
|
|
1210
|
+
},
|
|
1211
|
+
setCost: (usd) => {
|
|
1212
|
+
usage.costUsd = usd;
|
|
1213
|
+
span.setAttribute("autter.llm.cost_usd", usd);
|
|
1214
|
+
},
|
|
981
1215
|
setResponseModel,
|
|
982
1216
|
setModel: setResponseModel,
|
|
983
|
-
setAttributes: (attributes) => span.setAttributes(attributes)
|
|
1217
|
+
setAttributes: (attributes) => span.setAttributes(activeRedactor(attributes))
|
|
984
1218
|
};
|
|
985
1219
|
try {
|
|
986
|
-
const result = await
|
|
987
|
-
|
|
1220
|
+
const result = await _api.context.with(
|
|
1221
|
+
_api.trace.setSpan(_api.context.active(), span),
|
|
988
1222
|
() => fn(handle)
|
|
989
1223
|
);
|
|
990
|
-
span.setStatus({ code:
|
|
1224
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
991
1225
|
return result;
|
|
992
1226
|
} catch (err) {
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
span.setAttribute("error.type", err.name);
|
|
996
|
-
}
|
|
997
|
-
span.setStatus({
|
|
998
|
-
code: import_api2.SpanStatusCode.ERROR,
|
|
999
|
-
message: err instanceof Error ? err.message : String(err)
|
|
1000
|
-
});
|
|
1227
|
+
recordError(span, err);
|
|
1228
|
+
if (err instanceof Error) span.setAttribute("error.type", err.name);
|
|
1001
1229
|
throw err;
|
|
1002
1230
|
} finally {
|
|
1003
1231
|
span.end();
|
|
1232
|
+
_chunkP4VRTFAVcjs.recordOperationAiUsage.call(void 0, { ...usage, model: _nullishCoalesce(responseModel, () => ( info.model)) });
|
|
1004
1233
|
}
|
|
1005
1234
|
}
|
|
1006
1235
|
function recordLlmCall(tracer, call) {
|
|
1007
|
-
|
|
1236
|
+
_chunkP4VRTFAVcjs.recordOperationAiUsage.call(void 0, { ...call, model: call.model });
|
|
1237
|
+
const durationMs = Math.max(0, _nullishCoalesce(call.durationMs, () => ( 0)));
|
|
1008
1238
|
const endTime = /* @__PURE__ */ new Date();
|
|
1009
1239
|
const startTime = new Date(endTime.getTime() - durationMs);
|
|
1010
1240
|
const span = tracer.startSpan(
|
|
1011
|
-
`${call.operation
|
|
1241
|
+
`${_nullishCoalesce(call.operation, () => ( "chat"))} ${call.model}`,
|
|
1012
1242
|
{
|
|
1013
|
-
kind:
|
|
1243
|
+
kind: _api.SpanKind.CLIENT,
|
|
1014
1244
|
startTime,
|
|
1015
1245
|
attributes: { ...llmBaseAttributes(call), ...usageAttributes(call) }
|
|
1016
1246
|
}
|
|
1017
1247
|
);
|
|
1018
1248
|
if (call.error !== void 0 && call.error !== null) {
|
|
1249
|
+
recordError(span, call.error);
|
|
1019
1250
|
if (call.error instanceof Error) {
|
|
1020
|
-
span.recordException(call.error);
|
|
1021
1251
|
span.setAttribute("error.type", call.error.name);
|
|
1022
1252
|
}
|
|
1023
|
-
span.setStatus({
|
|
1024
|
-
code: import_api2.SpanStatusCode.ERROR,
|
|
1025
|
-
message: call.error instanceof Error ? call.error.message : String(call.error)
|
|
1026
|
-
});
|
|
1027
1253
|
} else {
|
|
1028
|
-
span.setStatus({ code:
|
|
1254
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
1029
1255
|
}
|
|
1030
1256
|
span.end(endTime);
|
|
1031
1257
|
}
|
|
1032
|
-
async function runWithSpan(tracer, name, fn, attributes) {
|
|
1033
|
-
const span = tracer.startSpan(name, {
|
|
1258
|
+
async function runWithSpan(tracer, name, fn, attributes, links) {
|
|
1259
|
+
const span = tracer.startSpan(name, {
|
|
1260
|
+
attributes,
|
|
1261
|
+
..._optionalChain([links, 'optionalAccess', _40 => _40.length]) ? { links } : {}
|
|
1262
|
+
});
|
|
1034
1263
|
try {
|
|
1035
|
-
const result = await
|
|
1036
|
-
|
|
1264
|
+
const result = await _api.context.with(
|
|
1265
|
+
_api.trace.setSpan(_api.context.active(), span),
|
|
1037
1266
|
fn
|
|
1038
1267
|
);
|
|
1039
|
-
span.setStatus({ code:
|
|
1268
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
1040
1269
|
return result;
|
|
1041
1270
|
} catch (err) {
|
|
1042
|
-
|
|
1043
|
-
span.setStatus({
|
|
1044
|
-
code: import_api2.SpanStatusCode.ERROR,
|
|
1045
|
-
message: err instanceof Error ? err.message : String(err)
|
|
1046
|
-
});
|
|
1271
|
+
recordError(span, err);
|
|
1047
1272
|
throw err;
|
|
1048
1273
|
} finally {
|
|
1049
1274
|
span.end();
|
|
1050
1275
|
}
|
|
1051
1276
|
}
|
|
1052
|
-
function
|
|
1053
|
-
const
|
|
1054
|
-
const
|
|
1055
|
-
if (
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1277
|
+
function recordError(span, err) {
|
|
1278
|
+
const isError = err instanceof Error;
|
|
1279
|
+
const message = activeRedactor.text(isError ? err.message : String(err));
|
|
1280
|
+
if (isError) {
|
|
1281
|
+
span.addEvent("exception", {
|
|
1282
|
+
"exception.type": err.name,
|
|
1283
|
+
"exception.message": message,
|
|
1284
|
+
...err.stack ? { "exception.stacktrace": activeRedactor.text(err.stack) } : {}
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message });
|
|
1288
|
+
}
|
|
1289
|
+
function redactWithActive(attributes) {
|
|
1290
|
+
return activeRedactor(attributes);
|
|
1059
1291
|
}
|
|
1060
1292
|
function captureExpressRoute(_span, response) {
|
|
1061
|
-
if (!(response instanceof
|
|
1062
|
-
const rpcMetadata = (0,
|
|
1063
|
-
if (rpcMetadata
|
|
1293
|
+
if (!(response instanceof _http.ServerResponse)) return;
|
|
1294
|
+
const rpcMetadata = _core.getRPCMetadata.call(void 0, _api.context.active());
|
|
1295
|
+
if (_optionalChain([rpcMetadata, 'optionalAccess', _41 => _41.type]) !== _core.RPCType.HTTP) return;
|
|
1064
1296
|
const setRoute = () => {
|
|
1065
1297
|
if (rpcMetadata.route) return;
|
|
1066
1298
|
const route = expressRouteOf(response.req);
|
|
@@ -1068,33 +1300,60 @@ function captureExpressRoute(_span, response) {
|
|
|
1068
1300
|
};
|
|
1069
1301
|
response.prependListener("finish", setRoute);
|
|
1070
1302
|
response.prependListener("close", setRoute);
|
|
1303
|
+
if (hookRequests) startHookRequest(response);
|
|
1304
|
+
}
|
|
1305
|
+
var hookRequests = false;
|
|
1306
|
+
function structuredErrorAttributes(error) {
|
|
1307
|
+
const attrs = { ..._chunkP4VRTFAVcjs.errorAttributes.call(void 0, error, { causes: false }) };
|
|
1308
|
+
const internal = _chunkP4VRTFAVcjs.errorInternal.call(void 0, error);
|
|
1309
|
+
if (internal) {
|
|
1310
|
+
try {
|
|
1311
|
+
attrs["autter.error.internal"] = JSON.stringify(
|
|
1312
|
+
activeRedactor(internal)
|
|
1313
|
+
).slice(0, 4e3);
|
|
1314
|
+
} catch (e21) {
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return attrs;
|
|
1071
1318
|
}
|
|
1072
1319
|
var active = null;
|
|
1073
1320
|
var activeAlwaysOnProvider = null;
|
|
1074
|
-
var activeRedactor = makeRedactor(true);
|
|
1321
|
+
var activeRedactor = _chunkP4VRTFAVcjs.makeRedactor.call(void 0, true);
|
|
1075
1322
|
function initAutterServer(options) {
|
|
1076
1323
|
if (active) return active;
|
|
1077
|
-
const endpoint = (options.endpoint
|
|
1324
|
+
const endpoint = (_nullishCoalesce(options.endpoint, () => ( "https://otlp.autter.dev"))).replace(
|
|
1078
1325
|
/\/$/,
|
|
1079
1326
|
""
|
|
1080
1327
|
);
|
|
1081
1328
|
const headers = { authorization: `Bearer ${options.apiKey}` };
|
|
1082
|
-
const
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1329
|
+
const traceExporter = () => new (0, _chunkGI47WGRRcjs.CountingExporter)(
|
|
1330
|
+
new RedactingSpanExporter(
|
|
1331
|
+
new (0, _exportertraceotlphttp.OTLPTraceExporter)({ url: `${endpoint}/v1/traces`, headers }),
|
|
1332
|
+
() => activeRedactor
|
|
1333
|
+
)
|
|
1334
|
+
);
|
|
1335
|
+
const environment = _nullishCoalesce(_nullishCoalesce(options.environment, () => ( process.env.NODE_ENV)), () => ( "production"));
|
|
1336
|
+
if (_chunkGI47WGRRcjs.isDebugEnabled.call(void 0, ) || options.debug === true) _chunkGI47WGRRcjs.setDebugMode.call(void 0, true);
|
|
1337
|
+
_chunkGI47WGRRcjs.debugLog.call(void 0, `initialising service=${options.service} endpoint=${endpoint}`);
|
|
1338
|
+
activeRedactor = _chunkP4VRTFAVcjs.makeRedactor.call(void 0, _nullishCoalesce(options.redactAttributes, () => ( true)));
|
|
1339
|
+
const distro = _nullishCoalesce(options.distro, () => ( _chunkGI47WGRRcjs.SDK_IDENTITY));
|
|
1340
|
+
_chunkGI47WGRRcjs.configureCompatCheck.call(void 0, { endpoint, enabled: options.compatCheck !== false, sdk: distro });
|
|
1341
|
+
const resource = new (0, _resources.Resource)({
|
|
1342
|
+
[_semanticconventions.ATTR_SERVICE_NAME]: options.service,
|
|
1343
|
+
"service.instance.id": (options.instanceId || process.env.AUTTER_RUNTIME_INSTANCE_ID || _crypto.randomUUID.call(void 0, )).slice(0, 128),
|
|
1344
|
+
...options.release ? { [_semanticconventions.ATTR_SERVICE_VERSION]: options.release } : {},
|
|
1090
1345
|
"deployment.environment": environment,
|
|
1346
|
+
// OTel semconv for SDK distributions: the ingester records which
|
|
1347
|
+
// Autter SDK version each service runs (version compatibility checks).
|
|
1348
|
+
"telemetry.distro.name": distro.name,
|
|
1349
|
+
"telemetry.distro.version": distro.version,
|
|
1091
1350
|
// Tells the ingester request metrics arrive on the metrics pipe, so
|
|
1092
1351
|
// it must not also fold our server spans into usage rollups (that
|
|
1093
1352
|
// would double-count every sampled request).
|
|
1094
1353
|
"autter.metrics_wired": true
|
|
1095
1354
|
});
|
|
1096
|
-
const headSampler = new
|
|
1097
|
-
root: new
|
|
1355
|
+
const headSampler = new (0, _sdktracebase.ParentBasedSampler)({
|
|
1356
|
+
root: new (0, _sdktracebase.TraceIdRatioBasedSampler)(_nullishCoalesce(options.traceSampleRate, () => ( 0.01)))
|
|
1098
1357
|
});
|
|
1099
1358
|
const retainOnError = options.retainTracesOnError !== false;
|
|
1100
1359
|
const slowThresholdMs = Number.isFinite(options.retainTracesAboveMs) ? Math.max(0, options.retainTracesAboveMs) : 0;
|
|
@@ -1102,33 +1361,27 @@ function initAutterServer(options) {
|
|
|
1102
1361
|
let sampler = retainTraces ? new RecordUnsampledSampler(headSampler) : headSampler;
|
|
1103
1362
|
if (options.llmTracing !== false) sampler = new LlmAwareSampler(sampler);
|
|
1104
1363
|
const errorTraceBuffer = retainTraces ? new ErrorTraceRetentionProcessor(
|
|
1105
|
-
new
|
|
1106
|
-
new CountingExporter(
|
|
1107
|
-
new import_exporter_trace_otlp_http.OTLPTraceExporter({ url: `${endpoint}/v1/traces`, headers })
|
|
1108
|
-
),
|
|
1109
|
-
{ scheduledDelayMillis: 2e3 }
|
|
1110
|
-
),
|
|
1364
|
+
new (0, _sdktracebase.BatchSpanProcessor)(traceExporter(), { scheduledDelayMillis: 2e3 }),
|
|
1111
1365
|
retainOnError,
|
|
1112
1366
|
slowThresholdMs
|
|
1113
1367
|
) : null;
|
|
1114
|
-
const mainSpanProcessor = new
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
exportIntervalMillis: options.metricIntervalMs ?? 6e4
|
|
1368
|
+
const mainSpanProcessor = new (0, _sdktracebase.BatchSpanProcessor)(traceExporter());
|
|
1369
|
+
const metricReader = new (0, _sdkmetrics.PeriodicExportingMetricReader)({
|
|
1370
|
+
exporter: new RedactingMetricExporter(
|
|
1371
|
+
new (0, _exportermetricsotlphttp.OTLPMetricExporter)({
|
|
1372
|
+
url: `${endpoint}/v1/metrics`,
|
|
1373
|
+
headers,
|
|
1374
|
+
// Deltas, not lifetime totals: the ingester SUMs data points
|
|
1375
|
+
// into runtime_metrics_1m, and the default (cumulative)
|
|
1376
|
+
// temporality would re-count every past request on each
|
|
1377
|
+
// 60 s export.
|
|
1378
|
+
temporalityPreference: _exportermetricsotlphttp.AggregationTemporalityPreference.DELTA
|
|
1379
|
+
}),
|
|
1380
|
+
() => activeRedactor
|
|
1381
|
+
),
|
|
1382
|
+
exportIntervalMillis: _nullishCoalesce(options.metricIntervalMs, () => ( 6e4))
|
|
1130
1383
|
});
|
|
1131
|
-
const sdk = new
|
|
1384
|
+
const sdk = new (0, _sdknode.NodeSDK)({
|
|
1132
1385
|
resource,
|
|
1133
1386
|
sampler,
|
|
1134
1387
|
spanProcessors: [
|
|
@@ -1137,105 +1390,129 @@ function initAutterServer(options) {
|
|
|
1137
1390
|
],
|
|
1138
1391
|
metricReader,
|
|
1139
1392
|
views: [
|
|
1140
|
-
new
|
|
1393
|
+
new (0, _sdkmetrics.View)({ instrumentName: "http.server.duration", aggregation: new (0, _sdkmetrics.ExplicitBucketHistogramAggregation)(
|
|
1141
1394
|
[5, 10, 25, 50, 100, 250, 500, 750, 1e3, 1500, 2e3, 3e3, 5e3, 7500, 1e4, 15e3, 2e4, 3e4, 6e4, 12e4]
|
|
1142
1395
|
) }),
|
|
1143
|
-
new
|
|
1396
|
+
new (0, _sdkmetrics.View)({ instrumentName: "http.server.request.duration", aggregation: new (0, _sdkmetrics.ExplicitBucketHistogramAggregation)(
|
|
1144
1397
|
[5e-3, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 5, 7.5, 10, 15, 20, 30, 60, 120]
|
|
1145
1398
|
) })
|
|
1146
1399
|
],
|
|
1147
1400
|
instrumentations: [
|
|
1148
|
-
new
|
|
1149
|
-
...options.instrumentations
|
|
1401
|
+
new (0, _instrumentationhttp.HttpInstrumentation)({ responseHook: captureExpressRoute }),
|
|
1402
|
+
..._nullishCoalesce(options.instrumentations, () => ( []))
|
|
1150
1403
|
]
|
|
1151
1404
|
});
|
|
1152
1405
|
sdk.start();
|
|
1153
1406
|
const stopMemoryMetrics = options.memoryMetrics === false ? null : startMemoryMetrics();
|
|
1154
|
-
|
|
1407
|
+
_chunkGI47WGRRcjs.noteCompatFeature.call(void 0, "endpoint_latency");
|
|
1408
|
+
if (stopMemoryMetrics) _chunkGI47WGRRcjs.noteCompatFeature.call(void 0, "memory_metrics");
|
|
1409
|
+
if (options.llmTracing !== false) _chunkGI47WGRRcjs.noteCompatFeature.call(void 0, "llm_calls");
|
|
1410
|
+
const alwaysOnProvider = new (0, _sdktracebase.BasicTracerProvider)({
|
|
1155
1411
|
resource,
|
|
1156
|
-
sampler: new
|
|
1412
|
+
sampler: new (0, _sdktracebase.AlwaysOnSampler)(),
|
|
1157
1413
|
spanProcessors: [
|
|
1158
|
-
new
|
|
1159
|
-
new CountingExporter(
|
|
1160
|
-
new import_exporter_trace_otlp_http.OTLPTraceExporter({ url: `${endpoint}/v1/traces`, headers })
|
|
1161
|
-
),
|
|
1162
|
-
{ scheduledDelayMillis: 2e3 }
|
|
1163
|
-
)
|
|
1414
|
+
new (0, _sdktracebase.BatchSpanProcessor)(traceExporter(), { scheduledDelayMillis: 2e3 })
|
|
1164
1415
|
]
|
|
1165
1416
|
});
|
|
1166
1417
|
const errorTracer = alwaysOnProvider.getTracer("autter-errors");
|
|
1167
1418
|
const processTracer = alwaysOnProvider.getTracer("autter-processes");
|
|
1168
1419
|
const llmTracer = alwaysOnProvider.getTracer("autter-llm");
|
|
1169
1420
|
function captureException2(error, attributes) {
|
|
1170
|
-
errorTraceBuffer
|
|
1171
|
-
telemetryStats.markCaptured();
|
|
1421
|
+
_optionalChain([errorTraceBuffer, 'optionalAccess', _42 => _42.retainActiveTrace, 'call', _43 => _43()]);
|
|
1422
|
+
_chunkGI47WGRRcjs.telemetryStats.markCaptured();
|
|
1172
1423
|
const isError = error instanceof Error;
|
|
1173
|
-
const message = isError ? error.message : String(error);
|
|
1424
|
+
const message = activeRedactor.text(isError ? error.message : String(error));
|
|
1425
|
+
const stackText = isError && error.stack ? activeRedactor.text(error.stack) : "";
|
|
1174
1426
|
const redacted = activeRedactor(attributes);
|
|
1175
|
-
const activeSpan =
|
|
1176
|
-
const reuseActive = activeSpan
|
|
1427
|
+
const activeSpan = _api.trace.getActiveSpan();
|
|
1428
|
+
const reuseActive = _optionalChain([activeSpan, 'optionalAccess', _44 => _44.isRecording, 'call', _45 => _45()]) === true;
|
|
1177
1429
|
const span = reuseActive ? activeSpan : errorTracer.startSpan(isError ? error.name : "Error");
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1430
|
+
const structured = structuredErrorAttributes(error);
|
|
1431
|
+
const causes = _chunkP4VRTFAVcjs.errorAttributes.call(void 0, error);
|
|
1432
|
+
const declared = Object.fromEntries(
|
|
1433
|
+
Object.entries(causes).filter(([key]) => key !== "autter.error.internal")
|
|
1434
|
+
);
|
|
1435
|
+
const requestId = _optionalChain([_chunkP4VRTFAVcjs.currentOperation.call(void 0, ), 'optionalAccess', _46 => _46.requestId]);
|
|
1436
|
+
span.setAttributes({
|
|
1437
|
+
"autter.severity": "error",
|
|
1438
|
+
...redacted,
|
|
1439
|
+
...structured,
|
|
1440
|
+
...requestId ? { "autter.request.id": requestId } : {}
|
|
1441
|
+
});
|
|
1442
|
+
markCaptured(error);
|
|
1443
|
+
_chunkP4VRTFAVcjs.noteOperationError.call(void 0, error);
|
|
1444
|
+
_chunkP4VRTFAVcjs.notifyException.call(void 0, error, redacted);
|
|
1445
|
+
if (isError && stackText) {
|
|
1446
|
+
span.addEvent("exception", {
|
|
1447
|
+
"exception.type": error.name,
|
|
1448
|
+
"exception.message": message,
|
|
1449
|
+
"exception.stacktrace": stackText,
|
|
1450
|
+
...redacted["autter.handled"] === true ? { "autter.handled": true, "autter.sampled": redacted["autter.sampled"] === true } : {},
|
|
1451
|
+
...declared
|
|
1452
|
+
});
|
|
1191
1453
|
} else {
|
|
1192
|
-
const stack = new Error().stack
|
|
1454
|
+
const stack = _optionalChain([new Error(), 'access', _47 => _47.stack, 'optionalAccess', _48 => _48.split, 'call', _49 => _49("\n"), 'access', _50 => _50.filter, 'call', _51 => _51((line, i) => i === 0 || !line.includes("captureException")), 'access', _52 => _52.join, 'call', _53 => _53("\n")]);
|
|
1193
1455
|
span.addEvent("exception", {
|
|
1194
1456
|
"exception.type": isError ? error.name : "Error",
|
|
1195
1457
|
"exception.message": message,
|
|
1196
|
-
...stack ? { "exception.stacktrace": stack } : {},
|
|
1197
|
-
...redacted["autter.handled"] === true ? { "autter.handled": true, "autter.sampled": redacted["autter.sampled"] === true } : {}
|
|
1458
|
+
...stack ? { "exception.stacktrace": activeRedactor.text(stack) } : {},
|
|
1459
|
+
...redacted["autter.handled"] === true ? { "autter.handled": true, "autter.sampled": redacted["autter.sampled"] === true } : {},
|
|
1460
|
+
...declared
|
|
1198
1461
|
});
|
|
1199
1462
|
}
|
|
1200
|
-
span.setStatus({ code:
|
|
1463
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message });
|
|
1201
1464
|
if (!reuseActive) span.end();
|
|
1202
1465
|
}
|
|
1203
1466
|
function captureMessage2(message, severity = "warning", attributes) {
|
|
1204
1467
|
if (severity === "error" || severity === "fatal") {
|
|
1205
|
-
errorTraceBuffer
|
|
1468
|
+
_optionalChain([errorTraceBuffer, 'optionalAccess', _54 => _54.retainActiveTrace, 'call', _55 => _55()]);
|
|
1206
1469
|
}
|
|
1207
|
-
telemetryStats.markCaptured();
|
|
1208
|
-
const stack = new Error().stack
|
|
1470
|
+
_chunkGI47WGRRcjs.telemetryStats.markCaptured();
|
|
1471
|
+
const stack = _optionalChain([new Error(), 'access', _56 => _56.stack, 'optionalAccess', _57 => _57.split, 'call', _58 => _58("\n"), 'access', _59 => _59.filter, 'call', _60 => _60((line, i) => i === 0 || !line.includes("captureMessage")), 'access', _61 => _61.join, 'call', _62 => _62("\n")]);
|
|
1472
|
+
const safeMessage = activeRedactor.text(message);
|
|
1209
1473
|
const span = errorTracer.startSpan("Message", {
|
|
1210
1474
|
attributes: { "autter.severity": severity, ...activeRedactor(attributes) }
|
|
1211
1475
|
});
|
|
1212
1476
|
span.addEvent("exception", {
|
|
1213
1477
|
"exception.type": "Message",
|
|
1214
|
-
"exception.message":
|
|
1215
|
-
...stack ? { "exception.stacktrace": stack } : {},
|
|
1478
|
+
"exception.message": safeMessage,
|
|
1479
|
+
...stack ? { "exception.stacktrace": activeRedactor.text(stack) } : {},
|
|
1216
1480
|
"autter.severity": severity
|
|
1217
1481
|
});
|
|
1218
|
-
span.setStatus({ code:
|
|
1482
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message: safeMessage });
|
|
1219
1483
|
span.end();
|
|
1220
1484
|
}
|
|
1221
1485
|
function reportOutcome2(name, message, attributes) {
|
|
1222
|
-
errorTraceBuffer
|
|
1223
|
-
telemetryStats.markCaptured();
|
|
1224
|
-
const activeSpan =
|
|
1225
|
-
const reuseActive = activeSpan
|
|
1486
|
+
_optionalChain([errorTraceBuffer, 'optionalAccess', _63 => _63.retainActiveTrace, 'call', _64 => _64()]);
|
|
1487
|
+
_chunkGI47WGRRcjs.telemetryStats.markCaptured();
|
|
1488
|
+
const activeSpan = _api.trace.getActiveSpan();
|
|
1489
|
+
const reuseActive = _optionalChain([activeSpan, 'optionalAccess', _65 => _65.isRecording, 'call', _66 => _66()]) === true;
|
|
1226
1490
|
const span = reuseActive ? activeSpan : errorTracer.startSpan("OutcomeFailure");
|
|
1227
1491
|
const safeOutcome = activeRedactor({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
1228
|
-
const safeName = String(safeOutcome["autter.outcome.name"]
|
|
1229
|
-
const safeMessage = String(safeOutcome["autter.outcome.message"]
|
|
1492
|
+
const safeName = String(_nullishCoalesce(safeOutcome["autter.outcome.name"], () => ( "operation")));
|
|
1493
|
+
const safeMessage = String(_nullishCoalesce(safeOutcome["autter.outcome.message"], () => ( "failed")));
|
|
1230
1494
|
span.addEvent("autter.outcome", {
|
|
1231
1495
|
...activeRedactor(attributes),
|
|
1232
1496
|
"autter.outcome.status": "error",
|
|
1233
1497
|
"autter.outcome.name": safeName,
|
|
1234
1498
|
"autter.outcome.message": safeMessage
|
|
1235
1499
|
});
|
|
1236
|
-
span.setStatus({ code:
|
|
1500
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message: safeMessage });
|
|
1237
1501
|
if (!reuseActive) span.end();
|
|
1238
1502
|
}
|
|
1503
|
+
_chunkP4VRTFAVcjs.configureRuntimeLogger.call(void 0, {
|
|
1504
|
+
endpoint,
|
|
1505
|
+
apiKey: options.apiKey,
|
|
1506
|
+
service: options.service,
|
|
1507
|
+
environment,
|
|
1508
|
+
distro,
|
|
1509
|
+
release: options.release,
|
|
1510
|
+
options: options.logging,
|
|
1511
|
+
redact: activeRedactor,
|
|
1512
|
+
run: (name, fn, attributes, links) => runWithSpan(processTracer, name, fn, activeRedactor(attributes), links),
|
|
1513
|
+
reportOutcome: reportOutcome2
|
|
1514
|
+
});
|
|
1515
|
+
hookRequests = _optionalChain([options, 'access', _67 => _67.logging, 'optionalAccess', _68 => _68.requests]) === true;
|
|
1239
1516
|
if (options.captureGlobalErrors !== false) {
|
|
1240
1517
|
process.on("uncaughtExceptionMonitor", (err) => {
|
|
1241
1518
|
captureException2(err, { "autter.unhandled": true });
|
|
@@ -1246,6 +1523,7 @@ function initAutterServer(options) {
|
|
|
1246
1523
|
const flushTarget = {
|
|
1247
1524
|
forceFlush: async () => {
|
|
1248
1525
|
const results = await Promise.allSettled([
|
|
1526
|
+
_chunkP4VRTFAVcjs.flushRuntimeLogs.call(void 0, ),
|
|
1249
1527
|
Promise.resolve().then(() => alwaysOnProvider.forceFlush()),
|
|
1250
1528
|
Promise.resolve().then(() => mainSpanProcessor.forceFlush()),
|
|
1251
1529
|
...errorTraceBuffer ? [Promise.resolve().then(() => errorTraceBuffer.forceFlush())] : [],
|
|
@@ -1259,10 +1537,10 @@ function initAutterServer(options) {
|
|
|
1259
1537
|
}
|
|
1260
1538
|
}
|
|
1261
1539
|
};
|
|
1262
|
-
registerFlushTarget("active-server", flushTarget);
|
|
1540
|
+
_chunkGI47WGRRcjs.registerFlushTarget.call(void 0, "active-server", flushTarget);
|
|
1263
1541
|
let autoFlushHandle = null;
|
|
1264
1542
|
if (options.autoFlush !== false) {
|
|
1265
|
-
autoFlushHandle = installAutterAutoFlush();
|
|
1543
|
+
autoFlushHandle = _chunkGI47WGRRcjs.installAutterAutoFlush.call(void 0, );
|
|
1266
1544
|
}
|
|
1267
1545
|
const server = {
|
|
1268
1546
|
captureException: captureException2,
|
|
@@ -1272,14 +1550,17 @@ function initAutterServer(options) {
|
|
|
1272
1550
|
withLlmCall: (info, fn) => runLlmSpan(llmTracer, info, fn),
|
|
1273
1551
|
trackLlmCall: (call) => recordLlmCall(llmTracer, call),
|
|
1274
1552
|
shutdown: async () => {
|
|
1275
|
-
|
|
1553
|
+
const logShutdown = await Promise.allSettled([_chunkP4VRTFAVcjs.shutdownRuntimeLogger.call(void 0, )]);
|
|
1554
|
+
hookRequests = false;
|
|
1555
|
+
_optionalChain([stopMemoryMetrics, 'optionalCall', _69 => _69()]);
|
|
1276
1556
|
active = null;
|
|
1277
1557
|
activeAlwaysOnProvider = null;
|
|
1278
|
-
autoFlushHandle
|
|
1558
|
+
_optionalChain([autoFlushHandle, 'optionalAccess', _70 => _70.dispose, 'call', _71 => _71()]);
|
|
1279
1559
|
autoFlushHandle = null;
|
|
1280
|
-
unregisterFlushTargets();
|
|
1281
|
-
telemetryStats.markAllFlushed();
|
|
1560
|
+
_chunkGI47WGRRcjs.unregisterFlushTargets.call(void 0, );
|
|
1561
|
+
_chunkGI47WGRRcjs.telemetryStats.markAllFlushed();
|
|
1282
1562
|
await Promise.allSettled([alwaysOnProvider.shutdown(), sdk.shutdown()]);
|
|
1563
|
+
if (_optionalChain([logShutdown, 'access', _72 => _72[0], 'optionalAccess', _73 => _73.status]) === "rejected") throw logShutdown[0].reason;
|
|
1283
1564
|
}
|
|
1284
1565
|
};
|
|
1285
1566
|
active = server;
|
|
@@ -1291,69 +1572,88 @@ function captureException(error, attributes) {
|
|
|
1291
1572
|
active.captureException(error, attributes);
|
|
1292
1573
|
return;
|
|
1293
1574
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1575
|
+
if (loggerOnlyCapture) {
|
|
1576
|
+
loggerOnlyCapture(error, attributes);
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
markCaptured(error);
|
|
1580
|
+
_chunkP4VRTFAVcjs.noteOperationError.call(void 0, error);
|
|
1581
|
+
_chunkP4VRTFAVcjs.notifyException.call(void 0, error, attributes);
|
|
1582
|
+
const span = _api.trace.getTracer("autter-errors").startSpan(error instanceof Error ? error.name : "Error", {
|
|
1583
|
+
attributes: activeRedactor(attributes)
|
|
1299
1584
|
});
|
|
1585
|
+
recordError(span, error);
|
|
1300
1586
|
span.end();
|
|
1301
1587
|
}
|
|
1588
|
+
var loggerOnlyCapture = null;
|
|
1589
|
+
function setLoggerOnlyCapture(fn) {
|
|
1590
|
+
loggerOnlyCapture = fn;
|
|
1591
|
+
}
|
|
1592
|
+
function serverActive() {
|
|
1593
|
+
return active !== null;
|
|
1594
|
+
}
|
|
1595
|
+
setRequestExceptionCapturer((error) => captureException(error));
|
|
1302
1596
|
function withProcessSpan(name, fn, attributes) {
|
|
1303
1597
|
if (active) return active.withProcessSpan(name, fn, attributes);
|
|
1304
|
-
return runWithSpan(
|
|
1598
|
+
return runWithSpan(
|
|
1599
|
+
_api.trace.getTracer("autter-processes"),
|
|
1600
|
+
name,
|
|
1601
|
+
fn,
|
|
1602
|
+
activeRedactor(attributes)
|
|
1603
|
+
);
|
|
1305
1604
|
}
|
|
1306
1605
|
function withLlmCall(info, fn) {
|
|
1307
1606
|
if (active) return active.withLlmCall(info, fn);
|
|
1308
|
-
return runLlmSpan(
|
|
1607
|
+
return runLlmSpan(_api.trace.getTracer("autter-llm"), info, fn);
|
|
1309
1608
|
}
|
|
1310
1609
|
function trackLlmCall(call) {
|
|
1311
1610
|
if (active) {
|
|
1312
1611
|
active.trackLlmCall(call);
|
|
1313
1612
|
return;
|
|
1314
1613
|
}
|
|
1315
|
-
recordLlmCall(
|
|
1614
|
+
recordLlmCall(_api.trace.getTracer("autter-llm"), call);
|
|
1316
1615
|
}
|
|
1317
1616
|
function captureMessage(message, severity = "warning", attributes) {
|
|
1318
1617
|
if (active) {
|
|
1319
1618
|
active.captureMessage(message, severity, attributes);
|
|
1320
1619
|
return;
|
|
1321
1620
|
}
|
|
1322
|
-
const
|
|
1323
|
-
|
|
1621
|
+
const safeMessage = activeRedactor.text(message);
|
|
1622
|
+
const span = _api.trace.getTracer("autter-errors").startSpan("Message", {
|
|
1623
|
+
attributes: { "autter.severity": severity, ...activeRedactor(attributes) }
|
|
1324
1624
|
});
|
|
1325
1625
|
span.addEvent("exception", {
|
|
1326
1626
|
"exception.type": "Message",
|
|
1327
|
-
"exception.message":
|
|
1627
|
+
"exception.message": safeMessage,
|
|
1328
1628
|
"autter.severity": severity
|
|
1329
1629
|
});
|
|
1330
|
-
span.setStatus({ code:
|
|
1630
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message: safeMessage });
|
|
1331
1631
|
span.end();
|
|
1332
1632
|
}
|
|
1333
1633
|
function reportOutcome(name, message, attributes) {
|
|
1334
1634
|
if (active) return active.reportOutcome(name, message, attributes);
|
|
1335
|
-
const span =
|
|
1336
|
-
const safeOutcome = redactAttributes({ "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
1337
|
-
const safeName = String(safeOutcome["autter.outcome.name"]
|
|
1338
|
-
const safeMessage = String(safeOutcome["autter.outcome.message"]
|
|
1635
|
+
const span = _api.trace.getTracer("autter-outcomes").startSpan("OutcomeFailure");
|
|
1636
|
+
const safeOutcome = _chunkP4VRTFAVcjs.redactAttributes.call(void 0, { "autter.outcome.name": name.slice(0, 200), "autter.outcome.message": message.slice(0, 1e3) });
|
|
1637
|
+
const safeName = String(_nullishCoalesce(safeOutcome["autter.outcome.name"], () => ( "operation")));
|
|
1638
|
+
const safeMessage = String(_nullishCoalesce(safeOutcome["autter.outcome.message"], () => ( "failed")));
|
|
1339
1639
|
span.addEvent("autter.outcome", {
|
|
1340
|
-
...redactAttributes(attributes),
|
|
1640
|
+
..._chunkP4VRTFAVcjs.redactAttributes.call(void 0, attributes),
|
|
1341
1641
|
"autter.outcome.status": "error",
|
|
1342
1642
|
"autter.outcome.name": safeName,
|
|
1343
1643
|
"autter.outcome.message": safeMessage
|
|
1344
1644
|
});
|
|
1345
|
-
span.setStatus({ code:
|
|
1645
|
+
span.setStatus({ code: _api.SpanStatusCode.ERROR, message: safeMessage });
|
|
1346
1646
|
span.end();
|
|
1347
1647
|
}
|
|
1348
1648
|
function makeSafeCapture(options) {
|
|
1349
|
-
const clean = (attributes) => attributes ? { ...redactAttributes(attributes, options) } : void 0;
|
|
1649
|
+
const clean = (attributes) => attributes ? { ..._chunkP4VRTFAVcjs.redactAttributes.call(void 0, attributes, options) } : void 0;
|
|
1350
1650
|
return {
|
|
1351
1651
|
captureException: (error, attributes) => captureException(error, clean(attributes)),
|
|
1352
|
-
captureMessage: (message, severity, attributes) => captureMessage(message, severity
|
|
1652
|
+
captureMessage: (message, severity, attributes) => captureMessage(message, _nullishCoalesce(severity, () => ( "warning")), clean(attributes))
|
|
1353
1653
|
};
|
|
1354
1654
|
}
|
|
1355
1655
|
function alwaysOnTracer(name) {
|
|
1356
|
-
return activeAlwaysOnProvider ? activeAlwaysOnProvider.getTracer(name) :
|
|
1656
|
+
return activeAlwaysOnProvider ? activeAlwaysOnProvider.getTracer(name) : _api.trace.getTracer(name);
|
|
1357
1657
|
}
|
|
1358
1658
|
function autterLlmTracer() {
|
|
1359
1659
|
return alwaysOnTracer("autter-llm");
|
|
@@ -1373,7 +1673,7 @@ async function emitLlmSelftestTrace() {
|
|
|
1373
1673
|
attributes: { "autter.selftest": true }
|
|
1374
1674
|
},
|
|
1375
1675
|
(llm) => {
|
|
1376
|
-
traceId =
|
|
1676
|
+
traceId = _nullishCoalesce(_optionalChain([_api.trace, 'access', _74 => _74.getActiveSpan, 'call', _75 => _75(), 'optionalAccess', _76 => _76.spanContext, 'call', _77 => _77(), 'access', _78 => _78.traceId]), () => ( ""));
|
|
1377
1677
|
llm.setUsage({ inputTokens: 1, outputTokens: 1 });
|
|
1378
1678
|
llm.setCost(0);
|
|
1379
1679
|
}
|
|
@@ -1383,7 +1683,10 @@ async function emitLlmSelftestTrace() {
|
|
|
1383
1683
|
}
|
|
1384
1684
|
|
|
1385
1685
|
// src/llm-instrument.ts
|
|
1386
|
-
|
|
1686
|
+
|
|
1687
|
+
|
|
1688
|
+
|
|
1689
|
+
|
|
1387
1690
|
var CALL_METHODS = /* @__PURE__ */ new Set([
|
|
1388
1691
|
"create",
|
|
1389
1692
|
// openai chat/completions/embeddings/responses, anthropic messages
|
|
@@ -1398,15 +1701,15 @@ var CALL_METHODS = /* @__PURE__ */ new Set([
|
|
|
1398
1701
|
// openai beta structured outputs
|
|
1399
1702
|
]);
|
|
1400
1703
|
function detectProvider(client) {
|
|
1401
|
-
const name = client.constructor
|
|
1704
|
+
const name = _nullishCoalesce(_optionalChain([client, 'access', _79 => _79.constructor, 'optionalAccess', _80 => _80.name, 'optionalAccess', _81 => _81.toLowerCase, 'call', _82 => _82()]), () => ( ""));
|
|
1402
1705
|
for (const known of ["openai", "anthropic", "mistral", "groq", "cohere"]) {
|
|
1403
1706
|
if (name.includes(known)) return known;
|
|
1404
1707
|
}
|
|
1405
1708
|
if (name.includes("google") || name.includes("genai")) return "google";
|
|
1406
1709
|
const baseUrl = String(
|
|
1407
|
-
client.baseURL
|
|
1710
|
+
_nullishCoalesce(_nullishCoalesce(client.baseURL, () => ( client.baseUrl)), () => ( ""))
|
|
1408
1711
|
);
|
|
1409
|
-
const host = baseUrl.match(/https?:\/\/([^/]+)/)
|
|
1712
|
+
const host = _nullishCoalesce(_optionalChain([baseUrl, 'access', _83 => _83.match, 'call', _84 => _84(/https?:\/\/([^/]+)/), 'optionalAccess', _85 => _85[1]]), () => ( ""));
|
|
1410
1713
|
if (host.includes("openai")) return "openai";
|
|
1411
1714
|
if (host.includes("anthropic")) return "anthropic";
|
|
1412
1715
|
if (host.includes("googleapis")) return "google";
|
|
@@ -1416,17 +1719,28 @@ function detectProvider(client) {
|
|
|
1416
1719
|
}
|
|
1417
1720
|
function extractUsage(result) {
|
|
1418
1721
|
const r = result;
|
|
1419
|
-
const usage = r
|
|
1420
|
-
const meta = r
|
|
1421
|
-
const
|
|
1422
|
-
const
|
|
1423
|
-
const
|
|
1722
|
+
const usage = _nullishCoalesce(_optionalChain([r, 'optionalAccess', _86 => _86.usage]), () => ( _optionalChain([r, 'optionalAccess', _87 => _87.message, 'optionalAccess', _88 => _88.usage])));
|
|
1723
|
+
const meta = _optionalChain([r, 'optionalAccess', _89 => _89.usageMetadata]);
|
|
1724
|
+
const details = _optionalChain([usage, 'optionalAccess', _90 => _90.prompt_tokens_details]);
|
|
1725
|
+
const cached = _nullishCoalesce(_nullishCoalesce(_optionalChain([usage, 'optionalAccess', _91 => _91.cache_read_input_tokens]), () => ( (typeof _optionalChain([details, 'optionalAccess', _92 => _92.cached_tokens]) === "number" ? details.cached_tokens : void 0))), () => ( _optionalChain([meta, 'optionalAccess', _93 => _93.cachedContentTokenCount])));
|
|
1726
|
+
const input = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([usage, 'optionalAccess', _94 => _94.prompt_tokens]), () => ( _optionalChain([usage, 'optionalAccess', _95 => _95.input_tokens]))), () => ( _optionalChain([meta, 'optionalAccess', _96 => _96.promptTokenCount]))), () => ( void 0));
|
|
1727
|
+
const output = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([usage, 'optionalAccess', _97 => _97.completion_tokens]), () => ( _optionalChain([usage, 'optionalAccess', _98 => _98.output_tokens]))), () => ( _optionalChain([meta, 'optionalAccess', _99 => _99.candidatesTokenCount]))), () => ( void 0));
|
|
1728
|
+
const responseModel = _nullishCoalesce(_optionalChain([r, 'optionalAccess', _100 => _100.model]), () => ( _optionalChain([r, 'optionalAccess', _101 => _101.modelVersion])));
|
|
1424
1729
|
return {
|
|
1425
1730
|
inputTokens: typeof input === "number" ? input : void 0,
|
|
1426
1731
|
outputTokens: typeof output === "number" ? output : void 0,
|
|
1732
|
+
cacheReadTokens: typeof cached === "number" ? cached : void 0,
|
|
1427
1733
|
responseModel: typeof responseModel === "string" ? responseModel : void 0
|
|
1428
1734
|
};
|
|
1429
1735
|
}
|
|
1736
|
+
function rollUp(model, usage) {
|
|
1737
|
+
_chunkP4VRTFAVcjs.recordOperationAiUsage.call(void 0, {
|
|
1738
|
+
model: _nullishCoalesce(usage.responseModel, () => ( model)),
|
|
1739
|
+
...usage.inputTokens !== void 0 ? { inputTokens: usage.inputTokens } : {},
|
|
1740
|
+
...usage.outputTokens !== void 0 ? { outputTokens: usage.outputTokens } : {},
|
|
1741
|
+
...usage.cacheReadTokens !== void 0 ? { cacheReadTokens: usage.cacheReadTokens } : {}
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1430
1744
|
function applyUsage(span, usage) {
|
|
1431
1745
|
if (usage.inputTokens !== void 0) {
|
|
1432
1746
|
span.setAttribute("gen_ai.usage.input_tokens", usage.inputTokens);
|
|
@@ -1439,14 +1753,10 @@ function applyUsage(span, usage) {
|
|
|
1439
1753
|
}
|
|
1440
1754
|
}
|
|
1441
1755
|
function endWithError(span, err) {
|
|
1442
|
-
|
|
1443
|
-
span.setStatus({
|
|
1444
|
-
code: import_api3.SpanStatusCode.ERROR,
|
|
1445
|
-
message: err instanceof Error ? err.message : String(err)
|
|
1446
|
-
});
|
|
1756
|
+
recordError(span, err);
|
|
1447
1757
|
span.end();
|
|
1448
1758
|
}
|
|
1449
|
-
function wrapStream(stream, span) {
|
|
1759
|
+
function wrapStream(stream, span, model) {
|
|
1450
1760
|
let ended = false;
|
|
1451
1761
|
const seen = {
|
|
1452
1762
|
inputTokens: void 0,
|
|
@@ -1457,11 +1767,12 @@ function wrapStream(stream, span) {
|
|
|
1457
1767
|
if (ended) return;
|
|
1458
1768
|
ended = true;
|
|
1459
1769
|
applyUsage(span, seen);
|
|
1770
|
+
rollUp(model, seen);
|
|
1460
1771
|
span.setAttribute("autter.llm.streamed", true);
|
|
1461
1772
|
if (err !== void 0) {
|
|
1462
1773
|
endWithError(span, err);
|
|
1463
1774
|
} else {
|
|
1464
|
-
span.setStatus({ code:
|
|
1775
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
1465
1776
|
span.end();
|
|
1466
1777
|
}
|
|
1467
1778
|
};
|
|
@@ -1478,6 +1789,7 @@ function wrapStream(stream, span) {
|
|
|
1478
1789
|
const usage = extractUsage(step.value);
|
|
1479
1790
|
if (usage.inputTokens !== void 0) seen.inputTokens = usage.inputTokens;
|
|
1480
1791
|
if (usage.outputTokens !== void 0) seen.outputTokens = usage.outputTokens;
|
|
1792
|
+
if (usage.cacheReadTokens !== void 0) seen.cacheReadTokens = usage.cacheReadTokens;
|
|
1481
1793
|
if (usage.responseModel) seen.responseModel = usage.responseModel;
|
|
1482
1794
|
} else {
|
|
1483
1795
|
finish();
|
|
@@ -1506,24 +1818,24 @@ function wrapStream(stream, span) {
|
|
|
1506
1818
|
});
|
|
1507
1819
|
}
|
|
1508
1820
|
function instrumentLlmClient(client, options) {
|
|
1509
|
-
const provider = (options
|
|
1821
|
+
const provider = (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _102 => _102.provider]), () => ( detectProvider(client)))).toLowerCase();
|
|
1510
1822
|
const proxied = /* @__PURE__ */ new WeakMap();
|
|
1511
1823
|
function resolveUserId() {
|
|
1512
|
-
return typeof options
|
|
1824
|
+
return typeof _optionalChain([options, 'optionalAccess', _103 => _103.userId]) === "function" ? options.userId() : _optionalChain([options, 'optionalAccess', _104 => _104.userId]);
|
|
1513
1825
|
}
|
|
1514
1826
|
function traceCall(fn, self, callPath, args) {
|
|
1515
1827
|
const request = args[0];
|
|
1516
1828
|
const operation = /embed/i.test(callPath) ? "embeddings" : "chat";
|
|
1517
1829
|
const userId = resolveUserId();
|
|
1518
1830
|
const span = autterLlmTracer().startSpan(`${operation} ${request.model}`, {
|
|
1519
|
-
kind:
|
|
1831
|
+
kind: _api.SpanKind.CLIENT,
|
|
1520
1832
|
attributes: {
|
|
1521
1833
|
"gen_ai.operation.name": operation,
|
|
1522
1834
|
"gen_ai.provider.name": provider,
|
|
1523
1835
|
"gen_ai.system": provider,
|
|
1524
1836
|
"gen_ai.request.model": request.model,
|
|
1525
1837
|
...userId ? { "autter.user_id": userId } : {},
|
|
1526
|
-
...options
|
|
1838
|
+
...redactWithActive(_optionalChain([options, 'optionalAccess', _105 => _105.attributes]))
|
|
1527
1839
|
}
|
|
1528
1840
|
});
|
|
1529
1841
|
let result;
|
|
@@ -1535,20 +1847,24 @@ function instrumentLlmClient(client, options) {
|
|
|
1535
1847
|
}
|
|
1536
1848
|
if (!(result instanceof Promise)) {
|
|
1537
1849
|
if (result && typeof result === "object" && Symbol.asyncIterator in result) {
|
|
1538
|
-
return wrapStream(result, span);
|
|
1850
|
+
return wrapStream(result, span, request.model);
|
|
1539
1851
|
}
|
|
1540
|
-
|
|
1541
|
-
span
|
|
1852
|
+
const usage = extractUsage(result);
|
|
1853
|
+
applyUsage(span, usage);
|
|
1854
|
+
rollUp(request.model, usage);
|
|
1855
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
1542
1856
|
span.end();
|
|
1543
1857
|
return result;
|
|
1544
1858
|
}
|
|
1545
1859
|
return result.then(
|
|
1546
1860
|
(resolved) => {
|
|
1547
1861
|
if (resolved && typeof resolved === "object" && Symbol.asyncIterator in resolved) {
|
|
1548
|
-
return wrapStream(resolved, span);
|
|
1862
|
+
return wrapStream(resolved, span, request.model);
|
|
1549
1863
|
}
|
|
1550
|
-
|
|
1551
|
-
span
|
|
1864
|
+
const usage = extractUsage(resolved);
|
|
1865
|
+
applyUsage(span, usage);
|
|
1866
|
+
rollUp(request.model, usage);
|
|
1867
|
+
span.setStatus({ code: _api.SpanStatusCode.OK });
|
|
1552
1868
|
span.end();
|
|
1553
1869
|
return resolved;
|
|
1554
1870
|
},
|
|
@@ -1596,11 +1912,11 @@ function instrumentLlmClient(client, options) {
|
|
|
1596
1912
|
}
|
|
1597
1913
|
|
|
1598
1914
|
// src/caught-exceptions.ts
|
|
1599
|
-
var
|
|
1915
|
+
var _inspector = require('inspector'); var _inspector2 = _interopRequireDefault(_inspector);
|
|
1600
1916
|
function startCaughtExceptionSampler(options = {}) {
|
|
1601
|
-
const rate = Math.max(0, Math.min(1, options.sampleRate
|
|
1602
|
-
const cap = Math.max(1, Math.min(100, options.maxPerMinute
|
|
1603
|
-
const session = new
|
|
1917
|
+
const rate = Math.max(0, Math.min(1, _nullishCoalesce(options.sampleRate, () => ( 0.01))));
|
|
1918
|
+
const cap = Math.max(1, Math.min(100, _nullishCoalesce(options.maxPerMinute, () => ( 10))));
|
|
1919
|
+
const session = new _inspector2.default.Session();
|
|
1604
1920
|
let active2 = true;
|
|
1605
1921
|
let minute = 0;
|
|
1606
1922
|
let sent = 0;
|
|
@@ -1616,7 +1932,7 @@ function startCaughtExceptionSampler(options = {}) {
|
|
|
1616
1932
|
}
|
|
1617
1933
|
if (sent >= cap || Math.random() >= rate) return;
|
|
1618
1934
|
sent++;
|
|
1619
|
-
const frames = message.params.callFrames.slice(0, 8).filter((frame) => frame.url && !frame.url.startsWith("node:")).map((frame) => ` at ${frame.functionName || "anonymous"} (${frame.url.split("?")[0]}:${frame.location.lineNumber + 1}:${(frame.location.columnNumber
|
|
1935
|
+
const frames = message.params.callFrames.slice(0, 8).filter((frame) => frame.url && !frame.url.startsWith("node:")).map((frame) => ` at ${frame.functionName || "anonymous"} (${frame.url.split("?")[0]}:${frame.location.lineNumber + 1}:${(_nullishCoalesce(frame.location.columnNumber, () => ( 0))) + 1})`);
|
|
1620
1936
|
if (!frames.length) return;
|
|
1621
1937
|
const error = new Error("Sampled caught exception");
|
|
1622
1938
|
error.name = "CaughtException";
|
|
@@ -1638,22 +1954,245 @@ ${frames.join("\n")}`;
|
|
|
1638
1954
|
});
|
|
1639
1955
|
} };
|
|
1640
1956
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
}
|
|
1957
|
+
|
|
1958
|
+
// src/logging-only.ts
|
|
1959
|
+
|
|
1960
|
+
|
|
1961
|
+
|
|
1962
|
+
|
|
1963
|
+
var activeLogging = null;
|
|
1964
|
+
function initAutterLogging(options) {
|
|
1965
|
+
if (activeLogging) return activeLogging;
|
|
1966
|
+
if (serverActive()) {
|
|
1967
|
+
console.warn(
|
|
1968
|
+
"[autter-runtime] initAutterLogging() ignored: initAutterServer() is already active and includes logging"
|
|
1969
|
+
);
|
|
1970
|
+
return {
|
|
1971
|
+
captureException,
|
|
1972
|
+
flush: _chunkP4VRTFAVcjs.flushRuntimeLogs,
|
|
1973
|
+
shutdown: async () => {
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
if (_chunkGI47WGRRcjs.isDebugEnabled.call(void 0, ) || options.debug === true) _chunkGI47WGRRcjs.setDebugMode.call(void 0, true);
|
|
1978
|
+
const endpoint = (_nullishCoalesce(options.endpoint, () => ( "https://otlp.autter.dev"))).replace(/\/$/, "");
|
|
1979
|
+
const environment = _nullishCoalesce(_nullishCoalesce(options.environment, () => ( process.env.NODE_ENV)), () => ( "production"));
|
|
1980
|
+
const redact = _chunkP4VRTFAVcjs.makeRedactor.call(void 0, _nullishCoalesce(options.redactAttributes, () => ( true)));
|
|
1981
|
+
const mode = _nullishCoalesce(options.exceptions, () => ( "auto"));
|
|
1982
|
+
_chunkGI47WGRRcjs.debugLog.call(void 0, `initialising logger-only service=${options.service} endpoint=${endpoint}`);
|
|
1983
|
+
function captureException2(error, attributes) {
|
|
1984
|
+
markCaptured(error);
|
|
1985
|
+
const redacted = redact(attributes);
|
|
1986
|
+
const span = _api.trace.getActiveSpan();
|
|
1987
|
+
if (mode === "auto" && _optionalChain([span, 'optionalAccess', _106 => _106.isRecording, 'call', _107 => _107()])) {
|
|
1988
|
+
_chunkP4VRTFAVcjs.noteOperationError.call(void 0, error);
|
|
1989
|
+
_chunkP4VRTFAVcjs.notifyException.call(void 0, error, redacted);
|
|
1990
|
+
span.setAttributes({ "autter.severity": "error", ...redacted, ...structuredErrorAttributes(error) });
|
|
1991
|
+
const declared = _chunkP4VRTFAVcjs.errorAttributes.call(void 0, error);
|
|
1992
|
+
if (error instanceof Error) {
|
|
1993
|
+
span.addEvent("exception", {
|
|
1994
|
+
"exception.type": error.name,
|
|
1995
|
+
"exception.message": error.message,
|
|
1996
|
+
...error.stack ? { "exception.stacktrace": error.stack } : {},
|
|
1997
|
+
...declared
|
|
1998
|
+
});
|
|
1999
|
+
} else {
|
|
2000
|
+
span.addEvent("exception", {
|
|
2001
|
+
"exception.type": "Error",
|
|
2002
|
+
"exception.message": String(error),
|
|
2003
|
+
...declared
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
span.setStatus({
|
|
2007
|
+
code: _api.SpanStatusCode.ERROR,
|
|
2008
|
+
message: error instanceof Error ? error.message : String(error)
|
|
2009
|
+
});
|
|
2010
|
+
return;
|
|
2011
|
+
}
|
|
2012
|
+
_chunkP4VRTFAVcjs.notifyException.call(void 0, error, redacted);
|
|
2013
|
+
_chunkP4VRTFAVcjs.captureExceptionAsLog.call(void 0, error, redacted);
|
|
2014
|
+
}
|
|
2015
|
+
const captured = /* @__PURE__ */ new WeakSet();
|
|
2016
|
+
_chunkP4VRTFAVcjs.configureRuntimeLogger.call(void 0, {
|
|
2017
|
+
endpoint,
|
|
2018
|
+
apiKey: _nullishCoalesce(options.apiKey, () => ( "")),
|
|
2019
|
+
service: options.service,
|
|
2020
|
+
environment,
|
|
2021
|
+
...options.release ? { release: options.release } : {},
|
|
2022
|
+
...options.logging ? { options: options.logging } : {},
|
|
2023
|
+
redact,
|
|
2024
|
+
reportOutcome: (name, message, attributes) => {
|
|
2025
|
+
_chunkP4VRTFAVcjs.runtimeLogger.error(message, {
|
|
2026
|
+
...attributes,
|
|
2027
|
+
"autter.outcome.name": name.slice(0, 200),
|
|
2028
|
+
"autter.outcome.message": message.slice(0, 1e3)
|
|
2029
|
+
});
|
|
2030
|
+
},
|
|
2031
|
+
captureThrown: (error) => {
|
|
2032
|
+
if (error && typeof error === "object") {
|
|
2033
|
+
if (captured.has(error)) return;
|
|
2034
|
+
captured.add(error);
|
|
2035
|
+
}
|
|
2036
|
+
captureException2(error);
|
|
2037
|
+
}
|
|
2038
|
+
});
|
|
2039
|
+
setLoggerOnlyCapture(captureException2);
|
|
2040
|
+
const onCrash = (error) => captureException2(error, { "autter.unhandled": true });
|
|
2041
|
+
if (options.captureGlobalErrors !== false)
|
|
2042
|
+
process.on("uncaughtExceptionMonitor", onCrash);
|
|
2043
|
+
_chunkGI47WGRRcjs.registerFlushTarget.call(void 0, "logging", { forceFlush: () => _chunkP4VRTFAVcjs.flushRuntimeLogs.call(void 0, ) });
|
|
2044
|
+
let autoFlushHandle = options.autoFlush === false ? null : _chunkGI47WGRRcjs.installAutterAutoFlush.call(void 0, );
|
|
2045
|
+
const handle = {
|
|
2046
|
+
captureException: captureException2,
|
|
2047
|
+
flush: _chunkP4VRTFAVcjs.flushRuntimeLogs,
|
|
2048
|
+
shutdown: async () => {
|
|
2049
|
+
process.off("uncaughtExceptionMonitor", onCrash);
|
|
2050
|
+
setLoggerOnlyCapture(null);
|
|
2051
|
+
_optionalChain([autoFlushHandle, 'optionalAccess', _108 => _108.dispose, 'call', _109 => _109()]);
|
|
2052
|
+
autoFlushHandle = null;
|
|
2053
|
+
_chunkGI47WGRRcjs.unregisterFlushTargets.call(void 0, );
|
|
2054
|
+
activeLogging = null;
|
|
2055
|
+
await _chunkP4VRTFAVcjs.shutdownRuntimeLogger.call(void 0, );
|
|
2056
|
+
}
|
|
2057
|
+
};
|
|
2058
|
+
activeLogging = handle;
|
|
2059
|
+
return handle;
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
// src/enrichers.ts
|
|
2063
|
+
function headerOf(req, name) {
|
|
2064
|
+
const headers = _optionalChain([req, 'optionalAccess', _110 => _110.headers]);
|
|
2065
|
+
if (!headers) return void 0;
|
|
2066
|
+
if (typeof headers.get === "function") {
|
|
2067
|
+
return _nullishCoalesce(headers.get(name), () => ( void 0));
|
|
2068
|
+
}
|
|
2069
|
+
const value = headers[name.toLowerCase()];
|
|
2070
|
+
if (Array.isArray(value)) return value[0] === void 0 ? void 0 : String(value[0]);
|
|
2071
|
+
return value === void 0 || value === null ? void 0 : String(value);
|
|
2072
|
+
}
|
|
2073
|
+
function enrichUserAgent() {
|
|
2074
|
+
return (event, { req }) => {
|
|
2075
|
+
const ua = headerOf(req, "user-agent");
|
|
2076
|
+
if (!ua) return;
|
|
2077
|
+
const info = _chunkP4VRTFAVcjs.parseUserAgent.call(void 0, ua);
|
|
2078
|
+
if (info.browser) event.attributes["user_agent.browser"] = info.browser;
|
|
2079
|
+
if (info.os) event.attributes["user_agent.os"] = info.os;
|
|
2080
|
+
event.attributes["user_agent.device"] = info.device;
|
|
2081
|
+
event.attributes["user_agent.bot"] = info.bot;
|
|
2082
|
+
};
|
|
2083
|
+
}
|
|
2084
|
+
function enrichRequestSize() {
|
|
2085
|
+
return (event, { req, res }) => {
|
|
2086
|
+
const request = Number(headerOf(req, "content-length"));
|
|
2087
|
+
if (Number.isFinite(request) && request >= 0)
|
|
2088
|
+
event.attributes["http.request.body.size"] = request;
|
|
2089
|
+
const raw = _optionalChain([res, 'optionalAccess', _111 => _111.getHeader, 'optionalCall', _112 => _112(
|
|
2090
|
+
"content-length"
|
|
2091
|
+
)]);
|
|
2092
|
+
const response = Number(raw);
|
|
2093
|
+
if (raw !== void 0 && Number.isFinite(response) && response >= 0)
|
|
2094
|
+
event.attributes["http.response.body.size"] = response;
|
|
2095
|
+
};
|
|
2096
|
+
}
|
|
2097
|
+
var COUNTRY_HEADERS = [
|
|
2098
|
+
"cf-ipcountry",
|
|
2099
|
+
"x-vercel-ip-country",
|
|
2100
|
+
"cloudfront-viewer-country",
|
|
2101
|
+
"x-country-code",
|
|
2102
|
+
"fastly-geo-country-code"
|
|
2103
|
+
];
|
|
2104
|
+
function enrichEdgeGeo() {
|
|
2105
|
+
return (event, { req }) => {
|
|
2106
|
+
for (const name of COUNTRY_HEADERS) {
|
|
2107
|
+
const value = _optionalChain([headerOf, 'call', _113 => _113(req, name), 'optionalAccess', _114 => _114.trim, 'call', _115 => _115(), 'access', _116 => _116.toUpperCase, 'call', _117 => _117()]);
|
|
2108
|
+
if (value && /^[A-Z]{2}$/.test(value) && value !== "XX" && value !== "T1") {
|
|
2109
|
+
event.attributes["geo.country.iso_code"] = value;
|
|
2110
|
+
return;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
var REGION_VARS = [
|
|
2116
|
+
"AUTTER_REGION",
|
|
2117
|
+
"AWS_REGION",
|
|
2118
|
+
"VERCEL_REGION",
|
|
2119
|
+
"FLY_REGION",
|
|
2120
|
+
"RAILWAY_REPLICA_REGION",
|
|
2121
|
+
"GOOGLE_CLOUD_REGION",
|
|
2122
|
+
"CLOUD_RUN_REGION",
|
|
2123
|
+
"RENDER_REGION",
|
|
2124
|
+
"AZURE_REGION"
|
|
2125
|
+
];
|
|
2126
|
+
var COMMIT_VARS = [
|
|
2127
|
+
"AUTTER_COMMIT",
|
|
2128
|
+
"GIT_SHA",
|
|
2129
|
+
"GIT_COMMIT",
|
|
2130
|
+
"COMMIT_SHA",
|
|
2131
|
+
"SOURCE_COMMIT",
|
|
2132
|
+
"VERCEL_GIT_COMMIT_SHA",
|
|
2133
|
+
"GITHUB_SHA",
|
|
2134
|
+
"RENDER_GIT_COMMIT",
|
|
2135
|
+
"RAILWAY_GIT_COMMIT_SHA",
|
|
2136
|
+
"CF_PAGES_COMMIT_SHA",
|
|
2137
|
+
"HEROKU_SLUG_COMMIT",
|
|
2138
|
+
"SOURCE_VERSION"
|
|
2139
|
+
];
|
|
2140
|
+
function enrichDeployment(env = process.env) {
|
|
2141
|
+
const pick = (names) => names.map((name) => _optionalChain([env, 'access', _118 => _118[name], 'optionalAccess', _119 => _119.trim, 'call', _120 => _120()])).find((value) => value);
|
|
2142
|
+
const region = _optionalChain([pick, 'call', _121 => _121(REGION_VARS), 'optionalAccess', _122 => _122.slice, 'call', _123 => _123(0, 64)]);
|
|
2143
|
+
const commit = _optionalChain([pick, 'call', _124 => _124(COMMIT_VARS), 'optionalAccess', _125 => _125.slice, 'call', _126 => _126(0, 64)]);
|
|
2144
|
+
return (event) => {
|
|
2145
|
+
if (region) event.attributes["deployment.region"] = region;
|
|
2146
|
+
if (commit) event.attributes["deployment.commit"] = commit;
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
|
|
2151
|
+
|
|
2152
|
+
|
|
2153
|
+
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
|
|
2157
|
+
|
|
2158
|
+
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
|
|
2164
|
+
|
|
2165
|
+
|
|
2166
|
+
|
|
2167
|
+
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
|
|
2171
|
+
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
|
|
2175
|
+
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
|
|
2179
|
+
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
|
|
2183
|
+
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
|
|
2191
|
+
|
|
2192
|
+
|
|
2193
|
+
|
|
2194
|
+
|
|
2195
|
+
|
|
2196
|
+
|
|
2197
|
+
|
|
2198
|
+
exports.CODE_PATTERN = _chunkP4VRTFAVcjs.CODE_PATTERN; exports.COMPAT_MANIFEST = _chunkGI47WGRRcjs.COMPAT_MANIFEST; exports.INGESTER_VERSION_HEADER = _chunkGI47WGRRcjs.INGESTER_VERSION_HEADER; exports.RuntimeError = _chunkP4VRTFAVcjs.RuntimeError; exports.SDK_IDENTITY = _chunkGI47WGRRcjs.SDK_IDENTITY; exports.autterErrorResponse = autterErrorResponse; exports.autterFastify = autterFastify; exports.autterRequests = autterRequests; exports.captureException = captureException; exports.captureMessage = captureMessage; exports.consoleSink = _chunkP4VRTFAVcjs.consoleSink; exports.createBrowserRelayFetchHandler = createBrowserRelayFetchHandler; exports.createBrowserRelayHandler = createBrowserRelayHandler; exports.createRuntimeLogger = _chunkP4VRTFAVcjs.createRuntimeLogger; exports.defineRuntimeErrors = _chunkP4VRTFAVcjs.defineRuntimeErrors; exports.emitLlmSelftestTrace = emitLlmSelftestTrace; exports.enrichDeployment = enrichDeployment; exports.enrichEdgeGeo = enrichEdgeGeo; exports.enrichRequestSize = enrichRequestSize; exports.enrichUserAgent = enrichUserAgent; exports.errorAttributes = _chunkP4VRTFAVcjs.errorAttributes; exports.evaluateCompat = _chunkGI47WGRRcjs.evaluateCompat; exports.fetchIngesterCompat = _chunkGI47WGRRcjs.fetchIngesterCompat; exports.fileSink = _chunkP4VRTFAVcjs.fileSink; exports.flushRuntimeLogs = _chunkP4VRTFAVcjs.flushRuntimeLogs; exports.initAutterLogging = initAutterLogging; exports.initAutterServer = initAutterServer; exports.installAutterAutoFlush = _chunkGI47WGRRcjs.installAutterAutoFlush; exports.instrumentLlmClient = instrumentLlmClient; exports.isRuntimeErrorLike = _chunkP4VRTFAVcjs.isRuntimeErrorLike; exports.makeSafeCapture = makeSafeCapture; exports.otlpSink = _chunkP4VRTFAVcjs.otlpSink; exports.redactAttributes = _chunkP4VRTFAVcjs.redactAttributes; exports.redactText = _chunkP4VRTFAVcjs.redactText; exports.reportOutcome = reportOutcome; exports.runDoctor = _chunkL6SRL65Jcjs.runDoctor; exports.runInBackground = _chunkP4VRTFAVcjs.runInBackground; exports.runtimeContext = _chunkP4VRTFAVcjs.runtimeContext; exports.runtimeLogStats = _chunkP4VRTFAVcjs.runtimeLogStats; exports.runtimeLogger = _chunkP4VRTFAVcjs.runtimeLogger; exports.sanitizeBrowserPayload = sanitizeBrowserPayload; exports.startCaughtExceptionSampler = startCaughtExceptionSampler; exports.toClientError = _chunkP4VRTFAVcjs.toClientError; exports.trackLlmCall = trackLlmCall; exports.withLlmCall = withLlmCall; exports.withProcessSpan = withProcessSpan; exports.withRuntimeOperation = _chunkP4VRTFAVcjs.withRuntimeOperation; exports.withRuntimeRequest = withRuntimeRequest;
|