autotel 6.5.0 → 7.0.1
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 +30 -23
- package/dist/{attribute-redacting-processor-Pk7lAzWd.d.cts → attribute-redacting-processor-CvBE0z1p.d.cts} +33 -1
- package/dist/{attribute-redacting-processor-Pk7lAzWd.d.ts → attribute-redacting-processor-CvBE0z1p.d.ts} +33 -1
- package/dist/attribute-redacting-processor.cjs +34 -32
- package/dist/attribute-redacting-processor.d.cts +1 -1
- package/dist/attribute-redacting-processor.d.ts +1 -1
- package/dist/attribute-redacting-processor.js +35 -32
- package/dist/{attributes-aDmJYral.cjs → attributes-Cxys8tgr.cjs} +34 -35
- package/dist/{attributes-B7wix2VG.js → attributes-Dt4YUYbP.js} +34 -35
- package/dist/attributes.cjs +1 -1
- package/dist/attributes.d.cts +1 -1
- package/dist/attributes.d.ts +1 -1
- package/dist/attributes.js +1 -1
- package/dist/auto.cjs +1 -1
- package/dist/auto.js +1 -1
- package/dist/business-baggage.cjs +19 -12
- package/dist/business-baggage.d.cts +8 -3
- package/dist/business-baggage.d.ts +8 -3
- package/dist/business-baggage.js +19 -12
- package/dist/{canonical-log-line-processor-DxtBGZIi.cjs → canonical-log-line-processor-DolzdawH.cjs} +43 -32
- package/dist/{canonical-log-line-processor-B4WgG-VS.d.cts → canonical-log-line-processor-cPB4Axk-.d.ts} +4 -3
- package/dist/{canonical-log-line-processor-B0vq_QR6.js → canonical-log-line-processor-hFUmS__K.js} +43 -32
- package/dist/{canonical-log-line-processor-CL_J7gb5.d.ts → canonical-log-line-processor-l0Aqe6yp.d.cts} +4 -3
- package/dist/config.d.cts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/{correlated-events-kSwLo3mi.cjs → correlated-events-CcuknWnU.cjs} +2 -1
- package/dist/{correlated-events-Bzh5y-UB.js → correlated-events-DwMMbItg.js} +3 -1
- package/dist/correlation-id.cjs +1 -1
- package/dist/correlation-id.js +1 -1
- package/dist/db.cjs +34 -19
- package/dist/db.js +34 -19
- package/dist/decorators.cjs +4 -2
- package/dist/decorators.d.cts +16 -11
- package/dist/decorators.d.ts +16 -11
- package/dist/decorators.js +4 -2
- package/dist/{define-event-CGG048HE.d.cts → define-event-BNeuKUPv.d.cts} +1 -1
- package/dist/{define-event-B2z1SBe7.d.ts → define-event-Bd8f8mST.d.ts} +1 -1
- package/dist/diagnostics.cjs +18 -16
- package/dist/diagnostics.d.cts +14 -10
- package/dist/diagnostics.d.ts +14 -10
- package/dist/diagnostics.js +18 -16
- package/dist/{event-subscriber-CWh8sTGh.d.cts → event-subscriber-DMACQA-1.d.cts} +19 -9
- package/dist/{event-subscriber-CWh8sTGh.d.ts → event-subscriber-DMACQA-1.d.ts} +19 -9
- package/dist/event-subscriber.d.cts +2 -2
- package/dist/event-subscriber.d.ts +2 -2
- package/dist/{event-testing-D0qWfqAy.d.cts → event-testing-CBtnJXE5.d.cts} +1 -1
- package/dist/{event-testing-CA2mIx1E.d.ts → event-testing-CkPgV3Ii.d.ts} +1 -1
- package/dist/event-testing.d.cts +1 -1
- package/dist/event-testing.d.ts +1 -1
- package/dist/event.cjs +1 -1
- package/dist/event.d.cts +5 -5
- package/dist/event.d.ts +5 -5
- package/dist/event.js +1 -1
- package/dist/exception-fingerprint.cjs +133 -0
- package/dist/exception-fingerprint.d.cts +51 -0
- package/dist/exception-fingerprint.d.ts +51 -0
- package/dist/exception-fingerprint.js +126 -0
- package/dist/{functional-C0uAZq2X.cjs → functional-C2ONG9PK.cjs} +27 -15
- package/dist/{functional-e6jw5zQj.d.cts → functional-CJn2zY4o.d.cts} +96 -39
- package/dist/{functional-AT22vCw6.d.ts → functional-DXy1cHFF.d.ts} +96 -39
- package/dist/{functional-DX7Zvag0.js → functional-nS5U4KCQ.js} +27 -15
- package/dist/functional.cjs +1 -1
- package/dist/functional.d.cts +2 -2
- package/dist/functional.d.ts +2 -2
- package/dist/functional.js +1 -1
- package/dist/http.cjs +11 -8
- package/dist/http.js +11 -8
- package/dist/{index-DolOVX6F.d.ts → index-CwrNAsgk.d.ts} +22 -26
- package/dist/{index-BPcxVucm.d.cts → index-DQHf4cNl.d.cts} +22 -26
- package/dist/index.cjs +41 -35
- package/dist/index.d.cts +45 -30
- package/dist/index.d.ts +45 -30
- package/dist/index.js +41 -35
- package/dist/{init-pPI3JRRf.d.ts → init-BgnYi2sm.d.ts} +6 -6
- package/dist/{init-CTtHITlX.cjs → init-C5aHRqi2.cjs} +111 -85
- package/dist/{init-WHYwyItd.js → init-DDyaLzeg.js} +106 -86
- package/dist/{init-ncTMKZ-s.d.cts → init-DrlL1eis.d.cts} +6 -6
- package/dist/instrumentation.cjs +2 -2
- package/dist/instrumentation.js +2 -2
- package/dist/{logger-D3Ej3DII.js → logger-DdPp__xW.js} +63 -54
- package/dist/{logger-CN4xpzMd.d.cts → logger-S1Fgl0g3.d.cts} +0 -20
- package/dist/{logger-CN4xpzMd.d.ts → logger-S1Fgl0g3.d.ts} +0 -20
- package/dist/{logger-thMPLpOG.cjs → logger-Sm66cjKl.cjs} +63 -54
- package/dist/logger.cjs +1 -1
- package/dist/logger.d.cts +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +1 -1
- package/dist/messaging-adapters.cjs +26 -12
- package/dist/messaging-adapters.d.cts +0 -30
- package/dist/messaging-adapters.d.ts +0 -30
- package/dist/messaging-adapters.js +26 -12
- package/dist/messaging.cjs +37 -34
- package/dist/messaging.d.cts +21 -62
- package/dist/messaging.d.ts +21 -62
- package/dist/messaging.js +37 -34
- package/dist/{metric-testing-CpvP3ZIa.d.cts → metric-testing-86WO1wan.d.cts} +1 -1
- package/dist/{metric-testing-CWm6UhaR.d.ts → metric-testing-CbCxdPBp.d.ts} +1 -1
- package/dist/metric-testing.d.cts +1 -1
- package/dist/metric-testing.d.ts +1 -1
- package/dist/metric.d.cts +3 -3
- package/dist/metric.d.ts +3 -3
- package/dist/{node-require-vROmTeJ8.js → node-require-DSPjaw_l.js} +3 -2
- package/dist/{node-require-PFqDihze.cjs → node-require-EifOMikz.cjs} +3 -2
- package/dist/parse-error.cjs +18 -12
- package/dist/parse-error.d.cts +2 -1
- package/dist/parse-error.d.ts +2 -1
- package/dist/parse-error.js +19 -12
- package/dist/policy.cjs +0 -0
- package/dist/policy.js +0 -0
- package/dist/processors.cjs +1 -1
- package/dist/processors.d.cts +1 -1
- package/dist/processors.d.ts +1 -1
- package/dist/processors.js +1 -1
- package/dist/{sampling-BR9fkSwx.d.cts → sampling-CM5S2Lp3.d.ts} +5 -6
- package/dist/{sampling-CP3e7-Yr.d.ts → sampling-CmRdnXUi.d.cts} +5 -6
- package/dist/sampling.cjs +3 -2
- package/dist/sampling.d.cts +1 -1
- package/dist/sampling.d.ts +1 -1
- package/dist/sampling.js +3 -2
- package/dist/semantic-helpers.cjs +9 -9
- package/dist/semantic-helpers.d.cts +1 -1
- package/dist/semantic-helpers.d.ts +1 -1
- package/dist/semantic-helpers.js +9 -9
- package/dist/{stable-hash-ChFBIhNt.js → stable-hash-BkoAYVks.js} +4 -3
- package/dist/{stable-hash-CS9BxvVQ.cjs → stable-hash-C0pOegH_.cjs} +4 -3
- package/dist/{structured-error-CHg7DoIQ.cjs → structured-error--_wXpd_C.cjs} +34 -25
- package/dist/{structured-error-9--cxBay.js → structured-error-YIuka-FE.js} +34 -25
- package/dist/test-span-collector.cjs +15 -8
- package/dist/test-span-collector.js +15 -8
- package/dist/testing.cjs +16 -18
- package/dist/testing.d.cts +7 -6
- package/dist/testing.d.ts +7 -6
- package/dist/testing.js +16 -18
- package/dist/{trace-context-IuyoPyNq.d.cts → trace-context-C1Cn1q0y.d.cts} +8 -7
- package/dist/{trace-context-IuyoPyNq.d.ts → trace-context-f89xPJbK.d.ts} +8 -7
- package/dist/trace-helpers.cjs +16 -13
- package/dist/trace-helpers.d.cts +9 -4
- package/dist/trace-helpers.d.ts +9 -4
- package/dist/trace-helpers.js +16 -13
- package/dist/tracer-provider.cjs +8 -12
- package/dist/tracer-provider.js +8 -12
- package/dist/validate.cjs +22 -20
- package/dist/validate.d.cts +3 -2
- package/dist/validate.d.ts +3 -2
- package/dist/validate.js +22 -20
- package/dist/values-BenyvWKz.js +141 -0
- package/dist/values-CeMH-mYG.d.cts +8 -0
- package/dist/values-CeMH-mYG.d.ts +8 -0
- package/dist/values-DApyq53y.cjs +267 -0
- package/dist/webhook.cjs +3 -3
- package/dist/webhook.d.cts +1 -1
- package/dist/webhook.d.ts +1 -1
- package/dist/webhook.js +3 -3
- package/dist/workflow-distributed.cjs +9 -7
- package/dist/workflow-distributed.d.cts +9 -8
- package/dist/workflow-distributed.d.ts +9 -8
- package/dist/workflow-distributed.js +9 -7
- package/dist/workflow.cjs +26 -17
- package/dist/workflow.d.cts +1 -28
- package/dist/workflow.d.ts +1 -28
- package/dist/workflow.js +26 -17
- package/dist/yaml-config.cjs +26 -11
- package/dist/yaml-config.d.cts +9 -3
- package/dist/yaml-config.d.ts +9 -3
- package/dist/yaml-config.js +26 -11
- package/package.json +6 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
2
|
+
//#region src/exception-fingerprint.d.ts
|
|
3
|
+
/** Attribute the fingerprint is written to. */
|
|
4
|
+
declare const EXCEPTION_FINGERPRINT_ATTRIBUTE = "exception.fingerprint";
|
|
5
|
+
interface ExceptionInput {
|
|
6
|
+
/** Error class name, e.g. `TypeError`. Defaults to `Error`. */
|
|
7
|
+
type?: string;
|
|
8
|
+
/** Error message. Only used for grouping when there is no usable stack. */
|
|
9
|
+
message?: string;
|
|
10
|
+
/** Raw stack string, as `Error.stack` produces it. */
|
|
11
|
+
stack?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Collapse a path to the part that identifies the code rather than the machine
|
|
15
|
+
* it ran on: a dependency becomes its package name, and an absolute path
|
|
16
|
+
* becomes the project-relative one. Without this, the same error fingerprints
|
|
17
|
+
* differently in CI, in Docker, and on a laptop.
|
|
18
|
+
*/
|
|
19
|
+
declare function normalizeFilePath(filePath: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Strip the parts of a message that change on every occurrence, so
|
|
22
|
+
* `timeout after 341ms` and `timeout after 78ms` are one issue rather than two.
|
|
23
|
+
*/
|
|
24
|
+
declare function normalizeMessage(message: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* `function@normalized-path` for the top N frames. Line and column are
|
|
27
|
+
* deliberately dropped: an edit one line above the throw is the same bug.
|
|
28
|
+
*/
|
|
29
|
+
declare function normalizeStackFrames(stack: string, count: number): string[];
|
|
30
|
+
/** 32-bit djb2-style hash, rendered as 8 hex characters. */
|
|
31
|
+
declare function hashFingerprintParts(parts: string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Group key for an exception. Returns `undefined` when there is nothing to
|
|
34
|
+
* group on, so callers never write an attribute that means "no information".
|
|
35
|
+
*/
|
|
36
|
+
declare function fingerprintException(input: ExceptionInput, frames?: number): string | undefined;
|
|
37
|
+
interface ExceptionFingerprintOptions {
|
|
38
|
+
/** Stack frames to fingerprint on. @default 5 */
|
|
39
|
+
frames?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Span enricher that stamps {@link EXCEPTION_FINGERPRINT_ATTRIBUTE} on every
|
|
43
|
+
* span that recorded an exception.
|
|
44
|
+
*
|
|
45
|
+
* Pass it to `init({ spanEnrichers: [...] })` rather than `spanProcessors`:
|
|
46
|
+
* enrichers add to the pipeline instead of replacing it, and sit outside the
|
|
47
|
+
* redaction wrapper so the attribute reaches every exporter.
|
|
48
|
+
*/
|
|
49
|
+
declare function exceptionFingerprint(options?: ExceptionFingerprintOptions): SpanProcessor;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { EXCEPTION_FINGERPRINT_ATTRIBUTE, ExceptionFingerprintOptions, ExceptionInput, exceptionFingerprint, fingerprintException, hashFingerprintParts, normalizeFilePath, normalizeMessage, normalizeStackFrames };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
2
|
+
//#region src/exception-fingerprint.d.ts
|
|
3
|
+
/** Attribute the fingerprint is written to. */
|
|
4
|
+
declare const EXCEPTION_FINGERPRINT_ATTRIBUTE = "exception.fingerprint";
|
|
5
|
+
interface ExceptionInput {
|
|
6
|
+
/** Error class name, e.g. `TypeError`. Defaults to `Error`. */
|
|
7
|
+
type?: string;
|
|
8
|
+
/** Error message. Only used for grouping when there is no usable stack. */
|
|
9
|
+
message?: string;
|
|
10
|
+
/** Raw stack string, as `Error.stack` produces it. */
|
|
11
|
+
stack?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Collapse a path to the part that identifies the code rather than the machine
|
|
15
|
+
* it ran on: a dependency becomes its package name, and an absolute path
|
|
16
|
+
* becomes the project-relative one. Without this, the same error fingerprints
|
|
17
|
+
* differently in CI, in Docker, and on a laptop.
|
|
18
|
+
*/
|
|
19
|
+
declare function normalizeFilePath(filePath: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Strip the parts of a message that change on every occurrence, so
|
|
22
|
+
* `timeout after 341ms` and `timeout after 78ms` are one issue rather than two.
|
|
23
|
+
*/
|
|
24
|
+
declare function normalizeMessage(message: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* `function@normalized-path` for the top N frames. Line and column are
|
|
27
|
+
* deliberately dropped: an edit one line above the throw is the same bug.
|
|
28
|
+
*/
|
|
29
|
+
declare function normalizeStackFrames(stack: string, count: number): string[];
|
|
30
|
+
/** 32-bit djb2-style hash, rendered as 8 hex characters. */
|
|
31
|
+
declare function hashFingerprintParts(parts: string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Group key for an exception. Returns `undefined` when there is nothing to
|
|
34
|
+
* group on, so callers never write an attribute that means "no information".
|
|
35
|
+
*/
|
|
36
|
+
declare function fingerprintException(input: ExceptionInput, frames?: number): string | undefined;
|
|
37
|
+
interface ExceptionFingerprintOptions {
|
|
38
|
+
/** Stack frames to fingerprint on. @default 5 */
|
|
39
|
+
frames?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Span enricher that stamps {@link EXCEPTION_FINGERPRINT_ATTRIBUTE} on every
|
|
43
|
+
* span that recorded an exception.
|
|
44
|
+
*
|
|
45
|
+
* Pass it to `init({ spanEnrichers: [...] })` rather than `spanProcessors`:
|
|
46
|
+
* enrichers add to the pipeline instead of replacing it, and sit outside the
|
|
47
|
+
* redaction wrapper so the attribute reaches every exporter.
|
|
48
|
+
*/
|
|
49
|
+
declare function exceptionFingerprint(options?: ExceptionFingerprintOptions): SpanProcessor;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { EXCEPTION_FINGERPRINT_ATTRIBUTE, ExceptionFingerprintOptions, ExceptionInput, exceptionFingerprint, fingerprintException, hashFingerprintParts, normalizeFilePath, normalizeMessage, normalizeStackFrames };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { g as nonEmptyString } from "./values-BenyvWKz.js";
|
|
2
|
+
|
|
3
|
+
//#region src/exception-fingerprint.ts
|
|
4
|
+
/** Attribute the fingerprint is written to. */
|
|
5
|
+
const EXCEPTION_FINGERPRINT_ATTRIBUTE = "exception.fingerprint";
|
|
6
|
+
/**
|
|
7
|
+
* Frames deep enough to separate two different bugs, shallow enough that the
|
|
8
|
+
* same bug reached through different callers still groups.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_FRAMES = 5;
|
|
11
|
+
const NODE_FRAME = /^at\s+(.+?)\s+\((.+?):(\d+):\d+\)$/;
|
|
12
|
+
const ANON_FRAME = /^at\s+(.+?):(\d+):\d+$/;
|
|
13
|
+
const BROWSER_FRAME = /^(.+?)@(.+?):(\d+):\d+$/;
|
|
14
|
+
/**
|
|
15
|
+
* Collapse a path to the part that identifies the code rather than the machine
|
|
16
|
+
* it ran on: a dependency becomes its package name, and an absolute path
|
|
17
|
+
* becomes the project-relative one. Without this, the same error fingerprints
|
|
18
|
+
* differently in CI, in Docker, and on a laptop.
|
|
19
|
+
*/
|
|
20
|
+
function normalizeFilePath(filePath) {
|
|
21
|
+
const nodeModulesMatch = filePath.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
|
|
22
|
+
if (nodeModulesMatch) return `[npm]/${nodeModulesMatch[1]}`;
|
|
23
|
+
return filePath.replace(/^.*?\/src\//, "src/").replace(/^.*?\/dist\//, "dist/").replace(/^.*?\/lib\//, "lib/").replace(/^file:\/\//, "");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Strip the parts of a message that change on every occurrence, so
|
|
27
|
+
* `timeout after 341ms` and `timeout after 78ms` are one issue rather than two.
|
|
28
|
+
*/
|
|
29
|
+
function normalizeMessage(message) {
|
|
30
|
+
return message.replaceAll(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "[UUID]").replaceAll(/\b[0-9a-f]{16,}\b/gi, "[ID]").replaceAll(/\d+/g, "[N]").replaceAll(/"[^"]*"/g, "\"[STR]\"").replaceAll(/'[^']*'/g, "'[STR]'").slice(0, 200);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* `function@normalized-path` for the top N frames. Line and column are
|
|
34
|
+
* deliberately dropped: an edit one line above the throw is the same bug.
|
|
35
|
+
*/
|
|
36
|
+
function normalizeStackFrames(stack, count) {
|
|
37
|
+
const frames = [];
|
|
38
|
+
for (const line of stack.split("\n")) {
|
|
39
|
+
if (frames.length >= count) break;
|
|
40
|
+
const trimmed = line.trim();
|
|
41
|
+
const node = NODE_FRAME.exec(trimmed);
|
|
42
|
+
if (node) {
|
|
43
|
+
frames.push(`${node[1] ?? "anonymous"}@${normalizeFilePath(node[2] ?? "")}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const anon = ANON_FRAME.exec(trimmed);
|
|
47
|
+
if (anon) {
|
|
48
|
+
frames.push(`anonymous@${normalizeFilePath(anon[1] ?? "")}`);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const browser = BROWSER_FRAME.exec(trimmed);
|
|
52
|
+
if (browser) frames.push(`${browser[1] ?? "anonymous"}@${normalizeFilePath(browser[2] ?? "")}`);
|
|
53
|
+
}
|
|
54
|
+
return frames;
|
|
55
|
+
}
|
|
56
|
+
/** 32-bit djb2-style hash, rendered as 8 hex characters. */
|
|
57
|
+
function hashFingerprintParts(parts) {
|
|
58
|
+
const value = parts.join("|");
|
|
59
|
+
let hash = 0;
|
|
60
|
+
for (let index = 0; index < value.length; index++) {
|
|
61
|
+
hash = (hash << 5) - hash + value.charCodeAt(index);
|
|
62
|
+
hash = hash & hash;
|
|
63
|
+
}
|
|
64
|
+
return Math.abs(hash).toString(16).padStart(8, "0");
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Group key for an exception. Returns `undefined` when there is nothing to
|
|
68
|
+
* group on, so callers never write an attribute that means "no information".
|
|
69
|
+
*/
|
|
70
|
+
function fingerprintException(input, frames = DEFAULT_FRAMES) {
|
|
71
|
+
const stackFrames = input.stack ? normalizeStackFrames(input.stack, frames) : [];
|
|
72
|
+
if (stackFrames.length === 0 && !input.message && !input.type) return;
|
|
73
|
+
const parts = [input.type || "Error"];
|
|
74
|
+
if (stackFrames.length > 0) parts.push(...stackFrames);
|
|
75
|
+
else if (input.message) parts.push(normalizeMessage(input.message));
|
|
76
|
+
return hashFingerprintParts(parts);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Read the error off a finished span, wherever it was recorded: the OTel
|
|
80
|
+
* `exception` event, the `exception.*` attributes autotel-web sets, or the
|
|
81
|
+
* `error.*` attributes structured errors write instead of an event.
|
|
82
|
+
*/
|
|
83
|
+
function readException(span) {
|
|
84
|
+
const { attributes } = span;
|
|
85
|
+
const event = span.events?.find((e) => e.name === "exception");
|
|
86
|
+
const eventAttributes = event?.attributes ?? {};
|
|
87
|
+
const type = nonEmptyString(attributes["exception.type"]) ?? nonEmptyString(attributes["error.type"]) ?? nonEmptyString(eventAttributes["exception.type"]);
|
|
88
|
+
const stack = nonEmptyString(attributes["exception.stacktrace"]) ?? nonEmptyString(attributes["exception.stack"]) ?? nonEmptyString(attributes["error.stack"]) ?? nonEmptyString(eventAttributes["exception.stacktrace"]) ?? nonEmptyString(eventAttributes["exception.stack"]);
|
|
89
|
+
if (!type && !stack && !event) return void 0;
|
|
90
|
+
return {
|
|
91
|
+
type,
|
|
92
|
+
message: nonEmptyString(attributes["exception.message"]) ?? nonEmptyString(attributes["error.message"]) ?? nonEmptyString(eventAttributes["exception.message"]) ?? nonEmptyString(span.status.message),
|
|
93
|
+
stack
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Span enricher that stamps {@link EXCEPTION_FINGERPRINT_ATTRIBUTE} on every
|
|
98
|
+
* span that recorded an exception.
|
|
99
|
+
*
|
|
100
|
+
* Pass it to `init({ spanEnrichers: [...] })` rather than `spanProcessors`:
|
|
101
|
+
* enrichers add to the pipeline instead of replacing it, and sit outside the
|
|
102
|
+
* redaction wrapper so the attribute reaches every exporter.
|
|
103
|
+
*/
|
|
104
|
+
function exceptionFingerprint(options = {}) {
|
|
105
|
+
const frames = options.frames ?? DEFAULT_FRAMES;
|
|
106
|
+
return {
|
|
107
|
+
onStart(_span, _context) {},
|
|
108
|
+
onEnd(span) {
|
|
109
|
+
const { attributes } = span;
|
|
110
|
+
if (attributes["exception.fingerprint"] !== void 0) return;
|
|
111
|
+
const exception = readException(span);
|
|
112
|
+
if (!exception) return;
|
|
113
|
+
const fingerprint = fingerprintException(exception, frames);
|
|
114
|
+
if (fingerprint) attributes[EXCEPTION_FINGERPRINT_ATTRIBUTE] = fingerprint;
|
|
115
|
+
},
|
|
116
|
+
forceFlush() {
|
|
117
|
+
return Promise.resolve();
|
|
118
|
+
},
|
|
119
|
+
shutdown() {
|
|
120
|
+
return Promise.resolve();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//#endregion
|
|
126
|
+
export { EXCEPTION_FINGERPRINT_ATTRIBUTE, exceptionFingerprint, fingerprintException, hashFingerprintParts, normalizeFilePath, normalizeMessage, normalizeStackFrames };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('./rolldown-runtime-C_NdSu1c.cjs');
|
|
2
|
+
const require_values = require('./values-DApyq53y.cjs');
|
|
2
3
|
const require_tracer_provider = require('./tracer-provider.cjs');
|
|
3
4
|
const require_config = require('./config.cjs');
|
|
4
5
|
const require_sampling = require('./sampling.cjs');
|
|
5
|
-
const require_init = require('./init-
|
|
6
|
+
const require_init = require('./init-C5aHRqi2.cjs');
|
|
6
7
|
const require_trace_helpers = require('./trace-helpers.cjs');
|
|
7
8
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
8
9
|
let node_fs = require("node:fs");
|
|
@@ -178,9 +179,9 @@ function getSpanName(options, fn, variableName) {
|
|
|
178
179
|
if (options.serviceName) return `${options.serviceName}.${fnName}`;
|
|
179
180
|
if (fnName !== "anonymous") return fnName;
|
|
180
181
|
const initConfig = require_init.getConfig();
|
|
181
|
-
if (
|
|
182
|
+
if (require_values.isDevelopment() && !unknownSpanNameWarningEmitted && initConfig?.logger?.warn) {
|
|
182
183
|
unknownSpanNameWarningEmitted = true;
|
|
183
|
-
initConfig.logger.warn({}, "[autotel] Span name resolved to \"unknown\".
|
|
184
|
+
initConfig.logger.warn({}, "[autotel] Span name resolved to \"unknown\". Use instrument({ key: \"operation.name\", fn }) for a reusable named wrapper.");
|
|
184
185
|
}
|
|
185
186
|
return "unknown";
|
|
186
187
|
}
|
|
@@ -207,7 +208,7 @@ function createDummyCtx() {
|
|
|
207
208
|
function serializeCapture(value) {
|
|
208
209
|
if (value === void 0) return void 0;
|
|
209
210
|
try {
|
|
210
|
-
const json =
|
|
211
|
+
const json = require_values.asString(value) ?? JSON.stringify(value);
|
|
211
212
|
if (json === void 0) return void 0;
|
|
212
213
|
return json.length > CAPTURE_MAX_CHARS ? `${json.slice(0, CAPTURE_MAX_CHARS)}…[truncated]` : json;
|
|
213
214
|
} catch {
|
|
@@ -333,7 +334,7 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
333
334
|
const fn = fnFactory(require_init.createTraceContext(span));
|
|
334
335
|
const argsAttributes = {
|
|
335
336
|
...captureInputAttrs(args, options.captureInput),
|
|
336
|
-
...options.attributesFromArgs
|
|
337
|
+
...options.attributesFromArgs?.(args)
|
|
337
338
|
};
|
|
338
339
|
const handleTailSampling = (success, duration, error) => {
|
|
339
340
|
if (needsTailSampling && sampler.shouldKeepTrace) {
|
|
@@ -358,9 +359,9 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
358
359
|
});
|
|
359
360
|
const resultAttributes = {
|
|
360
361
|
...captureOutputAttrs(result, options.captureOutput),
|
|
361
|
-
...options.attributesFromResult
|
|
362
|
+
...options.attributesFromResult?.(result)
|
|
362
363
|
};
|
|
363
|
-
span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
|
|
364
|
+
if (!require_init.hasExplicitSpanStatus(span)) span.setStatus({ code: _opentelemetry_api.SpanStatusCode.OK });
|
|
364
365
|
span.setAttributes({
|
|
365
366
|
...argsAttributes,
|
|
366
367
|
...resultAttributes,
|
|
@@ -373,8 +374,8 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
373
374
|
span.end();
|
|
374
375
|
return result;
|
|
375
376
|
};
|
|
376
|
-
const onError = (
|
|
377
|
-
finalizeThrownSpan(
|
|
377
|
+
const onError = (cause) => {
|
|
378
|
+
finalizeThrownSpan(cause, options.isError, {
|
|
378
379
|
span,
|
|
379
380
|
spanName,
|
|
380
381
|
duration: performance.now() - startTime,
|
|
@@ -383,7 +384,7 @@ function wrapWithTracingSync(fnFactory, options, variableName) {
|
|
|
383
384
|
handleTailSampling,
|
|
384
385
|
extraAttributes: argsAttributes
|
|
385
386
|
});
|
|
386
|
-
throw
|
|
387
|
+
throw cause;
|
|
387
388
|
};
|
|
388
389
|
try {
|
|
389
390
|
callCounter?.add(1, {
|
|
@@ -428,6 +429,10 @@ function wrapFactoryWithTracing(factory, options, variableName) {
|
|
|
428
429
|
function wrapPlainWithTracing(fn, options, variableName) {
|
|
429
430
|
return wrapWithTracingSync((_ctx) => fn, options, resolveVariableName(fn, variableName));
|
|
430
431
|
}
|
|
432
|
+
/** Run one operation immediately with its span-bound context. */
|
|
433
|
+
function runWithTraceContext(operation, options) {
|
|
434
|
+
return wrapFactoryWithTracing((ctx) => () => operation(ctx), options)();
|
|
435
|
+
}
|
|
431
436
|
|
|
432
437
|
//#endregion
|
|
433
438
|
//#region src/functional.ts
|
|
@@ -493,7 +498,7 @@ function getCtxValue() {
|
|
|
493
498
|
*
|
|
494
499
|
* @example
|
|
495
500
|
* ```typescript
|
|
496
|
-
* const getUser = trace(
|
|
501
|
+
* const getUser = trace(async function getUser(id: string) {
|
|
497
502
|
* getActiveTraceContext()?.setAttribute('user.id', id);
|
|
498
503
|
* return db.users.find(id);
|
|
499
504
|
* });
|
|
@@ -523,7 +528,8 @@ function getActiveTraceContext() {
|
|
|
523
528
|
* })
|
|
524
529
|
* ```
|
|
525
530
|
*/
|
|
526
|
-
const
|
|
531
|
+
const ctxProxyTarget = {};
|
|
532
|
+
const ctx = new Proxy(ctxProxyTarget, {
|
|
527
533
|
get(_target, prop) {
|
|
528
534
|
const ctxValue = getCtxValue();
|
|
529
535
|
if (!ctxValue) return;
|
|
@@ -545,11 +551,17 @@ const ctx = new Proxy({}, {
|
|
|
545
551
|
return Object.getOwnPropertyDescriptor(ctxValue, prop);
|
|
546
552
|
}
|
|
547
553
|
});
|
|
548
|
-
function
|
|
554
|
+
function traceImpl(fnOrNameOrOptions, maybeFn) {
|
|
549
555
|
if (typeof fnOrNameOrOptions === "function") return wrapPlainWithTracing(fnOrNameOrOptions, {});
|
|
550
|
-
|
|
551
|
-
|
|
556
|
+
const options = typeof fnOrNameOrOptions === "string" ? { name: fnOrNameOrOptions } : fnOrNameOrOptions;
|
|
557
|
+
if (maybeFn === void 0) return ((fn) => wrapPlainWithTracing(fn, options));
|
|
558
|
+
return wrapPlainWithTracing(maybeFn, options);
|
|
559
|
+
}
|
|
560
|
+
function run(nameOrOptions, operation) {
|
|
561
|
+
if (typeof operation !== "function") throw new TypeError("trace.run(name, operation): operation must be a function");
|
|
562
|
+
return runWithTraceContext(operation, typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions);
|
|
552
563
|
}
|
|
564
|
+
const trace = Object.assign(traceImpl, { run });
|
|
553
565
|
/**
|
|
554
566
|
* Approach 2: withTracing() - Middleware-style composable wrapper
|
|
555
567
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as TraceContext } from "./trace-context-
|
|
2
|
-
import { p as Sampler } from "./sampling-
|
|
3
|
-
import { Span, SpanKind } from "@opentelemetry/api";
|
|
1
|
+
import { n as TraceContext } from "./trace-context-C1Cn1q0y.cjs";
|
|
2
|
+
import { p as Sampler } from "./sampling-CmRdnXUi.cjs";
|
|
3
|
+
import { Attributes, Span, SpanKind } from "@opentelemetry/api";
|
|
4
4
|
//#region src/functional-wrapper.d.ts
|
|
5
5
|
type WrappedFunction<TArgs extends unknown[], TReturn> = (...args: TArgs) => TReturn | Promise<TReturn>;
|
|
6
6
|
/**
|
|
@@ -35,9 +35,10 @@ interface TracingOptions<TArgs extends unknown[] = unknown[], TReturn = unknown>
|
|
|
35
35
|
*/
|
|
36
36
|
withMetrics?: boolean;
|
|
37
37
|
/** Extract attributes from function arguments. */
|
|
38
|
-
attributesFromArgs?: (args: TArgs) =>
|
|
38
|
+
attributesFromArgs?: (args: TArgs) => Attributes;
|
|
39
39
|
/** Extract attributes from the function result. */
|
|
40
|
-
|
|
40
|
+
/** Receives the resolved value when the function returns a Promise. */
|
|
41
|
+
attributesFromResult?: (result: Awaited<TReturn>) => Attributes;
|
|
41
42
|
/**
|
|
42
43
|
* Capture arguments on the span as the truncated JSON `autotel.input`
|
|
43
44
|
* attribute. One argument is captured directly; multiple arguments are an
|
|
@@ -72,7 +73,7 @@ interface TracingOptions<TArgs extends unknown[] = unknown[], TReturn = unknown>
|
|
|
72
73
|
* as `redirect()` and `notFound()`.
|
|
73
74
|
* @default every throw is treated as an error
|
|
74
75
|
*/
|
|
75
|
-
isError?: (
|
|
76
|
+
isError?: (cause: unknown) => boolean;
|
|
76
77
|
}
|
|
77
78
|
/** Options for `instrument()` batch instrumentation. */
|
|
78
79
|
interface InstrumentOptions<T extends Record<string, AnyInstrumentable> = Record<string, AnyInstrumentable>> extends TracingOptions {
|
|
@@ -95,6 +96,33 @@ interface SingleInstrumentOptions<TFunction extends AnyInstrumentable = AnyInstr
|
|
|
95
96
|
}
|
|
96
97
|
//#endregion
|
|
97
98
|
//#region src/functional.d.ts
|
|
99
|
+
/**
|
|
100
|
+
* Complete trace context containing trace identifiers and span methods
|
|
101
|
+
*
|
|
102
|
+
* The ctx parameter in trace() functions provides:
|
|
103
|
+
* - traceId, spanId, correlationId from the active span
|
|
104
|
+
* - Span manipulation methods (setAttribute, setAttributes, setStatus, recordException)
|
|
105
|
+
*
|
|
106
|
+
* For custom context, access it directly in your functions (standard OpenTelemetry pattern).
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import { trace } from 'autotel'
|
|
111
|
+
*
|
|
112
|
+
* export const createUser = withTracing({})((ctx) => async (data: CreateUserData) => {
|
|
113
|
+
* // Get custom context directly (standard OTel approach)
|
|
114
|
+
* const userId = getCurrentUserId()
|
|
115
|
+
* const tenantId = getCurrentTenant()
|
|
116
|
+
*
|
|
117
|
+
* // Use ctx for span operations and trace IDs
|
|
118
|
+
* ctx.setAttribute('user.id', data.id)
|
|
119
|
+
* ctx.setAttribute('user.tenant', tenantId)
|
|
120
|
+
* console.log(ctx.traceId) // Trace IDs available
|
|
121
|
+
* })
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
/** Baggage entries: values that survive the W3C baggage header. */
|
|
125
|
+
type BaggageValues = Record<string, string | number | boolean>;
|
|
98
126
|
/**
|
|
99
127
|
* Get the autotel {@link TraceContext} for the currently active span.
|
|
100
128
|
*
|
|
@@ -105,7 +133,7 @@ interface SingleInstrumentOptions<TFunction extends AnyInstrumentable = AnyInstr
|
|
|
105
133
|
*
|
|
106
134
|
* @example
|
|
107
135
|
* ```typescript
|
|
108
|
-
* const getUser = trace(
|
|
136
|
+
* const getUser = trace(async function getUser(id: string) {
|
|
109
137
|
* getActiveTraceContext()?.setAttribute('user.id', id);
|
|
110
138
|
* return db.users.find(id);
|
|
111
139
|
* });
|
|
@@ -114,34 +142,17 @@ interface SingleInstrumentOptions<TFunction extends AnyInstrumentable = AnyInstr
|
|
|
114
142
|
* @see getActiveSpan for the raw OpenTelemetry span
|
|
115
143
|
* @see getRequestLogger which reads the active context when called with no args
|
|
116
144
|
*/
|
|
117
|
-
declare function getActiveTraceContext<TBaggage extends
|
|
118
|
-
/**
|
|
119
|
-
* Context object that lazily evaluates the active span on property access
|
|
120
|
-
*
|
|
121
|
-
* Access trace context directly without function call syntax.
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```typescript
|
|
125
|
-
* import { trace, ctx } from 'autotel'
|
|
126
|
-
*
|
|
127
|
-
* export const createUser = trace(async (data) => {
|
|
128
|
-
* // Direct property access - no function call!
|
|
129
|
-
* if (ctx.traceId) {
|
|
130
|
-
* ctx.setAttribute('user.id', data.id)
|
|
131
|
-
* console.log('Trace:', ctx.traceId)
|
|
132
|
-
* }
|
|
133
|
-
* })
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
145
|
+
declare function getActiveTraceContext<TBaggage extends BaggageValues | undefined = undefined>(): TraceContext<TBaggage> | undefined;
|
|
136
146
|
declare const ctx: TraceContext;
|
|
137
147
|
/**
|
|
138
|
-
* Wrap a plain function with
|
|
139
|
-
*
|
|
140
|
-
* {@link getActiveTraceContext} inside the function, or use {@link withTracing}
|
|
141
|
-
* for the explicit `(ctx) => (...args) => result` factory form.
|
|
148
|
+
* Wrap a plain function with a traced wrapper, or run one named operation
|
|
149
|
+
* immediately with {@link trace.run}.
|
|
142
150
|
*
|
|
143
|
-
* `trace()`
|
|
144
|
-
*
|
|
151
|
+
* Every `trace(...)` call returns a **wrapper**. Nothing runs until you call
|
|
152
|
+
* what you get back, so a `trace()` call can never execute your function at
|
|
153
|
+
* module load. Reach the span from inside the body through the ambient
|
|
154
|
+
* {@link ctx} - it resolves at any depth, so a helper three frames down sees
|
|
155
|
+
* the same span without being handed anything.
|
|
145
156
|
*
|
|
146
157
|
* @example Auto-inferred name
|
|
147
158
|
* ```typescript
|
|
@@ -150,24 +161,70 @@ declare const ctx: TraceContext;
|
|
|
150
161
|
* })
|
|
151
162
|
* ```
|
|
152
163
|
*
|
|
153
|
-
* @example
|
|
164
|
+
* @example Explicit name
|
|
154
165
|
* ```typescript
|
|
155
|
-
* export const createUser = trace(async (data) => {
|
|
156
|
-
* getActiveTraceContext()?.setAttribute('user.id', data.id)
|
|
166
|
+
* export const createUser = trace('user.create', async (data) => {
|
|
157
167
|
* return await db.users.create(data)
|
|
158
168
|
* })
|
|
159
169
|
* ```
|
|
160
170
|
*
|
|
161
|
-
* @example
|
|
171
|
+
* @example Ambient context, at any depth
|
|
162
172
|
* ```typescript
|
|
173
|
+
* import { trace, ctx } from 'autotel'
|
|
174
|
+
*
|
|
163
175
|
* export const createUser = trace('user.create', async (data) => {
|
|
176
|
+
* ctx.setAttribute('user.id', data.id)
|
|
164
177
|
* return await db.users.create(data)
|
|
165
178
|
* })
|
|
166
179
|
* ```
|
|
180
|
+
*
|
|
181
|
+
* @example Curried, for a shared configuration
|
|
182
|
+
* ```typescript
|
|
183
|
+
* const traced = trace({ serviceName: 'users' })
|
|
184
|
+
* export const createUser = traced(async (data) => db.users.create(data))
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @example One operation, run now - see {@link trace.run}
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const user = await trace.run('user.create', async (ctx) => {
|
|
190
|
+
* ctx.setAttribute('user.id', input.id)
|
|
191
|
+
* return db.users.create(input)
|
|
192
|
+
* })
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
declare function traceImpl<TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
196
|
+
declare function traceImpl<TArgs extends unknown[], TReturn>(name: string, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
197
|
+
declare function traceImpl<TArgs extends unknown[], TReturn>(options: TracingOptions<TArgs, TReturn>, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
198
|
+
declare function traceImpl(name: string): <TArgs extends unknown[], TReturn>(fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
|
|
199
|
+
declare function traceImpl<TArgs extends unknown[], TReturn>(options: TracingOptions<TArgs, TReturn>): (fn: (...args: TArgs) => TReturn) => (...args: TArgs) => TReturn;
|
|
200
|
+
/**
|
|
201
|
+
* Run one named operation immediately and return its result, with the
|
|
202
|
+
* {@link TraceContext} passed in.
|
|
203
|
+
*
|
|
204
|
+
* This is the counterpart to {@link trace}: `trace(...)` always hands back a
|
|
205
|
+
* wrapper to call later, `trace.run(...)` runs the operation now. Keeping them
|
|
206
|
+
* under separate names is deliberate - a single call shape that sometimes
|
|
207
|
+
* wrapped and sometimes ran is what made dispatch depend on a callback's
|
|
208
|
+
* parameter name, which a minifier is free to rewrite (#166).
|
|
209
|
+
*
|
|
210
|
+
* The body can equally read the ambient {@link ctx}; the parameter is here for
|
|
211
|
+
* when an explicit binding reads better.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* const user = await trace.run('user.create', async (ctx) => {
|
|
216
|
+
* ctx.setAttribute('user.id', input.id)
|
|
217
|
+
* return db.users.create(input)
|
|
218
|
+
* })
|
|
219
|
+
* ```
|
|
167
220
|
*/
|
|
168
|
-
declare function
|
|
169
|
-
declare function
|
|
170
|
-
declare function
|
|
221
|
+
declare function run<TReturn>(name: string, operation: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
|
|
222
|
+
declare function run<TReturn>(name: string, operation: (ctx: TraceContext) => TReturn): TReturn;
|
|
223
|
+
declare function run<TReturn>(options: TracingOptions<[], TReturn>, operation: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
|
|
224
|
+
declare function run<TReturn>(options: TracingOptions<[], TReturn>, operation: (ctx: TraceContext) => TReturn): TReturn;
|
|
225
|
+
declare const trace$1: typeof traceImpl & {
|
|
226
|
+
run: typeof run;
|
|
227
|
+
};
|
|
171
228
|
/**
|
|
172
229
|
* Approach 2: withTracing() - Middleware-style composable wrapper
|
|
173
230
|
*
|