@autter/runtime-node 1.5.0 → 1.6.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/dist/index.d.cts CHANGED
@@ -1,6 +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
+ 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, B as BreadcrumbInput } from './sinks-CPGDyfU8.cjs';
3
+ export { i as Breadcrumb, j as BreadcrumbLevel, k as BreadcrumbType, l as CODE_PATTERN, n as ClientErrorBody, o as ConsoleSinkOptions, O as OtlpSinkOptions, p as RuntimeError, q as RuntimeErrorCatalog, r as RuntimeErrorDefinition, s as RuntimeErrorExtras, t as RuntimeErrorFactory, u as RuntimeErrorLike, v as RuntimeErrorOptions, R as RuntimeEvent, w as RuntimeLogContextValue, x as RuntimeSinkContext, y as consoleSink, z as defineRuntimeErrors, A as errorAttributes, D as fileSink, E as isRuntimeErrorLike, G as otlpSink, H as redactAttributes, I as redactText, J as toClientError } from './sinks-CPGDyfU8.cjs';
4
4
  import { Attributes } from '@opentelemetry/api';
5
5
 
6
6
  /**
@@ -242,8 +242,23 @@ interface AutterServerOptions {
242
242
  metricIntervalMs?: number;
243
243
  /** Collect RSS, heap, limit, and GC signals per process instance. Default true. */
244
244
  memoryMetrics?: boolean;
245
- /** Capture crashing exceptions via process.uncaughtExceptionMonitor (default true). */
245
+ /**
246
+ * Capture crashing exceptions via process.uncaughtExceptionMonitor, and
247
+ * unhandled promise rejections (see `captureUnhandledRejections`).
248
+ * Default true; false turns both off.
249
+ */
246
250
  captureGlobalErrors?: boolean;
251
+ /**
252
+ * Record unhandled promise rejections as errors (severity "error",
253
+ * `autter.unhandled_rejection: true`). Never changes whether the process
254
+ * crashes: when Node would have crashed (the default
255
+ * `--unhandled-rejections=throw` mode and no other `unhandledRejection`
256
+ * listener), the rejection is rethrown on the next tick, so the process
257
+ * still exits with code 1 and the crash is recorded as fatal like any
258
+ * other. False restores 1.5.0 behaviour: a rejection is only seen when it
259
+ * crashes the process. Default true.
260
+ */
261
+ captureUnhandledRejections?: boolean;
247
262
  /**
248
263
  * Flush all exporters when the process exits (`beforeExit`, SIGINT,
249
264
  * SIGTERM) so a forgotten `shutdown()` doesn't silently drop buffered
@@ -344,7 +359,12 @@ interface TrackedLlmCall extends LlmCallInfo, LlmUsage {
344
359
  error?: unknown;
345
360
  }
346
361
  interface AutterServer {
347
- /** Report a handled exception. Always recorded (never sampled out). */
362
+ /**
363
+ * Report a handled exception. Always recorded (never sampled out).
364
+ * `attributes.fingerprint` (a string or up to 10 strings) groups every
365
+ * error that carries it into one issue (ingester 1.6.0+); it is sent as
366
+ * `autter.fingerprint` on the exception event, not as a span attribute.
367
+ */
348
368
  captureException(error: unknown, attributes?: Attributes): void;
349
369
  /**
350
370
  * Report a warning (or info) without an exception — deprecated code
@@ -566,6 +586,17 @@ interface RuntimeRequestOptions {
566
586
  /** Receives the log flush promise after the response (serverless `waitUntil`). */
567
587
  waitUntil?: (promise: Promise<unknown>) => void;
568
588
  }
589
+ /**
590
+ * Report an error that reached a request boundary — a framework error hook,
591
+ * an exception filter, Next.js `onRequestError`. Unlike `captureException`
592
+ * it reports each error once (an error a handler or another hook already
593
+ * captured is skipped), and it records the exception, with its stack, on the
594
+ * request's HTTP server span even when a child span is active, so the failed
595
+ * request and its exception stay one issue. When the error was already
596
+ * captured (e.g. by `withRuntimeRequest`), `attributes` still go on the
597
+ * request span, without a second exception.
598
+ */
599
+ declare function captureRequestError(error: unknown, attributes?: Attributes): void;
569
600
  /**
570
601
  * Express / Connect middleware. Mount it early (before routers; after body
571
602
  * parsers is fine too):
@@ -605,6 +636,101 @@ declare function autterFastify(fastify: FastifyLikeInstance, options: AutterRequ
605
636
  */
