@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/README.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
+
# Operation logging
|
|
2
|
+
|
|
3
|
+
Use `withRuntimeOperation`, `runtimeLogger`, and `createRuntimeLogger` to attach
|
|
4
|
+
application context to logs and completed operations. See the full
|
|
5
|
+
[operation logging guide](../../docs/OPERATION-LOGGING.md) for initialization,
|
|
6
|
+
steps, outcomes, redaction, export lifecycle, and release requirements.
|
|
7
|
+
|
|
8
|
+
# Requests and coded errors (1.5.0)
|
|
9
|
+
|
|
10
|
+
Requires ingester 1.5.0. One summary per request (always kept), request ids
|
|
11
|
+
echoed to clients, one issue per error code:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import {
|
|
15
|
+
autterRequests, autterErrorResponse, defineRuntimeErrors, runtimeContext,
|
|
16
|
+
} from "@autter/runtime-node";
|
|
17
|
+
|
|
18
|
+
export const billingErrors = defineRuntimeErrors("billing", {
|
|
19
|
+
declined: { status: 402, message: "Payment declined", expected: true,
|
|
20
|
+
why: "The card issuer rejected the charge", fix: "Ask for another card" },
|
|
21
|
+
limit: ({ plan }: { plan: string }) => ({ status: 429, message: `Plan ${plan} limit reached` }),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
app.use(autterRequests({ ignore: ["/healthz", "/metrics"] }));
|
|
25
|
+
app.post("/checkout", async (req, res) => {
|
|
26
|
+
runtimeContext.set({ cart: { items: req.body.items.length } });
|
|
27
|
+
runtimeContext.info("Applied coupon", { coupon: "SPRING" }); // folded into the summary
|
|
28
|
+
if (overLimit) throw billingErrors.limit({ plan: "free" }); // Express 5 (next(err) on 4)
|
|
29
|
+
res.json({ ok: true, requestId: runtimeContext.requestId });
|
|
30
|
+
});
|
|
31
|
+
app.use(autterErrorResponse()); // { error: { message, code, why?, fix?, link?, requestId } }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Also: `autterFastify`, `withRuntimeRequest` (fetch-style handlers),
|
|
35
|
+
`runtimeContext.fork` / `runInBackground` / `carrier()` for background work and
|
|
36
|
+
queues, the per-operation AI usage rollup, `waitUntil`, `initAutterLogging`
|
|
37
|
+
(no NodeSDK — for apps with their own OTel), enrichers (`enrichUserAgent`,
|
|
38
|
+
`enrichRequestSize`, `enrichEdgeGeo`, `enrichDeployment`), sinks (`otlpSink`,
|
|
39
|
+
`consoleSink`, `fileSink` → `.autter/runtime/*.jsonl` in development) and test
|
|
40
|
+
helpers:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { captureRuntime, expectOperation } from "@autter/runtime-node/testing";
|
|
44
|
+
const runtime = captureRuntime();
|
|
45
|
+
// … exercise the app …
|
|
46
|
+
expectOperation(runtime, "POST /checkout").toHaveOutcome("degraded").toHaveErrorCode("billing.declined");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Full guide: [Requests, coded errors and background work](../../docs/REQUESTS-AND-ERRORS.md).
|
|
50
|
+
|
|
1
51
|
# @autter/runtime-node
|
|
2
52
|
|
|
3
53
|
The server tracker exports per-instance RSS, heap, memory limit, and GC
|
|
@@ -117,6 +167,35 @@ import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
|
|
|
117
167
|
initAutterServer({ ..., instrumentations: [new ExpressInstrumentation()] });
|
|
118
168
|
```
|
|
119
169
|
|
|
170
|
+
### Version compatibility: checked for you
|
|
171
|
+
|
|
172
|
+
Some features need a minimum ingester version: operation logging needs
|
|
173
|
+
1.4.0, memory metrics 1.3.3, endpoint latency 1.3.1. After
|
|
174
|
+
`initAutterServer`, the SDK checks the ingester once in the background
|
|
175
|
+
(`GET /v1/compat`, unref'd, 3 s timeout). For each feature in use that the
|
|
176
|
+
ingester can't store, it prints one warning:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
[autter-runtime] Operation logging needs ingester >= 1.4.0; yours is 1.3.4. Upgrade the ingester: docker pull ghcr.io/autter-dev/otlp-ingester:latest and restart it (ClickHouse migrations run at boot). See …/docs/COMPATIBILITY.md
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The check never throws, never delays startup or exit, and is silent when
|
|
183
|
+
versions match or are unknown. `debug: true` logs the result. Turn it off
|
|
184
|
+
with `compatCheck: false` or `AUTTER_COMPAT_CHECK=0`. The browser relay does
|
|
185
|
+
the same for browser features such as CSP violation capture. The SDK reports
|
|
186
|
+
itself through the OTLP resource attributes `telemetry.distro.name` and
|
|
187
|
+
`telemetry.distro.version`, so the Autter dashboard shows the SDK version
|
|
188
|
+
each service runs.
|
|
189
|
+
|
|
190
|
+
For a full report (for example in CI or after a deploy):
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npx @autter/runtime-node doctor --endpoint https://ingest.example.com [--key "$AUTTER_RUNTIME_KEY"] [--json]
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Exit codes: 0 compatible, 1 mismatch or rejected key, 2 ingester unreachable.
|
|
197
|
+
See [docs/COMPATIBILITY.md](../../docs/COMPATIBILITY.md).
|
|
198
|
+
|
|
120
199
|
### Lifecycle: never lose telemetry to a forgotten shutdown()
|
|
121
200
|
|
|
122
201
|
Telemetry is batched (errors every ~2 s, healthy traces every ~5 s, metrics
|
|
@@ -148,23 +227,39 @@ default 1% sampling the span contribution is negligible; if you set
|
|
|
148
227
|
Tail-retained error traces don't distort this: their spans carry
|
|
149
228
|
`autter.tail_retained` and the ingester keeps them out of span-fed rollups.
|
|
150
229
|
|
|
151
|
-
### Privacy:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
default
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
230
|
+
### Privacy: secrets and PII are scrubbed before they leave the process
|
|
231
|
+
|
|
232
|
+
Error context is where secrets leak: `connect ECONNREFUSED
|
|
233
|
+
postgres://admin:hunter2@db…` in an exception message, a provider error
|
|
234
|
+
echoing an API key, a `?token=` in a request URL, a stray
|
|
235
|
+
`captureException(err, { "user.email": … })`. Everything the SDK exports is
|
|
236
|
+
therefore scrubbed by default — custom attributes, exception messages and
|
|
237
|
+
stack traces, span status messages, LLM call attributes and errors,
|
|
238
|
+
structured logs, and the browser events the relay forwards. A final pass at
|
|
239
|
+
export time scrubs every span regardless of who created it (HTTP
|
|
240
|
+
instrumentation URLs, third-party instrumentations, `recordException` in
|
|
241
|
+
your own code).
|
|
242
|
+
|
|
243
|
+
- secrets inside any string are masked in place, keeping the rest of the
|
|
244
|
+
message/stack readable: JWTs, `Bearer`/`Basic` credentials,
|
|
245
|
+
`Authorization:`/`Cookie:`/`Set-Cookie:` header text,
|
|
246
|
+
`scheme://user:pass@host` connection strings (postgres, mysql,
|
|
247
|
+
mongodb+srv, redis, …), vendor keys (`sk-…`, `sk_live_…`, `ghp_…`,
|
|
248
|
+
`github_pat_…`, `xox?-…`, `AIza…`, `AKIA…`, …), PEM private keys,
|
|
249
|
+
`password=`/`?token=`/`?api_key=`-style assignments, emails, and
|
|
250
|
+
Luhn-valid card numbers;
|
|
161
251
|
- attributes whose **key** looks sensitive (`password`, `token`, `secret`,
|
|
162
|
-
`api_key`, `authorization`, `cookie`, `ssn`, `card_number`, …)
|
|
163
|
-
wholesale;
|
|
164
|
-
- non-sensitive keys
|
|
165
|
-
dashboards keep working.
|
|
252
|
+
`api_key`, `authorization`, `cookie`, `session`, `ssn`, `card_number`, …)
|
|
253
|
+
are masked wholesale, at any nesting depth;
|
|
254
|
+
- non-sensitive keys, numbers (including LLM token counts) and booleans pass
|
|
255
|
+
through untouched, so grouping, dashboards and cost tracking keep working.
|
|
256
|
+
|
|
257
|
+
The same patterns run in the browser SDK, the relay, the Python adapter,
|
|
258
|
+
and again in the ingester before storage (shared test vectors in
|
|
259
|
+
`test-vectors/redaction.json`).
|
|
166
260
|
|
|
167
|
-
|
|
261
|
+
Extend it (applies to messages, stacks and URLs too) or disable it per
|
|
262
|
+
service:
|
|
168
263
|
|
|
169
264
|
```ts
|
|
170
265
|
initAutterServer({
|
|
@@ -186,7 +281,9 @@ const safe = makeSafeCapture();
|
|
|
186
281
|
safe.captureException(err, { "user.email": email }); // masked before export
|
|
187
282
|
```
|
|
188
283
|
|
|
189
|
-
The raw
|
|
284
|
+
The raw primitives are exported too (`redactAttributes(attrs, options)`,
|
|
285
|
+
`redactText(text, options)`). The browser relay takes the same options as
|
|
286
|
+
`createBrowserRelayHandler({ ..., redact })`.
|
|
190
287
|
This closes the server-side gap to match the browser relay's payload
|
|
191
288
|
whitelist; it is best-effort scrubbing of obvious PII shapes, not a DLP
|
|
192
289
|
engine — keep secrets out of attributes in the first place.
|
|
@@ -287,4 +384,4 @@ Note on the slow-process monitor: Autter flags HTTP routes from the
|
|
|
287
384
|
unsampled request metrics, so route detection works out of the box. Non-HTTP
|
|
288
385
|
work is only visible where a span exists — relying on 1%-sampled regular
|
|
289
386
|
traces there would undercount ~100×, which is why these spans skip head
|
|
290
|
-
sampling.
|
|
387
|
+
sampling.
|