@provide-io/telemetry 0.2.2

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 (122) hide show
  1. package/README.md +247 -0
  2. package/dist/backpressure.d.ts +19 -0
  3. package/dist/backpressure.d.ts.map +1 -0
  4. package/dist/backpressure.js +51 -0
  5. package/dist/cardinality.d.ts +15 -0
  6. package/dist/cardinality.d.ts.map +1 -0
  7. package/dist/cardinality.js +69 -0
  8. package/dist/classification.d.ts +29 -0
  9. package/dist/classification.d.ts.map +1 -0
  10. package/dist/classification.js +58 -0
  11. package/dist/config.d.ts +156 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +350 -0
  14. package/dist/consent.d.ts +11 -0
  15. package/dist/consent.d.ts.map +1 -0
  16. package/dist/consent.js +50 -0
  17. package/dist/context.d.ts +60 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +127 -0
  20. package/dist/exceptions.d.ts +14 -0
  21. package/dist/exceptions.d.ts.map +1 -0
  22. package/dist/exceptions.js +21 -0
  23. package/dist/fingerprint.d.ts +5 -0
  24. package/dist/fingerprint.d.ts.map +1 -0
  25. package/dist/fingerprint.js +50 -0
  26. package/dist/hash.d.ts +8 -0
  27. package/dist/hash.d.ts.map +1 -0
  28. package/dist/hash.js +102 -0
  29. package/dist/health.d.ts +54 -0
  30. package/dist/health.d.ts.map +1 -0
  31. package/dist/health.js +102 -0
  32. package/dist/index.d.ts +52 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +59 -0
  35. package/dist/logger.d.ts +28 -0
  36. package/dist/logger.d.ts.map +1 -0
  37. package/dist/logger.js +254 -0
  38. package/dist/metrics.d.ts +78 -0
  39. package/dist/metrics.d.ts.map +1 -0
  40. package/dist/metrics.js +238 -0
  41. package/dist/otel-logs.d.ts +29 -0
  42. package/dist/otel-logs.d.ts.map +1 -0
  43. package/dist/otel-logs.js +127 -0
  44. package/dist/otel-noop.d.ts +13 -0
  45. package/dist/otel-noop.d.ts.map +1 -0
  46. package/dist/otel-noop.js +5 -0
  47. package/dist/otel.d.ts +20 -0
  48. package/dist/otel.d.ts.map +1 -0
  49. package/dist/otel.js +80 -0
  50. package/dist/pii.d.ts +43 -0
  51. package/dist/pii.d.ts.map +1 -0
  52. package/dist/pii.js +278 -0
  53. package/dist/pretty.d.ts +12 -0
  54. package/dist/pretty.d.ts.map +1 -0
  55. package/dist/pretty.js +85 -0
  56. package/dist/propagation.d.ts +52 -0
  57. package/dist/propagation.d.ts.map +1 -0
  58. package/dist/propagation.js +183 -0
  59. package/dist/react.d.ts +38 -0
  60. package/dist/react.d.ts.map +1 -0
  61. package/dist/react.js +72 -0
  62. package/dist/receipts.d.ts +26 -0
  63. package/dist/receipts.d.ts.map +1 -0
  64. package/dist/receipts.js +69 -0
  65. package/dist/resilience.d.ts +26 -0
  66. package/dist/resilience.d.ts.map +1 -0
  67. package/dist/resilience.js +183 -0
  68. package/dist/runtime.d.ts +33 -0
  69. package/dist/runtime.d.ts.map +1 -0
  70. package/dist/runtime.js +133 -0
  71. package/dist/sampling.d.ts +9 -0
  72. package/dist/sampling.d.ts.map +1 -0
  73. package/dist/sampling.js +53 -0
  74. package/dist/sanitize.d.ts +6 -0
  75. package/dist/sanitize.d.ts.map +1 -0
  76. package/dist/sanitize.js +7 -0
  77. package/dist/schema.d.ts +41 -0
  78. package/dist/schema.d.ts.map +1 -0
  79. package/dist/schema.js +109 -0
  80. package/dist/shutdown.d.ts +2 -0
  81. package/dist/shutdown.d.ts.map +1 -0
  82. package/dist/shutdown.js +15 -0
  83. package/dist/slo.d.ts +25 -0
  84. package/dist/slo.d.ts.map +1 -0
  85. package/dist/slo.js +115 -0
  86. package/dist/testing.d.ts +10 -0
  87. package/dist/testing.d.ts.map +1 -0
  88. package/dist/testing.js +51 -0
  89. package/dist/tracing.d.ts +51 -0
  90. package/dist/tracing.d.ts.map +1 -0
  91. package/dist/tracing.js +181 -0
  92. package/package.json +139 -0
  93. package/src/backpressure.ts +68 -0
  94. package/src/cardinality.ts +83 -0
  95. package/src/classification.ts +87 -0
  96. package/src/config.ts +589 -0
  97. package/src/consent.ts +61 -0
  98. package/src/context.ts +157 -0
  99. package/src/exceptions.ts +24 -0
  100. package/src/fingerprint.ts +53 -0
  101. package/src/hash.ts +118 -0
  102. package/src/health.ts +175 -0
  103. package/src/index.ts +183 -0
  104. package/src/logger.ts +287 -0
  105. package/src/metrics.ts +204 -0
  106. package/src/otel-logs.ts +161 -0
  107. package/src/otel-noop.ts +19 -0
  108. package/src/otel.ts +112 -0
  109. package/src/pii.ts +358 -0
  110. package/src/pretty.ts +93 -0
  111. package/src/propagation.ts +222 -0
  112. package/src/react.ts +98 -0
  113. package/src/receipts.ts +97 -0
  114. package/src/resilience.ts +220 -0
  115. package/src/runtime.ts +171 -0
  116. package/src/sampling.ts +68 -0
  117. package/src/sanitize.ts +8 -0
  118. package/src/schema.ts +135 -0
  119. package/src/shutdown.ts +18 -0
  120. package/src/slo.ts +156 -0
  121. package/src/testing.ts +56 -0
  122. package/src/tracing.ts +211 -0