606
637
  declare function withRuntimeRequest<A extends unknown[]>(handler: (request: Request, ...rest: A) => Response | Promise<Response>, options?: RuntimeRequestOptions): (request: Request, ...rest: A) => Promise<Response>;
607
638
 
639
+ /**
640
+ * Server error hooks for Express, Fastify and Koa. Each records the error,
641
+ * with its stack, on the request's span through `captureException`, then
642
+ * lets the framework carry on exactly as before (same error, same response).
643
+ * Without them a thrown error only reaches Autter as the 500 the framework
644
+ * answers with: a stackless `HttpServerError` grouped by route.
645
+ *
646
+ * No framework is a dependency: the request/reply shapes are structural.
647
+ */
648
+ interface AutterErrorHandlerOptions {
649
+ /**
650
+ * Which errors to report. Default: errors with status ≥ 500 (or no
651
+ * status), RuntimeErrors and any error with a valid code — so 4xx errors
652
+ * such as `ctx.throw(404)` or validation failures stay out of your issues.
653
+ * `true` reports every error; a predicate decides per error.
654
+ */
655
+ capture?: boolean | ((error: unknown) => boolean);
656
+ }
657
+ /**
658
+ * Express (4/5) / Connect error middleware that reports the error and calls
659
+ * `next(err)` unchanged. Mount it after your routes and before your own
660
+ * error handlers:
661
+ *
662
+ * app.use(autterErrorHandler());
663
+ * app.use((err, req, res, next) => res.status(500).send("…")); // yours
664
+ *
665
+ * (`autterErrorResponse()` reports too, and also answers the request.)
666
+ */
667
+ declare function autterErrorHandler(options?: AutterErrorHandlerOptions): (error: unknown, req: IncomingMessage, _res: ServerResponse, next: (error?: unknown) => void) => void;
668
+ interface FastifyHookInstance {
669
+ addHook(name: string, hook: (...args: never[]) => unknown): unknown;
670
+ }
671
+ /**
672
+ * Fastify (4/5) `onError` hook that reports the error; Fastify's error
673
+ * handler still builds the response. Register it as a plugin, or call it on
674
+ * the instance directly:
675
+ *
676
+ * app.register(autterFastifyErrors); // or: autterFastifyErrors(app)
677
+ * app.register(autterFastifyErrors, { capture: true });
678
+ *
679
+ * It skips plugin encapsulation, so it covers every route. `autterFastify`
680
+ * (request summaries) already includes the same hook; you don't need both.
681
+ */
682
+ declare function autterFastifyErrors(fastify: FastifyHookInstance, options?: AutterErrorHandlerOptions, done?: (error?: Error) => void): void;
683
+ interface KoaContextLike {
684
+ req?: IncomingMessage;
685
+ }
686
+ /**
687
+ * Koa (2/3) middleware that reports errors thrown downstream and rethrows
688
+ * them, so Koa's own error handling (and `app.on("error")`) is unchanged.
689
+ * Mount it first:
690
+ *
691
+ * app.use(autterKoa());
692
+ */
693
+ declare function autterKoa(options?: AutterErrorHandlerOptions): (ctx: KoaContextLike, next: () => Promise<unknown>) => Promise<void>;
694
+
695
+ /**
696
+ * Unhandled promise rejections, recorded without changing whether the
697
+ * process crashes.
698
+ *
699
+ * Node's `--unhandled-rejections` mode decides what an unhandled rejection
700
+ * does, and most modes behave differently once ANY `unhandledRejection`
701
+ * listener exists:
702
+ *
703
+ * mode no listener with a listener
704
+ * throw (default) crash (uncaught exception) listener only — no crash
705
+ * strict crash, then the listener same
706
+ * warn warning listener + warning
707
+ * warn-with-error-code warning + exit code 1 listener only
708
+ * none nothing listener only
709
+ *
710
+ * Adding our listener would therefore silently stop the default crash. So
711
+ * when ours is the only listener we do what Node would have done:
712
+ *
713
+ * - throw: rethrow the reason (or Node's `UnhandledPromiseRejection`
714
+ * wrapper for a non-error reason) on the next tick. The process crashes
715
+ * with exit code 1 as before, and `uncaughtExceptionMonitor` records it
716
+ * as a crash (fatal), exactly as it did without this listener. The one
717
+ * visible difference: `uncaughtException` listeners and the monitor
718
+ * receive origin `"uncaughtException"` instead of `"unhandledRejection"`.
719
+ * - warn-with-error-code: print Node's warning and set `process.exitCode = 1`.
720
+ * - strict: no listener at all — Node raises the rejection as an uncaught
721
+ * exception first, which the crash monitor already records.
722
+ *
723
+ * Everything else — the app has its own listener (it decides what happens),
724
+ * or the mode never crashes — is recorded as an error (severity "error", not
725
+ * fatal) with `autter.unhandled_rejection: true`.
726
+ */
727
+ type UnhandledRejectionsMode = "throw" | "strict" | "warn" | "warn-with-error-code" | "none";
728
+ /**
729
+ * Node's effective `--unhandled-rejections` mode: `NODE_OPTIONS` first, then
730
+ * the command line (which wins), last occurrence wins. Default `"throw"`.
731
+ */
732
+ declare function unhandledRejectionsMode(execArgv?: readonly string[], nodeOptions?: string | undefined): UnhandledRejectionsMode;
733
+
608
734
  /**
609
735
  * Logger-only mode: requests, operations, coded errors, sinks and enrichers
610
736
  * WITHOUT starting the OpenTelemetry NodeSDK. For apps that already run
@@ -629,8 +755,12 @@ interface AutterLoggingOptions {
629
755
  logging?: RuntimeLoggingOptions;
630
756
  /** Same semantics as initAutterServer. Default true. */
