@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.
Files changed (227) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +155 -0
  3. package/dist/browser/index.d.ts +8 -0
  4. package/dist/browser/index.d.ts.map +1 -0
  5. package/dist/browser/index.js +19 -0
  6. package/dist/browser/index.js.map +1 -0
  7. package/dist/browser/init.d.ts +75 -0
  8. package/dist/browser/init.d.ts.map +1 -0
  9. package/dist/browser/init.js +169 -0
  10. package/dist/browser/init.js.map +1 -0
  11. package/dist/browser/resilient-exporter.d.ts +43 -0
  12. package/dist/browser/resilient-exporter.d.ts.map +1 -0
  13. package/dist/browser/resilient-exporter.js +88 -0
  14. package/dist/browser/resilient-exporter.js.map +1 -0
  15. package/dist/common/contracts/tier2-traces.d.ts +75 -0
  16. package/dist/common/contracts/tier2-traces.d.ts.map +1 -0
  17. package/dist/common/contracts/tier2-traces.js +186 -0
  18. package/dist/common/contracts/tier2-traces.js.map +1 -0
  19. package/dist/common/deployment-type.d.ts +18 -0
  20. package/dist/common/deployment-type.d.ts.map +1 -0
  21. package/dist/common/deployment-type.js +30 -0
  22. package/dist/common/deployment-type.js.map +1 -0
  23. package/dist/common/guardrails.d.ts +116 -0
  24. package/dist/common/guardrails.d.ts.map +1 -0
  25. package/dist/common/guardrails.js +189 -0
  26. package/dist/common/guardrails.js.map +1 -0
  27. package/dist/common/index.d.ts +16 -0
  28. package/dist/common/index.d.ts.map +1 -0
  29. package/dist/common/index.js +32 -0
  30. package/dist/common/index.js.map +1 -0
  31. package/dist/common/log-sanitizer.d.ts +78 -0
  32. package/dist/common/log-sanitizer.d.ts.map +1 -0
  33. package/dist/common/log-sanitizer.js +340 -0
  34. package/dist/common/log-sanitizer.js.map +1 -0
  35. package/dist/common/policy-evaluator.d.ts +103 -0
  36. package/dist/common/policy-evaluator.d.ts.map +1 -0
  37. package/dist/common/policy-evaluator.js +200 -0
  38. package/dist/common/policy-evaluator.js.map +1 -0
  39. package/dist/common/resource.d.ts +62 -0
  40. package/dist/common/resource.d.ts.map +1 -0
  41. package/dist/common/resource.js +106 -0
  42. package/dist/common/resource.js.map +1 -0
  43. package/dist/common/tier-hints.d.ts +182 -0
  44. package/dist/common/tier-hints.d.ts.map +1 -0
  45. package/dist/common/tier-hints.js +209 -0
  46. package/dist/common/tier-hints.js.map +1 -0
  47. package/dist/index.d.ts +43 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +76 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/lint/forbidden-attributes.d.ts +149 -0
  52. package/dist/lint/forbidden-attributes.d.ts.map +1 -0
  53. package/dist/lint/forbidden-attributes.js +214 -0
  54. package/dist/lint/forbidden-attributes.js.map +1 -0
  55. package/dist/lint/index.d.ts +9 -0
  56. package/dist/lint/index.d.ts.map +1 -0
  57. package/dist/lint/index.js +16 -0
  58. package/dist/lint/index.js.map +1 -0
  59. package/dist/llmobs/index.d.ts +22 -0
  60. package/dist/llmobs/index.d.ts.map +1 -0
  61. package/dist/llmobs/index.js +29 -0
  62. package/dist/llmobs/index.js.map +1 -0
  63. package/dist/llmobs/tier1-exporter.d.ts +146 -0
  64. package/dist/llmobs/tier1-exporter.d.ts.map +1 -0
  65. package/dist/llmobs/tier1-exporter.js +196 -0
  66. package/dist/llmobs/tier1-exporter.js.map +1 -0
  67. package/dist/llmobs/tier2-summarizer.d.ts +268 -0
  68. package/dist/llmobs/tier2-summarizer.d.ts.map +1 -0
  69. package/dist/llmobs/tier2-summarizer.js +650 -0
  70. package/dist/llmobs/tier2-summarizer.js.map +1 -0
  71. package/dist/node/exporters/resilient-exporter.d.ts +77 -0
  72. package/dist/node/exporters/resilient-exporter.d.ts.map +1 -0
  73. package/dist/node/exporters/resilient-exporter.js +129 -0
  74. package/dist/node/exporters/resilient-exporter.js.map +1 -0
  75. package/dist/node/index.d.ts +11 -0
  76. package/dist/node/index.d.ts.map +1 -0
  77. package/dist/node/index.js +24 -0
  78. package/dist/node/index.js.map +1 -0
  79. package/dist/node/init.d.ts +75 -0
  80. package/dist/node/init.d.ts.map +1 -0
  81. package/dist/node/init.js +245 -0
  82. package/dist/node/init.js.map +1 -0
  83. package/dist/node/log-processor.d.ts +83 -0
  84. package/dist/node/log-processor.d.ts.map +1 -0
  85. package/dist/node/log-processor.js +266 -0
  86. package/dist/node/log-processor.js.map +1 -0
  87. package/dist/node/metrics-client.d.ts +66 -0
  88. package/dist/node/metrics-client.d.ts.map +1 -0
  89. package/dist/node/metrics-client.js +193 -0
  90. package/dist/node/metrics-client.js.map +1 -0
  91. package/dist/node/traced-socket.d.ts +76 -0
  92. package/dist/node/traced-socket.d.ts.map +1 -0
  93. package/dist/node/traced-socket.js +261 -0
  94. package/dist/node/traced-socket.js.map +1 -0
  95. package/dist/testing/in-memory-exporter.d.ts +179 -0
  96. package/dist/testing/in-memory-exporter.d.ts.map +1 -0
  97. package/dist/testing/in-memory-exporter.js +254 -0
  98. package/dist/testing/in-memory-exporter.js.map +1 -0
  99. package/dist/testing/index.d.ts +8 -0
  100. package/dist/testing/index.d.ts.map +1 -0
  101. package/dist/testing/index.js +19 -0
  102. package/dist/testing/index.js.map +1 -0
  103. package/dist/testing/test-init.d.ts +80 -0
  104. package/dist/testing/test-init.d.ts.map +1 -0
  105. package/dist/testing/test-init.js +144 -0
  106. package/dist/testing/test-init.js.map +1 -0
  107. package/dist/types/index.d.ts +40 -0
  108. package/dist/types/index.d.ts.map +1 -0
  109. package/dist/types/index.js +23 -0
  110. package/dist/types/index.js.map +1 -0
  111. package/dist/types/policy.d.ts +92 -0
  112. package/dist/types/policy.d.ts.map +1 -0
  113. package/dist/types/policy.js +125 -0
  114. package/dist/types/policy.js.map +1 -0
  115. package/dist-esm/browser/index.d.ts +8 -0
  116. package/dist-esm/browser/index.d.ts.map +1 -0
  117. package/dist-esm/browser/index.js +9 -0
  118. package/dist-esm/browser/index.js.map +1 -0
  119. package/dist-esm/browser/init.d.ts +75 -0
  120. package/dist-esm/browser/init.d.ts.map +1 -0
  121. package/dist-esm/browser/init.js +162 -0
  122. package/dist-esm/browser/init.js.map +1 -0
  123. package/dist-esm/browser/resilient-exporter.d.ts +43 -0
  124. package/dist-esm/browser/resilient-exporter.d.ts.map +1 -0
  125. package/dist-esm/browser/resilient-exporter.js +84 -0
  126. package/dist-esm/browser/resilient-exporter.js.map +1 -0
  127. package/dist-esm/common/contracts/tier2-traces.d.ts +75 -0
  128. package/dist-esm/common/contracts/tier2-traces.d.ts.map +1 -0
  129. package/dist-esm/common/contracts/tier2-traces.js +178 -0
  130. package/dist-esm/common/contracts/tier2-traces.js.map +1 -0
  131. package/dist-esm/common/deployment-type.d.ts +18 -0
  132. package/dist-esm/common/deployment-type.d.ts.map +1 -0
  133. package/dist-esm/common/deployment-type.js +27 -0
  134. package/dist-esm/common/deployment-type.js.map +1 -0
  135. package/dist-esm/common/guardrails.d.ts +116 -0
  136. package/dist-esm/common/guardrails.d.ts.map +1 -0
  137. package/dist-esm/common/guardrails.js +179 -0
  138. package/dist-esm/common/guardrails.js.map +1 -0
  139. package/dist-esm/common/index.d.ts +16 -0
  140. package/dist-esm/common/index.d.ts.map +1 -0
  141. package/dist-esm/common/index.js +16 -0
  142. package/dist-esm/common/index.js.map +1 -0
  143. package/dist-esm/common/log-sanitizer.d.ts +78 -0
  144. package/dist-esm/common/log-sanitizer.d.ts.map +1 -0
  145. package/dist-esm/common/log-sanitizer.js +331 -0
  146. package/dist-esm/common/log-sanitizer.js.map +1 -0
  147. package/dist-esm/common/policy-evaluator.d.ts +103 -0
  148. package/dist-esm/common/policy-evaluator.d.ts.map +1 -0
  149. package/dist-esm/common/policy-evaluator.js +196 -0
  150. package/dist-esm/common/policy-evaluator.js.map +1 -0
  151. package/dist-esm/common/resource.d.ts +62 -0
  152. package/dist-esm/common/resource.d.ts.map +1 -0
  153. package/dist-esm/common/resource.js +100 -0
  154. package/dist-esm/common/resource.js.map +1 -0
  155. package/dist-esm/common/tier-hints.d.ts +182 -0
  156. package/dist-esm/common/tier-hints.d.ts.map +1 -0
  157. package/dist-esm/common/tier-hints.js +199 -0
  158. package/dist-esm/common/tier-hints.js.map +1 -0
  159. package/dist-esm/index.d.ts +43 -0
  160. package/dist-esm/index.d.ts.map +1 -0
  161. package/dist-esm/index.js +53 -0
  162. package/dist-esm/index.js.map +1 -0
  163. package/dist-esm/lint/forbidden-attributes.d.ts +149 -0
  164. package/dist-esm/lint/forbidden-attributes.d.ts.map +1 -0
  165. package/dist-esm/lint/forbidden-attributes.js +209 -0
  166. package/dist-esm/lint/forbidden-attributes.js.map +1 -0
  167. package/dist-esm/lint/index.d.ts +9 -0
  168. package/dist-esm/lint/index.d.ts.map +1 -0
  169. package/dist-esm/lint/index.js +9 -0
  170. package/dist-esm/lint/index.js.map +1 -0
  171. package/dist-esm/llmobs/index.d.ts +22 -0
  172. package/dist-esm/llmobs/index.d.ts.map +1 -0
  173. package/dist-esm/llmobs/index.js +22 -0
  174. package/dist-esm/llmobs/index.js.map +1 -0
  175. package/dist-esm/llmobs/tier1-exporter.d.ts +146 -0
  176. package/dist-esm/llmobs/tier1-exporter.d.ts.map +1 -0
  177. package/dist-esm/llmobs/tier1-exporter.js +190 -0
  178. package/dist-esm/llmobs/tier1-exporter.js.map +1 -0
  179. package/dist-esm/llmobs/tier2-summarizer.d.ts +268 -0
  180. package/dist-esm/llmobs/tier2-summarizer.d.ts.map +1 -0
  181. package/dist-esm/llmobs/tier2-summarizer.js +646 -0
  182. package/dist-esm/llmobs/tier2-summarizer.js.map +1 -0
  183. package/dist-esm/node/exporters/resilient-exporter.d.ts +77 -0
  184. package/dist-esm/node/exporters/resilient-exporter.d.ts.map +1 -0
  185. package/dist-esm/node/exporters/resilient-exporter.js +125 -0
  186. package/dist-esm/node/exporters/resilient-exporter.js.map +1 -0
  187. package/dist-esm/node/index.d.ts +11 -0
  188. package/dist-esm/node/index.d.ts.map +1 -0
  189. package/dist-esm/node/index.js +11 -0
  190. package/dist-esm/node/index.js.map +1 -0
  191. package/dist-esm/node/init.d.ts +75 -0
  192. package/dist-esm/node/init.d.ts.map +1 -0
  193. package/dist-esm/node/init.js +239 -0
  194. package/dist-esm/node/init.js.map +1 -0
  195. package/dist-esm/node/log-processor.d.ts +83 -0
  196. package/dist-esm/node/log-processor.d.ts.map +1 -0
  197. package/dist-esm/node/log-processor.js +261 -0
  198. package/dist-esm/node/log-processor.js.map +1 -0
  199. package/dist-esm/node/metrics-client.d.ts +66 -0
  200. package/dist-esm/node/metrics-client.d.ts.map +1 -0
  201. package/dist-esm/node/metrics-client.js +189 -0
  202. package/dist-esm/node/metrics-client.js.map +1 -0
  203. package/dist-esm/node/traced-socket.d.ts +76 -0
  204. package/dist-esm/node/traced-socket.d.ts.map +1 -0
  205. package/dist-esm/node/traced-socket.js +257 -0
  206. package/dist-esm/node/traced-socket.js.map +1 -0
  207. package/dist-esm/testing/in-memory-exporter.d.ts +179 -0
  208. package/dist-esm/testing/in-memory-exporter.d.ts.map +1 -0
  209. package/dist-esm/testing/in-memory-exporter.js +248 -0
  210. package/dist-esm/testing/in-memory-exporter.js.map +1 -0
  211. package/dist-esm/testing/index.d.ts +8 -0
  212. package/dist-esm/testing/index.d.ts.map +1 -0
  213. package/dist-esm/testing/index.js +8 -0
  214. package/dist-esm/testing/index.js.map +1 -0
  215. package/dist-esm/testing/test-init.d.ts +80 -0
  216. package/dist-esm/testing/test-init.d.ts.map +1 -0
  217. package/dist-esm/testing/test-init.js +137 -0
  218. package/dist-esm/testing/test-init.js.map +1 -0
  219. package/dist-esm/types/index.d.ts +40 -0
  220. package/dist-esm/types/index.d.ts.map +1 -0
  221. package/dist-esm/types/index.js +7 -0
  222. package/dist-esm/types/index.js.map +1 -0
  223. package/dist-esm/types/policy.d.ts +92 -0
  224. package/dist-esm/types/policy.d.ts.map +1 -0
  225. package/dist-esm/types/policy.js +122 -0
  226. package/dist-esm/types/policy.js.map +1 -0
  227. 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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"}