@@ -0,0 +1,50 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 provide.io llc. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Stable error fingerprinting — generates a 12-char hex hash from
5
+ * exception type + top 3 stack frames (file:function, no line numbers).
6
+ *
7
+ * Cross-language compatible: same error in Python and TypeScript produces
8
+ * the same fingerprint when the call path is equivalent.
9
+ */
10
+ import { shortHash12 } from './hash';
11
+ /**
12
+ * Parse an Error stack trace into normalized frames: `basename:function`.
13
+ * Returns at most 3 frames (most recent).
14
+ */
15
+ function extractFrames(stack) {
16
+ // Stryker disable next-line ConditionalExpression -- equivalent: falsy stack always yields no frames
17
+ if (!stack)
18
+ return [];
19
+ const frames = [];
20
+ // V8: "at functionName (filename:line:col)" or "at filename:line:col"
21
+ // Stryker disable next-line Regex -- \s+ vs \s and trailing \d+ vs \d are equivalent for real stacks
22
+ const v8Re = /at\s+(?:(.+?)\s+\()?(.*?):\d+:\d+\)?/g;
23
+ // SpiderMonkey/JSC: "functionName@filename:line:col"
24
+ // Stryker disable next-line Regex -- trailing \d+ vs \d is equivalent for file extraction
25
+ const smRe = /(.+?)@(.*?):\d+:\d+/g;
26
+ for (const re of [v8Re, smRe]) {
27
+ let match;
28
+ while ((match = re.exec(stack)) !== null) {
29
+ const func = String(match[1] || '').toLowerCase();
30
+ const file = String(match[2] || '');
31
+ const parts = file.split('/');
32
+ const last = parts[parts.length - 1] || '';
33
+ const winParts = last.split('\\');
34
+ const leaf = winParts[winParts.length - 1] || '';
35
+ const basename = leaf.replace(/\.[^.]+$/, '').toLowerCase();
36
+ if (basename) {
37
+ frames.push(`${basename}:${func}`);
38
+ }
39
+ }
40
+ }
41
+ return frames.slice(-3);
42
+ }
43
+ /**
44
+ * Compute a stable 12-char hex fingerprint for an error.
45
+ */
46
+ export function computeErrorFingerprint(errorName, stack) {
47
+ const parts = [errorName.toLowerCase()];
48
+ parts.push(...extractFrames(stack));
49
+ return shortHash12(parts.join(':'));
50
+ }
package/dist/hash.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export declare function sha256Hex(input: string): string;
2
+ export declare function shortHash12(input: string): string;
3
+ /**
4
+ * Generate `numBytes` random bytes and return them as a lowercase hex string.
5
+ * Uses the Web Crypto API (available in Node.js 15+, browsers, and edge runtimes).
6
+ */
7
+ export declare function randomHex(numBytes: number): string;
8
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AA8BA,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAyE/C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIlD"}
package/dist/hash.js ADDED
@@ -0,0 +1,102 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 provide.io llc. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ const INITIAL_HASH = [
4
+ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
5
+ ];
6
+ const ROUND_CONSTANTS = [
7
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
8
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
9
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
10
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
11
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
12
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
13
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
14
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
15
+ ];
16
+ function add32(...values) {
17
+ let sum = 0;
18
+ for (const value of values) {
19
+ sum = (sum + (value >>> 0)) >>> 0;
20
+ }
21
+ return sum;
22
+ }
23
+ function rotateRight(value, bits) {
24
+ return (value >>> bits) | (value << (32 - bits));
25
+ }
26
+ export function sha256Hex(input) {
27
+ const bytes = new TextEncoder().encode(input);
28
+ const bitLength = bytes.length * 8;
29
+ const paddedLength = Math.ceil((bytes.length + 9) / 64) * 64;
30
+ const padded = new Uint8Array(paddedLength);
31
+ padded.set(bytes);
32
+ padded[bytes.length] = 0x80;
33
+ const view = new DataView(padded.buffer);
34
+ // Stryker disable next-line ArithmeticOperator: highBits is always 0 for inputs under 512 MB — division vs multiplication both produce 0 after ToUint32 coercion
35
+ const highBits = Math.floor(bitLength / 0x100000000);
36
+ const lowBits = bitLength >>> 0;
37
+ // Stryker disable next-line BooleanLiteral: highBits is 0 for all testable inputs — big-endian vs little-endian of 0 is identical
38
+ view.setUint32(paddedLength - 8, highBits, false);
39
+ view.setUint32(paddedLength - 4, lowBits, false);
40
+ const words = new Uint32Array(64);
41
+ let [h0, h1, h2, h3, h4, h5, h6, h7] = INITIAL_HASH;
42
+ for (let offset = 0; offset < paddedLength; offset += 64) {
43
+ for (let i = 0; i < 16; i++) {
44
+ words[i] = view.getUint32(offset + i * 4, false);
45
+ }
46
+ // Stryker disable next-line EqualityOperator: Uint32Array(64) silently ignores writes to index 64 — the extra iteration is a no-op
47
+ for (let i = 16; i < 64; i++) {
48
+ const w15 = words[i - 15];
49
+ const w2 = words[i - 2];
50
+ const sigma0 = rotateRight(w15, 7) ^ rotateRight(w15, 18) ^ (w15 >>> 3);
51
+ const sigma1 = rotateRight(w2, 17) ^ rotateRight(w2, 19) ^ (w2 >>> 10);
52
+ words[i] = add32(words[i - 16], sigma0, words[i - 7], sigma1);
53
+ }
54
+ let a = h0;
55
+ let b = h1;
56
+ let c = h2;
57
+ let d = h3;
58
+ let e = h4;
59
+ let f = h5;
60
+ let g = h6;
61
+ let h = h7;
62
+ for (let i = 0; i < 64; i++) {
63
+ const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
64
+ const choose = (e & f) ^ (~e & g);
65
+ const temp1 = add32(h, sum1, choose, ROUND_CONSTANTS[i], words[i]);
66
+ const sum0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
67
+ const majority = (a & b) ^ (a & c) ^ (b & c);
68
+ const temp2 = add32(sum0, majority);
69
+ h = g;
70
+ g = f;
71
+ f = e;
72
+ e = add32(d, temp1);
73
+ d = c;
74
+ c = b;
75
+ b = a;
76
+ a = add32(temp1, temp2);
77
+ }
78
+ h0 = add32(h0, a);
79
+ h1 = add32(h1, b);
80
+ h2 = add32(h2, c);
81
+ h3 = add32(h3, d);
82
+ h4 = add32(h4, e);
83
+ h5 = add32(h5, f);
84
+ h6 = add32(h6, g);
85
+ h7 = add32(h7, h);
86
+ }
87
+ return [h0, h1, h2, h3, h4, h5, h6, h7]
88
+ .map((word) => word.toString(16).padStart(8, '0'))
89
+ .join('');
90
+ }
91
+ export function shortHash12(input) {
92
+ return sha256Hex(input).slice(0, 12);
93
+ }
94
+ /**
95
+ * Generate `numBytes` random bytes and return them as a lowercase hex string.
96
+ * Uses the Web Crypto API (available in Node.js 15+, browsers, and edge runtimes).
97
+ */
98
+ export function randomHex(numBytes) {
99
+ const bytes = new Uint8Array(numBytes);
100
+ crypto.getRandomValues(bytes);
101
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
102
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Internal self-observability counters — mirrors Python provide.telemetry.health.
3
+ * Canonical 25-field layout: 8 per signal (logs, traces, metrics) + 1 global.
4
+ */
5
+ export interface HealthSnapshot {
6
+ logsEmitted: number;
7
+ logsDropped: number;
8
+ exportFailuresLogs: number;
9
+ retriesLogs: number;
10
+ exportLatencyMsLogs: number;
11
+ asyncBlockingRiskLogs: number;
12
+ circuitStateLogs: string;
13
+ circuitOpenCountLogs: number;
14
+ tracesEmitted: number;
15
+ tracesDropped: number;
16
+ exportFailuresTraces: number;
17
+ retriesTraces: number;
18
+ exportLatencyMsTraces: number;
19
+ asyncBlockingRiskTraces: number;
20
+ circuitStateTraces: string;
21
+ circuitOpenCountTraces: number;
22
+ metricsEmitted: number;
23
+ metricsDropped: number;
24
+ exportFailuresMetrics: number;
25
+ retriesMetrics: number;
26
+ exportLatencyMsMetrics: number;
27
+ asyncBlockingRiskMetrics: number;
28
+ circuitStateMetrics: string;
29
+ circuitOpenCountMetrics: number;
30
+ setupError: string | null;
31
+ }
32
+ /** Numeric fields that live in the mutable _state object (not derived circuit fields). */
33
+ type NumericHealthField = 'logsEmitted' | 'logsDropped' | 'tracesEmitted' | 'tracesDropped' | 'metricsEmitted' | 'metricsDropped' | 'exportFailuresLogs' | 'exportFailuresTraces' | 'exportFailuresMetrics' | 'retriesLogs' | 'retriesTraces' | 'retriesMetrics' | 'exportLatencyMsLogs' | 'exportLatencyMsTraces' | 'exportLatencyMsMetrics' | 'asyncBlockingRiskLogs' | 'asyncBlockingRiskTraces' | 'asyncBlockingRiskMetrics';
34
+ type CircuitStateResult = {
35
+ state: string;
36
+ openCount: number;
37
+ cooldownRemainingMs: number;
38
+ };
39
+ type CircuitStateFn = (signal: string) => CircuitStateResult;
40
+ /** Called by resilience module to register the getCircuitState function. */
41
+ export declare function _registerCircuitStateFn(fn: CircuitStateFn): void;
42
+ export declare function getHealthSnapshot(): HealthSnapshot;
43
+ export declare function setSetupError(error: string | null): void;
44
+ export declare function _incrementHealth(field: NumericHealthField, by?: number): void;
45
+ /** Map a signal name to the per-signal export-failures field. */
46
+ export declare function _exportFailuresField(signal: string): 'exportFailuresLogs' | 'exportFailuresTraces' | 'exportFailuresMetrics';
47
+ /** Map a signal name to the per-signal retries field. */
48
+ export declare function _retriesField(signal: string): 'retriesLogs' | 'retriesTraces' | 'retriesMetrics';
49
+ /** Map a signal name to the per-signal export latency field. */
50
+ export declare function _exportLatencyField(signal: string): 'exportLatencyMsLogs' | 'exportLatencyMsTraces' | 'exportLatencyMsMetrics';
51
+ export declare function _recordExportLatency(signal: string, ms: number): void;
52
+ export declare function _resetHealthForTests(): void;
53
+ export {};
54
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAE7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAE7B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAE/B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,EAAE,MAAM,CAAC;IACjC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAEhC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,0FAA0F;AAC1F,KAAK,kBAAkB,GACnB,aAAa,GACb,aAAa,GACb,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,sBAAsB,GACtB,uBAAuB,GACvB,aAAa,GACb,eAAe,GACf,gBAAgB,GAChB,qBAAqB,GACrB,uBAAuB,GACvB,wBAAwB,GACxB,uBAAuB,GACvB,yBAAyB,GACzB,0BAA0B,CAAC;AA2B/B,KAAK,kBAAkB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5F,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,CAAC;AAS7D,4EAA4E;AAC5E,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI,CAEhE;AAED,wBAAgB,iBAAiB,IAAI,cAAc,CAclD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,kBAAkB,EAAE,EAAE,GAAE,MAAU,GAAG,IAAI,CAEhF;AAED,iEAAiE;AACjE,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,GACb,oBAAoB,GAAG,sBAAsB,GAAG,uBAAuB,CAIzE;AAED,yDAAyD;AACzD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,eAAe,GAAG,gBAAgB,CAIhG;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GACb,qBAAqB,GAAG,uBAAuB,GAAG,wBAAwB,CAI5E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAErE;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAoB3C"}
package/dist/health.js ADDED
@@ -0,0 +1,102 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 provide.io llc. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ let _setupError = null;
4
+ const _state = {
5
+ logsEmitted: 0,
6
+ logsDropped: 0,
7
+ tracesEmitted: 0,
8
+ tracesDropped: 0,
9
+ metricsEmitted: 0,
10
+ metricsDropped: 0,
11
+ exportFailuresLogs: 0,
12
+ exportFailuresTraces: 0,
13
+ exportFailuresMetrics: 0,
14
+ retriesLogs: 0,
15
+ retriesTraces: 0,
16
+ retriesMetrics: 0,
17
+ exportLatencyMsLogs: 0,
18
+ exportLatencyMsTraces: 0,
19
+ exportLatencyMsMetrics: 0,
20
+ asyncBlockingRiskLogs: 0,
21
+ asyncBlockingRiskTraces: 0,
22
+ asyncBlockingRiskMetrics: 0,
23
+ };
24
+ const _defaultCircuitState = {
25
+ state: 'closed',
26
+ openCount: 0,
27
+ cooldownRemainingMs: 0,
28
+ };
29
+ let _circuitStateFn = () => _defaultCircuitState;
30
+ /** Called by resilience module to register the getCircuitState function. */
31
+ export function _registerCircuitStateFn(fn) {
32
+ _circuitStateFn = fn;
33
+ }
34
+ export function getHealthSnapshot() {
35
+ const csLogs = _circuitStateFn('logs');
36
+ const csTraces = _circuitStateFn('traces');
37
+ const csMetrics = _circuitStateFn('metrics');
38
+ return {
39
+ ..._state,
40
+ circuitStateLogs: csLogs.state,
41
+ circuitStateTraces: csTraces.state,
42
+ circuitStateMetrics: csMetrics.state,
43
+ circuitOpenCountLogs: csLogs.openCount,
44
+ circuitOpenCountTraces: csTraces.openCount,
45
+ circuitOpenCountMetrics: csMetrics.openCount,
46
+ setupError: _setupError,
47
+ };
48
+ }
49
+ export function setSetupError(error) {
50
+ _setupError = error;
51
+ }
52
+ export function _incrementHealth(field, by = 1) {
53
+ _state[field] += by;
54
+ }
55
+ /** Map a signal name to the per-signal export-failures field. */
56
+ export function _exportFailuresField(signal) {
57
+ if (signal === 'traces')
58
+ return 'exportFailuresTraces';
59
+ if (signal === 'metrics')
60
+ return 'exportFailuresMetrics';
61
+ return 'exportFailuresLogs';
62
+ }
63
+ /** Map a signal name to the per-signal retries field. */
64
+ export function _retriesField(signal) {
65
+ if (signal === 'traces')
66
+ return 'retriesTraces';
67
+ if (signal === 'metrics')
68
+ return 'retriesMetrics';
69
+ return 'retriesLogs';
70
+ }
71
+ /** Map a signal name to the per-signal export latency field. */
72
+ export function _exportLatencyField(signal) {
73
+ if (signal === 'traces')
74
+ return 'exportLatencyMsTraces';
75
+ if (signal === 'metrics')
76
+ return 'exportLatencyMsMetrics';
77
+ return 'exportLatencyMsLogs';
78
+ }
79
+ export function _recordExportLatency(signal, ms) {
80
+ _state[_exportLatencyField(signal)] = ms;
81
+ }
82
+ export function _resetHealthForTests() {
83
+ _state.logsEmitted = 0;
84
+ _state.logsDropped = 0;
85
+ _state.tracesEmitted = 0;
86
+ _state.tracesDropped = 0;
87
+ _state.metricsEmitted = 0;
88
+ _state.metricsDropped = 0;
89
+ _state.exportFailuresLogs = 0;
90
+ _state.exportFailuresTraces = 0;
91
+ _state.exportFailuresMetrics = 0;
92
+ _state.retriesLogs = 0;
93
+ _state.retriesTraces = 0;
94
+ _state.retriesMetrics = 0;
95
+ _state.exportLatencyMsLogs = 0;
96
+ _state.exportLatencyMsTraces = 0;
97
+ _state.exportLatencyMsMetrics = 0;
98
+ _state.asyncBlockingRiskLogs = 0;
99
+ _state.asyncBlockingRiskTraces = 0;
100
+ _state.asyncBlockingRiskMetrics = 0;
101
+ _setupError = null;
102
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @provide-io/telemetry — TypeScript structured logging + OTEL
3
+ *
4
+ * Feature parity with the Python provide.telemetry package.
5
+ *
6
+ * Quick start:
7
+ * import { setupTelemetry, getLogger, bindContext } from '@provide-io/telemetry';
8
+ *
9
+ * setupTelemetry({ serviceName: 'my-app', logLevel: 'debug' });
10
+ * const log = getLogger('api');
11
+ * log.info({ event: 'request_ok', method: 'GET', path: '/api/v1/users', status: 200 });
12
+ */
13
+ export { setupTelemetry, applyConfigPolicies, getConfig, configFromEnv, parseOtlpHeaders, redactConfig, version, __version__, } from './config';
14
+ export type { TelemetryConfig, RuntimeOverrides } from './config';
15
+ export { getLogger, logger } from './logger';
16
+ export type { Logger } from './logger';
17
+ export { bindContext, unbindContext, clearContext, getContext, runWithContext, bindSessionContext, getSessionId, clearSessionContext, } from './context';
18
+ export { computeErrorFingerprint } from './fingerprint';
19
+ export { formatPretty, supportsColor } from './pretty';
20
+ export { counter, gauge, histogram, getMeter, CounterInstrument, GaugeInstrument, HistogramInstrument, } from './metrics';
21
+ export type { Counter, Histogram, Meter, MetricOptions, UpDownCounter } from './metrics';
22
+ export { withTrace, traceDecorator as trace, getActiveTraceIds, getTracer, tracer, setTraceContext, getTraceContext, } from './tracing';
23
+ export { registerOtelProviders } from './otel';
24
+ export { sanitize, DEFAULT_SANITIZE_FIELDS, sanitizePayload, registerPiiRule, getPiiRules, replacePiiRules, resetPiiRulesForTests, } from './pii';
25
+ export type { MaskMode, PIIRule, SanitizePayloadOptions } from './pii';
26
+ export { TelemetryError, ConfigurationError } from './exceptions';
27
+ export { getHealthSnapshot, setSetupError } from './health';
28
+ export type { HealthSnapshot } from './health';
29
+ export { setQueuePolicy, getQueuePolicy, tryAcquire, release } from './backpressure';
30
+ export type { QueuePolicy, QueueTicket } from './backpressure';
31
+ export { OVERFLOW_VALUE, registerCardinalityLimit, getCardinalityLimits, clearCardinalityLimits, guardAttributes, } from './cardinality';
32
+ export type { CardinalityLimit } from './cardinality';
33
+ export { setSamplingPolicy, getSamplingPolicy, shouldSample } from './sampling';
34
+ export type { SamplingPolicy } from './sampling';
35
+ export { setExporterPolicy, getExporterPolicy, runWithResilience, getCircuitState, TelemetryTimeoutError, } from './resilience';
36
+ export type { ExporterPolicy, CircuitState } from './resilience';
37
+ export { EventSchemaError, event, eventName, validateEventName, validateRequiredKeys, } from './schema';
38
+ export type { EventRecord } from './schema';
39
+ export { recordRedMetrics, recordUseMetrics, classifyError } from './slo';
40
+ export type { ErrorClassification } from './slo';
41
+ export { extractW3cContext, bindPropagationContext, clearPropagationContext, getActivePropagationContext, } from './propagation';
42
+ export type { PropagationContext } from './propagation';
43
+ export { getRuntimeConfig, updateRuntimeConfig, reloadRuntimeFromEnv, reconfigureTelemetry, } from './runtime';
44
+ export { resetTelemetryState, resetTraceContext, telemetryTestPlugin } from './testing';
45
+ export type { ConsentLevel } from './consent';
46
+ export { setConsentLevel, getConsentLevel, shouldAllow, loadConsentFromEnv, resetConsentForTests, } from './consent';
47
+ export type { DataClass, ClassificationRule, ClassificationPolicy } from './classification';
48
+ export { registerClassificationRules, setClassificationPolicy, getClassificationPolicy, resetClassificationForTests, } from './classification';
49
+ export type { RedactionReceipt } from './receipts';
50
+ export { enableReceipts, getEmittedReceiptsForTests, resetReceiptsForTests } from './receipts';
51
+ export { shutdownTelemetry } from './shutdown';
52
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) 2025-2026 provide.io llc. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * @provide-io/telemetry — TypeScript structured logging + OTEL
5
+ *
6
+ * Feature parity with the Python provide.telemetry package.
7
+ *
8
+ * Quick start:
9
+ * import { setupTelemetry, getLogger, bindContext } from '@provide-io/telemetry';
10
+ *
11
+ * setupTelemetry({ serviceName: 'my-app', logLevel: 'debug' });
12
+ * const log = getLogger('api');
13
+ * log.info({ event: 'request_ok', method: 'GET', path: '/api/v1/users', status: 200 });
14
+ */
15
+ // Config + setup
16
+ export { setupTelemetry, applyConfigPolicies, getConfig, configFromEnv, parseOtlpHeaders, redactConfig, version, __version__, } from './config';
17
+ // Logger
18
+ export { getLogger, logger } from './logger';
19
+ // Context binding (mirrors Python bind_context / unbind_context / clear_context)
20
+ export { bindContext, unbindContext, clearContext, getContext, runWithContext, bindSessionContext, getSessionId, clearSessionContext, } from './context';
21
+ // Error fingerprinting (mirrors Python add_error_fingerprint processor)
22
+ export { computeErrorFingerprint } from './fingerprint';
23
+ // Pretty ANSI renderer (mirrors Python PrettyRenderer)
24
+ export { formatPretty, supportsColor } from './pretty';
25
+ // Metrics (mirrors Python counter / gauge / histogram)
26
+ export { counter, gauge, histogram, getMeter, CounterInstrument, GaugeInstrument, HistogramInstrument, } from './metrics';
27
+ // Tracing (mirrors Python @trace decorator)
28
+ export { withTrace, traceDecorator as trace, getActiveTraceIds, getTracer, tracer, setTraceContext, getTraceContext, } from './tracing';
29
+ // Optional OTEL SDK wiring (call after setupTelemetry to activate exporters)
30
+ export { registerOtelProviders } from './otel';
31
+ // PII sanitization utilities
32
+ export { sanitize, DEFAULT_SANITIZE_FIELDS, sanitizePayload, registerPiiRule, getPiiRules, replacePiiRules, resetPiiRulesForTests, } from './pii';
33
+ // Exceptions
34
+ export { TelemetryError, ConfigurationError } from './exceptions';
35
+ // Health
36
+ export { getHealthSnapshot, setSetupError } from './health';
37
+ // Backpressure
38
+ export { setQueuePolicy, getQueuePolicy, tryAcquire, release } from './backpressure';
39
+ // Cardinality
40
+ export { OVERFLOW_VALUE, registerCardinalityLimit, getCardinalityLimits, clearCardinalityLimits, guardAttributes, } from './cardinality';
41
+ // Sampling
42
+ export { setSamplingPolicy, getSamplingPolicy, shouldSample } from './sampling';
43
+ // Resilience
44
+ export { setExporterPolicy, getExporterPolicy, runWithResilience, getCircuitState, TelemetryTimeoutError, } from './resilience';
45
+ // Schema
46
+ export { EventSchemaError, event, eventName, validateEventName, validateRequiredKeys, } from './schema';
47
+ // SLO
48
+ export { recordRedMetrics, recordUseMetrics, classifyError } from './slo';
49
+ // Propagation
50
+ export { extractW3cContext, bindPropagationContext, clearPropagationContext, getActivePropagationContext, } from './propagation';
51
+ // Runtime reconfiguration
52
+ export { getRuntimeConfig, updateRuntimeConfig, reloadRuntimeFromEnv, reconfigureTelemetry, } from './runtime';
53
+ // Test utilities
54
+ export { resetTelemetryState, resetTraceContext, telemetryTestPlugin } from './testing';
55
+ export { setConsentLevel, getConsentLevel, shouldAllow, loadConsentFromEnv, resetConsentForTests, } from './consent';
56
+ export { registerClassificationRules, setClassificationPolicy, getClassificationPolicy, resetClassificationForTests, } from './classification';
57
+ export { enableReceipts, getEmittedReceiptsForTests, resetReceiptsForTests } from './receipts';
58
+ // Shutdown
59
+ export { shutdownTelemetry } from './shutdown';
@@ -0,0 +1,28 @@
1
+ /** Public Logger interface — consumers should type against this, not pino.Logger. */
2
+ export interface Logger {
3
+ trace(obj: Record<string, unknown>, msg?: string): void;
4
+ debug(obj: Record<string, unknown>, msg?: string): void;
5
+ info(obj: Record<string, unknown>, msg?: string): void;
6
+ warn(obj: Record<string, unknown>, msg?: string): void;
7
+ error(obj: Record<string, unknown>, msg?: string): void;
8
+ /** Create a child logger with additional bound fields. */
9
+ child(bindings: Record<string, unknown>): Logger;
10
+ }
11
+ /**
12
+ * Build the write hook that enriches, sanitizes, captures, and optionally
13
+ * emits each log record. Config is read dynamically on every invocation so
14
+ * that resetTelemetryState() + setupTelemetry() changes take effect without
15
+ * needing to rebuild the hook closure.
16
+ */
17
+ export declare function makeWriteHook(): (obj: object) => void;
18
+ /**
19
+ * Return a logger for the given name.
20
+ * Name appears as the `name` field in every log record.
21
+ * Mirrors Python: get_logger(name)
22
+ */
23
+ export declare function getLogger(name?: string): Logger;
24
+ /** Reset the root logger (forces re-creation with current config on next call). */
25
+ export declare function _resetRootLogger(): void;
26
+ /** Module-level lazy singleton logger. Mirrors Python: logger = get_logger('default'). */
27
+ export declare const logger: Logger;
28
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAoCA,qFAAqF;AACrF,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxD,0DAA0D;IAC1D,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAClD;AAKD;;;;;GAKG;AACH,wBAAgB,aAAa,KAEnB,KAAK,MAAM,KAAG,IAAI,CA8G3B;AA+ED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB/C;AAED,mFAAmF;AAEnF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,0FAA0F;AAE1F,eAAO,MAAM,MAAM,EAAE,MAOpB,CAAC"}