631
757
  redactAttributes?: boolean | RedactOptions;
632
- /** Capture crashes via process.uncaughtExceptionMonitor. Default true. */
758
+ /** Capture crashes via process.uncaughtExceptionMonitor, and unhandled
759
+ * rejections (`captureUnhandledRejections`). Default true. */
633
760
  captureGlobalErrors?: boolean;
761
+ /** Same semantics as initAutterServer: record unhandled rejections as
762
+ * errors without changing whether the process crashes. Default true. */
763
+ captureUnhandledRejections?: boolean;
634
764
  /** Flush records on beforeExit/SIGINT/SIGTERM. Default true. */
635
765
  autoFlush?: boolean;
636
766
  debug?: boolean;
@@ -679,7 +809,9 @@ declare function enrichDeployment(env?: Record<string, string | undefined>): Run
679
809
  * Adding a feature: append an entry to compat-manifest.json with the first
680
810
  * ingester release that handles it, the migrations it writes to, its route
681
811
  * (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.
812
+ * consistency test in compat.test.ts checks ids, migrations and routes, and
813
+ * that no version is ahead of its package's package.json: a feature for the
814
+ * next release bumps the packages it names in the same change.
683
815
  */
684
816
  interface CompatFeature {
685
817
  id: string;
@@ -811,4 +943,13 @@ interface DoctorReport {
811
943
  }
812
944
  declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
813
945
 
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 };
946
+ /**
947
+ * Record a step (type "custom" unless you say otherwise) on the current
948
+ * request. The next exception captured in it carries the last 30. Message
949
+ * and data are scrubbed with your `redact` settings. Never throws.
950
+ *
951
+ * addBreadcrumb({ message: "Loaded cart", data: { items: 3 } });
952
+ */
953
+ declare function addBreadcrumb(input: BreadcrumbInput): void;
954
+
955
+ export { type AutoFlushHandle, type AutoFlushOptions, type AutterErrorHandlerOptions, type AutterErrorResponseOptions, type AutterLogging, type AutterLoggingOptions, type AutterRequestsOptions, type AutterServer, type AutterServerOptions, type AutterSeverity, BreadcrumbInput, 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, type UnhandledRejectionsMode, addBreadcrumb, autterErrorHandler, autterErrorResponse, autterFastify, autterFastifyErrors, autterKoa, autterRequests, captureException, captureMessage, captureRequestError, 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, unhandledRejectionsMode, withLlmCall, withProcessSpan, withRuntimeOperation, withRuntimeRequest };
package/dist/index.d.ts CHANGED
@@ -1,6 +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.js';
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.js';
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, B as BreadcrumbInput } from './sinks-CPGDyfU8.js';
3
+ export { i as Breadcrumb, j as BreadcrumbLevel, k as BreadcrumbType, l as CODE_PATTERN, n as ClientErrorBody, o as ConsoleSinkOptions, O as OtlpSinkOptions, p as RuntimeError, q as RuntimeErrorCatalog, r as RuntimeErrorDefinition, s as RuntimeErrorExtras, t as RuntimeErrorFactory, u as RuntimeErrorLike, v as RuntimeErrorOptions, R as RuntimeEvent, w as RuntimeLogContextValue, x as RuntimeSinkContext, y as consoleSink, z as defineRuntimeErrors, A as errorAttributes, D as fileSink, E as isRuntimeErrorLike, G as otlpSink, H as redactAttributes, I as redactText, J as toClientError } from './sinks-CPGDyfU8.js';
4
4
  import { Attributes } from '@opentelemetry/api';
