@autter/runtime-node 1.8.0 → 1.9.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 +69 -1
- package/dist/{chunk-7H3FCV4P.cjs → chunk-AN45KLWD.cjs} +11 -11
- package/dist/{chunk-MOZOUEMA.cjs → chunk-BHYHORUD.cjs} +44 -3
- package/dist/{chunk-QKY2OQSO.js → chunk-HHKQ3UCH.js} +533 -31
- package/dist/{chunk-UC3QH4PC.js → chunk-JSGGUWRD.js} +1 -1
- package/dist/{chunk-37W7YYXO.cjs → chunk-YWTIKZSI.cjs} +596 -94
- package/dist/{chunk-B5ZMOCEM.js → chunk-ZKM76SDP.js} +44 -3
- package/dist/cli.cjs +8 -8
- package/dist/cli.js +2 -2
- package/dist/index.cjs +424 -209
- package/dist/index.d.cts +75 -3
- package/dist/index.d.ts +75 -3
- package/dist/index.js +231 -16
- package/dist/{sinks-CIdlmYwy.d.cts → sinks-CLtQFPnn.d.cts} +39 -3
- package/dist/{sinks-CIdlmYwy.d.ts → sinks-CLtQFPnn.d.ts} +39 -3
- package/dist/testing.cjs +8 -8
- package/dist/testing.d.cts +2 -2
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +2 -2
- package/package.json +7 -3
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, I as IgnoreErrorPattern, B as BreadcrumbInput } from './sinks-
|
|
3
|
-
export {
|
|
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, I as IgnoreErrorPattern, i as CaptureLoggedErrorsOption, B as BreadcrumbInput } from './sinks-CLtQFPnn.cjs';
|
|
3
|
+
export { j as Breadcrumb, k as BreadcrumbLevel, l as BreadcrumbType, n as CODE_PATTERN, o as ClientErrorBody, p as ConsoleSinkOptions, L as LoggedErrorSource, O as OtlpSinkOptions, q as RuntimeError, r as RuntimeErrorCatalog, s as RuntimeErrorDefinition, t as RuntimeErrorExtras, u as RuntimeErrorFactory, v as RuntimeErrorLike, w as RuntimeErrorOptions, R as RuntimeEvent, x as RuntimeLogContextValue, y as RuntimeSinkContext, z as consoleSink, A as defineRuntimeErrors, D as errorAttributes, E as fileSink, G as isRuntimeErrorLike, H as otlpSink, J as redactAttributes, K as redactText, N as toClientError } from './sinks-CLtQFPnn.cjs';
|
|
4
4
|
import { Attributes } from '@opentelemetry/api';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -23,6 +23,37 @@ interface RelayOptions {
|
|
|
23
23
|
* `false` to disable (e.g. when a WAF already rate-limits).
|
|
24
24
|
*/
|
|
25
25
|
perIpRateLimit?: number | false;
|
|
26
|
+
/**
|
|
27
|
+
* How the per-client rate limit finds the visitor's address. A caller can
|
|
28
|
+
* write anything into `X-Forwarded-For`, so the relay never takes its
|
|
29
|
+
* first (leftmost) entry unless told to.
|
|
30
|
+
*
|
|
31
|
+
* - `"auto"` (default): works behind any load balancer, CDN or platform
|
|
32
|
+
* proxy without setup. Proxies append the address they saw to the right
|
|
33
|
+
* of the header (or overwrite it), so the relay reads it right to left
|
|
34
|
+
* and takes the first public address, skipping private and loopback
|
|
35
|
+
* hops. The Node handler only does this when the connection itself came
|
|
36
|
+
* from a private address (a proxy on your network); a public peer is the
|
|
37
|
+
* visitor and its header is ignored. On Cloudflare Workers it uses
|
|
38
|
+
* `CF-Connecting-IP`.
|
|
39
|
+
* - a number `n`: exactly `n` proxies you control sit in front; use the
|
|
40
|
+
* entry `n` from the right (Express `trust proxy` semantics). Use `1`
|
|
41
|
+
* for a Node origin behind Cloudflare with no load balancer.
|
|
42
|
+
* - `true`: every proxy in front is yours and strips client values; use
|
|
43
|
+
* the leftmost entry.
|
|
44
|
+
* - `false`: never read the header. The Node handler keys the socket peer;
|
|
45
|
+
* the fetch handler keys one shared bucket for the route.
|
|
46
|
+
*
|
|
47
|
+
* Strings from environment variables are read too (`"auto"`, `"true"`,
|
|
48
|
+
* `"false"`, `"0"`, `"2"`); anything else falls back to `"auto"`.
|
|
49
|
+
*/
|
|
50
|
+
trustProxy?: boolean | "auto" | number | string;
|
|
51
|
+
/**
|
|
52
|
+
* Return the visitor's address yourself (Deno's `info.remoteAddr`, Bun's
|
|
53
|
+
* `server.requestIP`, a header your edge sets). Wins over `trustProxy`
|
|
54
|
+
* when it returns a non-empty string.
|
|
55
|
+
*/
|
|
56
|
+
clientIp?: (request: Request | IncomingMessage) => string | null | undefined;
|
|
26
57
|
/** Called when the async forward fails (default: console.warn). */
|
|
27
58
|
onError?: (err: unknown) => void;
|
|
28
59
|
/**
|
|
@@ -167,6 +198,19 @@ declare const runtimeContext: {
|
|
|
167
198
|
warn(message: string, attributes?: RuntimeLogContext): void;
|
|
168
199
|
/** Log an error and attach it (code/why/fix) to the current summary. */
|
|
169
200
|
error(error: unknown, attributes?: RuntimeLogContext): void;
|
|
201
|
+
/**
|
|
202
|
+
* The app caught `error` and chose to continue on a fallback (RF-02):
|
|
203
|
+
*
|
|
204
|
+
* } catch (err) {
|
|
205
|
+
* runtimeContext.degraded(err, "pricing service down, using cached prices");
|
|
206
|
+
* }
|
|
207
|
+
*
|
|
208
|
+
* Recorded as an occurrence at `warning` severity, marked
|
|
209
|
+
* `autter.handling = "deliberate"` with the reason (grouped by its code
|
|
210
|
+
* when the error has one), never an incident. The current request or
|
|
211
|
+
* operation ends "degraded" unless it failed or set its outcome.
|
|
212
|
+
*/
|
|
213
|
+
degraded(error: unknown, reason: string, attributes?: RuntimeLogContext): void;
|
|
170
214
|
/** Current operation id. */
|
|
171
215
|
readonly id: string | undefined;
|
|
172
216
|
/** Current request id (inherited by child operations and forks). */
|
|
@@ -268,6 +312,20 @@ interface AutterServerOptions {
|
|
|
268
312
|
* Default true; false turns both off.
|
|
269
313
|
*/
|
|
270
314
|
captureGlobalErrors?: boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Errors the app caught and logged count (RF-01): an `Error` passed to
|
|
317
|
+
* `console.error`, pino, winston, bunyan or `runtimeLogger.error` becomes
|
|
318
|
+
* an occurrence at `error` severity, marked `autter.handled` /
|
|
319
|
+
* `autter.handling: "caught"`, with the log line as context
|
|
320
|
+
* (`autter.log.source`, `autter.log.message`). Log lines without an error
|
|
321
|
+
* object are untouched; an error also passed to `captureException` in
|
|
322
|
+
* the same tick is reported once; a burst limit per error type and throw
|
|
323
|
+
* site keeps ten at once, then one every ten seconds (the count left out
|
|
324
|
+
* is reported). It never fails a request on its own. `false` turns it
|
|
325
|
+
* off; an object turns single loggers off, e.g. `{ console: false }`.
|
|
326
|
+
* Default true.
|
|
327
|
+
*/
|
|
328
|
+
captureLoggedErrors?: CaptureLoggedErrorsOption;
|
|
271
329
|
/**
|
|
272
330
|
* Record unhandled promise rejections as errors (severity "error",
|
|
273
331
|
* `autter.unhandled_rejection: true`). Never changes whether the process
|
|
@@ -617,6 +675,18 @@ interface RuntimeRequestOptions {
|
|
|
617
675
|
ignore?: string[];
|
|
618
676
|
/** Receives the log flush promise after the response (serverless `waitUntil`). */
|
|
619
677
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
678
|
+
/**
|
|
679
|
+
* Report thrown errors (default true): `false`, or a predicate per error.
|
|
680
|
+
* An error it turns down is rethrown untouched and does not fail the
|
|
681
|
+
* summary (Next.js `redirect()` / `notFound()` signals).
|
|
682
|
+
*/
|
|
683
|
+
capture?: boolean | ((error: unknown) => boolean);
|
|
684
|
+
/**
|
|
685
|
+
* Answer a thrown error with `toClientError` JSON and the error's own
|
|
686
|
+
* 4xx/5xx status (else 500) instead of rethrowing it, so a thrown 4xx is
|
|
687
|
+
* recorded with its stack and still answered as a 4xx. Default false.
|
|
688
|
+
*/
|
|
689
|
+
errorResponse?: boolean | ((error: unknown) => boolean);
|
|
620
690
|
}
|
|
621
691
|
/**
|
|
622
692
|
* Report an error that reached a request boundary — a framework error hook,
|
|
@@ -806,6 +876,8 @@ interface AutterLoggingOptions {
|
|
|
806
876
|
sampleRate?: number;
|
|
807
877
|
/** Same semantics as initAutterServer: errors never reported (type or message). */
|
|
808
878
|
ignoreErrors?: IgnoreErrorPattern[];
|
|
879
|
+
/** Same semantics as initAutterServer: errors logged through console.error, pino, winston, bunyan or runtimeLogger.error are occurrences. Default true. */
|
|
880
|
+
captureLoggedErrors?: CaptureLoggedErrorsOption;
|
|
809
881
|
}
|
|
810
882
|
interface AutterLogging {
|
|
811
883
|
captureException(error: unknown, attributes?: Attributes): void;
|
|
@@ -988,4 +1060,4 @@ declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
|
|
|
988
1060
|
*/
|
|
989
1061
|
declare function addBreadcrumb(input: BreadcrumbInput): void;
|
|
990
1062
|
|
|
991
|
-
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 };
|
|
1063
|
+
export { type AutoFlushHandle, type AutoFlushOptions, type AutterErrorHandlerOptions, type AutterErrorResponseOptions, type AutterLogging, type AutterLoggingOptions, type AutterRequestsOptions, type AutterServer, type AutterServerOptions, type AutterSeverity, BreadcrumbInput, COMPAT_MANIFEST, CaptureLoggedErrorsOption, 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, I as IgnoreErrorPattern, B as BreadcrumbInput } from './sinks-
|
|
3
|
-
export {
|
|
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, I as IgnoreErrorPattern, i as CaptureLoggedErrorsOption, B as BreadcrumbInput } from './sinks-CLtQFPnn.js';
|
|
3
|
+
export { j as Breadcrumb, k as BreadcrumbLevel, l as BreadcrumbType, n as CODE_PATTERN, o as ClientErrorBody, p as ConsoleSinkOptions, L as LoggedErrorSource, O as OtlpSinkOptions, q as RuntimeError, r as RuntimeErrorCatalog, s as RuntimeErrorDefinition, t as RuntimeErrorExtras, u as RuntimeErrorFactory, v as RuntimeErrorLike, w as RuntimeErrorOptions, R as RuntimeEvent, x as RuntimeLogContextValue, y as RuntimeSinkContext, z as consoleSink, A as defineRuntimeErrors, D as errorAttributes, E as fileSink, G as isRuntimeErrorLike, H as otlpSink, J as redactAttributes, K as redactText, N as toClientError } from './sinks-CLtQFPnn.js';
|
|
4
4
|
import { Attributes } from '@opentelemetry/api';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -23,6 +23,37 @@ interface RelayOptions {
|
|
|
23
23
|
* `false` to disable (e.g. when a WAF already rate-limits).
|
|
24
24
|
*/
|
|
25
25
|
perIpRateLimit?: number | false;
|
|
26
|
+
/**
|
|
27
|
+
* How the per-client rate limit finds the visitor's address. A caller can
|
|
28
|
+
* write anything into `X-Forwarded-For`, so the relay never takes its
|
|
29
|
+
* first (leftmost) entry unless told to.
|
|
30
|
+
*
|
|
31
|
+
* - `"auto"` (default): works behind any load balancer, CDN or platform
|
|
32
|
+
* proxy without setup. Proxies append the address they saw to the right
|
|
33
|
+
* of the header (or overwrite it), so the relay reads it right to left
|
|
34
|
+
* and takes the first public address, skipping private and loopback
|
|
35
|
+
* hops. The Node handler only does this when the connection itself came
|
|
36
|
+
* from a private address (a proxy on your network); a public peer is the
|
|
37
|
+
* visitor and its header is ignored. On Cloudflare Workers it uses
|
|
38
|
+
* `CF-Connecting-IP`.
|
|
39
|
+
* - a number `n`: exactly `n` proxies you control sit in front; use the
|
|
40
|
+
* entry `n` from the right (Express `trust proxy` semantics). Use `1`
|
|
41
|
+
* for a Node origin behind Cloudflare with no load balancer.
|
|
42
|
+
* - `true`: every proxy in front is yours and strips client values; use
|
|
43
|
+
* the leftmost entry.
|
|
44
|
+
* - `false`: never read the header. The Node handler keys the socket peer;
|
|
45
|
+
* the fetch handler keys one shared bucket for the route.
|
|
46
|
+
*
|
|
47
|
+
* Strings from environment variables are read too (`"auto"`, `"true"`,
|
|
48
|
+
* `"false"`, `"0"`, `"2"`); anything else falls back to `"auto"`.
|
|
49
|
+
*/
|
|
50
|
+
trustProxy?: boolean | "auto" | number | string;
|
|
51
|
+
/**
|
|
52
|
+
* Return the visitor's address yourself (Deno's `info.remoteAddr`, Bun's
|
|
53
|
+
* `server.requestIP`, a header your edge sets). Wins over `trustProxy`
|
|
54
|
+
* when it returns a non-empty string.
|
|
55
|
+
*/
|
|
56
|
+
clientIp?: (request: Request | IncomingMessage) => string | null | undefined;
|
|
26
57
|
/** Called when the async forward fails (default: console.warn). */
|
|
27
58
|
onError?: (err: unknown) => void;
|
|
28
59
|
/**
|
|
@@ -167,6 +198,19 @@ declare const runtimeContext: {
|
|
|
167
198
|
warn(message: string, attributes?: RuntimeLogContext): void;
|
|
168
199
|
/** Log an error and attach it (code/why/fix) to the current summary. */
|
|
169
200
|
error(error: unknown, attributes?: RuntimeLogContext): void;
|
|
201
|
+
/**
|
|
202
|
+
* The app caught `error` and chose to continue on a fallback (RF-02):
|
|
203
|
+
*
|
|
204
|
+
* } catch (err) {
|
|
205
|
+
* runtimeContext.degraded(err, "pricing service down, using cached prices");
|
|
206
|
+
* }
|
|
207
|
+
*
|
|
208
|
+
* Recorded as an occurrence at `warning` severity, marked
|
|
209
|
+
* `autter.handling = "deliberate"` with the reason (grouped by its code
|
|
210
|
+
* when the error has one), never an incident. The current request or
|
|
211
|
+
* operation ends "degraded" unless it failed or set its outcome.
|
|
212
|
+
*/
|
|
213
|
+
degraded(error: unknown, reason: string, attributes?: RuntimeLogContext): void;
|
|
170
214
|
/** Current operation id. */
|
|
171
215
|
readonly id: string | undefined;
|
|
172
216
|
/** Current request id (inherited by child operations and forks). */
|
|
@@ -268,6 +312,20 @@ interface AutterServerOptions {
|
|
|
268
312
|
* Default true; false turns both off.
|
|
269
313
|
*/
|
|
270
314
|
captureGlobalErrors?: boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Errors the app caught and logged count (RF-01): an `Error` passed to
|
|
317
|
+
* `console.error`, pino, winston, bunyan or `runtimeLogger.error` becomes
|
|
318
|
+
* an occurrence at `error` severity, marked `autter.handled` /
|
|
319
|
+
* `autter.handling: "caught"`, with the log line as context
|
|
320
|
+
* (`autter.log.source`, `autter.log.message`). Log lines without an error
|
|
321
|
+
* object are untouched; an error also passed to `captureException` in
|
|
322
|
+
* the same tick is reported once; a burst limit per error type and throw
|
|
323
|
+
* site keeps ten at once, then one every ten seconds (the count left out
|
|
324
|
+
* is reported). It never fails a request on its own. `false` turns it
|
|
325
|
+
* off; an object turns single loggers off, e.g. `{ console: false }`.
|
|
326
|
+
* Default true.
|
|
327
|
+
*/
|
|
328
|
+
captureLoggedErrors?: CaptureLoggedErrorsOption;
|
|
271
329
|
/**
|
|
272
330
|
* Record unhandled promise rejections as errors (severity "error",
|
|
273
331
|
* `autter.unhandled_rejection: true`). Never changes whether the process
|
|
@@ -617,6 +675,18 @@ interface RuntimeRequestOptions {
|
|
|
617
675
|
ignore?: string[];
|
|
618
676
|
/** Receives the log flush promise after the response (serverless `waitUntil`). */
|
|
619
677
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
678
|
+
/**
|
|
679
|
+
* Report thrown errors (default true): `false`, or a predicate per error.
|
|
680
|
+
* An error it turns down is rethrown untouched and does not fail the
|
|
681
|
+
* summary (Next.js `redirect()` / `notFound()` signals).
|
|
682
|
+
*/
|
|
683
|
+
capture?: boolean | ((error: unknown) => boolean);
|
|
684
|
+
/**
|
|
685
|
+
* Answer a thrown error with `toClientError` JSON and the error's own
|
|
686
|
+
* 4xx/5xx status (else 500) instead of rethrowing it, so a thrown 4xx is
|
|
687
|
+
* recorded with its stack and still answered as a 4xx. Default false.
|
|
688
|
+
*/
|
|
689
|
+
errorResponse?: boolean | ((error: unknown) => boolean);
|
|
620
690
|
}
|
|
621
691
|
/**
|
|
622
692
|
* Report an error that reached a request boundary — a framework error hook,
|
|
@@ -806,6 +876,8 @@ interface AutterLoggingOptions {
|
|
|
806
876
|
sampleRate?: number;
|
|
807
877
|
/** Same semantics as initAutterServer: errors never reported (type or message). */
|
|
808
878
|
ignoreErrors?: IgnoreErrorPattern[];
|
|
879
|
+
/** Same semantics as initAutterServer: errors logged through console.error, pino, winston, bunyan or runtimeLogger.error are occurrences. Default true. */
|
|
880
|
+
captureLoggedErrors?: CaptureLoggedErrorsOption;
|
|
809
881
|
}
|
|
810
882
|
interface AutterLogging {
|
|
811
883
|
captureException(error: unknown, attributes?: Attributes): void;
|
|
@@ -988,4 +1060,4 @@ declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
|
|
|
988
1060
|
*/
|
|
989
1061
|
declare function addBreadcrumb(input: BreadcrumbInput): void;
|
|
990
1062
|
|
|
991
|
-
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 };
|
|
1063
|
+
export { type AutoFlushHandle, type AutoFlushOptions, type AutterErrorHandlerOptions, type AutterErrorResponseOptions, type AutterLogging, type AutterLoggingOptions, type AutterRequestsOptions, type AutterServer, type AutterServerOptions, type AutterSeverity, BreadcrumbInput, COMPAT_MANIFEST, CaptureLoggedErrorsOption, 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.js
CHANGED
|
@@ -21,10 +21,12 @@ import {
|
|
|
21
21
|
fingerprintEventAttributes,
|
|
22
22
|
fingerprintValues,
|
|
23
23
|
flushRuntimeLogs,
|
|
24
|
+
isCaptured,
|
|
24
25
|
isError,
|
|
25
26
|
isRuntimeErrorLike,
|
|
26
27
|
local,
|
|
27
28
|
makeRedactor,
|
|
29
|
+
markCaptured,
|
|
28
30
|
normalizeRoutePath,
|
|
29
31
|
noteOperationError,
|
|
30
32
|
notifyException,
|
|
@@ -42,14 +44,17 @@ import {
|
|
|
42
44
|
runtimeLogStats,
|
|
43
45
|
runtimeLogger,
|
|
44
46
|
sanitizeBreadcrumbs,
|
|
47
|
+
setHandledCapture,
|
|
45
48
|
shutdownRuntimeLogger,
|
|
46
49
|
splitFingerprint,
|
|
50
|
+
startLoggedErrorCapture,
|
|
51
|
+
stopLoggedErrorCapture,
|
|
47
52
|
toClientError,
|
|
48
53
|
withRuntimeOperation
|
|
49
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-HHKQ3UCH.js";
|
|
50
55
|
import {
|
|
51
56
|
runDoctor
|
|
52
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-JSGGUWRD.js";
|
|
53
58
|
import {
|
|
54
59
|
COMPAT_MANIFEST,
|
|
55
60
|
CountingExporter,
|
|
@@ -71,7 +76,7 @@ import {
|
|
|
71
76
|
sharedSlot,
|
|
72
77
|
telemetryStats,
|
|
73
78
|
unregisterFlushTargets
|
|
74
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-ZKM76SDP.js";
|
|
75
80
|
|
|
76
81
|
// src/relay.ts
|
|
77
82
|
var IpWindow = class {
|
|
@@ -96,6 +101,112 @@ function firstForwardedFor(value) {
|
|
|
96
101
|
const raw = Array.isArray(value) ? value[0] : value;
|
|
97
102
|
return raw ? (raw.split(",")[0] ?? "").trim() : "";
|
|
98
103
|
}
|
|
104
|
+
var TRUST_AUTO = { mode: "auto" };
|
|
105
|
+
var warnedTrustProxy = false;
|
|
106
|
+
function resolveTrustProxy(value) {
|
|
107
|
+
if (value === void 0 || value === null || value === "auto") return TRUST_AUTO;
|
|
108
|
+
if (value === true) return { mode: "all" };
|
|
109
|
+
if (value === false || value === 0) return { mode: "never" };
|
|
110
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 100) {
|
|
111
|
+
return { mode: "hops", hops: value };
|
|
112
|
+
}
|
|
113
|
+
if (typeof value === "string") {
|
|
114
|
+
const v = value.trim().toLowerCase();
|
|
115
|
+
if (v === "" || v === "auto") return TRUST_AUTO;
|
|
116
|
+
if (v === "false" || v === "0" || v === "no" || v === "off") return { mode: "never" };
|
|
117
|
+
if (v === "true" || v === "yes" || v === "on") return { mode: "all" };
|
|
118
|
+
if (/^[1-9][0-9]?$/.test(v)) return { mode: "hops", hops: Number(v) };
|
|
119
|
+
}
|
|
120
|
+
if (!warnedTrustProxy) {
|
|
121
|
+
warnedTrustProxy = true;
|
|
122
|
+
console.warn(
|
|
123
|
+
`[autter-runtime] relay: trustProxy ${JSON.stringify(value)} is not recognised; using "auto".`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return TRUST_AUTO;
|
|
127
|
+
}
|
|
128
|
+
var IPV4_RE = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/;
|
|
129
|
+
function normalizeAddress(entry) {
|
|
130
|
+
if (!entry) return null;
|
|
131
|
+
let a = entry.trim();
|
|
132
|
+
if (!a || a.length > 64) return null;
|
|
133
|
+
const bracketed = /^\[([0-9A-Fa-f:.]+)\](?::\d{1,5})?$/.exec(a);
|
|
134
|
+
if (bracketed) a = bracketed[1] ?? "";
|
|
135
|
+
else if (/^[\d.]+:\d{1,5}$/.test(a)) a = a.slice(0, a.lastIndexOf(":"));
|
|
136
|
+
a = a.toLowerCase();
|
|
137
|
+
if (a.startsWith("::ffff:") && IPV4_RE.test(a.slice(7))) a = a.slice(7);
|
|
138
|
+
if (IPV4_RE.test(a)) return a;
|
|
139
|
+
if (/^[0-9a-f:]+(:(\d{1,3}\.){3}\d{1,3})?$/.test(a) && a.includes(":") && a.split(":").length <= 9) {
|
|
140
|
+
return a;
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
function isPrivateAddress(a) {
|
|
145
|
+
if (IPV4_RE.test(a)) {
|
|
146
|
+
const [x, y] = a.split(".").map(Number);
|
|
147
|
+
return x === 10 || x === 127 || x === 0 || x === 169 && y === 254 || x === 172 && y >= 16 && y <= 31 || x === 192 && y === 168 || x === 100 && y >= 64 && y <= 127;
|
|
148
|
+
}
|
|
149
|
+
return a === "::1" || a === "::" || /^f[cd]/.test(a) || /^fe[89ab]/.test(a);
|
|
150
|
+
}
|
|
151
|
+
function forwardedEntries(value) {
|
|
152
|
+
const raw = Array.isArray(value) ? value.join(",") : value;
|
|
153
|
+
if (!raw) return [];
|
|
154
|
+
const out = [];
|
|
155
|
+
for (const part of raw.split(",")) {
|
|
156
|
+
const a = normalizeAddress(part);
|
|
157
|
+
if (a) out.push(a);
|
|
158
|
+
}
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
function rightmostPublic(entries) {
|
|
162
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
163
|
+
const a = entries[i];
|
|
164
|
+
if (a && !isPrivateAddress(a)) return a;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function fromCustom(opts, request) {
|
|
169
|
+
if (!opts.clientIp) return null;
|
|
170
|
+
try {
|
|
171
|
+
const v = opts.clientIp(request);
|
|
172
|
+
return typeof v === "string" && v.trim() ? v.trim().slice(0, 64) : null;
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function fetchClientKey(request, opts) {
|
|
178
|
+
const custom = fromCustom(opts, request);
|
|
179
|
+
if (custom) return custom;
|
|
180
|
+
const trust = resolveTrustProxy(opts.trustProxy);
|
|
181
|
+
if (trust.mode === "never") return "shared";
|
|
182
|
+
const header = request.headers.get("x-forwarded-for");
|
|
183
|
+
if (trust.mode === "all") return firstForwardedFor(header) || "shared";
|
|
184
|
+
const entries = forwardedEntries(header);
|
|
185
|
+
if (trust.mode === "hops") {
|
|
186
|
+
return entries[Math.max(0, entries.length - trust.hops)] ?? "shared";
|
|
187
|
+
}
|
|
188
|
+
const cf = request.cf;
|
|
189
|
+
if (cf !== null && typeof cf === "object") {
|
|
190
|
+
const viaCf = normalizeAddress(request.headers.get("cf-connecting-ip"));
|
|
191
|
+
if (viaCf) return viaCf;
|
|
192
|
+
}
|
|
193
|
+
return rightmostPublic(entries) ?? entries[entries.length - 1] ?? "shared";
|
|
194
|
+
}
|
|
195
|
+
function nodeClientKey(req, opts) {
|
|
196
|
+
const custom = fromCustom(opts, req);
|
|
197
|
+
if (custom) return custom;
|
|
198
|
+
const trust = resolveTrustProxy(opts.trustProxy);
|
|
199
|
+
const peer = normalizeAddress(req.socket?.remoteAddress);
|
|
200
|
+
if (trust.mode === "never") return peer ?? "unknown";
|
|
201
|
+
const header = req.headers["x-forwarded-for"];
|
|
202
|
+
if (trust.mode === "all") return firstForwardedFor(header) || peer || "unknown";
|
|
203
|
+
const entries = forwardedEntries(header);
|
|
204
|
+
if (trust.mode === "hops") {
|
|
205
|
+
return entries[Math.max(0, entries.length - trust.hops)] ?? peer ?? "unknown";
|
|
206
|
+
}
|
|
207
|
+
if (peer && !isPrivateAddress(peer)) return peer;
|
|
208
|
+
return rightmostPublic(entries) ?? peer ?? entries[entries.length - 1] ?? "unknown";
|
|
209
|
+
}
|
|
99
210
|
var DEFAULT_ENDPOINT = "https://otlp.autter.dev";
|
|
100
211
|
var DEFAULT_MAX_BODY = 64 * 1024;
|
|
101
212
|
var MAX_EVENTS = 50;
|
|
@@ -329,7 +440,7 @@ function createBrowserRelayFetchHandler(opts) {
|
|
|
329
440
|
return new Response(null, { status: 405 });
|
|
330
441
|
}
|
|
331
442
|
if (limiter) {
|
|
332
|
-
const ip =
|
|
443
|
+
const ip = fetchClientKey(request, opts);
|
|
333
444
|
if (!limiter.allow(ip)) {
|
|
334
445
|
return new Response(JSON.stringify({ error: "rate limit exceeded" }), {
|
|
335
446
|
status: 429
|
|
@@ -395,7 +506,7 @@ function createBrowserRelayHandler(opts) {
|
|
|
395
506
|
return;
|
|
396
507
|
}
|
|
397
508
|
if (limiter) {
|
|
398
|
-
const ip =
|
|
509
|
+
const ip = nodeClientKey(req, opts);
|
|
399
510
|
if (!limiter.allow(ip)) {
|
|
400
511
|
respond(res, 429, { error: "rate limit exceeded" });
|
|
401
512
|
return;
|
|
@@ -746,7 +857,6 @@ import { context, trace } from "@opentelemetry/api";
|
|
|
746
857
|
import { getRPCMetadata, RPCType } from "@opentelemetry/core";
|
|
747
858
|
var REQUEST_STATE = /* @__PURE__ */ Symbol.for("autter.runtime.request");
|
|
748
859
|
var BOUND = /* @__PURE__ */ Symbol.for("autter.runtime.bound");
|
|
749
|
-
var CAPTURED = sharedSlot("requests", () => ({ captured: /* @__PURE__ */ new WeakSet() })).captured;
|
|
750
860
|
var capturer = () => {
|
|
751
861
|
};
|
|
752
862
|
function setRequestExceptionCapturer(fn) {
|
|
@@ -757,8 +867,14 @@ var annotator = () => {
|
|
|
757
867
|
function setRequestSpanAnnotator(fn) {
|
|
758
868
|
annotator = fn;
|
|
759
869
|
}
|
|
760
|
-
function
|
|
761
|
-
if (
|
|
870
|
+
function decide(rule, error, fallback) {
|
|
871
|
+
if (rule === void 0) return fallback;
|
|
872
|
+
if (typeof rule !== "function") return rule;
|
|
873
|
+
try {
|
|
874
|
+
return rule(error) === true;
|
|
875
|
+
} catch {
|
|
876
|
+
return false;
|
|
877
|
+
}
|
|
762
878
|
}
|
|
763
879
|
function expressRouteOf(req) {
|
|
764
880
|
const props = req;
|
|
@@ -789,7 +905,7 @@ function captureAtBoundary(error, state, rule = void 0, attributes) {
|
|
|
789
905
|
wanted = false;
|
|
790
906
|
}
|
|
791
907
|
if (!wanted) return;
|
|
792
|
-
if (
|
|
908
|
+
if (isCaptured(error)) return;
|
|
793
909
|
markCaptured(error);
|
|
794
910
|
try {
|
|
795
911
|
const run = () => onRequestSpan(() => capturer(error, attributes));
|
|
@@ -803,7 +919,7 @@ function requestStateOf(req) {
|
|
|
803
919
|
return req[REQUEST_STATE];
|
|
804
920
|
}
|
|
805
921
|
function captureRequestError(error, attributes) {
|
|
806
|
-
if (
|
|
922
|
+
if (isCaptured(error)) {
|
|
807
923
|
if (!attributes) return;
|
|
808
924
|
try {
|
|
809
925
|
onRequestSpan(() => annotator(attributes));
|
|
@@ -895,7 +1011,8 @@ function finishRequest(state, input) {
|
|
|
895
1011
|
...state.error !== void 0 ? { error: state.error } : {},
|
|
896
1012
|
...state.errorThrown ? { thrown: true } : {},
|
|
897
1013
|
status: input.status,
|
|
898
|
-
aborted: input.aborted
|
|
1014
|
+
aborted: input.aborted,
|
|
1015
|
+
...state.degraded ? { degraded: true } : {}
|
|
899
1016
|
});
|
|
900
1017
|
const span = trace.getActiveSpan();
|
|
901
1018
|
if (span?.isRecording()) span.setAttribute("autter.operation.outcome", state.outcome);
|
|
@@ -1120,9 +1237,15 @@ function withRuntimeRequest(handler, options = {}) {
|
|
|
1120
1237
|
try {
|
|
1121
1238
|
return await handler(request, ...rest);
|
|
1122
1239
|
} catch (error) {
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1240
|
+
if (decide(options.capture, error, true)) {
|
|
1241
|
+
noteOperationError(error, true, state);
|
|
1242
|
+
captureAtBoundary(error, state, true);
|
|
1243
|
+
}
|
|
1244
|
+
if (!decide(options.errorResponse, error, false)) throw error;
|
|
1245
|
+
return new Response(JSON.stringify(toClientError(error, requestId)), {
|
|
1246
|
+
status: responseStatusOf(error),
|
|
1247
|
+
headers: { "content-type": "application/json; charset=utf-8" }
|
|
1248
|
+
});
|
|
1126
1249
|
}
|
|
1127
1250
|
});
|
|
1128
1251
|
status = response.status;
|
|
@@ -1320,6 +1443,8 @@ var S = sharedSlot("server", () => ({
|
|
|
1320
1443
|
alwaysOnProvider: null,
|
|
1321
1444
|
redactor: makeRedactor(true),
|
|
1322
1445
|
loggerOnlyCapture: null,
|
|
1446
|
+
handled: null,
|
|
1447
|
+
loggerOnlyHandled: null,
|
|
1323
1448
|
hookRequests: false
|
|
1324
1449
|
}));
|
|
1325
1450
|
var LLM_MARKER_ATTRIBUTES = [
|
|
@@ -1896,6 +2021,37 @@ function initAutterServer(options) {
|
|
|
1896
2021
|
span.setStatus({ code: SpanStatusCode.ERROR, message: safeMessage });
|
|
1897
2022
|
if (!reuseActive) span.end();
|
|
1898
2023
|
}
|
|
2024
|
+
function captureHandled(error, attributes, severity) {
|
|
2025
|
+
const isErr = isError(error);
|
|
2026
|
+
if (!errorFilter({
|
|
2027
|
+
type: isErr ? String(error.name ?? "") : "Error",
|
|
2028
|
+
message: isErr ? String(error.message ?? "") : String(error),
|
|
2029
|
+
severity
|
|
2030
|
+
})) return;
|
|
2031
|
+
if (severity === "error") errorTraceBuffer?.retainActiveTrace();
|
|
2032
|
+
telemetryStats.markCaptured();
|
|
2033
|
+
const message = redactor.text(isErr ? error.message : String(error));
|
|
2034
|
+
const stack = isErr && error.stack ? error.stack : new Error().stack?.split("\n").filter((line, i) => i === 0 || !/captureHandled|report(?:Degraded|LoggedError)/.test(line)).join("\n");
|
|
2035
|
+
const split = splitFingerprint(attributes);
|
|
2036
|
+
const fingerprint = fingerprintEventAttributes(split.fingerprint, redactor.text);
|
|
2037
|
+
const redacted = redactor(split.attributes);
|
|
2038
|
+
const activeSpan = trace2.getActiveSpan();
|
|
2039
|
+
const reuseActive = activeSpan?.isRecording() === true;
|
|
2040
|
+
const span = reuseActive ? activeSpan : errorTracer.startSpan(isErr ? error.name : "Error");
|
|
2041
|
+
markCaptured(error);
|
|
2042
|
+
notifyException(error, { ...redacted, ...fingerprint, "autter.severity": severity });
|
|
2043
|
+
span.addEvent("exception", {
|
|
2044
|
+
...redacted,
|
|
2045
|
+
"exception.type": isErr ? error.name : "Error",
|
|
2046
|
+
"exception.message": message,
|
|
2047
|
+
...stack ? { "exception.stacktrace": redactor.text(stack) } : {},
|
|
2048
|
+
"autter.severity": severity,
|
|
2049
|
+
...errorAttributes(error),
|
|
2050
|
+
...fingerprint,
|
|
2051
|
+
...breadcrumbEventAttributes(redactor.text, error)
|
|
2052
|
+
});
|
|
2053
|
+
if (!reuseActive) span.end();
|
|
2054
|
+
}
|
|
1899
2055
|
configureRuntimeLogger({
|
|
1900
2056
|
endpoint,
|
|
1901
2057
|
apiKey: options.apiKey,
|
|
@@ -1909,6 +2065,8 @@ function initAutterServer(options) {
|
|
|
1909
2065
|
reportOutcome: reportOutcome2
|
|
1910
2066
|
});
|
|
1911
2067
|
S.hookRequests = options.logging?.requests === true;
|
|
2068
|
+
S.handled = captureHandled;
|
|
2069
|
+
startLoggedErrorCapture(options.captureLoggedErrors);
|
|
1912
2070
|
let onCrash = null;
|
|
1913
2071
|
let uninstallRejections = null;
|
|
1914
2072
|
if (options.captureGlobalErrors !== false) {
|
|
@@ -1955,6 +2113,7 @@ function initAutterServer(options) {
|
|
|
1955
2113
|
withLlmCall: (info, fn) => runLlmSpan(llmTracer, info, fn),
|
|
1956
2114
|
trackLlmCall: (call) => recordLlmCall(llmTracer, call),
|
|
1957
2115
|
shutdown: async () => {
|
|
2116
|
+
if (S.active === server) stopLoggedErrorCapture();
|
|
1958
2117
|
const logShutdown = await Promise.allSettled([shutdownRuntimeLogger()]);
|
|
1959
2118
|
if (onCrash) process.off("uncaughtExceptionMonitor", onCrash);
|
|
1960
2119
|
uninstallRejections?.();
|
|
@@ -1962,6 +2121,7 @@ function initAutterServer(options) {
|
|
|
1962
2121
|
if (S.active === server) {
|
|
1963
2122
|
S.active = null;
|
|
1964
2123
|
S.alwaysOnProvider = null;
|
|
2124
|
+
S.handled = null;
|
|
1965
2125
|
S.hookRequests = false;
|
|
1966
2126
|
S.redactor = makeRedactor(true);
|
|
1967
2127
|
}
|
|
@@ -1997,13 +2157,39 @@ function captureException(error, attributes) {
|
|
|
1997
2157
|
recordError(span, error);
|
|
1998
2158
|
span.end();
|
|
1999
2159
|
}
|
|
2000
|
-
function setLoggerOnlyCapture(fn) {
|
|
2160
|
+
function setLoggerOnlyCapture(fn, handled = null) {
|
|
2001
2161
|
S.loggerOnlyCapture = fn;
|
|
2162
|
+
S.loggerOnlyHandled = handled;
|
|
2163
|
+
}
|
|
2164
|
+
function captureHandledError(error, attributes, severity) {
|
|
2165
|
+
if (S.active) {
|
|
2166
|
+
S.handled?.(error, attributes, severity);
|
|
2167
|
+
return;
|
|
2168
|
+
}
|
|
2169
|
+
if (S.loggerOnlyHandled) {
|
|
2170
|
+
S.loggerOnlyHandled(error, attributes, severity);
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
markCaptured(error);
|
|
2174
|
+
const split = splitFingerprint(attributes);
|
|
2175
|
+
notifyException(error, { ...split.attributes, "autter.severity": severity });
|
|
2176
|
+
const span = trace2.getTracer("autter-errors").startSpan(isError(error) ? error.name : "Error");
|
|
2177
|
+
span.addEvent("exception", {
|
|
2178
|
+
...S.redactor(split.attributes),
|
|
2179
|
+
"exception.type": isError(error) ? error.name : "Error",
|
|
2180
|
+
"exception.message": S.redactor.text(isError(error) ? error.message : String(error)),
|
|
2181
|
+
...isError(error) && error.stack ? { "exception.stacktrace": S.redactor.text(error.stack) } : {},
|
|
2182
|
+
"autter.severity": severity,
|
|
2183
|
+
...errorAttributes(error),
|
|
2184
|
+
...fingerprintEventAttributes(split.fingerprint, S.redactor.text)
|
|
2185
|
+
});
|
|
2186
|
+
span.end();
|
|
2002
2187
|
}
|
|
2003
2188
|
function serverActive() {
|
|
2004
2189
|
return S.active !== null;
|
|
2005
2190
|
}
|
|
2006
2191
|
setRequestExceptionCapturer((error, attributes) => captureException(error, attributes));
|
|
2192
|
+
setHandledCapture(captureHandledError);
|
|
2007
2193
|
setRequestSpanAnnotator((attributes) => {
|
|
2008
2194
|
const span = trace2.getActiveSpan();
|
|
2009
2195
|
if (span?.isRecording()) span.setAttributes(S.redactor(splitFingerprint(attributes).attributes));
|
|
@@ -2474,6 +2660,33 @@ function initAutterLogging(options) {
|
|
|
2474
2660
|
notifyException(error, { ...redacted, ...fingerprint });
|
|
2475
2661
|
captureExceptionAsLog(error, { ...redacted, ...fingerprint });
|
|
2476
2662
|
}
|
|
2663
|
+
function captureHandled(error, attributes, severity) {
|
|
2664
|
+
markCaptured(error);
|
|
2665
|
+
const isErrValue = isError(error);
|
|
2666
|
+
if (!errorFilter({
|
|
2667
|
+
type: isErrValue ? String(error.name ?? "") : "Error",
|
|
2668
|
+
message: isErrValue ? String(error.message ?? "") : String(error),
|
|
2669
|
+
severity
|
|
2670
|
+
})) return;
|
|
2671
|
+
const split = splitFingerprint(attributes);
|
|
2672
|
+
const fingerprint = fingerprintEventAttributes(split.fingerprint, redact.text);
|
|
2673
|
+
const redacted = redact(split.attributes);
|
|
2674
|
+
notifyException(error, { ...redacted, ...fingerprint, "autter.severity": severity });
|
|
2675
|
+
const span = trace3.getActiveSpan();
|
|
2676
|
+
if (mode === "auto" && span?.isRecording()) {
|
|
2677
|
+
span.addEvent("exception", {
|
|
2678
|
+
...redacted,
|
|
2679
|
+
"exception.type": isErrValue ? error.name : "Error",
|
|
2680
|
+
"exception.message": redact.text(isErrValue ? error.message : String(error)),
|
|
2681
|
+
...isErrValue && error.stack ? { "exception.stacktrace": redact.text(error.stack) } : {},
|
|
2682
|
+
"autter.severity": severity,
|
|
2683
|
+
...errorAttributes(error),
|
|
2684
|
+
...fingerprint
|
|
2685
|
+
});
|
|
2686
|
+
return;
|
|
2687
|
+
}
|
|
2688
|
+
captureExceptionAsLog(error, { ...redacted, ...fingerprint }, severity);
|
|
2689
|
+
}
|
|
2477
2690
|
const captured = /* @__PURE__ */ new WeakSet();
|
|
2478
2691
|
configureRuntimeLogger({
|
|
2479
2692
|
endpoint,
|
|
@@ -2498,7 +2711,8 @@ function initAutterLogging(options) {
|
|
|
2498
2711
|
captureException2(error);
|
|
2499
2712
|
}
|
|
2500
2713
|
});
|
|
2501
|
-
setLoggerOnlyCapture(captureException2);
|
|
2714
|
+
setLoggerOnlyCapture(captureException2, captureHandled);
|
|
2715
|
+
startLoggedErrorCapture(options.captureLoggedErrors);
|
|
2502
2716
|
const onCrash = (error) => {
|
|
2503
2717
|
if (recordedAsRejection(error)) return;
|
|
2504
2718
|
captureException2(error, { "autter.unhandled": true });
|
|
@@ -2517,6 +2731,7 @@ function initAutterLogging(options) {
|
|
|
2517
2731
|
captureException: captureException2,
|
|
2518
2732
|
flush: flushRuntimeLogs,
|
|
2519
2733
|
shutdown: async () => {
|
|
2734
|
+
if (L.active === handle) stopLoggedErrorCapture();
|
|
2520
2735
|
process.off("uncaughtExceptionMonitor", onCrash);
|
|
2521
2736
|
uninstallRejections?.();
|
|
2522
2737
|
uninstallRejections = null;
|