@superblocksteam/telemetry 2.0.83-next.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/LICENSE.txt +87 -0
- package/README.md +155 -0
- package/dist/browser/index.d.ts +8 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +19 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/init.d.ts +75 -0
- package/dist/browser/init.d.ts.map +1 -0
- package/dist/browser/init.js +169 -0
- package/dist/browser/init.js.map +1 -0
- package/dist/browser/resilient-exporter.d.ts +43 -0
- package/dist/browser/resilient-exporter.d.ts.map +1 -0
- package/dist/browser/resilient-exporter.js +88 -0
- package/dist/browser/resilient-exporter.js.map +1 -0
- package/dist/common/contracts/tier2-traces.d.ts +75 -0
- package/dist/common/contracts/tier2-traces.d.ts.map +1 -0
- package/dist/common/contracts/tier2-traces.js +186 -0
- package/dist/common/contracts/tier2-traces.js.map +1 -0
- package/dist/common/deployment-type.d.ts +18 -0
- package/dist/common/deployment-type.d.ts.map +1 -0
- package/dist/common/deployment-type.js +30 -0
- package/dist/common/deployment-type.js.map +1 -0
- package/dist/common/guardrails.d.ts +116 -0
- package/dist/common/guardrails.d.ts.map +1 -0
- package/dist/common/guardrails.js +189 -0
- package/dist/common/guardrails.js.map +1 -0
- package/dist/common/index.d.ts +16 -0
- package/dist/common/index.d.ts.map +1 -0
- package/dist/common/index.js +32 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/log-sanitizer.d.ts +78 -0
- package/dist/common/log-sanitizer.d.ts.map +1 -0
- package/dist/common/log-sanitizer.js +340 -0
- package/dist/common/log-sanitizer.js.map +1 -0
- package/dist/common/policy-evaluator.d.ts +103 -0
- package/dist/common/policy-evaluator.d.ts.map +1 -0
- package/dist/common/policy-evaluator.js +200 -0
- package/dist/common/policy-evaluator.js.map +1 -0
- package/dist/common/resource.d.ts +62 -0
- package/dist/common/resource.d.ts.map +1 -0
- package/dist/common/resource.js +106 -0
- package/dist/common/resource.js.map +1 -0
- package/dist/common/tier-hints.d.ts +182 -0
- package/dist/common/tier-hints.d.ts.map +1 -0
- package/dist/common/tier-hints.js +209 -0
- package/dist/common/tier-hints.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/lint/forbidden-attributes.d.ts +149 -0
- package/dist/lint/forbidden-attributes.d.ts.map +1 -0
- package/dist/lint/forbidden-attributes.js +214 -0
- package/dist/lint/forbidden-attributes.js.map +1 -0
- package/dist/lint/index.d.ts +9 -0
- package/dist/lint/index.d.ts.map +1 -0
- package/dist/lint/index.js +16 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/llmobs/index.d.ts +22 -0
- package/dist/llmobs/index.d.ts.map +1 -0
- package/dist/llmobs/index.js +29 -0
- package/dist/llmobs/index.js.map +1 -0
- package/dist/llmobs/tier1-exporter.d.ts +146 -0
- package/dist/llmobs/tier1-exporter.d.ts.map +1 -0
- package/dist/llmobs/tier1-exporter.js +196 -0
- package/dist/llmobs/tier1-exporter.js.map +1 -0
- package/dist/llmobs/tier2-summarizer.d.ts +268 -0
- package/dist/llmobs/tier2-summarizer.d.ts.map +1 -0
- package/dist/llmobs/tier2-summarizer.js +650 -0
- package/dist/llmobs/tier2-summarizer.js.map +1 -0
- package/dist/node/exporters/resilient-exporter.d.ts +77 -0
- package/dist/node/exporters/resilient-exporter.d.ts.map +1 -0
- package/dist/node/exporters/resilient-exporter.js +129 -0
- package/dist/node/exporters/resilient-exporter.js.map +1 -0
- package/dist/node/index.d.ts +11 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +24 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/init.d.ts +75 -0
- package/dist/node/init.d.ts.map +1 -0
- package/dist/node/init.js +245 -0
- package/dist/node/init.js.map +1 -0
- package/dist/node/log-processor.d.ts +83 -0
- package/dist/node/log-processor.d.ts.map +1 -0
- package/dist/node/log-processor.js +266 -0
- package/dist/node/log-processor.js.map +1 -0
- package/dist/node/metrics-client.d.ts +66 -0
- package/dist/node/metrics-client.d.ts.map +1 -0
- package/dist/node/metrics-client.js +193 -0
- package/dist/node/metrics-client.js.map +1 -0
- package/dist/node/traced-socket.d.ts +76 -0
- package/dist/node/traced-socket.d.ts.map +1 -0
- package/dist/node/traced-socket.js +261 -0
- package/dist/node/traced-socket.js.map +1 -0
- package/dist/testing/in-memory-exporter.d.ts +179 -0
- package/dist/testing/in-memory-exporter.d.ts.map +1 -0
- package/dist/testing/in-memory-exporter.js +254 -0
- package/dist/testing/in-memory-exporter.js.map +1 -0
- package/dist/testing/index.d.ts +8 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +19 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/test-init.d.ts +80 -0
- package/dist/testing/test-init.d.ts.map +1 -0
- package/dist/testing/test-init.js +144 -0
- package/dist/testing/test-init.js.map +1 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/policy.d.ts +92 -0
- package/dist/types/policy.d.ts.map +1 -0
- package/dist/types/policy.js +125 -0
- package/dist/types/policy.js.map +1 -0
- package/dist-esm/browser/index.d.ts +8 -0
- package/dist-esm/browser/index.d.ts.map +1 -0
- package/dist-esm/browser/index.js +9 -0
- package/dist-esm/browser/index.js.map +1 -0
- package/dist-esm/browser/init.d.ts +75 -0
- package/dist-esm/browser/init.d.ts.map +1 -0
- package/dist-esm/browser/init.js +162 -0
- package/dist-esm/browser/init.js.map +1 -0
- package/dist-esm/browser/resilient-exporter.d.ts +43 -0
- package/dist-esm/browser/resilient-exporter.d.ts.map +1 -0
- package/dist-esm/browser/resilient-exporter.js +84 -0
- package/dist-esm/browser/resilient-exporter.js.map +1 -0
- package/dist-esm/common/contracts/tier2-traces.d.ts +75 -0
- package/dist-esm/common/contracts/tier2-traces.d.ts.map +1 -0
- package/dist-esm/common/contracts/tier2-traces.js +178 -0
- package/dist-esm/common/contracts/tier2-traces.js.map +1 -0
- package/dist-esm/common/deployment-type.d.ts +18 -0
- package/dist-esm/common/deployment-type.d.ts.map +1 -0
- package/dist-esm/common/deployment-type.js +27 -0
- package/dist-esm/common/deployment-type.js.map +1 -0
- package/dist-esm/common/guardrails.d.ts +116 -0
- package/dist-esm/common/guardrails.d.ts.map +1 -0
- package/dist-esm/common/guardrails.js +179 -0
- package/dist-esm/common/guardrails.js.map +1 -0
- package/dist-esm/common/index.d.ts +16 -0
- package/dist-esm/common/index.d.ts.map +1 -0
- package/dist-esm/common/index.js +16 -0
- package/dist-esm/common/index.js.map +1 -0
- package/dist-esm/common/log-sanitizer.d.ts +78 -0
- package/dist-esm/common/log-sanitizer.d.ts.map +1 -0
- package/dist-esm/common/log-sanitizer.js +331 -0
- package/dist-esm/common/log-sanitizer.js.map +1 -0
- package/dist-esm/common/policy-evaluator.d.ts +103 -0
- package/dist-esm/common/policy-evaluator.d.ts.map +1 -0
- package/dist-esm/common/policy-evaluator.js +196 -0
- package/dist-esm/common/policy-evaluator.js.map +1 -0
- package/dist-esm/common/resource.d.ts +62 -0
- package/dist-esm/common/resource.d.ts.map +1 -0
- package/dist-esm/common/resource.js +100 -0
- package/dist-esm/common/resource.js.map +1 -0
- package/dist-esm/common/tier-hints.d.ts +182 -0
- package/dist-esm/common/tier-hints.d.ts.map +1 -0
- package/dist-esm/common/tier-hints.js +199 -0
- package/dist-esm/common/tier-hints.js.map +1 -0
- package/dist-esm/index.d.ts +43 -0
- package/dist-esm/index.d.ts.map +1 -0
- package/dist-esm/index.js +53 -0
- package/dist-esm/index.js.map +1 -0
- package/dist-esm/lint/forbidden-attributes.d.ts +149 -0
- package/dist-esm/lint/forbidden-attributes.d.ts.map +1 -0
- package/dist-esm/lint/forbidden-attributes.js +209 -0
- package/dist-esm/lint/forbidden-attributes.js.map +1 -0
- package/dist-esm/lint/index.d.ts +9 -0
- package/dist-esm/lint/index.d.ts.map +1 -0
- package/dist-esm/lint/index.js +9 -0
- package/dist-esm/lint/index.js.map +1 -0
- package/dist-esm/llmobs/index.d.ts +22 -0
- package/dist-esm/llmobs/index.d.ts.map +1 -0
- package/dist-esm/llmobs/index.js +22 -0
- package/dist-esm/llmobs/index.js.map +1 -0
- package/dist-esm/llmobs/tier1-exporter.d.ts +146 -0
- package/dist-esm/llmobs/tier1-exporter.d.ts.map +1 -0
- package/dist-esm/llmobs/tier1-exporter.js +190 -0
- package/dist-esm/llmobs/tier1-exporter.js.map +1 -0
- package/dist-esm/llmobs/tier2-summarizer.d.ts +268 -0
- package/dist-esm/llmobs/tier2-summarizer.d.ts.map +1 -0
- package/dist-esm/llmobs/tier2-summarizer.js +646 -0
- package/dist-esm/llmobs/tier2-summarizer.js.map +1 -0
- package/dist-esm/node/exporters/resilient-exporter.d.ts +77 -0
- package/dist-esm/node/exporters/resilient-exporter.d.ts.map +1 -0
- package/dist-esm/node/exporters/resilient-exporter.js +125 -0
- package/dist-esm/node/exporters/resilient-exporter.js.map +1 -0
- package/dist-esm/node/index.d.ts +11 -0
- package/dist-esm/node/index.d.ts.map +1 -0
- package/dist-esm/node/index.js +11 -0
- package/dist-esm/node/index.js.map +1 -0
- package/dist-esm/node/init.d.ts +75 -0
- package/dist-esm/node/init.d.ts.map +1 -0
- package/dist-esm/node/init.js +239 -0
- package/dist-esm/node/init.js.map +1 -0
- package/dist-esm/node/log-processor.d.ts +83 -0
- package/dist-esm/node/log-processor.d.ts.map +1 -0
- package/dist-esm/node/log-processor.js +261 -0
- package/dist-esm/node/log-processor.js.map +1 -0
- package/dist-esm/node/metrics-client.d.ts +66 -0
- package/dist-esm/node/metrics-client.d.ts.map +1 -0
- package/dist-esm/node/metrics-client.js +189 -0
- package/dist-esm/node/metrics-client.js.map +1 -0
- package/dist-esm/node/traced-socket.d.ts +76 -0
- package/dist-esm/node/traced-socket.d.ts.map +1 -0
- package/dist-esm/node/traced-socket.js +257 -0
- package/dist-esm/node/traced-socket.js.map +1 -0
- package/dist-esm/testing/in-memory-exporter.d.ts +179 -0
- package/dist-esm/testing/in-memory-exporter.d.ts.map +1 -0
- package/dist-esm/testing/in-memory-exporter.js +248 -0
- package/dist-esm/testing/in-memory-exporter.js.map +1 -0
- package/dist-esm/testing/index.d.ts +8 -0
- package/dist-esm/testing/index.d.ts.map +1 -0
- package/dist-esm/testing/index.js +8 -0
- package/dist-esm/testing/index.js.map +1 -0
- package/dist-esm/testing/test-init.d.ts +80 -0
- package/dist-esm/testing/test-init.d.ts.map +1 -0
- package/dist-esm/testing/test-init.js +137 -0
- package/dist-esm/testing/test-init.js.map +1 -0
- package/dist-esm/types/index.d.ts +40 -0
- package/dist-esm/types/index.d.ts.map +1 -0
- package/dist-esm/types/index.js +7 -0
- package/dist-esm/types/index.js.map +1 -0
- package/dist-esm/types/policy.d.ts +92 -0
- package/dist-esm/types/policy.d.ts.map +1 -0
- package/dist-esm/types/policy.js +122 -0
- package/dist-esm/types/policy.js.map +1 -0
- package/package.json +101 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resilient Exporter
|
|
3
|
+
*
|
|
4
|
+
* Wrapper that ensures Tier 2/3 export failures never block core request paths.
|
|
5
|
+
* Export failures are observable via metrics, not via blocking or exceptions.
|
|
6
|
+
*/
|
|
7
|
+
import type { SpanExporter, ReadableSpan } from "@opentelemetry/sdk-trace-base";
|
|
8
|
+
import { ExportResult } from "@opentelemetry/core";
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for the resilient exporter.
|
|
11
|
+
*/
|
|
12
|
+
export interface ResilientExporterConfig {
|
|
13
|
+
/** Underlying exporter to wrap */
|
|
14
|
+
delegate: SpanExporter;
|
|
15
|
+
/** Max items to buffer before dropping (default: 2048) */
|
|
16
|
+
maxQueueSize?: number;
|
|
17
|
+
/** Export timeout in ms (default: 30000) */
|
|
18
|
+
exportTimeoutMs?: number;
|
|
19
|
+
/** Callback when items are dropped due to backpressure */
|
|
20
|
+
onDrop?: (count: number, reason: "queue_full" | "export_failed" | "timeout") => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Metrics exposed by the resilient exporter.
|
|
24
|
+
*/
|
|
25
|
+
export interface ResilientExporterMetrics {
|
|
26
|
+
/** Total spans dropped due to backpressure or failure */
|
|
27
|
+
dropped: number;
|
|
28
|
+
/** Current queue size */
|
|
29
|
+
queued: number;
|
|
30
|
+
/** Total export failures */
|
|
31
|
+
failures: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resilient exporter wrapper that:
|
|
35
|
+
* - Drops spans when queue is full (never blocks)
|
|
36
|
+
* - Catches export failures and emits metrics
|
|
37
|
+
* - Times out stalled exports
|
|
38
|
+
*
|
|
39
|
+
* CRITICAL: Telemetry export must be fire-and-forget from the application's perspective.
|
|
40
|
+
* Export failures should be observable via metrics, not via blocking or exceptions.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ResilientExporter implements SpanExporter {
|
|
43
|
+
private readonly delegate;
|
|
44
|
+
private readonly maxQueueSize;
|
|
45
|
+
private readonly exportTimeoutMs;
|
|
46
|
+
private readonly onDrop;
|
|
47
|
+
private queuedCount;
|
|
48
|
+
private droppedCount;
|
|
49
|
+
private exportFailures;
|
|
50
|
+
private shuttingDown;
|
|
51
|
+
constructor(config: ResilientExporterConfig);
|
|
52
|
+
/**
|
|
53
|
+
* Export spans with resilient error handling.
|
|
54
|
+
*
|
|
55
|
+
* IMPORTANT: Always returns SUCCESS to caller - export failures are
|
|
56
|
+
* observable via metrics, not via the result callback.
|
|
57
|
+
*/
|
|
58
|
+
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
59
|
+
/**
|
|
60
|
+
* Shutdown the underlying exporter.
|
|
61
|
+
* Marks exporter as shutting down to reject new exports.
|
|
62
|
+
*/
|
|
63
|
+
shutdown(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Force flush the underlying exporter.
|
|
66
|
+
*/
|
|
67
|
+
forceFlush(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Get current metrics for observability.
|
|
70
|
+
*/
|
|
71
|
+
getMetrics(): ResilientExporterMetrics;
|
|
72
|
+
/**
|
|
73
|
+
* Reset metrics (for testing).
|
|
74
|
+
*/
|
|
75
|
+
resetMetrics(): void;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=resilient-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilient-exporter.d.ts","sourceRoot":"","sources":["../../../src/node/exporters/resilient-exporter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,CACP,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,GAAG,eAAe,GAAG,SAAS,KAC/C,IAAI,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGb;IAEV,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,uBAAuB;IAO3C;;;;;OAKG;IACH,MAAM,CACJ,KAAK,EAAE,YAAY,EAAE,EACrB,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAC7C,IAAI;IA0DP;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAK/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC;;OAEG;IACH,UAAU,IAAI,wBAAwB;IAQtC;;OAEG;IACH,YAAY,IAAI,IAAI;CAIrB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Resilient Exporter
|
|
4
|
+
*
|
|
5
|
+
* Wrapper that ensures Tier 2/3 export failures never block core request paths.
|
|
6
|
+
* Export failures are observable via metrics, not via blocking or exceptions.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ResilientExporter = void 0;
|
|
10
|
+
const core_1 = require("@opentelemetry/core");
|
|
11
|
+
/**
|
|
12
|
+
* Resilient exporter wrapper that:
|
|
13
|
+
* - Drops spans when queue is full (never blocks)
|
|
14
|
+
* - Catches export failures and emits metrics
|
|
15
|
+
* - Times out stalled exports
|
|
16
|
+
*
|
|
17
|
+
* CRITICAL: Telemetry export must be fire-and-forget from the application's perspective.
|
|
18
|
+
* Export failures should be observable via metrics, not via blocking or exceptions.
|
|
19
|
+
*/
|
|
20
|
+
class ResilientExporter {
|
|
21
|
+
delegate;
|
|
22
|
+
maxQueueSize;
|
|
23
|
+
exportTimeoutMs;
|
|
24
|
+
onDrop;
|
|
25
|
+
queuedCount = 0;
|
|
26
|
+
droppedCount = 0;
|
|
27
|
+
exportFailures = 0;
|
|
28
|
+
shuttingDown = false;
|
|
29
|
+
constructor(config) {
|
|
30
|
+
this.delegate = config.delegate;
|
|
31
|
+
this.maxQueueSize = config.maxQueueSize ?? 2048;
|
|
32
|
+
this.exportTimeoutMs = config.exportTimeoutMs ?? 30000;
|
|
33
|
+
this.onDrop = config.onDrop ?? (() => { });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Export spans with resilient error handling.
|
|
37
|
+
*
|
|
38
|
+
* IMPORTANT: Always returns SUCCESS to caller - export failures are
|
|
39
|
+
* observable via metrics, not via the result callback.
|
|
40
|
+
*/
|
|
41
|
+
export(spans, resultCallback) {
|
|
42
|
+
// Don't accept new exports during shutdown
|
|
43
|
+
if (this.shuttingDown) {
|
|
44
|
+
resultCallback({ code: core_1.ExportResultCode.SUCCESS });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Check backpressure - drop if queue is full
|
|
48
|
+
if (this.queuedCount + spans.length > this.maxQueueSize) {
|
|
49
|
+
this.droppedCount += spans.length;
|
|
50
|
+
this.onDrop(spans.length, "queue_full");
|
|
51
|
+
// Still return success - don't block the caller
|
|
52
|
+
resultCallback({ code: core_1.ExportResultCode.SUCCESS });
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.queuedCount += spans.length;
|
|
56
|
+
let completed = false;
|
|
57
|
+
// Wrap with timeout
|
|
58
|
+
const timeoutId = setTimeout(() => {
|
|
59
|
+
if (completed)
|
|
60
|
+
return;
|
|
61
|
+
completed = true;
|
|
62
|
+
this.queuedCount -= spans.length;
|
|
63
|
+
this.droppedCount += spans.length;
|
|
64
|
+
this.onDrop(spans.length, "timeout");
|
|
65
|
+
resultCallback({ code: core_1.ExportResultCode.SUCCESS }); // Don't propagate failure
|
|
66
|
+
}, this.exportTimeoutMs);
|
|
67
|
+
try {
|
|
68
|
+
this.delegate.export(spans, (result) => {
|
|
69
|
+
if (completed)
|
|
70
|
+
return;
|
|
71
|
+
completed = true;
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
this.queuedCount -= spans.length;
|
|
74
|
+
if (result.code !== core_1.ExportResultCode.SUCCESS) {
|
|
75
|
+
this.exportFailures++;
|
|
76
|
+
this.droppedCount += spans.length;
|
|
77
|
+
this.onDrop(spans.length, "export_failed");
|
|
78
|
+
}
|
|
79
|
+
// Always return success to caller - export failures are observable via metrics
|
|
80
|
+
resultCallback({ code: core_1.ExportResultCode.SUCCESS });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (completed)
|
|
85
|
+
return;
|
|
86
|
+
completed = true;
|
|
87
|
+
clearTimeout(timeoutId);
|
|
88
|
+
this.queuedCount -= spans.length;
|
|
89
|
+
this.exportFailures++;
|
|
90
|
+
this.droppedCount += spans.length;
|
|
91
|
+
this.onDrop(spans.length, "export_failed");
|
|
92
|
+
console.warn("[Telemetry] Span export threw:", error);
|
|
93
|
+
resultCallback({ code: core_1.ExportResultCode.SUCCESS }); // Don't propagate failure
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Shutdown the underlying exporter.
|
|
98
|
+
* Marks exporter as shutting down to reject new exports.
|
|
99
|
+
*/
|
|
100
|
+
async shutdown() {
|
|
101
|
+
this.shuttingDown = true;
|
|
102
|
+
return this.delegate.shutdown();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Force flush the underlying exporter.
|
|
106
|
+
*/
|
|
107
|
+
async forceFlush() {
|
|
108
|
+
return this.delegate.forceFlush?.() ?? Promise.resolve();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get current metrics for observability.
|
|
112
|
+
*/
|
|
113
|
+
getMetrics() {
|
|
114
|
+
return {
|
|
115
|
+
dropped: this.droppedCount,
|
|
116
|
+
queued: this.queuedCount,
|
|
117
|
+
failures: this.exportFailures,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Reset metrics (for testing).
|
|
122
|
+
*/
|
|
123
|
+
resetMetrics() {
|
|
124
|
+
this.droppedCount = 0;
|
|
125
|
+
this.exportFailures = 0;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.ResilientExporter = ResilientExporter;
|
|
129
|
+
//# sourceMappingURL=resilient-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilient-exporter.js","sourceRoot":"","sources":["../../../src/node/exporters/resilient-exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js Telemetry Bootstrap
|
|
3
|
+
*
|
|
4
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
5
|
+
*/
|
|
6
|
+
export { initNodeTelemetry, getTelemetryInstance, isTelemetryInitialized, resetTelemetry, type NodeTelemetryInstance, } from "./init.js";
|
|
7
|
+
export { MetricsClient, type Labels, type CounterHandle, type GaugeHandle, type HistogramHandle, } from "./metrics-client.js";
|
|
8
|
+
export { TracedSocket, type TracedSocketConfig, type TracedSocketOptions, } from "./traced-socket.js";
|
|
9
|
+
export { ResilientExporter, type ResilientExporterConfig, type ResilientExporterMetrics, } from "./exporters/resilient-exporter.js";
|
|
10
|
+
export { PolicyAwareLogProcessor, LogExportMode, getLoggingPolicy, type LoggingPolicyConfig, } from "./log-processor.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,aAAa,EACb,KAAK,MAAM,EACX,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,EACjB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Node.js Telemetry Bootstrap
|
|
4
|
+
*
|
|
5
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.getLoggingPolicy = exports.LogExportMode = exports.PolicyAwareLogProcessor = exports.ResilientExporter = exports.TracedSocket = exports.MetricsClient = exports.resetTelemetry = exports.isTelemetryInitialized = exports.getTelemetryInstance = exports.initNodeTelemetry = void 0;
|
|
9
|
+
var init_js_1 = require("./init.js");
|
|
10
|
+
Object.defineProperty(exports, "initNodeTelemetry", { enumerable: true, get: function () { return init_js_1.initNodeTelemetry; } });
|
|
11
|
+
Object.defineProperty(exports, "getTelemetryInstance", { enumerable: true, get: function () { return init_js_1.getTelemetryInstance; } });
|
|
12
|
+
Object.defineProperty(exports, "isTelemetryInitialized", { enumerable: true, get: function () { return init_js_1.isTelemetryInitialized; } });
|
|
13
|
+
Object.defineProperty(exports, "resetTelemetry", { enumerable: true, get: function () { return init_js_1.resetTelemetry; } });
|
|
14
|
+
var metrics_client_js_1 = require("./metrics-client.js");
|
|
15
|
+
Object.defineProperty(exports, "MetricsClient", { enumerable: true, get: function () { return metrics_client_js_1.MetricsClient; } });
|
|
16
|
+
var traced_socket_js_1 = require("./traced-socket.js");
|
|
17
|
+
Object.defineProperty(exports, "TracedSocket", { enumerable: true, get: function () { return traced_socket_js_1.TracedSocket; } });
|
|
18
|
+
var resilient_exporter_js_1 = require("./exporters/resilient-exporter.js");
|
|
19
|
+
Object.defineProperty(exports, "ResilientExporter", { enumerable: true, get: function () { return resilient_exporter_js_1.ResilientExporter; } });
|
|
20
|
+
var log_processor_js_1 = require("./log-processor.js");
|
|
21
|
+
Object.defineProperty(exports, "PolicyAwareLogProcessor", { enumerable: true, get: function () { return log_processor_js_1.PolicyAwareLogProcessor; } });
|
|
22
|
+
Object.defineProperty(exports, "LogExportMode", { enumerable: true, get: function () { return log_processor_js_1.LogExportMode; } });
|
|
23
|
+
Object.defineProperty(exports, "getLoggingPolicy", { enumerable: true, get: function () { return log_processor_js_1.getLoggingPolicy; } });
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,qCAMmB;AALjB,4GAAA,iBAAiB,OAAA;AACjB,+GAAA,oBAAoB,OAAA;AACpB,iHAAA,sBAAsB,OAAA;AACtB,yGAAA,cAAc,OAAA;AAIhB,yDAM6B;AAL3B,kHAAA,aAAa,OAAA;AAOf,uDAI4B;AAH1B,gHAAA,YAAY,OAAA;AAKd,2EAI2C;AAHzC,0HAAA,iBAAiB,OAAA;AAKnB,uDAK4B;AAJ1B,2HAAA,uBAAuB,OAAA;AACvB,iHAAA,aAAa,OAAA;AACb,oHAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js Telemetry Bootstrap
|
|
3
|
+
*
|
|
4
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
5
|
+
* Direct NodeSDK usage outside this package is prohibited.
|
|
6
|
+
*/
|
|
7
|
+
import { Tracer, Meter } from "@opentelemetry/api";
|
|
8
|
+
import { Logger } from "@opentelemetry/api-logs";
|
|
9
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
10
|
+
import { TelemetryPolicyEvaluator } from "../common/policy-evaluator.js";
|
|
11
|
+
import type { NodeTelemetryConfig } from "../types/index.js";
|
|
12
|
+
import { TelemetryPolicy } from "../types/policy.js";
|
|
13
|
+
import { MetricsClient } from "./metrics-client.js";
|
|
14
|
+
/**
|
|
15
|
+
* Telemetry instance returned by initNodeTelemetry.
|
|
16
|
+
*/
|
|
17
|
+
export interface NodeTelemetryInstance {
|
|
18
|
+
/** The underlying NodeSDK instance (undefined in CI/no-op mode) */
|
|
19
|
+
sdk?: NodeSDK;
|
|
20
|
+
/** Policy evaluator for runtime decisions */
|
|
21
|
+
policyEvaluator: TelemetryPolicyEvaluator;
|
|
22
|
+
/** Get a tracer for the service */
|
|
23
|
+
getTracer: (name?: string) => Tracer;
|
|
24
|
+
/** Get a meter for the service */
|
|
25
|
+
getMeter: (name?: string) => Meter;
|
|
26
|
+
/** Get a logger for the service */
|
|
27
|
+
getLogger: (name?: string) => Logger;
|
|
28
|
+
/** Metrics client for recording counters, gauges, and histograms */
|
|
29
|
+
metricsClient: MetricsClient;
|
|
30
|
+
/** Graceful shutdown */
|
|
31
|
+
shutdown: () => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Initialize Node.js telemetry with policy enforcement.
|
|
35
|
+
*
|
|
36
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
37
|
+
* Direct NodeSDK usage outside this package is prohibited.
|
|
38
|
+
*
|
|
39
|
+
* @param config - Service configuration
|
|
40
|
+
* @param policy - Telemetry policy (REQUIRED)
|
|
41
|
+
* @returns Telemetry instance with SDK and utilities
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* import { initNodeTelemetry } from '@superblocksteam/telemetry/node';
|
|
46
|
+
* import { getDefaultPolicy, DeploymentType } from '@superblocksteam/shared';
|
|
47
|
+
*
|
|
48
|
+
* const policy = getDefaultPolicy(DeploymentType.CLOUD_PREM);
|
|
49
|
+
* const telemetry = initNodeTelemetry({
|
|
50
|
+
* serviceName: 'my-service',
|
|
51
|
+
* serviceVersion: '1.0.0',
|
|
52
|
+
* environment: 'production',
|
|
53
|
+
* otlpUrl: 'http://localhost:4318',
|
|
54
|
+
* }, policy);
|
|
55
|
+
*
|
|
56
|
+
* const tracer = telemetry.getTracer();
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function initNodeTelemetry(config: NodeTelemetryConfig, policy: TelemetryPolicy): NodeTelemetryInstance;
|
|
60
|
+
/**
|
|
61
|
+
* Get the current telemetry instance.
|
|
62
|
+
*
|
|
63
|
+
* @throws Error if not initialized
|
|
64
|
+
*/
|
|
65
|
+
export declare function getTelemetryInstance(): NodeTelemetryInstance;
|
|
66
|
+
/**
|
|
67
|
+
* Check if telemetry is initialized.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isTelemetryInitialized(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Reset telemetry (for testing only).
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
export declare function resetTelemetry(): void;
|
|
75
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/node/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAS,MAAM,EAAW,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAQ,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAWvD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAIlD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAiB,MAAM,oBAAoB,CAAC;AAOpE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mEAAmE;IACnE,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6CAA6C;IAC7C,eAAe,EAAE,wBAAwB,CAAC;IAC1C,mCAAmC;IACnC,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,kCAAkC;IAClC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC;IACnC,mCAAmC;IACnC,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,oEAAoE;IACpE,aAAa,EAAE,aAAa,CAAC;IAC7B,wBAAwB;IACxB,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AA0ED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,eAAe,GACtB,qBAAqB,CAkJvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,qBAAqB,CAO5D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Node.js Telemetry Bootstrap
|
|
4
|
+
*
|
|
5
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
6
|
+
* Direct NodeSDK usage outside this package is prohibited.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.initNodeTelemetry = initNodeTelemetry;
|
|
10
|
+
exports.getTelemetryInstance = getTelemetryInstance;
|
|
11
|
+
exports.isTelemetryInitialized = isTelemetryInitialized;
|
|
12
|
+
exports.resetTelemetry = resetTelemetry;
|
|
13
|
+
const api_1 = require("@opentelemetry/api");
|
|
14
|
+
const api_logs_1 = require("@opentelemetry/api-logs");
|
|
15
|
+
const context_async_hooks_1 = require("@opentelemetry/context-async-hooks");
|
|
16
|
+
const core_1 = require("@opentelemetry/core");
|
|
17
|
+
const exporter_logs_otlp_http_1 = require("@opentelemetry/exporter-logs-otlp-http");
|
|
18
|
+
const exporter_metrics_otlp_http_1 = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
19
|
+
const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
|
|
20
|
+
const sdk_logs_1 = require("@opentelemetry/sdk-logs");
|
|
21
|
+
const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
|
|
22
|
+
const sdk_node_1 = require("@opentelemetry/sdk-node");
|
|
23
|
+
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
24
|
+
const resource_js_1 = require("../common/resource.js");
|
|
25
|
+
const policy_evaluator_js_1 = require("../common/policy-evaluator.js");
|
|
26
|
+
const policy_js_1 = require("../types/policy.js");
|
|
27
|
+
const resilient_exporter_js_1 = require("./exporters/resilient-exporter.js");
|
|
28
|
+
const log_processor_js_1 = require("./log-processor.js");
|
|
29
|
+
const metrics_client_js_1 = require("./metrics-client.js");
|
|
30
|
+
// Singleton instance
|
|
31
|
+
let instance;
|
|
32
|
+
/**
|
|
33
|
+
* Create a no-op telemetry instance for CI environments.
|
|
34
|
+
*
|
|
35
|
+
* IMPORTANT: We intentionally do NOT use NodeSDK here. NodeSDK.start()
|
|
36
|
+
* auto-configures OTLP exporters for traces, metrics, and logs from
|
|
37
|
+
* environment defaults (localhost:4318). During shutdown, these exporters
|
|
38
|
+
* try to flush to the non-existent collector, causing ECONNREFUSED errors
|
|
39
|
+
* that fail test suites even when all tests pass.
|
|
40
|
+
*
|
|
41
|
+
* Instead, we return a lightweight instance that uses the global OTel API
|
|
42
|
+
* (which returns no-op tracers/meters/loggers when no provider is registered).
|
|
43
|
+
*/
|
|
44
|
+
function createNoOpInstance(config, policy) {
|
|
45
|
+
const policyEvaluator = new policy_evaluator_js_1.TelemetryPolicyEvaluator(policy);
|
|
46
|
+
// Use a no-op meter for the metrics client
|
|
47
|
+
const defaultMeter = api_1.metrics.getMeter(config.serviceName, config.serviceVersion);
|
|
48
|
+
return {
|
|
49
|
+
sdk: undefined,
|
|
50
|
+
policyEvaluator,
|
|
51
|
+
getTracer: (name) => api_1.trace.getTracer(name ?? config.serviceName, config.serviceVersion),
|
|
52
|
+
getMeter: (name) => api_1.metrics.getMeter(name ?? config.serviceName, config.serviceVersion),
|
|
53
|
+
getLogger: (name) => api_logs_1.logs.getLogger(name ?? config.serviceName, config.serviceVersion),
|
|
54
|
+
metricsClient: new metrics_client_js_1.MetricsClient(defaultMeter),
|
|
55
|
+
shutdown: async () => {
|
|
56
|
+
// No-op: nothing to flush or shut down
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validate telemetry configuration.
|
|
62
|
+
*
|
|
63
|
+
* @param config - Configuration to validate
|
|
64
|
+
* @throws Error if configuration is invalid
|
|
65
|
+
*/
|
|
66
|
+
function validateNodeTelemetryConfig(config) {
|
|
67
|
+
if (!config.serviceName?.trim()) {
|
|
68
|
+
throw new Error("[Telemetry] serviceName is required and cannot be empty");
|
|
69
|
+
}
|
|
70
|
+
if (!config.serviceVersion?.trim()) {
|
|
71
|
+
throw new Error("[Telemetry] serviceVersion is required and cannot be empty");
|
|
72
|
+
}
|
|
73
|
+
if (!config.environment?.trim()) {
|
|
74
|
+
throw new Error("[Telemetry] environment is required and cannot be empty");
|
|
75
|
+
}
|
|
76
|
+
if (config.otlpUrl) {
|
|
77
|
+
try {
|
|
78
|
+
new URL(config.otlpUrl);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw new Error(`[Telemetry] Invalid otlpUrl: ${config.otlpUrl} (${error.message})`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Initialize Node.js telemetry with policy enforcement.
|
|
87
|
+
*
|
|
88
|
+
* This is the ONLY approved way to initialize telemetry in Node.js services.
|
|
89
|
+
* Direct NodeSDK usage outside this package is prohibited.
|
|
90
|
+
*
|
|
91
|
+
* @param config - Service configuration
|
|
92
|
+
* @param policy - Telemetry policy (REQUIRED)
|
|
93
|
+
* @returns Telemetry instance with SDK and utilities
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* import { initNodeTelemetry } from '@superblocksteam/telemetry/node';
|
|
98
|
+
* import { getDefaultPolicy, DeploymentType } from '@superblocksteam/shared';
|
|
99
|
+
*
|
|
100
|
+
* const policy = getDefaultPolicy(DeploymentType.CLOUD_PREM);
|
|
101
|
+
* const telemetry = initNodeTelemetry({
|
|
102
|
+
* serviceName: 'my-service',
|
|
103
|
+
* serviceVersion: '1.0.0',
|
|
104
|
+
* environment: 'production',
|
|
105
|
+
* otlpUrl: 'http://localhost:4318',
|
|
106
|
+
* }, policy);
|
|
107
|
+
*
|
|
108
|
+
* const tracer = telemetry.getTracer();
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
function initNodeTelemetry(config, policy) {
|
|
112
|
+
// Policy is required
|
|
113
|
+
if (!policy) {
|
|
114
|
+
throw new Error("[Telemetry] Policy is required. Cannot initialize telemetry without a policy.");
|
|
115
|
+
}
|
|
116
|
+
// Validate config
|
|
117
|
+
validateNodeTelemetryConfig(config);
|
|
118
|
+
// Return existing instance if already initialized
|
|
119
|
+
if (instance) {
|
|
120
|
+
// Warn if config differs from existing
|
|
121
|
+
const existingPolicy = instance.policyEvaluator.getPolicy();
|
|
122
|
+
if (existingPolicy.deploymentType !== policy.deploymentType) {
|
|
123
|
+
console.warn(`[Telemetry] Already initialized with different deployment type ` +
|
|
124
|
+
`(existing: ${existingPolicy.deploymentType}, requested: ${policy.deploymentType}). ` +
|
|
125
|
+
`Returning existing instance.`);
|
|
126
|
+
}
|
|
127
|
+
return instance;
|
|
128
|
+
}
|
|
129
|
+
// CI environment detection - use no-op telemetry
|
|
130
|
+
if (process.env.CI === "true") {
|
|
131
|
+
console.debug("[Telemetry] CI environment detected, using no-op telemetry");
|
|
132
|
+
instance = createNoOpInstance(config, policy);
|
|
133
|
+
return instance;
|
|
134
|
+
}
|
|
135
|
+
const policyEvaluator = new policy_evaluator_js_1.TelemetryPolicyEvaluator(policy);
|
|
136
|
+
const resource = (0, resource_js_1.buildResource)(config);
|
|
137
|
+
// Validate resource has required attributes
|
|
138
|
+
(0, resource_js_1.validateResource)(resource);
|
|
139
|
+
// Track dropped spans for observability
|
|
140
|
+
let droppedSpans = 0;
|
|
141
|
+
const onDrop = (count, reason) => {
|
|
142
|
+
droppedSpans += count;
|
|
143
|
+
console.warn(`[Telemetry] Dropped ${count} spans (${reason}). Total dropped: ${droppedSpans}`);
|
|
144
|
+
};
|
|
145
|
+
// Create trace exporter if URL provided and Tier 2 export is enabled
|
|
146
|
+
// Use isExportEnabled (not canExport) - sampling applies at runtime, not initialization
|
|
147
|
+
let traceExporter;
|
|
148
|
+
if (config.otlpUrl &&
|
|
149
|
+
policyEvaluator.isExportEnabled(policy_js_1.TelemetryTier.TIER_2_OPERATIONAL)) {
|
|
150
|
+
traceExporter = new resilient_exporter_js_1.ResilientExporter({
|
|
151
|
+
delegate: new exporter_trace_otlp_http_1.OTLPTraceExporter({ url: `${config.otlpUrl}/v1/traces` }),
|
|
152
|
+
onDrop,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Create metric exporter if enabled
|
|
156
|
+
// Use isExportEnabled (not canExport) - sampling applies at runtime, not initialization
|
|
157
|
+
let metricReader;
|
|
158
|
+
if (config.otlpUrl &&
|
|
159
|
+
config.metricsEnabled !== false &&
|
|
160
|
+
policyEvaluator.isExportEnabled(policy_js_1.TelemetryTier.TIER_2_OPERATIONAL)) {
|
|
161
|
+
metricReader = new sdk_metrics_1.PeriodicExportingMetricReader({
|
|
162
|
+
exporter: new exporter_metrics_otlp_http_1.OTLPMetricExporter({
|
|
163
|
+
url: `${config.otlpUrl}/v1/metrics`,
|
|
164
|
+
temporalityPreference: sdk_metrics_1.AggregationTemporality.DELTA,
|
|
165
|
+
}),
|
|
166
|
+
exportIntervalMillis: 10000, // every 10 seconds
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
// Create log processor with policy-aware filtering and sanitization
|
|
170
|
+
// The PolicyAwareLogProcessor wraps the batch processor to:
|
|
171
|
+
// 1. Filter logs by severity level based on export mode (LOCAL_ONLY, ERRORS_ONLY, INFO_AND_ABOVE)
|
|
172
|
+
// 2. Sanitize log bodies and attributes to remove PII, file paths, stack traces
|
|
173
|
+
// 3. Remove forbidden fields that should never be exported
|
|
174
|
+
let logProcessor;
|
|
175
|
+
const loggingPolicy = (0, log_processor_js_1.getLoggingPolicy)(policy);
|
|
176
|
+
if (config.otlpUrl &&
|
|
177
|
+
config.logsEnabled !== false &&
|
|
178
|
+
policyEvaluator.isExportEnabled(policy_js_1.TelemetryTier.TIER_2_OPERATIONAL) &&
|
|
179
|
+
loggingPolicy.exportMode !== log_processor_js_1.LogExportMode.LOCAL_ONLY) {
|
|
180
|
+
const batchProcessor = new sdk_logs_1.BatchLogRecordProcessor(new exporter_logs_otlp_http_1.OTLPLogExporter({ url: `${config.otlpUrl}/v1/logs` }));
|
|
181
|
+
logProcessor = new log_processor_js_1.PolicyAwareLogProcessor(loggingPolicy, batchProcessor);
|
|
182
|
+
}
|
|
183
|
+
// Create the SDK
|
|
184
|
+
// Note: instrumentations typed as unknown[] for flexibility with various OTEL instrumentation packages
|
|
185
|
+
const sdk = new sdk_node_1.NodeSDK({
|
|
186
|
+
resource,
|
|
187
|
+
spanProcessor: traceExporter
|
|
188
|
+
? new sdk_trace_base_1.BatchSpanProcessor(traceExporter)
|
|
189
|
+
: undefined,
|
|
190
|
+
metricReader,
|
|
191
|
+
logRecordProcessor: logProcessor,
|
|
192
|
+
contextManager: new context_async_hooks_1.AsyncLocalStorageContextManager(),
|
|
193
|
+
textMapPropagator: new core_1.W3CTraceContextPropagator(),
|
|
194
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- OTEL instrumentation types vary
|
|
195
|
+
instrumentations: (config.instrumentations ?? []),
|
|
196
|
+
});
|
|
197
|
+
sdk.start();
|
|
198
|
+
console.info(`[Telemetry] Initialized for ${config.serviceName} (${policy.deploymentType})` +
|
|
199
|
+
` | Traces: ${traceExporter ? "enabled" : "disabled"}` +
|
|
200
|
+
` | Metrics: ${metricReader ? "enabled" : "disabled"}` +
|
|
201
|
+
` | Logs: ${logProcessor ? "enabled" : "disabled"}`);
|
|
202
|
+
const defaultMeter = api_1.metrics.getMeter(config.serviceName, config.serviceVersion);
|
|
203
|
+
instance = {
|
|
204
|
+
sdk,
|
|
205
|
+
policyEvaluator,
|
|
206
|
+
getTracer: (name) => api_1.trace.getTracer(name ?? config.serviceName, config.serviceVersion),
|
|
207
|
+
getMeter: (name) => api_1.metrics.getMeter(name ?? config.serviceName, config.serviceVersion),
|
|
208
|
+
getLogger: (name) => api_logs_1.logs.getLogger(name ?? config.serviceName, config.serviceVersion),
|
|
209
|
+
metricsClient: new metrics_client_js_1.MetricsClient(defaultMeter),
|
|
210
|
+
shutdown: async () => {
|
|
211
|
+
try {
|
|
212
|
+
await sdk.shutdown();
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
instance = undefined;
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
return instance;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get the current telemetry instance.
|
|
223
|
+
*
|
|
224
|
+
* @throws Error if not initialized
|
|
225
|
+
*/
|
|
226
|
+
function getTelemetryInstance() {
|
|
227
|
+
if (!instance) {
|
|
228
|
+
throw new Error("[Telemetry] Not initialized. Call initNodeTelemetry() first.");
|
|
229
|
+
}
|
|
230
|
+
return instance;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Check if telemetry is initialized.
|
|
234
|
+
*/
|
|
235
|
+
function isTelemetryInitialized() {
|
|
236
|
+
return instance !== undefined;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Reset telemetry (for testing only).
|
|
240
|
+
* @internal
|
|
241
|
+
*/
|
|
242
|
+
function resetTelemetry() {
|
|
243
|
+
instance = undefined;
|
|
244
|
+
}
|
|
245
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/node/init.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAmJH,8CAqJC;AAOD,oDAOC;AAKD,wDAEC;AAMD,wCAEC;AAnUD,4CAAmE;AACnE,sDAAuD;AACvD,4EAAqF;AACrF,8CAAgE;AAChE,oFAAyE;AACzE,0FAA+E;AAC/E,sFAA4E;AAC5E,sDAAkE;AAClE,4DAGoC;AACpC,sDAAkD;AAClD,kEAAmE;AAEnE,uDAAwE;AACxE,uEAAyE;AAEzE,kDAAoE;AACpE,6EAAsE;AACtE,yDAI4B;AAC5B,2DAAoD;AAsBpD,qBAAqB;AACrB,IAAI,QAA2C,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,SAAS,kBAAkB,CACzB,MAA2B,EAC3B,MAAuB;IAEvB,MAAM,eAAe,GAAG,IAAI,8CAAwB,CAAC,MAAM,CAAC,CAAC;IAE7D,2CAA2C;IAC3C,MAAM,YAAY,GAAG,aAAO,CAAC,QAAQ,CACnC,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,cAAc,CACtB,CAAC;IAEF,OAAO;QACL,GAAG,EAAE,SAAS;QACd,eAAe;QACf,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE,CAC3B,WAAK,CAAC,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACpE,QAAQ,EAAE,CAAC,IAAa,EAAE,EAAE,CAC1B,aAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACrE,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE,CAC3B,eAAI,CAAC,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACnE,aAAa,EAAE,IAAI,iCAAa,CAAC,YAAY,CAAC;QAC9C,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,uCAAuC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,2BAA2B,CAAC,MAA2B;IAC9D,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,gCAAgC,MAAM,CAAC,OAAO,KAAM,KAAe,CAAC,OAAO,GAAG,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,iBAAiB,CAC/B,MAA2B,EAC3B,MAAuB;IAEvB,qBAAqB;IACrB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,kDAAkD;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,uCAAuC;QACvC,MAAM,cAAc,GAAG,QAAQ,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;QAC5D,IAAI,cAAc,CAAC,cAAc,KAAK,MAAM,CAAC,cAAc,EAAE,CAAC;YAC5D,OAAO,CAAC,IAAI,CACV,iEAAiE;gBAC/D,cAAc,cAAc,CAAC,cAAc,gBAAgB,MAAM,CAAC,cAAc,KAAK;gBACrF,8BAA8B,CACjC,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,QAAQ,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,8CAAwB,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAA,2BAAa,EAAC,MAAM,CAAC,CAAC;IAEvC,4CAA4C;IAC5C,IAAA,8BAAgB,EAAC,QAAQ,CAAC,CAAC;IAE3B,wCAAwC;IACxC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,MAAc,EAAE,EAAE;QAC/C,YAAY,IAAI,KAAK,CAAC;QACtB,OAAO,CAAC,IAAI,CACV,uBAAuB,KAAK,WAAW,MAAM,qBAAqB,YAAY,EAAE,CACjF,CAAC;IACJ,CAAC,CAAC;IAEF,qEAAqE;IACrE,wFAAwF;IACxF,IAAI,aAA4C,CAAC;IACjD,IACE,MAAM,CAAC,OAAO;QACd,eAAe,CAAC,eAAe,CAAC,yBAAa,CAAC,kBAAkB,CAAC,EACjE,CAAC;QACD,aAAa,GAAG,IAAI,yCAAiB,CAAC;YACpC,QAAQ,EAAE,IAAI,4CAAiB,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,YAAY,EAAE,CAAC;YACvE,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IAED,oCAAoC;IACpC,wFAAwF;IACxF,IAAI,YAAuD,CAAC;IAC5D,IACE,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,cAAc,KAAK,KAAK;QAC/B,eAAe,CAAC,eAAe,CAAC,yBAAa,CAAC,kBAAkB,CAAC,EACjE,CAAC;QACD,YAAY,GAAG,IAAI,2CAA6B,CAAC;YAC/C,QAAQ,EAAE,IAAI,+CAAkB,CAAC;gBAC/B,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,aAAa;gBACnC,qBAAqB,EAAE,oCAAsB,CAAC,KAAK;aACpD,CAAC;YACF,oBAAoB,EAAE,KAAK,EAAE,mBAAmB;SACjD,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IACpE,4DAA4D;IAC5D,kGAAkG;IAClG,gFAAgF;IAChF,2DAA2D;IAC3D,IAAI,YAAiD,CAAC;IACtD,MAAM,aAAa,GAAG,IAAA,mCAAgB,EAAC,MAAM,CAAC,CAAC;IAE/C,IACE,MAAM,CAAC,OAAO;QACd,MAAM,CAAC,WAAW,KAAK,KAAK;QAC5B,eAAe,CAAC,eAAe,CAAC,yBAAa,CAAC,kBAAkB,CAAC;QACjE,aAAa,CAAC,UAAU,KAAK,gCAAa,CAAC,UAAU,EACrD,CAAC;QACD,MAAM,cAAc,GAAG,IAAI,kCAAuB,CAChD,IAAI,yCAAe,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,UAAU,EAAE,CAAC,CAC1D,CAAC;QACF,YAAY,GAAG,IAAI,0CAAuB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC5E,CAAC;IAED,iBAAiB;IACjB,uGAAuG;IACvG,MAAM,GAAG,GAAG,IAAI,kBAAO,CAAC;QACtB,QAAQ;QACR,aAAa,EAAE,aAAa;YAC1B,CAAC,CAAC,IAAI,mCAAkB,CAAC,aAAa,CAAC;YACvC,CAAC,CAAC,SAAS;QACb,YAAY;QACZ,kBAAkB,EAAE,YAAY;QAChC,cAAc,EAAE,IAAI,qDAA+B,EAAE;QACrD,iBAAiB,EAAE,IAAI,gCAAyB,EAAE;QAClD,iGAAiG;QACjG,gBAAgB,EAAE,CAAC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAAQ;KACzD,CAAC,CAAC;IAEH,GAAG,CAAC,KAAK,EAAE,CAAC;IAEZ,OAAO,CAAC,IAAI,CACV,+BAA+B,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,cAAc,GAAG;QAC5E,cAAc,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE;QACtD,eAAe,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE;QACtD,YAAY,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CACtD,CAAC;IAEF,MAAM,YAAY,GAAG,aAAO,CAAC,QAAQ,CACnC,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,cAAc,CACtB,CAAC;IAEF,QAAQ,GAAG;QACT,GAAG;QACH,eAAe;QACf,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE,CAC3B,WAAK,CAAC,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACpE,QAAQ,EAAE,CAAC,IAAa,EAAE,EAAE,CAC1B,aAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACrE,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE,CAC3B,eAAI,CAAC,SAAS,CAAC,IAAI,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,CAAC;QACnE,aAAa,EAAE,IAAI,iCAAa,CAAC,YAAY,CAAC;QAC9C,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC;YACvB,CAAC;oBAAS,CAAC;gBACT,QAAQ,GAAG,SAAS,CAAC;YACvB,CAAC;QACH,CAAC;KACF,CAAC;IAEF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB;IAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB;IACpC,OAAO,QAAQ,KAAK,SAAS,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc;IAC5B,QAAQ,GAAG,SAAS,CAAC;AACvB,CAAC"}
|