5
5
 
6
6
  /**
@@ -242,8 +242,23 @@ interface AutterServerOptions {
242
242
  metricIntervalMs?: number;
243
243
  /** Collect RSS, heap, limit, and GC signals per process instance. Default true. */
244
244
  memoryMetrics?: boolean;
245
- /** Capture crashing exceptions via process.uncaughtExceptionMonitor (default true). */
245
+ /**
246
+ * Capture crashing exceptions via process.uncaughtExceptionMonitor, and
247
+ * unhandled promise rejections (see `captureUnhandledRejections`).
248
+ * Default true; false turns both off.
249
+ */
246
250
  captureGlobalErrors?: boolean;
251
+ /**
252
+ * Record unhandled promise rejections as errors (severity "error",
253
+ * `autter.unhandled_rejection: true`). Never changes whether the process
254
+ * crashes: when Node would have crashed (the default
255
+ * `--unhandled-rejections=throw` mode and no other `unhandledRejection`
256
+ * listener), the rejection is rethrown on the next tick, so the process
257
+ * still exits with code 1 and the crash is recorded as fatal like any
258
+ * other. False restores 1.5.0 behaviour: a rejection is only seen when it
259
+ * crashes the process. Default true.
260
+ */
261
+ captureUnhandledRejections?: boolean;
247
262
  /**
248
263
  * Flush all exporters when the process exits (`beforeExit`, SIGINT,
249
264
  * SIGTERM) so a forgotten `shutdown()` doesn't silently drop buffered
@@ -344,7 +359,12 @@ interface TrackedLlmCall extends LlmCallInfo, LlmUsage {
344
359
  error?: unknown;
345
360
  }
346
361
  interface AutterServer {
347
- /** Report a handled exception. Always recorded (never sampled out). */
362
+ /**
363
+ * Report a handled exception. Always recorded (never sampled out).
364
+ * `attributes.fingerprint` (a string or up to 10 strings) groups every
365
+ * error that carries it into one issue (ingester 1.6.0+); it is sent as
366
+ * `autter.fingerprint` on the exception event, not as a span attribute.
367
+ */
348
368
  captureException(error: unknown, attributes?: Attributes): void;
349
369
  /**
350
370
  * Report a warning (or info) without an exception — deprecated code
@@ -566,6 +586,17 @@ interface RuntimeRequestOptions {
566
586
  /** Receives the log flush promise after the response (serverless `waitUntil`). */
567
587
  waitUntil?: (promise: Promise<unknown>) => void;
568
588
  }
589
+ /**
590
+ * Report an error that reached a request boundary — a framework error hook,
591
+ * an exception filter, Next.js `onRequestError`. Unlike `captureException`
592
+ * it reports each error once (an error a handler or another hook already
593
+ * captured is skipped), and it records the exception, with its stack, on the
594
+ * request's HTTP server span even when a child span is active, so the failed
595
+ * request and its exception stay one issue. When the error was already
596
+ * captured (e.g. by `withRuntimeRequest`), `attributes` still go on the
597
+ * request span, without a second exception.
598
+ */
599
+ declare function captureRequestError(error: unknown, attributes?: Attributes): void;
569
600
  /**
570
601
  * Express / Connect middleware. Mount it early (before routers; after body
571
602
  * parsers is fine too):
@@ -605,6 +636,101 @@ declare function autterFastify(fastify: FastifyLikeInstance, options: AutterRequ
605
636
  */
