@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,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy-Aware Log Processor
|
|
3
|
+
*
|
|
4
|
+
* Wraps a delegate LogRecordProcessor to provide:
|
|
5
|
+
* 1. Export mode filtering (LOCAL_ONLY, ERRORS_ONLY, INFO_AND_ABOVE)
|
|
6
|
+
* 2. Severity level filtering
|
|
7
|
+
* 3. Log body and attribute sanitization
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/superblocksteam/engineering/blob/main/projects/o11y-refactor/epics/epic-c4-logging-strategy.md
|
|
10
|
+
*/
|
|
11
|
+
import type { LogRecordProcessor, ReadableLogRecord } from "@opentelemetry/sdk-logs";
|
|
12
|
+
import type { Context } from "@opentelemetry/api";
|
|
13
|
+
import { TelemetryPolicy } from "../types/policy.js";
|
|
14
|
+
/**
|
|
15
|
+
* Controls what logs are exported via OTEL.
|
|
16
|
+
*/
|
|
17
|
+
export declare enum LogExportMode {
|
|
18
|
+
/** No log export - local stdout/stderr only */
|
|
19
|
+
LOCAL_ONLY = "local_only",
|
|
20
|
+
/** Export WARN/ERROR/FATAL only (default for cloud-prem) */
|
|
21
|
+
ERRORS_ONLY = "errors_only",
|
|
22
|
+
/** Export INFO and above (not recommended for cloud-prem) */
|
|
23
|
+
INFO_AND_ABOVE = "info_and_above"
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Logging-specific policy configuration.
|
|
27
|
+
*/
|
|
28
|
+
export interface LoggingPolicyConfig {
|
|
29
|
+
/** What logs to export */
|
|
30
|
+
exportMode: LogExportMode;
|
|
31
|
+
/** Maximum log level for local retention */
|
|
32
|
+
localMaxLevel: "trace" | "debug" | "info" | "warn" | "error" | "fatal";
|
|
33
|
+
/** Regex patterns to redact from log content */
|
|
34
|
+
redactPatterns: RegExp[];
|
|
35
|
+
/** Fields to never include in exported logs */
|
|
36
|
+
forbiddenFields: Set<string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get logging policy based on telemetry policy.
|
|
40
|
+
*
|
|
41
|
+
* @param policy - Telemetry policy
|
|
42
|
+
* @returns Logging policy configuration
|
|
43
|
+
*/
|
|
44
|
+
export declare function getLoggingPolicy(policy: TelemetryPolicy): LoggingPolicyConfig;
|
|
45
|
+
/**
|
|
46
|
+
* Log processor that filters and sanitizes logs based on policy.
|
|
47
|
+
*
|
|
48
|
+
* This processor:
|
|
49
|
+
* 1. Blocks all logs if exportMode is LOCAL_ONLY
|
|
50
|
+
* 2. Filters by severity level based on exportMode
|
|
51
|
+
* 3. Sanitizes log body and attributes before forwarding
|
|
52
|
+
*/
|
|
53
|
+
export declare class PolicyAwareLogProcessor implements LogRecordProcessor {
|
|
54
|
+
private readonly policy;
|
|
55
|
+
private readonly delegate;
|
|
56
|
+
constructor(policy: LoggingPolicyConfig, delegate: LogRecordProcessor);
|
|
57
|
+
/**
|
|
58
|
+
* Called when a log record is emitted.
|
|
59
|
+
*/
|
|
60
|
+
onEmit(logRecord: ReadableLogRecord, context?: Context): void;
|
|
61
|
+
/**
|
|
62
|
+
* Sanitize a log record for export.
|
|
63
|
+
* Mutates the log record in place to preserve OTEL SDK internal state.
|
|
64
|
+
*/
|
|
65
|
+
private sanitizeLogRecord;
|
|
66
|
+
/**
|
|
67
|
+
* Check if a string contains a stack trace.
|
|
68
|
+
*/
|
|
69
|
+
private containsStackTrace;
|
|
70
|
+
/**
|
|
71
|
+
* Sanitize log attributes.
|
|
72
|
+
*/
|
|
73
|
+
private sanitizeAttributes;
|
|
74
|
+
/**
|
|
75
|
+
* Shutdown the processor.
|
|
76
|
+
*/
|
|
77
|
+
shutdown(): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Force flush pending logs.
|
|
80
|
+
*/
|
|
81
|
+
forceFlush(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=log-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-processor.d.ts","sourceRoot":"","sources":["../../src/node/log-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAiB,MAAM,oBAAoB,CAAC;AAepE;;GAEG;AACH,oBAAY,aAAa;IACvB,+CAA+C;IAC/C,UAAU,eAAe;IACzB,4DAA4D;IAC5D,WAAW,gBAAgB;IAC3B,6DAA6D;IAC7D,cAAc,mBAAmB;CAClC;AAMD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0BAA0B;IAC1B,UAAU,EAAE,aAAa,CAAC;IAC1B,4CAA4C;IAC5C,aAAa,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACvE,gDAAgD;IAChD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,+CAA+C;IAC/C,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,mBAAmB,CAyC7E;AAuDD;;;;;;;GAOG;AACH,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;gBAElC,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,kBAAkB;IAKrE;;OAEG;IACH,MAAM,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI;IAsB7D;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyC1B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAGlC"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Policy-Aware Log Processor
|
|
4
|
+
*
|
|
5
|
+
* Wraps a delegate LogRecordProcessor to provide:
|
|
6
|
+
* 1. Export mode filtering (LOCAL_ONLY, ERRORS_ONLY, INFO_AND_ABOVE)
|
|
7
|
+
* 2. Severity level filtering
|
|
8
|
+
* 3. Log body and attribute sanitization
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/superblocksteam/engineering/blob/main/projects/o11y-refactor/epics/epic-c4-logging-strategy.md
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.PolicyAwareLogProcessor = exports.LogExportMode = void 0;
|
|
14
|
+
exports.getLoggingPolicy = getLoggingPolicy;
|
|
15
|
+
const policy_js_1 = require("../types/policy.js");
|
|
16
|
+
const policy_evaluator_js_1 = require("../common/policy-evaluator.js");
|
|
17
|
+
const log_sanitizer_js_1 = require("../common/log-sanitizer.js");
|
|
18
|
+
const shared_1 = require("@superblocksteam/shared");
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Log Export Mode
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Controls what logs are exported via OTEL.
|
|
24
|
+
*/
|
|
25
|
+
var LogExportMode;
|
|
26
|
+
(function (LogExportMode) {
|
|
27
|
+
/** No log export - local stdout/stderr only */
|
|
28
|
+
LogExportMode["LOCAL_ONLY"] = "local_only";
|
|
29
|
+
/** Export WARN/ERROR/FATAL only (default for cloud-prem) */
|
|
30
|
+
LogExportMode["ERRORS_ONLY"] = "errors_only";
|
|
31
|
+
/** Export INFO and above (not recommended for cloud-prem) */
|
|
32
|
+
LogExportMode["INFO_AND_ABOVE"] = "info_and_above";
|
|
33
|
+
})(LogExportMode || (exports.LogExportMode = LogExportMode = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Get logging policy based on telemetry policy.
|
|
36
|
+
*
|
|
37
|
+
* @param policy - Telemetry policy
|
|
38
|
+
* @returns Logging policy configuration
|
|
39
|
+
*/
|
|
40
|
+
function getLoggingPolicy(policy) {
|
|
41
|
+
const evaluator = new policy_evaluator_js_1.TelemetryPolicyEvaluator(policy);
|
|
42
|
+
// Check if Tier 2 export is allowed
|
|
43
|
+
const canExportTier2 = evaluator.isExportEnabled(policy_js_1.TelemetryTier.TIER_2_OPERATIONAL);
|
|
44
|
+
if (!canExportTier2) {
|
|
45
|
+
return {
|
|
46
|
+
exportMode: LogExportMode.LOCAL_ONLY,
|
|
47
|
+
localMaxLevel: "debug",
|
|
48
|
+
redactPatterns: [],
|
|
49
|
+
forbiddenFields: log_sanitizer_js_1.TIER1_FORBIDDEN_LOG_FIELDS,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Cloud-prem: export errors only, with full sanitization
|
|
53
|
+
if (policy.deploymentType === shared_1.DeploymentTypeEnum.CLOUD_PREM) {
|
|
54
|
+
return {
|
|
55
|
+
exportMode: LogExportMode.ERRORS_ONLY,
|
|
56
|
+
localMaxLevel: "debug",
|
|
57
|
+
redactPatterns: [
|
|
58
|
+
// JWTs
|
|
59
|
+
/\b[A-Za-z0-9-_]{20,}\.[A-Za-z0-9-_]{20,}\.[A-Za-z0-9-_]{20,}\b/g,
|
|
60
|
+
// Bearer tokens
|
|
61
|
+
/(\bbearer\s+)[a-zA-Z0-9\-._~+/]+=*/gi,
|
|
62
|
+
// API keys
|
|
63
|
+
/(\bapi[_\s]?key[:\s=]+)[a-zA-Z0-9\-._~+/]+=*/gi,
|
|
64
|
+
],
|
|
65
|
+
forbiddenFields: log_sanitizer_js_1.TIER1_FORBIDDEN_LOG_FIELDS,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Cloud: more permissive (INFO and above)
|
|
69
|
+
return {
|
|
70
|
+
exportMode: LogExportMode.INFO_AND_ABOVE,
|
|
71
|
+
localMaxLevel: "debug",
|
|
72
|
+
redactPatterns: [],
|
|
73
|
+
forbiddenFields: new Set(), // Cloud can export more
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// Severity Level Utilities
|
|
78
|
+
// ============================================================================
|
|
79
|
+
/**
|
|
80
|
+
* OTEL severity numbers:
|
|
81
|
+
* 1-4: TRACE
|
|
82
|
+
* 5-8: DEBUG
|
|
83
|
+
* 9-12: INFO
|
|
84
|
+
* 13-16: WARN
|
|
85
|
+
* 17-20: ERROR
|
|
86
|
+
* 21-24: FATAL
|
|
87
|
+
*/
|
|
88
|
+
function getSeverityName(severityNumber) {
|
|
89
|
+
if (!severityNumber)
|
|
90
|
+
return "info";
|
|
91
|
+
if (severityNumber <= 4)
|
|
92
|
+
return "trace";
|
|
93
|
+
if (severityNumber <= 8)
|
|
94
|
+
return "debug";
|
|
95
|
+
if (severityNumber <= 12)
|
|
96
|
+
return "info";
|
|
97
|
+
if (severityNumber <= 16)
|
|
98
|
+
return "warn";
|
|
99
|
+
if (severityNumber <= 20)
|
|
100
|
+
return "error";
|
|
101
|
+
return "fatal";
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check if a severity level should be exported based on export mode.
|
|
105
|
+
*/
|
|
106
|
+
function shouldExportSeverity(severityNumber, mode) {
|
|
107
|
+
if (mode === LogExportMode.LOCAL_ONLY) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const severity = getSeverityName(severityNumber);
|
|
111
|
+
if (mode === LogExportMode.ERRORS_ONLY) {
|
|
112
|
+
return severity === "warn" || severity === "error" || severity === "fatal";
|
|
113
|
+
}
|
|
114
|
+
// INFO_AND_ABOVE
|
|
115
|
+
return (severity === "info" ||
|
|
116
|
+
severity === "warn" ||
|
|
117
|
+
severity === "error" ||
|
|
118
|
+
severity === "fatal");
|
|
119
|
+
}
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Policy-Aware Log Processor
|
|
122
|
+
// ============================================================================
|
|
123
|
+
/**
|
|
124
|
+
* Log processor that filters and sanitizes logs based on policy.
|
|
125
|
+
*
|
|
126
|
+
* This processor:
|
|
127
|
+
* 1. Blocks all logs if exportMode is LOCAL_ONLY
|
|
128
|
+
* 2. Filters by severity level based on exportMode
|
|
129
|
+
* 3. Sanitizes log body and attributes before forwarding
|
|
130
|
+
*/
|
|
131
|
+
class PolicyAwareLogProcessor {
|
|
132
|
+
policy;
|
|
133
|
+
delegate;
|
|
134
|
+
constructor(policy, delegate) {
|
|
135
|
+
this.policy = policy;
|
|
136
|
+
this.delegate = delegate;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Called when a log record is emitted.
|
|
140
|
+
*/
|
|
141
|
+
onEmit(logRecord, context) {
|
|
142
|
+
// Check if export mode allows this log
|
|
143
|
+
if (this.policy.exportMode === LogExportMode.LOCAL_ONLY) {
|
|
144
|
+
return; // Don't export anything
|
|
145
|
+
}
|
|
146
|
+
// Check if severity level should be exported
|
|
147
|
+
if (!shouldExportSeverity(logRecord.severityNumber, this.policy.exportMode)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Sanitize the log record in place before forwarding
|
|
151
|
+
// The logRecord is actually an SdkLogRecord at runtime, we mutate it directly
|
|
152
|
+
this.sanitizeLogRecord(logRecord);
|
|
153
|
+
// Forward to delegate - cast is safe because logRecord is SdkLogRecord at runtime
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
155
|
+
this.delegate.onEmit(logRecord, context);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Sanitize a log record for export.
|
|
159
|
+
* Mutates the log record in place to preserve OTEL SDK internal state.
|
|
160
|
+
*/
|
|
161
|
+
sanitizeLogRecord(logRecord) {
|
|
162
|
+
// Sanitize body - mutate in place
|
|
163
|
+
if (typeof logRecord.body === "string") {
|
|
164
|
+
// Apply policy-specific redact patterns first
|
|
165
|
+
let sanitizedBody = logRecord.body;
|
|
166
|
+
for (const pattern of this.policy.redactPatterns) {
|
|
167
|
+
pattern.lastIndex = 0; // Reset regex state
|
|
168
|
+
sanitizedBody = sanitizedBody.replace(pattern, "[REDACTED]");
|
|
169
|
+
}
|
|
170
|
+
// Check for stack traces
|
|
171
|
+
if (this.containsStackTrace(sanitizedBody)) {
|
|
172
|
+
// Use setAttribute pattern for LogRecord mutation
|
|
173
|
+
logRecord.body =
|
|
174
|
+
(0, log_sanitizer_js_1.redactStackTrace)(sanitizedBody);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
logRecord.body =
|
|
178
|
+
(0, log_sanitizer_js_1.sanitizeLogMessage)(sanitizedBody);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (logRecord.body && typeof logRecord.body === "object") {
|
|
182
|
+
logRecord.body = (0, log_sanitizer_js_1.sanitizeLogObject)(logRecord.body);
|
|
183
|
+
}
|
|
184
|
+
// Sanitize attributes - mutate in place
|
|
185
|
+
const attrs = logRecord.attributes;
|
|
186
|
+
if (attrs) {
|
|
187
|
+
const sanitizedAttributes = this.sanitizeAttributes(attrs);
|
|
188
|
+
// Clear and repopulate attributes
|
|
189
|
+
for (const key of Object.keys(attrs)) {
|
|
190
|
+
delete attrs[key];
|
|
191
|
+
}
|
|
192
|
+
for (const [key, value] of Object.entries(sanitizedAttributes)) {
|
|
193
|
+
attrs[key] = value;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Check if a string contains a stack trace.
|
|
199
|
+
*/
|
|
200
|
+
containsStackTrace(text) {
|
|
201
|
+
// Node.js stack traces
|
|
202
|
+
if (/at .+\(.+:\d+:\d+\)/.test(text))
|
|
203
|
+
return true;
|
|
204
|
+
// Go stack traces
|
|
205
|
+
if (/goroutine \d+ \[.+\]:/.test(text))
|
|
206
|
+
return true;
|
|
207
|
+
// Python stack traces
|
|
208
|
+
if (/File ".+", line \d+/.test(text))
|
|
209
|
+
return true;
|
|
210
|
+
// Java stack traces
|
|
211
|
+
if (/at \w+\.\w+\(.+\.java:\d+\)/.test(text))
|
|
212
|
+
return true;
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Sanitize log attributes.
|
|
217
|
+
*/
|
|
218
|
+
sanitizeAttributes(attributes) {
|
|
219
|
+
if (!attributes) {
|
|
220
|
+
return {};
|
|
221
|
+
}
|
|
222
|
+
const sanitized = {};
|
|
223
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
224
|
+
const lowerKey = key.toLowerCase();
|
|
225
|
+
// Skip forbidden fields (exact match from policy)
|
|
226
|
+
if (this.policy.forbiddenFields.has(lowerKey)) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
// Skip fields matching secret field patterns (word-boundary aware)
|
|
230
|
+
if ((0, log_sanitizer_js_1.isSecretField)(key)) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
// Sanitize string values
|
|
234
|
+
if (typeof value === "string") {
|
|
235
|
+
// Apply policy-specific redact patterns
|
|
236
|
+
let sanitizedValue = value;
|
|
237
|
+
for (const pattern of this.policy.redactPatterns) {
|
|
238
|
+
pattern.lastIndex = 0;
|
|
239
|
+
sanitizedValue = sanitizedValue.replace(pattern, "[REDACTED]");
|
|
240
|
+
}
|
|
241
|
+
sanitized[key] = (0, log_sanitizer_js_1.sanitizeLogMessage)(sanitizedValue);
|
|
242
|
+
}
|
|
243
|
+
else if (value && typeof value === "object") {
|
|
244
|
+
sanitized[key] = (0, log_sanitizer_js_1.sanitizeLogObject)(value);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
sanitized[key] = value;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return sanitized;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Shutdown the processor.
|
|
254
|
+
*/
|
|
255
|
+
async shutdown() {
|
|
256
|
+
return this.delegate.shutdown();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Force flush pending logs.
|
|
260
|
+
*/
|
|
261
|
+
async forceFlush() {
|
|
262
|
+
return this.delegate.forceFlush();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
exports.PolicyAwareLogProcessor = PolicyAwareLogProcessor;
|
|
266
|
+
//# sourceMappingURL=log-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-processor.js","sourceRoot":"","sources":["../../src/node/log-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics Client for Node.js Telemetry
|
|
3
|
+
*
|
|
4
|
+
* Provides a simple interface for recording metrics via OpenTelemetry.
|
|
5
|
+
* This is the recommended way to record metrics in services using the telemetry package.
|
|
6
|
+
*/
|
|
7
|
+
import type { Meter } from "@opentelemetry/api";
|
|
8
|
+
/**
|
|
9
|
+
* Labels for metrics (key-value pairs).
|
|
10
|
+
*/
|
|
11
|
+
export type Labels = Record<string, string | number>;
|
|
12
|
+
/**
|
|
13
|
+
* Handle for a counter metric.
|
|
14
|
+
*/
|
|
15
|
+
export interface CounterHandle {
|
|
16
|
+
inc(labels?: Labels, value?: number): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Handle for a gauge metric.
|
|
20
|
+
*/
|
|
21
|
+
export interface GaugeHandle {
|
|
22
|
+
set(labels: Labels, value: number): void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Handle for a histogram metric.
|
|
26
|
+
*/
|
|
27
|
+
export interface HistogramHandle {
|
|
28
|
+
observe(labels: Labels, value: number): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Metrics client that provides a unified interface for recording OTEL metrics.
|
|
32
|
+
*/
|
|
33
|
+
export declare class MetricsClient {
|
|
34
|
+
private readonly meter;
|
|
35
|
+
private counters;
|
|
36
|
+
private histograms;
|
|
37
|
+
private gaugeValues;
|
|
38
|
+
constructor(meter: Meter);
|
|
39
|
+
/**
|
|
40
|
+
* Creates or retrieves a counter and returns a handle.
|
|
41
|
+
*/
|
|
42
|
+
counter(name: string): CounterHandle;
|
|
43
|
+
/**
|
|
44
|
+
* Creates or retrieves a gauge and returns a handle.
|
|
45
|
+
* Note: OTEL gauges are async/observable, so we store the value and emit via callback.
|
|
46
|
+
* Values are automatically expired after 5 minutes to prevent unbounded memory growth.
|
|
47
|
+
*/
|
|
48
|
+
gauge(name: string): GaugeHandle;
|
|
49
|
+
/**
|
|
50
|
+
* Creates or retrieves a histogram and returns a handle.
|
|
51
|
+
*/
|
|
52
|
+
histogram(name: string): HistogramHandle;
|
|
53
|
+
/**
|
|
54
|
+
* Increments a counter by name (creates if not exists).
|
|
55
|
+
*/
|
|
56
|
+
incCounter(name: string, labels?: Labels, value?: number): void;
|
|
57
|
+
/**
|
|
58
|
+
* Sets a gauge value by name (creates if not exists).
|
|
59
|
+
*/
|
|
60
|
+
setGauge(name: string, labels: Labels, value: number): void;
|
|
61
|
+
/**
|
|
62
|
+
* Observes a histogram value by name (creates if not exists).
|
|
63
|
+
*/
|
|
64
|
+
observeHistogram(name: string, labels: Labels, value: number): void;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=metrics-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-client.d.ts","sourceRoot":"","sources":["../../src/node/metrics-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAkC,MAAM,oBAAoB,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAoHrD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED;;GAEG;AACH,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,KAAK;IALlC,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,UAAU,CAAgC;IAElD,OAAO,CAAC,WAAW,CAAkC;gBAExB,KAAK,EAAE,KAAK;IAEzC;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAapC;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IA2BhC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAaxC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI;IAIlE;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI3D;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;CAGpE"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Metrics Client for Node.js Telemetry
|
|
4
|
+
*
|
|
5
|
+
* Provides a simple interface for recording metrics via OpenTelemetry.
|
|
6
|
+
* This is the recommended way to record metrics in services using the telemetry package.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MetricsClient = void 0;
|
|
10
|
+
/**
|
|
11
|
+
* Converts Labels to OTEL Attributes.
|
|
12
|
+
*/
|
|
13
|
+
function labelsToAttributes(labels) {
|
|
14
|
+
if (!labels)
|
|
15
|
+
return {};
|
|
16
|
+
const attributes = {};
|
|
17
|
+
for (const [key, value] of Object.entries(labels)) {
|
|
18
|
+
attributes[key] = String(value);
|
|
19
|
+
}
|
|
20
|
+
return attributes;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* TTL configuration for gauge values.
|
|
24
|
+
*/
|
|
25
|
+
const GAUGE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
26
|
+
const GAUGE_MAX_ENTRIES = 10_000; // Max entries per gauge to prevent unbounded growth
|
|
27
|
+
const GAUGE_CLEANUP_INTERVAL_MS = 60 * 1000; // Cleanup every minute
|
|
28
|
+
/**
|
|
29
|
+
* TTL-based map for gauge values with automatic cleanup.
|
|
30
|
+
*/
|
|
31
|
+
class TTLGaugeMap {
|
|
32
|
+
ttlMs;
|
|
33
|
+
maxEntries;
|
|
34
|
+
entries = new Map();
|
|
35
|
+
cleanupTimer = null;
|
|
36
|
+
constructor(ttlMs = GAUGE_TTL_MS, maxEntries = GAUGE_MAX_ENTRIES) {
|
|
37
|
+
this.ttlMs = ttlMs;
|
|
38
|
+
this.maxEntries = maxEntries;
|
|
39
|
+
// Start periodic cleanup
|
|
40
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), GAUGE_CLEANUP_INTERVAL_MS);
|
|
41
|
+
// Don't prevent Node.js from exiting
|
|
42
|
+
this.cleanupTimer.unref();
|
|
43
|
+
}
|
|
44
|
+
set(labelsKey, value) {
|
|
45
|
+
// If at max capacity, remove oldest entry
|
|
46
|
+
if (this.entries.size >= this.maxEntries && !this.entries.has(labelsKey)) {
|
|
47
|
+
this.evictOldest();
|
|
48
|
+
}
|
|
49
|
+
this.entries.set(labelsKey, {
|
|
50
|
+
value,
|
|
51
|
+
updatedAt: Date.now(),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Gets all non-expired entries.
|
|
56
|
+
*/
|
|
57
|
+
getAll() {
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
const result = new Map();
|
|
60
|
+
for (const [key, entry] of this.entries) {
|
|
61
|
+
if (now - entry.updatedAt <= this.ttlMs) {
|
|
62
|
+
result.set(key, entry.value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Removes expired entries.
|
|
69
|
+
*/
|
|
70
|
+
cleanup() {
|
|
71
|
+
const now = Date.now();
|
|
72
|
+
for (const [key, entry] of this.entries) {
|
|
73
|
+
if (now - entry.updatedAt > this.ttlMs) {
|
|
74
|
+
this.entries.delete(key);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Evicts the oldest entry when at max capacity.
|
|
80
|
+
*/
|
|
81
|
+
evictOldest() {
|
|
82
|
+
let oldestKey = null;
|
|
83
|
+
let oldestTime = Infinity;
|
|
84
|
+
for (const [key, entry] of this.entries) {
|
|
85
|
+
if (entry.updatedAt < oldestTime) {
|
|
86
|
+
oldestTime = entry.updatedAt;
|
|
87
|
+
oldestKey = key;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (oldestKey) {
|
|
91
|
+
this.entries.delete(oldestKey);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Stops the cleanup timer.
|
|
96
|
+
*/
|
|
97
|
+
destroy() {
|
|
98
|
+
if (this.cleanupTimer) {
|
|
99
|
+
clearInterval(this.cleanupTimer);
|
|
100
|
+
this.cleanupTimer = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Metrics client that provides a unified interface for recording OTEL metrics.
|
|
106
|
+
*/
|
|
107
|
+
class MetricsClient {
|
|
108
|
+
meter;
|
|
109
|
+
counters = new Map();
|
|
110
|
+
histograms = new Map();
|
|
111
|
+
// Gauges use TTL-based maps to prevent unbounded memory growth
|
|
112
|
+
gaugeValues = new Map();
|
|
113
|
+
constructor(meter) {
|
|
114
|
+
this.meter = meter;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Creates or retrieves a counter and returns a handle.
|
|
118
|
+
*/
|
|
119
|
+
counter(name) {
|
|
120
|
+
if (!this.counters.has(name)) {
|
|
121
|
+
this.counters.set(name, this.meter.createCounter(name));
|
|
122
|
+
}
|
|
123
|
+
const counter = this.counters.get(name);
|
|
124
|
+
return {
|
|
125
|
+
inc: (labels, value = 1) => {
|
|
126
|
+
counter.add(value, labelsToAttributes(labels));
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Creates or retrieves a gauge and returns a handle.
|
|
132
|
+
* Note: OTEL gauges are async/observable, so we store the value and emit via callback.
|
|
133
|
+
* Values are automatically expired after 5 minutes to prevent unbounded memory growth.
|
|
134
|
+
*/
|
|
135
|
+
gauge(name) {
|
|
136
|
+
if (!this.gaugeValues.has(name)) {
|
|
137
|
+
const ttlMap = new TTLGaugeMap();
|
|
138
|
+
this.gaugeValues.set(name, ttlMap);
|
|
139
|
+
// Create an observable gauge that reads from the TTL map
|
|
140
|
+
this.meter.createObservableGauge(name, {}).addCallback((result) => {
|
|
141
|
+
const ttlMapRef = this.gaugeValues.get(name);
|
|
142
|
+
if (ttlMapRef) {
|
|
143
|
+
// getAll() only returns non-expired entries
|
|
144
|
+
for (const [labelsKey, value] of ttlMapRef.getAll()) {
|
|
145
|
+
const labels = JSON.parse(labelsKey);
|
|
146
|
+
result.observe(value, labelsToAttributes(labels));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
set: (labels, value) => {
|
|
153
|
+
const ttlMap = this.gaugeValues.get(name);
|
|
154
|
+
const labelsKey = JSON.stringify(labels);
|
|
155
|
+
ttlMap.set(labelsKey, value);
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Creates or retrieves a histogram and returns a handle.
|
|
161
|
+
*/
|
|
162
|
+
histogram(name) {
|
|
163
|
+
if (!this.histograms.has(name)) {
|
|
164
|
+
this.histograms.set(name, this.meter.createHistogram(name));
|
|
165
|
+
}
|
|
166
|
+
const histogram = this.histograms.get(name);
|
|
167
|
+
return {
|
|
168
|
+
observe: (labels, value) => {
|
|
169
|
+
histogram.record(value, labelsToAttributes(labels));
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Increments a counter by name (creates if not exists).
|
|
175
|
+
*/
|
|
176
|
+
incCounter(name, labels, value = 1) {
|
|
177
|
+
this.counter(name).inc(labels, value);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Sets a gauge value by name (creates if not exists).
|
|
181
|
+
*/
|
|
182
|
+
setGauge(name, labels, value) {
|
|
183
|
+
this.gauge(name).set(labels, value);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Observes a histogram value by name (creates if not exists).
|
|
187
|
+
*/
|
|
188
|
+
observeHistogram(name, labels, value) {
|
|
189
|
+
this.histogram(name).observe(labels, value);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
exports.MetricsClient = MetricsClient;
|
|
193
|
+
//# sourceMappingURL=metrics-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-client.js","sourceRoot":"","sources":["../../src/node/metrics-client.ts"],"names":[],"mappings":"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"}
|