@autter/runtime-node 1.4.0 → 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 +106 -16
- 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 +1272 -1141
- package/dist/index.d.cts +420 -42
- package/dist/index.d.ts +420 -42
- package/dist/index.js +1083 -917
- 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.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import { b as RedactOptions, c as Redactor$1, d as RuntimeLogLevel, e as RuntimeOperationKind, f as RuntimeSink, F as FileSinkOptions, g as RuntimeLogContext, a as RuntimeOutcome, h as RuntimeCarrier } from './sinks-RFV76lF1.cjs';
|
|
3
|
+
export { i as CODE_PATTERN, j as ClientErrorBody, k as ConsoleSinkOptions, O as OtlpSinkOptions, l as RuntimeError, n as RuntimeErrorCatalog, o as RuntimeErrorDefinition, p as RuntimeErrorExtras, q as RuntimeErrorFactory, r as RuntimeErrorLike, s as RuntimeErrorOptions, R as RuntimeEvent, t as RuntimeLogContextValue, u as RuntimeSinkContext, v as consoleSink, w as defineRuntimeErrors, x as errorAttributes, y as fileSink, z as isRuntimeErrorLike, A as otlpSink, B as redactAttributes, D as redactText, E as toClientError } from './sinks-RFV76lF1.cjs';
|
|
2
4
|
import { Attributes } from '@opentelemetry/api';
|
|
3
5
|
|
|
4
6
|
/**
|
|
@@ -23,8 +25,25 @@ interface RelayOptions {
|
|
|
23
25
|
perIpRateLimit?: number | false;
|
|
24
26
|
/** Called when the async forward fails (default: console.warn). */
|
|
25
27
|
onError?: (err: unknown) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Scrub secrets/PII from browser events (message, stack, name, nested
|
|
30
|
+
* context) before they leave your server — the same patterns as
|
|
31
|
+
* `initAutterServer({ redactAttributes })`. Catches old browser SDK
|
|
32
|
+
* versions and anything the browser's lean redactor misses. Pass a
|
|
33
|
+
* RedactOptions object to add your own patterns; `false` disables.
|
|
34
|
+
* Default true.
|
|
35
|
+
*/
|
|
36
|
+
redact?: boolean | RedactOptions;
|
|
37
|
+
/**
|
|
38
|
+
* Warn once (server-side) when browser features in the forwarded events
|
|
39
|
+
* — CSP violations, network/timing capture — need a newer ingester than
|
|
40
|
+
* the one answering. Reads the ingester's version header from the forward
|
|
41
|
+
* response; never blocks the 202. Also disabled by AUTTER_COMPAT_CHECK=0.
|
|
42
|
+
* Default true.
|
|
43
|
+
*/
|
|
44
|
+
compatCheck?: boolean;
|
|
26
45
|
}
|
|
27
|
-
declare function sanitizeBrowserPayload(raw: unknown): object | null;
|
|
46
|
+
declare function sanitizeBrowserPayload(raw: unknown, redactor?: Redactor$1): object | null;
|
|
28
47
|
/**
|
|
29
48
|
* Fetch-style handler (Next.js App Router route, Remix, Hono, Bun, Deno):
|
|
30
49
|
*
|
|
@@ -43,42 +62,55 @@ declare function createBrowserRelayHandler(opts: RelayOptions): (req: IncomingMe
|
|
|
43
62
|
body?: unknown;
|
|
44
63
|
}, res: ServerResponse) => void;
|
|
45
64
|
|
|
46
|
-
|
|
65
|
+
/** Mutable view of a record handed to enrichers before redaction/bounding. */
|
|
66
|
+
interface RuntimeEnrichEvent {
|
|
67
|
+
level: RuntimeLogLevel;
|
|
68
|
+
message: string;
|
|
69
|
+
attributes: Record<string, unknown>;
|
|
70
|
+
}
|
|
71
|
+
interface RuntimeEnrichContext {
|
|
72
|
+
/** The inbound request of a request summary (Node IncomingMessage or fetch Request). */
|
|
73
|
+
req?: unknown;
|
|
74
|
+
/** The response object, when the framework exposes one. */
|
|
75
|
+
res?: unknown;
|
|
76
|
+
operation: {
|
|
77
|
+
id: string;
|
|
78
|
+
name: string;
|
|
79
|
+
kind: RuntimeOperationKind;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Adds attributes to operation/request summaries. Must be cheap; errors are ignored. */
|
|
83
|
+
type RuntimeEnricher = (event: RuntimeEnrichEvent, context: RuntimeEnrichContext) => void;
|
|
84
|
+
interface RuntimeLoggingOptions {
|
|
85
|
+
/** Print records to the console (default sinks only). Default true. */
|
|
86
|
+
console?: boolean;
|
|
87
|
+
/** Drop plain log records below this level. Summaries are always kept. */
|
|
88
|
+
minLevel?: RuntimeLogLevel;
|
|
47
89
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
90
|
+
* Fold debug/info messages logged inside an operation into its summary
|
|
91
|
+
* (`autter.operation.logs`, max 50) instead of emitting separate records;
|
|
92
|
+
* warn/error are folded AND emitted. Default true.
|
|
51
93
|
*/
|
|
52
|
-
|
|
94
|
+
inline?: boolean;
|
|
95
|
+
/** Run on every operation/request summary before redaction. */
|
|
96
|
+
enrich?: RuntimeEnricher[];
|
|
53
97
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
98
|
+
* Replace the default sinks (`[otlpSink(), consoleSink()]`, plus
|
|
99
|
+
* `fileSink()` when NODE_ENV=development).
|
|
56
100
|
*/
|
|
57
|
-
|
|
58
|
-
/** Replacement token. Default "[redacted]". */
|
|
59
|
-
mask?: string;
|
|
101
|
+
sinks?: RuntimeSink[];
|
|
60
102
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
103
|
+
* Local NDJSON files (`.autter/runtime/YYYY-MM-DD.jsonl`). Default: on only
|
|
104
|
+
* when NODE_ENV === "development". Ignored when `sinks` is set.
|
|
63
105
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
type RuntimeLogContextValue = string | number | boolean | null | undefined | RuntimeLogContextValue[] | {
|
|
74
|
-
[key: string]: RuntimeLogContextValue;
|
|
75
|
-
};
|
|
76
|
-
type RuntimeLogContext = Record<string, RuntimeLogContextValue>;
|
|
77
|
-
type RuntimeLogLevel = "debug" | "info" | "warning" | "error";
|
|
78
|
-
type RuntimeOutcome = "succeeded" | "failed" | "degraded" | "cancelled" | "pending";
|
|
79
|
-
interface RuntimeLoggingOptions {
|
|
80
|
-
console?: boolean;
|
|
81
|
-
minLevel?: RuntimeLogLevel;
|
|
106
|
+
file?: boolean | FileSinkOptions;
|
|
107
|
+
/**
|
|
108
|
+
* EXPERIMENTAL zero-code request summaries for plain `node:http` servers
|
|
109
|
+
* via the HTTP instrumentation hook (initAutterServer only). Uses
|
|
110
|
+
* AsyncLocalStorage.enterWith, which can leak context across keep-alive /
|
|
111
|
+
* pipelined requests on one socket — prefer `autterRequests()`. Default false.
|
|
112
|
+
*/
|
|
113
|
+
requests?: boolean;
|
|
82
114
|
}
|
|
83
115
|
interface RuntimeOperation {
|
|
84
116
|
readonly id: string;
|
|
@@ -86,6 +118,12 @@ interface RuntimeOperation {
|
|
|
86
118
|
outcome(status: RuntimeOutcome, message?: string): void;
|
|
87
119
|
step<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
|
|
88
120
|
}
|
|
121
|
+
interface RuntimeOperationOptions {
|
|
122
|
+
/** Carrier from `runtimeContext.carrier()` (object or JSON string): links parent op, request id and trace. */
|
|
123
|
+
from?: RuntimeCarrier | string | null;
|
|
124
|
+
/** Receives the log flush promise once the operation completes (serverless `waitUntil`). */
|
|
125
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
126
|
+
}
|
|
89
127
|
declare function runtimeLogStats(): {
|
|
90
128
|
buffered: number;
|
|
91
129
|
dropped: number;
|
|
@@ -103,8 +141,45 @@ declare const runtimeLogger: {
|
|
|
103
141
|
warn: (message: string, extra?: RuntimeLogContext) => void;
|
|
104
142
|
error: (error: unknown, extra?: RuntimeLogContext) => void;
|
|
105
143
|
};
|
|
106
|
-
/**
|
|
107
|
-
|
|
144
|
+
/**
|
|
145
|
+
* Run `fn` as a named operation: one summary record (outcome, duration,
|
|
146
|
+
* steps, context, inline messages) when it ends. Nested operations link via
|
|
147
|
+
* `autter.operation.parent_id`; pass `{ from: carrier }` to continue work
|
|
148
|
+
* handed over through a queue or another process.
|
|
149
|
+
*/
|
|
150
|
+
declare function withRuntimeOperation<T>(name: string, fn: (operation: RuntimeOperation) => T | Promise<T>, attributes?: RuntimeLogContext, options?: RuntimeOperationOptions): Promise<T>;
|
|
151
|
+
/**
|
|
152
|
+
* Like `runtimeContext.fork` but not awaited: errors are recorded on the
|
|
153
|
+
* child operation (and its span) and never become unhandled rejections.
|
|
154
|
+
*/
|
|
155
|
+
declare function runInBackground<T>(name: string, fn: (operation: RuntimeOperation) => T | Promise<T>): Promise<T | undefined>;
|
|
156
|
+
/**
|
|
157
|
+
* The current request/operation, from anywhere in its async call tree.
|
|
158
|
+
* Every method is a safe no-op (or plain log) outside an operation.
|
|
159
|
+
*/
|
|
160
|
+
declare const runtimeContext: {
|
|
161
|
+
/** Merge attributes into the current summary's context. */
|
|
162
|
+
set(attributes: RuntimeLogContext): void;
|
|
163
|
+
/** Set the outcome explicitly (wins over status/thrown-error rules). */
|
|
164
|
+
outcome(status: RuntimeOutcome, message?: string): void;
|
|
165
|
+
debug(message: string, attributes?: RuntimeLogContext): void;
|
|
166
|
+
info(message: string, attributes?: RuntimeLogContext): void;
|
|
167
|
+
warn(message: string, attributes?: RuntimeLogContext): void;
|
|
168
|
+
/** Log an error and attach it (code/why/fix) to the current summary. */
|
|
169
|
+
error(error: unknown, attributes?: RuntimeLogContext): void;
|
|
170
|
+
/** Current operation id. */
|
|
171
|
+
readonly id: string | undefined;
|
|
172
|
+
/** Current request id (inherited by child operations and forks). */
|
|
173
|
+
readonly requestId: string | undefined;
|
|
174
|
+
/**
|
|
175
|
+
* Run `fn` as a child operation whose parent link is captured NOW, so it
|
|
176
|
+
* still links after the parent has finished (background work).
|
|
177
|
+
*/
|
|
178
|
+
fork<T>(name: string, fn: (operation: RuntimeOperation) => T | Promise<T>): Promise<T>;
|
|
179
|
+
/** Serialisable link for queue payloads: `{ v: 1, op, req?, traceparent? }`. */
|
|
180
|
+
carrier(): RuntimeCarrier | undefined;
|
|
181
|
+
};
|
|
182
|
+
type RuntimeContextHandle = typeof runtimeContext;
|
|
108
183
|
|
|
109
184
|
/**
|
|
110
185
|
* Curated OpenTelemetry setup for Autter Runtime — deliberately NOT the
|
|
@@ -125,10 +200,16 @@ declare function withRuntimeOperation<T>(name: string, fn: (operation: RuntimeOp
|
|
|
125
200
|
* request metrics : aggregated every 60 s, keyed by route
|
|
126
201
|
* template (Express routes detected
|
|
127
202
|
* out of the box — see captureExpressRoute)
|
|
128
|
-
*
|
|
203
|
+
* operation / request summaries: 100% (withRuntimeOperation,
|
|
204
|
+
* autterRequests, … — one wide
|
|
205
|
+
* record per unit of work, never
|
|
206
|
+
* sampled)
|
|
207
|
+
* logs : runtimeLogger / runtimeContext records
|
|
208
|
+
* (debug/info folded into the current
|
|
209
|
+
* operation's summary; minLevel applies)
|
|
129
210
|
*
|
|
130
211
|
* Exports OTLP/HTTP JSON to the Autter ingester (`/v1/traces`,
|
|
131
|
-
* `/v1/metrics`) with the ingest key as a bearer header.
|
|
212
|
+
* `/v1/metrics`, `/v1/logs`) with the ingest key as a bearer header.
|
|
132
213
|
*/
|
|
133
214
|
interface AutterServerOptions {
|
|
134
215
|
/** Structured logs and completed operation summaries. */
|
|
@@ -171,12 +252,17 @@ interface AutterServerOptions {
|
|
|
171
252
|
*/
|
|
172
253
|
autoFlush?: boolean;
|
|
173
254
|
/**
|
|
174
|
-
* Mask PII
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
255
|
+
* Mask secrets/PII before anything leaves the process — custom
|
|
256
|
+
* attributes, exception messages and stack traces, span status
|
|
257
|
+
* messages, URLs/query strings and attributes set by any
|
|
258
|
+
* instrumentation (scrubbed again at export), and structured logs:
|
|
259
|
+
* JWTs, bearer/basic credentials, Cookie/Authorization header text,
|
|
260
|
+
* `scheme://user:pass@` connection strings, vendor API keys (sk-, sk_live_,
|
|
261
|
+
* ghp_, xox*-, AIza, AKIA, …), PEM private keys, `password=`/`?token=`
|
|
262
|
+
* assignments, emails, card numbers, and anything whose attribute KEY
|
|
263
|
+
* looks sensitive (password/token/secret/cookie/authorization/session/…).
|
|
264
|
+
* `true`/undefined = defaults; pass a RedactOptions object to add your
|
|
265
|
+
* own key/value patterns; `false` disables (not recommended).
|
|
180
266
|
* Default true.
|
|
181
267
|
*/
|
|
182
268
|
redactAttributes?: boolean | RedactOptions;
|
|
@@ -194,6 +280,22 @@ interface AutterServerOptions {
|
|
|
194
280
|
llmTracing?: boolean;
|
|
195
281
|
/** Extra instrumentations (e.g. `new ExpressInstrumentation()`). */
|
|
196
282
|
instrumentations?: unknown[];
|
|
283
|
+
/**
|
|
284
|
+
* Check once, in the background, that the ingester supports the features
|
|
285
|
+
* in use (operation logging, memory metrics, …) and print one warning per
|
|
286
|
+
* mismatch naming both versions and the fix. Never throws or delays
|
|
287
|
+
* startup. Also disabled by AUTTER_COMPAT_CHECK=0. Default true.
|
|
288
|
+
* Run `npx @autter/runtime-node doctor` for a full report.
|
|
289
|
+
*/
|
|
290
|
+
compatCheck?: boolean;
|
|
291
|
+
/**
|
|
292
|
+
* @internal Wrapper packages (`@autter/runtime-next`) report their own
|
|
293
|
+
* name/version as the OTLP `telemetry.distro.*` resource attributes.
|
|
294
|
+
*/
|
|
295
|
+
distro?: {
|
|
296
|
+
name: string;
|
|
297
|
+
version: string;
|
|
298
|
+
};
|
|
197
299
|
}
|
|
198
300
|
type AutterSeverity = "fatal" | "error" | "warning" | "info";
|
|
199
301
|
/** Token usage (and optionally exact cost) of one LLM call. */
|
|
@@ -205,6 +307,8 @@ interface LlmUsage {
|
|
|
205
307
|
* built-in per-model price estimate.
|
|
206
308
|
*/
|
|
207
309
|
costUsd?: number;
|
|
310
|
+
/** Prompt tokens served from the provider cache (rolled into `autter.operation.ai`). */
|
|
311
|
+
cacheReadTokens?: number;
|
|
208
312
|
}
|
|
209
313
|
interface LlmCallInfo {
|
|
210
314
|
/** Provider system: "openai", "anthropic", "google", "mistral_ai", … */
|
|
@@ -433,4 +537,278 @@ declare function startCaughtExceptionSampler(options?: {
|
|
|
433
537
|
stop(): void;
|
|
434
538
|
};
|
|
435
539
|
|
|
436
|
-
|
|
540
|
+
interface AutterRequestsOptions {
|
|
541
|
+
/** Path globs never summarised: `*` = one segment, `**` = any depth. */
|
|
542
|
+
ignore?: string[];
|
|
543
|
+
/** Request id header to honour and echo. Default "x-request-id". */
|
|
544
|
+
requestIdHeader?: string;
|
|
545
|
+
/** Honour an inbound request id that matches `^[\w.-]{8,128}$`. Default true. */
|
|
546
|
+
trustRequestId?: boolean;
|
|
547
|
+
}
|
|
548
|
+
interface AutterErrorResponseOptions {
|
|
549
|
+
/**
|
|
550
|
+
* Report the error as an exception. Default: errors with status ≥ 500,
|
|
551
|
+
* RuntimeErrors and any error with a valid code (expected ones included —
|
|
552
|
+
* they are recorded but never open incidents).
|
|
553
|
+
*/
|
|
554
|
+
capture?: boolean | ((error: unknown) => boolean);
|
|
555
|
+
/** Header the request id is read from when no request summary is active. */
|
|
556
|
+
requestIdHeader?: string;
|
|
557
|
+
}
|
|
558
|
+
interface RuntimeRequestOptions {
|
|
559
|
+
/** Summary name suffix (default: the route). Name = `METHOD name`. */
|
|
560
|
+
name?: string;
|
|
561
|
+
/** Route template for `http.route` (default: pathname with ids → `:id`). */
|
|
562
|
+
route?: string;
|
|
563
|
+
requestIdHeader?: string;
|
|
564
|
+
trustRequestId?: boolean;
|
|
565
|
+
ignore?: string[];
|
|
566
|
+
/** Receives the log flush promise after the response (serverless `waitUntil`). */
|
|
567
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Express / Connect middleware. Mount it early (before routers; after body
|
|
571
|
+
* parsers is fine too):
|
|
572
|
+
*
|
|
573
|
+
* app.use(autterRequests({ ignore: ["/healthz", "/metrics"] }));
|
|
574
|
+
*
|
|
575
|
+
* Echoes the request id in the response (`x-request-id`), stamps it on the
|
|
576
|
+
* server span and every record, and emits the summary on finish/close.
|
|
577
|
+
*/
|
|
578
|
+
declare function autterRequests(options?: AutterRequestsOptions): (req: IncomingMessage, res: ServerResponse, next: (error?: unknown) => void) => void;
|
|
579
|
+
/**
|
|
580
|
+
* Express error middleware: records the error on the request summary,
|
|
581
|
+
* reports it (see `capture`), and answers with
|
|
582
|
+
* `{ error: { message, code?, why?, fix?, link?, requestId? } }` and the
|
|
583
|
+
* error's status (default 500). Never includes `internal`, stacks or causes;
|
|
584
|
+
* unstructured 5xx messages are replaced with a generic one.
|
|
585
|
+
*
|
|
586
|
+
* app.use(autterErrorResponse()); // after your routes
|
|
587
|
+
*/
|
|
588
|
+
declare function autterErrorResponse(options?: AutterErrorResponseOptions): (error: unknown, req: IncomingMessage, res: ServerResponse, next: (error?: unknown) => void) => void;
|
|
589
|
+
interface FastifyLikeInstance {
|
|
590
|
+
addHook(name: string, hook: (...args: never[]) => unknown): unknown;
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Fastify plugin (Fastify 4/5, no dependency on fastify itself):
|
|
594
|
+
*
|
|
595
|
+
* app.register(autterFastify, { ignore: ["/healthz"] });
|
|
596
|
+
*
|
|
597
|
+
* Skips plugin encapsulation, so its hooks cover every route.
|
|
598
|
+
*/
|
|
599
|
+
declare function autterFastify(fastify: FastifyLikeInstance, options: AutterRequestsOptions | undefined, done: (error?: Error) => void): void;
|
|
600
|
+
/**
|
|
601
|
+
* Wrap a fetch-style handler `(request, ...rest) => Response` in a request
|
|
602
|
+
* summary. Thrown errors are recorded and reported, then rethrown.
|
|
603
|
+
*
|
|
604
|
+
* export const POST = withRuntimeRequest(handler, { name: "checkout" });
|
|
605
|
+
*/
|
|
606
|
+
declare function withRuntimeRequest<A extends unknown[]>(handler: (request: Request, ...rest: A) => Response | Promise<Response>, options?: RuntimeRequestOptions): (request: Request, ...rest: A) => Promise<Response>;
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Logger-only mode: requests, operations, coded errors, sinks and enrichers
|
|
610
|
+
* WITHOUT starting the OpenTelemetry NodeSDK. For apps that already run
|
|
611
|
+
* their own OTel (a second NodeSDK would fight it) or want logs only.
|
|
612
|
+
*
|
|
613
|
+
* initAutterLogging({ apiKey: process.env.AUTTER_RUNTIME_KEY, service: "api" });
|
|
614
|
+
*
|
|
615
|
+
* Exceptions are recorded on the app's active span when there is one
|
|
616
|
+
* (`exceptions: "auto"`); otherwise — or always with `exceptions: "log"` —
|
|
617
|
+
* they become error log records with `exception.*` and
|
|
618
|
+
* `autter.capture.mode = "log"`, which the ingester (1.5.0+) promotes to
|
|
619
|
+
* occurrences. Without an apiKey records go to the console/file sinks only.
|
|
620
|
+
*/
|
|
621
|
+
interface AutterLoggingOptions {
|
|
622
|
+
/** Private ingest key (autter_rt_…). Omit to log locally only. */
|
|
623
|
+
apiKey?: string;
|
|
624
|
+
/** Ingester base URL. Default: https://otlp.autter.dev */
|
|
625
|
+
endpoint?: string;
|
|
626
|
+
service: string;
|
|
627
|
+
environment?: string;
|
|
628
|
+
release?: string;
|
|
629
|
+
logging?: RuntimeLoggingOptions;
|
|
630
|
+
/** Same semantics as initAutterServer. Default true. */
|
|
631
|
+
redactAttributes?: boolean | RedactOptions;
|
|
632
|
+
/** Capture crashes via process.uncaughtExceptionMonitor. Default true. */
|
|
633
|
+
captureGlobalErrors?: boolean;
|
|
634
|
+
/** Flush records on beforeExit/SIGINT/SIGTERM. Default true. */
|
|
635
|
+
autoFlush?: boolean;
|
|
636
|
+
debug?: boolean;
|
|
637
|
+
/**
|
|
638
|
+
* "auto" (default): record on the app's active recording span if any,
|
|
639
|
+
* else emit a promoted log record. "log": always emit the log record
|
|
640
|
+
* (use when the app's own spans are not exported to Autter).
|
|
641
|
+
*/
|
|
642
|
+
exceptions?: "auto" | "log";
|
|
643
|
+
}
|
|
644
|
+
interface AutterLogging {
|
|
645
|
+
captureException(error: unknown, attributes?: Attributes): void;
|
|
646
|
+
flush(): Promise<void>;
|
|
647
|
+
shutdown(): Promise<void>;
|
|
648
|
+
}
|
|
649
|
+
declare function initAutterLogging(options: AutterLoggingOptions): AutterLogging;
|
|
650
|
+
|
|
651
|
+
/** `user_agent.browser` ("Chrome 120"), `user_agent.os`, `user_agent.device`, `user_agent.bot`. */
|
|
652
|
+
declare function enrichUserAgent(): RuntimeEnricher;
|
|
653
|
+
/** `http.request.body.size` / `http.response.body.size` from Content-Length. */
|
|
654
|
+
declare function enrichRequestSize(): RuntimeEnricher;
|
|
655
|
+
/** `geo.country.iso_code` from CDN/edge headers (Cloudflare, Vercel, CloudFront, Fastly). Country only. */
|
|
656
|
+
declare function enrichEdgeGeo(): RuntimeEnricher;
|
|
657
|
+
/** `deployment.region` and `deployment.commit` from common platform environment variables. */
|
|
658
|
+
declare function enrichDeployment(env?: Record<string, string | undefined>): RuntimeEnricher;
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Version compatibility between Autter Runtime SDKs, this ingester and its
|
|
662
|
+
* ClickHouse schema — the single source of truth.
|
|
663
|
+
*
|
|
664
|
+
* `compat-manifest.json` lists every feature that needs a minimum ingester
|
|
665
|
+
* version, a ClickHouse migration, a dedicated ingest route, or a minimum SDK
|
|
666
|
+
* version. Everything else derives from it:
|
|
667
|
+
*
|
|
668
|
+
* - the ingester serves it (evaluated against its own version and applied
|
|
669
|
+
* migrations) at `GET /v1/compat`;
|
|
670
|
+
* - `@autter/runtime-node` / `@autter/runtime-next` bundle this file at build
|
|
671
|
+
* time to warn once when an enabled feature needs a newer ingester, and to
|
|
672
|
+
* power `npx @autter/runtime-node doctor`;
|
|
673
|
+
* - the Python adapter (`adapters/python/compat.py`) embeds a copy that a
|
|
674
|
+
* parity test keeps identical.
|
|
675
|
+
*
|
|
676
|
+
* This module is dependency-free and side-effect-free on purpose: it is
|
|
677
|
+
* bundled into the Node SDK. Keep it that way.
|
|
678
|
+
*
|
|
679
|
+
* Adding a feature: append an entry to compat-manifest.json with the first
|
|
680
|
+
* ingester release that handles it, the migrations it writes to, its route
|
|
681
|
+
* (if it has its own), and the first SDK release that emits it. The
|
|
682
|
+
* consistency test in compat.test.ts checks ids, migrations and routes.
|
|
683
|
+
*/
|
|
684
|
+
interface CompatFeature {
|
|
685
|
+
id: string;
|
|
686
|
+
title: string;
|
|
687
|
+
/** First ingester release that stores this feature correctly. */
|
|
688
|
+
ingester: string;
|
|
689
|
+
/** ClickHouse migrations (migrations.ts ids) the feature writes to. */
|
|
690
|
+
migrations: string[];
|
|
691
|
+
/** Dedicated ingest route, when the feature has one. */
|
|
692
|
+
route?: string;
|
|
693
|
+
/** First release of each SDK package that emits the feature. */
|
|
694
|
+
sdks: Record<string, string>;
|
|
695
|
+
/** Browser payload event types that belong to this feature. */
|
|
696
|
+
browserEvents?: string[];
|
|
697
|
+
}
|
|
698
|
+
interface CompatManifest {
|
|
699
|
+
manifestVersion: number;
|
|
700
|
+
docs: string;
|
|
701
|
+
upgrade: {
|
|
702
|
+
ingester: string;
|
|
703
|
+
sdk: string;
|
|
704
|
+
};
|
|
705
|
+
features: CompatFeature[];
|
|
706
|
+
}
|
|
707
|
+
declare const COMPAT_MANIFEST: CompatManifest;
|
|
708
|
+
/** Response header carrying the ingester version on every ingest response. */
|
|
709
|
+
declare const INGESTER_VERSION_HEADER = "x-autter-ingester-version";
|
|
710
|
+
type SchemaStatus = "ready" | "pending" | "failed" | "unconfigured";
|
|
711
|
+
/** What is known about the ingester an SDK talks to. */
|
|
712
|
+
interface IngesterCompatInfo {
|
|
713
|
+
/** Exact version, or null when the ingester predates /v1/compat. */
|
|
714
|
+
version: string | null;
|
|
715
|
+
/** True when /v1/compat returned 404 (ingester 1.4.0 or older). */
|
|
716
|
+
legacy?: boolean;
|
|
717
|
+
schema?: {
|
|
718
|
+
status: SchemaStatus;
|
|
719
|
+
applied: string[];
|
|
720
|
+
};
|
|
721
|
+
/** Legacy ingesters: route → exists, learned by probing. */
|
|
722
|
+
routes?: Record<string, boolean>;
|
|
723
|
+
}
|
|
724
|
+
type CompatIssueKind = "ingester_too_old" | "schema_not_applied" | "sdk_too_old";
|
|
725
|
+
interface CompatIssue {
|
|
726
|
+
feature: string;
|
|
727
|
+
title: string;
|
|
728
|
+
kind: CompatIssueKind;
|
|
729
|
+
/** Package that must change: the ingester or an SDK package name. */
|
|
730
|
+
component: string;
|
|
731
|
+
required: string;
|
|
732
|
+
/** What was found ("1.3.4", "1.4.0 or older", …). */
|
|
733
|
+
actual: string;
|
|
734
|
+
/** One line: what is wrong, versions, and the fix. */
|
|
735
|
+
message: string;
|
|
736
|
+
fix: string;
|
|
737
|
+
}
|
|
738
|
+
interface SdkIdentity {
|
|
739
|
+
name: string;
|
|
740
|
+
version: string;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Every incompatibility for the features in use. Unknown is never an issue:
|
|
744
|
+
* when the ingester version can't be determined (and a legacy route probe
|
|
745
|
+
* didn't prove a route missing) nothing is reported, so the check has no
|
|
746
|
+
* false positives.
|
|
747
|
+
*/
|
|
748
|
+
declare function evaluateCompat(input: {
|
|
749
|
+
features: Iterable<string>;
|
|
750
|
+
ingester: IngesterCompatInfo | null;
|
|
751
|
+
sdk?: SdkIdentity | null;
|
|
752
|
+
manifest?: CompatManifest;
|
|
753
|
+
}): CompatIssue[];
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* One-time, fire-and-forget version compatibility check.
|
|
757
|
+
*
|
|
758
|
+
* When a feature that needs a newer ingester is in use (operation logging,
|
|
759
|
+
* memory metrics, …), ask the ingester once — `GET /v1/compat`, or the
|
|
760
|
+
* `x-autter-ingester-version` header on responses the SDK already receives —
|
|
761
|
+
* and print ONE clear warning per incompatible feature naming both versions
|
|
762
|
+
* and the fix. Never throws, never blocks or delays startup or exit (the
|
|
763
|
+
* socket is unref'd), and is silent when versions match or can't be
|
|
764
|
+
* determined. Disable with `compatCheck: false` or AUTTER_COMPAT_CHECK=0.
|
|
765
|
+
*/
|
|
766
|
+
declare const SDK_IDENTITY: SdkIdentity;
|
|
767
|
+
/**
|
|
768
|
+
* What the ingester at `endpoint` supports. `null` = unknown (unreachable,
|
|
769
|
+
* auth proxy, 5xx). A 404 on /v1/compat means a pre-compat ingester (1.4.0 or
|
|
770
|
+
* older); `probeRoutes` then learns which feature routes exist (an
|
|
771
|
+
* unauthenticated POST answers 401/503/… when the route exists, 404 when not).
|
|
772
|
+
*/
|
|
773
|
+
declare function fetchIngesterCompat(endpoint: string, options?: {
|
|
774
|
+
probeRoutes?: string[];
|
|
775
|
+
unref?: boolean;
|
|
776
|
+
timeoutMs?: number;
|
|
777
|
+
}): Promise<{
|
|
778
|
+
info: IngesterCompatInfo | null;
|
|
779
|
+
report: unknown;
|
|
780
|
+
error?: string;
|
|
781
|
+
}>;
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* `npx @autter/runtime-node doctor` — one-shot version compatibility report:
|
|
785
|
+
* installed Autter SDK versions, the ingester's version and ClickHouse schema
|
|
786
|
+
* level, the ingest key (optional), and every feature the installed SDKs can
|
|
787
|
+
* use that the ingester can't store. Exit codes: 0 compatible, 1 a mismatch
|
|
788
|
+
* or rejected key, 2 the ingester could not be reached or identified.
|
|
789
|
+
*/
|
|
790
|
+
interface DoctorOptions {
|
|
791
|
+
endpoint?: string;
|
|
792
|
+
key?: string;
|
|
793
|
+
features?: string[];
|
|
794
|
+
json?: boolean;
|
|
795
|
+
cwd?: string;
|
|
796
|
+
timeoutMs?: number;
|
|
797
|
+
}
|
|
798
|
+
interface DoctorReport {
|
|
799
|
+
endpoint: string;
|
|
800
|
+
sdks: SdkIdentity[];
|
|
801
|
+
ingester: IngesterCompatInfo | null;
|
|
802
|
+
ingesterError?: string;
|
|
803
|
+
key?: "accepted" | "rejected" | "client_key" | "storage_unavailable" | "unknown";
|
|
804
|
+
features: Array<{
|
|
805
|
+
id: string;
|
|
806
|
+
title: string;
|
|
807
|
+
status: "ok" | "incompatible" | "unknown";
|
|
808
|
+
}>;
|
|
809
|
+
issues: CompatIssue[];
|
|
810
|
+
exitCode: 0 | 1 | 2;
|
|
811
|
+
}
|
|
812
|
+
declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
|
|
813
|
+
|
|
814
|
+
export { type AutoFlushHandle, type AutoFlushOptions, type AutterErrorResponseOptions, type AutterLogging, type AutterLoggingOptions, type AutterRequestsOptions, type AutterServer, type AutterServerOptions, type AutterSeverity, COMPAT_MANIFEST, type CompatIssue, type DoctorOptions, type DoctorReport, FileSinkOptions, type FlushTarget, INGESTER_VERSION_HEADER, type IngesterCompatInfo, type InstrumentLlmOptions, type LlmCallHandle, type LlmCallInfo, type LlmUsage, RedactOptions, type RelayOptions, RuntimeCarrier, type RuntimeContextHandle, type RuntimeEnrichContext, type RuntimeEnrichEvent, type RuntimeEnricher, RuntimeLogContext, RuntimeLogLevel, type RuntimeLoggingOptions, type RuntimeOperation, RuntimeOperationKind, type RuntimeOperationOptions, RuntimeOutcome, type RuntimeRequestOptions, RuntimeSink, SDK_IDENTITY, type SafeCapture, type SdkIdentity, type TrackedLlmCall, autterErrorResponse, autterFastify, autterRequests, captureException, captureMessage, createBrowserRelayFetchHandler, createBrowserRelayHandler, createRuntimeLogger, emitLlmSelftestTrace, enrichDeployment, enrichEdgeGeo, enrichRequestSize, enrichUserAgent, evaluateCompat, fetchIngesterCompat, flushRuntimeLogs, initAutterLogging, initAutterServer, installAutterAutoFlush, instrumentLlmClient, makeSafeCapture, reportOutcome, runDoctor, runInBackground, runtimeContext, runtimeLogStats, runtimeLogger, sanitizeBrowserPayload, startCaughtExceptionSampler, trackLlmCall, withLlmCall, withProcessSpan, withRuntimeOperation, withRuntimeRequest };
|