606
637
  declare function withRuntimeRequest<A extends unknown[]>(handler: (request: Request, ...rest: A) => Response | Promise<Response>, options?: RuntimeRequestOptions): (request: Request, ...rest: A) => Promise<Response>;
607
638
 
639
+ /**
640
+ * Server error hooks for Express, Fastify and Koa. Each records the error,
641
+ * with its stack, on the request's span through `captureException`, then
642
+ * lets the framework carry on exactly as before (same error, same response).
643
+ * Without them a thrown error only reaches Autter as the 500 the framework
644
+ * answers with: a stackless `HttpServerError` grouped by route.
645
+ *
646
+ * No framework is a dependency: the request/reply shapes are structural.
647
+ */
648
+ interface AutterErrorHandlerOptions {
649
+ /**
650
+ * Which errors to report. Default: errors with status ≥ 500 (or no
651
+ * status), RuntimeErrors and any error with a valid code — so 4xx errors
652
+ * such as `ctx.throw(404)` or validation failures stay out of your issues.
653
+ * `true` reports every error; a predicate decides per error.
654
+ */
655
+ capture?: boolean | ((error: unknown) => boolean);
656
+ }
657
+ /**
658
+ * Express (4/5) / Connect error middleware that reports the error and calls
659
+ * `next(err)` unchanged. Mount it after your routes and before your own
660
+ * error handlers:
661
+ *
662
+ * app.use(autterErrorHandler());
663
+ * app.use((err, req, res, next) => res.status(500).send("…")); // yours
664
+ *
665
+ * (`autterErrorResponse()` reports too, and also answers the request.)
666
+ */
667
+ declare function autterErrorHandler(options?: AutterErrorHandlerOptions): (error: unknown, req: IncomingMessage, _res: ServerResponse, next: (error?: unknown) => void) => void;
668
+ interface FastifyHookInstance {
669
+ addHook(name: string, hook: (...args: never[]) => unknown): unknown;
670
+ }
671
+ /**
672
+ * Fastify (4/5) `onError` hook that reports the error; Fastify's error
673
+ * handler still builds the response. Register it as a plugin, or call it on
674
+ * the instance directly:
675
+ *
676
+ * app.register(autterFastifyErrors); // or: autterFastifyErrors(app)
677
+ * app.register(autterFastifyErrors, { capture: true });
678
+ *
679
+ * It skips plugin encapsulation, so it covers every route. `autterFastify`
680
+ * (request summaries) already includes the same hook; you don't need both.
681
+ */
682
+ declare function autterFastifyErrors(fastify: FastifyHookInstance, options?: AutterErrorHandlerOptions, done?: (error?: Error) => void): void;
683
+ interface KoaContextLike {
684
+ req?: IncomingMessage;
685
+ }
686
+ /**
687
+ * Koa (2/3) middleware that reports errors thrown downstream and rethrows
688
+ * them, so Koa's own error handling (and `app.on("error")`) is unchanged.
689
+ * Mount it first:
690
+ *
691
+ * app.use(autterKoa());
692
+ */
693
+ declare function autterKoa(options?: AutterErrorHandlerOptions): (ctx: KoaContextLike, next: () => Promise<unknown>) => Promise<void>;
694
+
695
+ /**
696
+ * Unhandled promise rejections, recorded without changing whether the
697
+ * process crashes.
698
+ *
699
+ * Node's `--unhandled-rejections` mode decides what an unhandled rejection
700
+ * does, and most modes behave differently once ANY `unhandledRejection`
701
+ * listener exists:
702
+ *
703
+ * mode no listener with a listener
704
+ * throw (default) crash (uncaught exception) listener only — no crash
705
+ * strict crash, then the listener same
706
+ * warn warning listener + warning
707
+ * warn-with-error-code warning + exit code 1 listener only
708
+ * none nothing listener only
709
+ *
710
+ * Adding our listener would therefore silently stop the default crash. So
711
+ * when ours is the only listener we do what Node would have done:
712
+ *
713
+ * - throw: rethrow the reason (or Node's `UnhandledPromiseRejection`
714
+ * wrapper for a non-error reason) on the next tick. The process crashes
715
+ * with exit code 1 as before, and `uncaughtExceptionMonitor` records it
716
+ * as a crash (fatal), exactly as it did without this listener. The one
717
+ * visible difference: `uncaughtException` listeners and the monitor
718
+ * receive origin `"uncaughtException"` instead of `"unhandledRejection"`.
719
+ * - warn-with-error-code: print Node's warning and set `process.exitCode = 1`.
720
+ * - strict: no listener at all — Node raises the rejection as an uncaught
721
+ * exception first, which the crash monitor already records.
722
+ *
723
+ * Everything else — the app has its own listener (it decides what happens),
724
+ * or the mode never crashes — is recorded as an error (severity "error", not
725
+ * fatal) with `autter.unhandled_rejection: true`.
726
+ */
727
+ type UnhandledRejectionsMode = "throw" | "strict" | "warn" | "warn-with-error-code" | "none";
728
+ /**
729
+ * Node's effective `--unhandled-rejections` mode: `NODE_OPTIONS` first, then
730
+ * the command line (which wins), last occurrence wins. Default `"throw"`.
731
+ */
732
+ declare function unhandledRejectionsMode(execArgv?: readonly string[], nodeOptions?: string | undefined): UnhandledRejectionsMode;
733
+
608
734
  /**
609
735
  * Logger-only mode: requests, operations, coded errors, sinks and enrichers
610
736
  * WITHOUT starting the OpenTelemetry NodeSDK. For apps that already run
@@ -629,8 +755,12 @@ interface AutterLoggingOptions {
629
755
  logging?: RuntimeLoggingOptions;
630
756
  /** Same semantics as initAutterServer. Default true. */
631
757
  redactAttributes?: boolean | RedactOptions;
632
- /** Capture crashes via process.uncaughtExceptionMonitor. Default true. */
758
+ /** Capture crashes via process.uncaughtExceptionMonitor, and unhandled
759
+ * rejections (`captureUnhandledRejections`). Default true. */
633
760
  captureGlobalErrors?: boolean;
761
+ /** Same semantics as initAutterServer: record unhandled rejections as
762
+ * errors without changing whether the process crashes. Default true. */
763
+ captureUnhandledRejections?: boolean;
634
764
  /** Flush records on beforeExit/SIGINT/SIGTERM. Default true. */
635
765
  autoFlush?: boolean;
636
766
  debug?: boolean;
@@ -679,7 +809,9 @@ declare function enrichDeployment(env?: Record<string, string | undefined>): Run
679
809
  * Adding a feature: append an entry to compat-manifest.json with the first
680
810
  * ingester release that handles it, the migrations it writes to, its route
681
811
  * (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.
812
+ * consistency test in compat.test.ts checks ids, migrations and routes, and
813
+ * that no version is ahead of its package's package.json: a feature for the
814
+ * next release bumps the packages it names in the same change.
683
815
  */
684
816
  interface CompatFeature {
685
817
  id: string;
@@ -811,4 +943,13 @@ interface DoctorReport {
811
943
  }
812
944
  declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
813
945
 
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 };
946
+ /**
947
+ * Record a step (type "custom" unless you say otherwise) on the current
948
+ * request. The next exception captured in it carries the last 30. Message
949
+ * and data are scrubbed with your `redact` settings. Never throws.
950
+ *
951
+ * addBreadcrumb({ message: "Loaded cart", data: { items: 3 } });
952
+ */
953
+ declare function addBreadcrumb(input: BreadcrumbInput): void;
954
+
955
+ export { type AutoFlushHandle, type AutoFlushOptions, type AutterErrorHandlerOptions, type AutterErrorResponseOptions, type AutterLogging, type AutterLoggingOptions, type AutterRequestsOptions, type AutterServer, type AutterServerOptions, type AutterSeverity, BreadcrumbInput, 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, type UnhandledRejectionsMode, addBreadcrumb, autterErrorHandler, autterErrorResponse, autterFastify, autterFastifyErrors, autterKoa, autterRequests, captureException, captureMessage, captureRequestError, 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, unhandledRejectionsMode, withLlmCall, withProcessSpan, withRuntimeOperation, withRuntimeRequest };