@ogcio/o11y-sdk-node 0.4.1 → 0.6.0
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/dist/sdk-core/index.d.ts +1 -0
- package/dist/sdk-core/index.js +1 -0
- package/dist/sdk-core/lib/index.d.ts +2 -0
- package/dist/sdk-core/lib/index.js +2 -0
- package/dist/sdk-core/lib/redaction/basic-redactor.d.ts +7 -0
- package/dist/sdk-core/lib/redaction/basic-redactor.js +18 -0
- package/dist/sdk-core/lib/redaction/email-redactor.d.ts +8 -0
- package/dist/sdk-core/lib/redaction/email-redactor.js +17 -0
- package/dist/sdk-core/lib/redaction/index.d.ts +9 -0
- package/dist/sdk-core/lib/redaction/index.js +4 -0
- package/dist/sdk-core/lib/redaction/ip-redactor.d.ts +9 -0
- package/dist/sdk-core/lib/redaction/ip-redactor.js +23 -0
- package/dist/sdk-core/lib/redaction/ppsn-redactor.d.ts +8 -0
- package/dist/sdk-core/lib/redaction/ppsn-redactor.js +17 -0
- package/dist/sdk-core/lib/utils/data-structures.d.ts +15 -0
- package/dist/{lib/internals/redaction/pii-detection.js → sdk-core/lib/utils/data-structures.js} +4 -27
- package/dist/sdk-core/lib/utils/index.d.ts +2 -0
- package/dist/sdk-core/lib/utils/index.js +2 -0
- package/dist/sdk-core/lib/utils/string-decoding.d.ts +7 -0
- package/dist/sdk-core/lib/utils/string-decoding.js +22 -0
- package/dist/{index.d.ts → sdk-node/index.d.ts} +1 -0
- package/dist/{index.js → sdk-node/index.js} +1 -0
- package/dist/sdk-node/lib/config-manager.d.ts +3 -0
- package/dist/{lib → sdk-node/lib}/config-manager.js +1 -4
- package/dist/sdk-node/lib/exporter/console.d.ts +3 -0
- package/dist/sdk-node/lib/exporter/grpc.d.ts +3 -0
- package/dist/sdk-node/lib/exporter/http.d.ts +3 -0
- package/dist/{lib → sdk-node/lib}/exporter/index.d.ts +2 -2
- package/dist/{lib → sdk-node/lib}/exporter/pii-exporter-decorator.d.ts +6 -6
- package/dist/{lib → sdk-node/lib}/exporter/pii-exporter-decorator.js +7 -3
- package/dist/sdk-node/lib/exporter/processor-config.d.ts +7 -0
- package/dist/{lib → sdk-node/lib}/exporter/processor-config.js +4 -0
- package/dist/{lib → sdk-node/lib}/index.d.ts +11 -0
- package/dist/{lib → sdk-node/lib}/instrumentation.node.js +1 -1
- package/dist/sdk-node/lib/internals/redaction/redactors/email.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/email.js +19 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/index.d.ts +16 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/index.js +13 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ip.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ip.js +20 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ppsn.d.ts +8 -0
- package/dist/sdk-node/lib/internals/redaction/redactors/ppsn.js +18 -0
- package/dist/{lib → sdk-node/lib}/metrics.d.ts +1 -1
- package/dist/{lib → sdk-node/lib}/processor/enrich-logger-processor.d.ts +3 -3
- package/dist/{lib → sdk-node/lib}/processor/enrich-span-processor.d.ts +3 -3
- package/dist/sdk-node/lib/processor/nextjs-logger-processor.d.ts +7 -0
- package/dist/sdk-node/lib/processor/nextjs-logger-processor.js +30 -0
- package/dist/sdk-node/lib/processor/nextjs-span-processor.d.ts +8 -0
- package/dist/sdk-node/lib/processor/nextjs-span-processor.js +25 -0
- package/dist/{lib → sdk-node/lib}/resource.d.ts +2 -2
- package/dist/{lib → sdk-node/lib}/traces.d.ts +1 -1
- package/dist/{lib → sdk-node/lib}/traces.js +2 -2
- package/dist/{lib → sdk-node/lib}/url-sampler.d.ts +3 -3
- package/dist/{lib → sdk-node/lib}/utils.d.ts +1 -1
- package/dist/sdk-node/package.json +62 -0
- package/package.json +25 -22
- package/CHANGELOG.md +0 -226
- package/dist/lib/config-manager.d.ts +0 -3
- package/dist/lib/exporter/console.d.ts +0 -3
- package/dist/lib/exporter/grpc.d.ts +0 -3
- package/dist/lib/exporter/http.d.ts +0 -3
- package/dist/lib/exporter/processor-config.d.ts +0 -5
- package/dist/lib/internals/redaction/pii-detection.d.ts +0 -25
- package/dist/lib/internals/redaction/redactors/email.d.ts +0 -8
- package/dist/lib/internals/redaction/redactors/email.js +0 -48
- package/dist/lib/internals/redaction/redactors/index.d.ts +0 -4
- package/dist/lib/internals/redaction/redactors/index.js +0 -6
- package/dist/lib/internals/redaction/redactors/ip.d.ts +0 -10
- package/dist/lib/internals/redaction/redactors/ip.js +0 -54
- package/dist/lib/internals/shared-metrics.d.ts +0 -7
- package/dist/lib/internals/shared-metrics.js +0 -18
- package/dist/package.json +0 -59
- package/dist/vitest.config.d.ts +0 -2
- package/dist/vitest.config.js +0 -45
- package/index.ts +0 -9
- package/lib/config-manager.ts +0 -16
- package/lib/exporter/console.ts +0 -33
- package/lib/exporter/grpc.ts +0 -65
- package/lib/exporter/http.ts +0 -56
- package/lib/exporter/index.ts +0 -9
- package/lib/exporter/pii-exporter-decorator.ts +0 -187
- package/lib/exporter/processor-config.ts +0 -23
- package/lib/index.ts +0 -118
- package/lib/instrumentation.node.ts +0 -115
- package/lib/internals/hooks.ts +0 -14
- package/lib/internals/redaction/pii-detection.ts +0 -113
- package/lib/internals/redaction/redactors/email.ts +0 -58
- package/lib/internals/redaction/redactors/index.ts +0 -12
- package/lib/internals/redaction/redactors/ip.ts +0 -68
- package/lib/internals/shared-metrics.ts +0 -34
- package/lib/metrics.ts +0 -75
- package/lib/processor/enrich-logger-processor.ts +0 -34
- package/lib/processor/enrich-span-processor.ts +0 -39
- package/lib/resource.ts +0 -30
- package/lib/traces.ts +0 -78
- package/lib/url-sampler.ts +0 -52
- package/lib/utils.ts +0 -22
- package/test/config-manager.test.ts +0 -34
- package/test/exporter/pii-exporter-decorator.test.ts +0 -88
- package/test/index.test.ts +0 -70
- package/test/integration/README.md +0 -26
- package/test/integration/http-tracing.integration.test.ts +0 -56
- package/test/integration/pii.integration.test.ts +0 -68
- package/test/integration/run.sh +0 -88
- package/test/internals/hooks.test.ts +0 -45
- package/test/internals/pii-detection.test.ts +0 -265
- package/test/internals/redactors/email.test.ts +0 -81
- package/test/internals/redactors/ip.test.ts +0 -93
- package/test/internals/shared-metrics.test.ts +0 -34
- package/test/metrics.test.ts +0 -142
- package/test/node-config.test.ts +0 -190
- package/test/processor/enrich-logger-processor.test.ts +0 -58
- package/test/processor/enrich-span-processor.test.ts +0 -52
- package/test/resource.test.ts +0 -33
- package/test/traces/active-span.test.ts +0 -28
- package/test/traces/with-span.test.ts +0 -340
- package/test/url-sampler.test.ts +0 -215
- package/test/utils/alloy-log-parser.ts +0 -53
- package/test/utils/mock-signals.ts +0 -144
- package/test/validation.test.ts +0 -103
- package/tsconfig.json +0 -15
- package/vitest.config.ts +0 -46
- /package/dist/{lib → sdk-node/lib}/exporter/console.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/grpc.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/http.js +0 -0
- /package/dist/{lib → sdk-node/lib}/exporter/index.js +0 -0
- /package/dist/{lib → sdk-node/lib}/index.js +0 -0
- /package/dist/{lib → sdk-node/lib}/instrumentation.node.d.ts +0 -0
- /package/dist/{lib → sdk-node/lib}/internals/hooks.d.ts +0 -0
- /package/dist/{lib → sdk-node/lib}/internals/hooks.js +0 -0
- /package/dist/{lib → sdk-node/lib}/metrics.js +0 -0
- /package/dist/{lib → sdk-node/lib}/processor/enrich-logger-processor.js +0 -0
- /package/dist/{lib → sdk-node/lib}/processor/enrich-span-processor.js +0 -0
- /package/dist/{lib → sdk-node/lib}/resource.js +0 -0
- /package/dist/{lib → sdk-node/lib}/url-sampler.js +0 -0
- /package/dist/{lib → sdk-node/lib}/utils.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./lib/index.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./lib/index.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StringKind, RedactionResult } from "./index.js";
|
|
2
|
+
export declare abstract class BasicRedactor {
|
|
3
|
+
constructor();
|
|
4
|
+
process(value: string, source: string, kind: StringKind): string;
|
|
5
|
+
protected redact(_value: string, _source: string, _kind: StringKind): RedactionResult<Record<string, unknown>>;
|
|
6
|
+
protected exportMetrics(_context: RedactionResult<Record<string, unknown>>["context"], _source: string, _kind: StringKind): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export class BasicRedactor {
|
|
2
|
+
constructor() { }
|
|
3
|
+
process(value, source, kind) {
|
|
4
|
+
const { redactedValue, context } = this.redact(value, source, kind);
|
|
5
|
+
this.exportMetrics(context, source, kind);
|
|
6
|
+
return redactedValue;
|
|
7
|
+
}
|
|
8
|
+
redact(_value, _source, _kind) {
|
|
9
|
+
// no-op by default
|
|
10
|
+
return {
|
|
11
|
+
redactedValue: _value,
|
|
12
|
+
context: {},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
exportMetrics(_context, _source, _kind) {
|
|
16
|
+
// no-op by default
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
import type { RedactionResult } from "./index.js";
|
|
3
|
+
export declare class EmailRedactor extends BasicRedactor {
|
|
4
|
+
private static readonly EMAIL_REGEX;
|
|
5
|
+
protected redact(value: string): RedactionResult<{
|
|
6
|
+
domains: Record<string, number>;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
export class EmailRedactor extends BasicRedactor {
|
|
3
|
+
static EMAIL_REGEX = /[\p{L}\p{N}._%+-]+@((?:[\p{L}\p{N}-]+\.)+[\p{L}]{2,})/giu;
|
|
4
|
+
redact(value) {
|
|
5
|
+
const domains = {};
|
|
6
|
+
const redactedValue = value.replace(EmailRedactor.EMAIL_REGEX, (_, domain) => {
|
|
7
|
+
domains[domain] = (domains[domain] || 0) + 1;
|
|
8
|
+
return "[REDACTED EMAIL]";
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
redactedValue: redactedValue,
|
|
12
|
+
context: {
|
|
13
|
+
domains,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface RedactionResult<T extends Record<string, unknown>> {
|
|
2
|
+
redactedValue: string;
|
|
3
|
+
context: T;
|
|
4
|
+
}
|
|
5
|
+
export type StringKind = "string" | "url";
|
|
6
|
+
export { BasicRedactor } from "./basic-redactor.js";
|
|
7
|
+
export { EmailRedactor } from "./email-redactor.js";
|
|
8
|
+
export { IpRedactor } from "./ip-redactor.js";
|
|
9
|
+
export { PpsnRedactor } from "./ppsn-redactor.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
import type { RedactionResult } from "./index.js";
|
|
3
|
+
export declare class IpRedactor extends BasicRedactor {
|
|
4
|
+
private static readonly IPV4_REGEX;
|
|
5
|
+
private static readonly IPV6_REGEX;
|
|
6
|
+
protected redact(value: string): RedactionResult<{
|
|
7
|
+
counters: Record<string, number>;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
export class IpRedactor extends BasicRedactor {
|
|
3
|
+
static IPV4_REGEX = /(?<!\d)(?:%[0-9A-Fa-f]{2})?(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}(?:%[0-9A-Fa-f]{2})?(?!\d)/gi;
|
|
4
|
+
static IPV6_REGEX = /(?<![0-9a-f:])(?:%[0-9A-Fa-f]{2})?((?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,7}:|:(?::[0-9A-Fa-f]{1,4}){1,7}|(?:[0-9A-Fa-f]{1,4}:){1,6}:[0-9A-Fa-f]{1,4}|(?:[0-9A-Fa-f]{1,4}:){1,5}(?::[0-9A-Fa-f]{1,4}){1,2}|(?:[0-9A-Fa-f]{1,4}:){1,4}(?::[0-9A-Fa-f]{1,4}){1,3}|(?:[0-9A-Fa-f]{1,4}:){1,3}(?::[0-9A-Fa-f]{1,4}){1,4}|(?:[0-9A-Fa-f]{1,4}:){1,2}(?::[0-9A-Fa-f]{1,4}){1,5}|[0-9A-Fa-f]{1,4}:(?::[0-9A-Fa-f]{1,4}){1,6}|:(?::[0-9A-Fa-f]{1,4}){1,7}:?|(?:[0-9A-Fa-f]{1,4}:){1,4}:(?:25[0-5]|2[0-4]\d|1\d\d|\d{1,2})(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|\d{1,2})){3})(?:%[0-9A-Fa-f]{2})?(?![0-9a-f:])/gi;
|
|
5
|
+
redact(value) {
|
|
6
|
+
const counters = {};
|
|
7
|
+
const redactedValue = value
|
|
8
|
+
.replace(IpRedactor.IPV4_REGEX, () => {
|
|
9
|
+
counters["IPv4"] = (counters["IPv4"] || 0) + 1;
|
|
10
|
+
return "[REDACTED IPV4]";
|
|
11
|
+
})
|
|
12
|
+
.replace(IpRedactor.IPV6_REGEX, () => {
|
|
13
|
+
counters["IPv6"] = (counters["IPv6"] || 0) + 1;
|
|
14
|
+
return "[REDACTED IPV6]";
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
redactedValue: redactedValue,
|
|
18
|
+
context: {
|
|
19
|
+
counters,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
import type { RedactionResult } from "./index.js";
|
|
3
|
+
export declare class PpsnRedactor extends BasicRedactor {
|
|
4
|
+
private static readonly PPSN_REGEX;
|
|
5
|
+
protected redact(value: string): RedactionResult<{
|
|
6
|
+
redactedCounter: number;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BasicRedactor } from "./basic-redactor.js";
|
|
2
|
+
export class PpsnRedactor extends BasicRedactor {
|
|
3
|
+
static PPSN_REGEX = /(?<!([0-9]|[a-z]))[0-9]{7}[a-z]{1,2}(?!([0-9]|[a-z]))/gi;
|
|
4
|
+
redact(value) {
|
|
5
|
+
let redactedCounter = 0;
|
|
6
|
+
const redactedValue = value.replace(PpsnRedactor.PPSN_REGEX, (_) => {
|
|
7
|
+
redactedCounter++;
|
|
8
|
+
return "[REDACTED PPSN]";
|
|
9
|
+
});
|
|
10
|
+
return {
|
|
11
|
+
redactedValue: redactedValue,
|
|
12
|
+
context: {
|
|
13
|
+
redactedCounter,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AnyValue } from "@opentelemetry/api-logs";
|
|
2
|
+
import { BasicRedactor } from "../redaction/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cleans a string by redacting configured PIIs and emitting metrics for redacted values.
|
|
5
|
+
*
|
|
6
|
+
* If the string is URL-encoded, it will be decoded before redaction.
|
|
7
|
+
*
|
|
8
|
+
* @param {string} value - The input value to sanitize.
|
|
9
|
+
* @param {string} source - The source context of the input, used in metrics.
|
|
10
|
+
* @param {BasicRedactor[]} redactors - The string redactors containing the redaction logic.
|
|
11
|
+
*
|
|
12
|
+
* @returns {string} The cleaned string with any configured PII replaced by `[REDACTED PII_TYPE]`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function _cleanStringPII<T extends string>(value: string, source: T, redactors: BasicRedactor[]): string;
|
|
15
|
+
export declare function _recursiveObjectClean<T extends AnyValue, R extends string>(value: T, source: R, redactors: BasicRedactor[]): T;
|
package/dist/{lib/internals/redaction/pii-detection.js → sdk-core/lib/utils/data-structures.js}
RENAMED
|
@@ -1,37 +1,14 @@
|
|
|
1
|
+
import { _containsEncodedComponents } from "./string-decoding.js";
|
|
1
2
|
const decoder = new TextDecoder();
|
|
2
3
|
const encoder = new TextEncoder();
|
|
3
|
-
/**
|
|
4
|
-
* Checks whether a string contains URI-encoded components.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} value - The string to inspect.
|
|
7
|
-
* @returns {boolean} `true` if the string is encoded, `false` otherwise.
|
|
8
|
-
*/
|
|
9
|
-
export function _containsEncodedComponents(value) {
|
|
10
|
-
try {
|
|
11
|
-
const decodedURIComponent = decodeURIComponent(value);
|
|
12
|
-
if (decodeURI(value) !== decodedURIComponent) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
if (value !== decodedURIComponent) {
|
|
16
|
-
return (encodeURIComponent(decodedURIComponent) === value ||
|
|
17
|
-
encodeURI(decodedURIComponent) === value);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
4
|
/**
|
|
26
5
|
* Cleans a string by redacting configured PIIs and emitting metrics for redacted values.
|
|
27
6
|
*
|
|
28
7
|
* If the string is URL-encoded, it will be decoded before redaction.
|
|
29
8
|
*
|
|
30
|
-
* @template T
|
|
31
|
-
*
|
|
32
9
|
* @param {string} value - The input value to sanitize.
|
|
33
|
-
* @param {
|
|
34
|
-
* @param {
|
|
10
|
+
* @param {string} source - The source context of the input, used in metrics.
|
|
11
|
+
* @param {BasicRedactor[]} redactors - The string redactors containing the redaction logic.
|
|
35
12
|
*
|
|
36
13
|
* @returns {string} The cleaned string with any configured PII replaced by `[REDACTED PII_TYPE]`.
|
|
37
14
|
*/
|
|
@@ -45,7 +22,7 @@ export function _cleanStringPII(value, source, redactors) {
|
|
|
45
22
|
decodedValue = decodeURIComponent(value);
|
|
46
23
|
kind = "url";
|
|
47
24
|
}
|
|
48
|
-
return redactors.reduce((redactedValue, currentRedactor) => currentRedactor(redactedValue, source, kind), decodedValue);
|
|
25
|
+
return redactors.reduce((redactedValue, currentRedactor) => currentRedactor.process(redactedValue, source, kind), decodedValue);
|
|
49
26
|
}
|
|
50
27
|
export function _recursiveObjectClean(value, source, redactors) {
|
|
51
28
|
if (typeof value === "string") {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a string contains URI-encoded components.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} value - The string to inspect.
|
|
5
|
+
* @returns {boolean} `true` if the string is encoded, `false` otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export declare function _containsEncodedComponents(value: string): boolean;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether a string contains URI-encoded components.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} value - The string to inspect.
|
|
5
|
+
* @returns {boolean} `true` if the string is encoded, `false` otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export function _containsEncodedComponents(value) {
|
|
8
|
+
try {
|
|
9
|
+
const decodedURIComponent = decodeURIComponent(value);
|
|
10
|
+
if (decodeURI(value) !== decodedURIComponent) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (value !== decodedURIComponent) {
|
|
14
|
+
return (encodeURIComponent(decodedURIComponent) === value ||
|
|
15
|
+
encodeURI(decodedURIComponent) === value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
@@ -3,9 +3,6 @@ export const setNodeSdkConfig = (config) => {
|
|
|
3
3
|
nodeSDKConfig = config;
|
|
4
4
|
};
|
|
5
5
|
export const getNodeSdkConfig = () => {
|
|
6
|
-
if (!nodeSDKConfig) {
|
|
7
|
-
throw new Error("Node SDK Config was not initialized.");
|
|
8
|
-
}
|
|
9
6
|
// Ensure getters do not edit config.
|
|
10
|
-
return JSON.parse(JSON.stringify(nodeSDKConfig));
|
|
7
|
+
return nodeSDKConfig ? JSON.parse(JSON.stringify(nodeSDKConfig)) : undefined;
|
|
11
8
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
1
|
+
import type { LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
2
|
import type { metrics } from "@opentelemetry/sdk-node";
|
|
3
|
-
import { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
import type { SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
export type Exporters = {
|
|
5
5
|
spans: SpanProcessor[];
|
|
6
6
|
metrics: metrics.MetricReader;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ExportResult } from "@opentelemetry/core";
|
|
1
|
+
import type { ExportResult } from "@opentelemetry/core";
|
|
2
2
|
import { OTLPExporterBase } from "@opentelemetry/otlp-exporter-base";
|
|
3
|
-
import { ReadableLogRecord } from "@opentelemetry/sdk-logs";
|
|
4
|
-
import { PushMetricExporter, ResourceMetrics } from "@opentelemetry/sdk-metrics";
|
|
5
|
-
import { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
6
|
-
import { NodeSDKConfig } from "../index.js";
|
|
3
|
+
import type { ReadableLogRecord } from "@opentelemetry/sdk-logs";
|
|
4
|
+
import type { PushMetricExporter, ResourceMetrics } from "@opentelemetry/sdk-metrics";
|
|
5
|
+
import type { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
|
|
6
|
+
import type { NodeSDKConfig } from "../index.js";
|
|
7
7
|
export declare class PIIExporterDecorator extends OTLPExporterBase<(ReadableSpan | ReadableLogRecord)[] | ResourceMetrics> implements SpanExporter, PushMetricExporter {
|
|
8
8
|
private readonly _exporter;
|
|
9
9
|
private readonly _config;
|
|
10
10
|
private readonly _redactors;
|
|
11
|
-
constructor(exporter: OTLPExporterBase<(ReadableSpan | ReadableLogRecord)[] | ResourceMetrics>, config: NodeSDKConfig);
|
|
11
|
+
constructor(exporter: OTLPExporterBase<(ReadableSpan | ReadableLogRecord)[] | ResourceMetrics>, config: NodeSDKConfig | undefined);
|
|
12
12
|
forceFlush(): Promise<void>;
|
|
13
13
|
shutdown(): Promise<void>;
|
|
14
14
|
export(items: (ReadableSpan | ReadableLogRecord)[] | ResourceMetrics, resultCallback: (result: ExportResult) => void): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OTLPExporterBase } from "@opentelemetry/otlp-exporter-base";
|
|
2
|
-
import { _cleanStringPII, _recursiveObjectClean, } from "../internals/redaction/pii-detection.js";
|
|
3
2
|
import { redactors, } from "../internals/redaction/redactors/index.js";
|
|
3
|
+
import { _cleanStringPII, _recursiveObjectClean, BasicRedactor, } from "../../../sdk-core/index.js";
|
|
4
4
|
export class PIIExporterDecorator extends OTLPExporterBase {
|
|
5
5
|
_exporter;
|
|
6
6
|
_config;
|
|
@@ -9,7 +9,7 @@ export class PIIExporterDecorator extends OTLPExporterBase {
|
|
|
9
9
|
super(exporter["_delegate"]);
|
|
10
10
|
this._exporter = exporter;
|
|
11
11
|
this._config = config;
|
|
12
|
-
this._redactors = this._buildRedactors(config
|
|
12
|
+
this._redactors = this._buildRedactors(config?.detection);
|
|
13
13
|
}
|
|
14
14
|
forceFlush() {
|
|
15
15
|
return this._exporter.forceFlush();
|
|
@@ -110,10 +110,14 @@ export class PIIExporterDecorator extends OTLPExporterBase {
|
|
|
110
110
|
}
|
|
111
111
|
// Default opt-in every redactor available, excluding only those explicitly configured to false
|
|
112
112
|
_buildRedactors(redactorsConfig = {}) {
|
|
113
|
-
|
|
113
|
+
const defaultRedactors = Object.entries(redactors)
|
|
114
114
|
.filter(([key]) => {
|
|
115
115
|
return redactorsConfig[key] !== false;
|
|
116
116
|
})
|
|
117
117
|
.map(([_, value]) => value);
|
|
118
|
+
const customRedactors = redactorsConfig.custom?.length
|
|
119
|
+
? (redactorsConfig.custom.filter((redactor) => redactor instanceof BasicRedactor) ?? [])
|
|
120
|
+
: [];
|
|
121
|
+
return [...defaultRedactors, ...customRedactors];
|
|
118
122
|
}
|
|
119
123
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NodeSDKConfig } from "../index.js";
|
|
2
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
3
|
+
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
4
|
+
import { NextJsLogProcessor } from "../processor/nextjs-logger-processor.js";
|
|
5
|
+
import { NextJsSpanProcessor } from "../processor/nextjs-span-processor.js";
|
|
6
|
+
export declare function _spansProcessorConfig(config: NodeSDKConfig): (EnrichSpanProcessor | NextJsSpanProcessor)[];
|
|
7
|
+
export declare function _logsProcessorConfig(config: NodeSDKConfig): (EnrichLogProcessor | NextJsLogProcessor)[];
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
2
2
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
3
|
+
import { NextJsLogProcessor } from "../processor/nextjs-logger-processor.js";
|
|
4
|
+
import { NextJsSpanProcessor } from "../processor/nextjs-span-processor.js";
|
|
3
5
|
export function _spansProcessorConfig(config) {
|
|
4
6
|
const _processor = [];
|
|
7
|
+
_processor.push(new NextJsSpanProcessor());
|
|
5
8
|
if (config.spanAttributes) {
|
|
6
9
|
_processor.push(new EnrichSpanProcessor(config.spanAttributes));
|
|
7
10
|
}
|
|
@@ -9,6 +12,7 @@ export function _spansProcessorConfig(config) {
|
|
|
9
12
|
}
|
|
10
13
|
export function _logsProcessorConfig(config) {
|
|
11
14
|
const _processor = [];
|
|
15
|
+
_processor.push(new NextJsLogProcessor());
|
|
12
16
|
if (config.spanAttributes) {
|
|
13
17
|
_processor.push(new EnrichLogProcessor(config.spanAttributes));
|
|
14
18
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Metadata } from "@grpc/grpc-js";
|
|
2
|
+
import { BasicRedactor } from "../../sdk-core/lib/redaction/basic-redactor.js";
|
|
2
3
|
export interface NodeSDKConfig {
|
|
3
4
|
/**
|
|
4
5
|
* The opentelemetry collector entrypoint GRPC url.
|
|
@@ -83,6 +84,16 @@ export interface NodeSDKConfig {
|
|
|
83
84
|
* @default true
|
|
84
85
|
*/
|
|
85
86
|
ip?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Redact PPSN (Personal Public Service Number)
|
|
89
|
+
* @default true
|
|
90
|
+
*/
|
|
91
|
+
ppsn?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Custom redactors to be added together with the default ones
|
|
94
|
+
* @default []
|
|
95
|
+
*/
|
|
96
|
+
custom?: BasicRedactor[];
|
|
86
97
|
};
|
|
87
98
|
}
|
|
88
99
|
export interface SamplerCondition {
|
|
@@ -56,7 +56,7 @@ export default async function buildNodeInstrumentation(config) {
|
|
|
56
56
|
],
|
|
57
57
|
spanProcessors: exporter.spans,
|
|
58
58
|
serviceName: config.serviceName,
|
|
59
|
-
|
|
59
|
+
metricReaders: [exporter.metrics],
|
|
60
60
|
logRecordProcessors: exporter.logs,
|
|
61
61
|
sampler: mainSampler,
|
|
62
62
|
textMapPropagator: new W3CTraceContextPropagator(),
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PIISource, RedactionMetric } from "./index.js";
|
|
2
|
+
import type { Counter } from "@opentelemetry/api";
|
|
3
|
+
import { EmailRedactor, type StringKind } from "../../../../../sdk-core/index.js";
|
|
4
|
+
export declare class EmailRedactorWithMetrics extends EmailRedactor {
|
|
5
|
+
protected _counterRedactionMetric: Counter<RedactionMetric>;
|
|
6
|
+
constructor(metric: Counter<RedactionMetric>);
|
|
7
|
+
protected exportMetrics(context: ReturnType<typeof this.redact>["context"], source: PIISource, kind: StringKind): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EmailRedactor, } from "../../../../../sdk-core/index.js";
|
|
2
|
+
export class EmailRedactorWithMetrics extends EmailRedactor {
|
|
3
|
+
_counterRedactionMetric;
|
|
4
|
+
constructor(metric) {
|
|
5
|
+
super();
|
|
6
|
+
this._counterRedactionMetric = metric;
|
|
7
|
+
}
|
|
8
|
+
exportMetrics(context, source, kind) {
|
|
9
|
+
const { domains } = context;
|
|
10
|
+
for (const [domain, domainCount] of Object.entries(domains)) {
|
|
11
|
+
this._counterRedactionMetric.add(domainCount, {
|
|
12
|
+
pii_type: "email",
|
|
13
|
+
redaction_source: source,
|
|
14
|
+
pii_email_domain: domain,
|
|
15
|
+
pii_format: kind,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NodeSDKConfig } from "../../../index.js";
|
|
2
|
+
import type { Attributes } from "@opentelemetry/api";
|
|
3
|
+
import { BasicRedactor } from "../../../../../sdk-core/index.js";
|
|
4
|
+
export type PIISource = "trace" | "log" | "metric";
|
|
5
|
+
export interface RedactionMetric extends Attributes {
|
|
6
|
+
/** Type of PII redacted (e.g., "email", "phone"). */
|
|
7
|
+
pii_type: string;
|
|
8
|
+
/** Domain part of the redacted PII (e.g., "gmail.com"). */
|
|
9
|
+
pii_email_domain?: string;
|
|
10
|
+
/** Source of the redaction (trace, log or metric). */
|
|
11
|
+
redaction_source: PIISource;
|
|
12
|
+
/** Format or structure of the redacted value. */
|
|
13
|
+
pii_format: "string" | "url";
|
|
14
|
+
}
|
|
15
|
+
export type RedactorKeys = keyof Omit<NonNullable<NodeSDKConfig["detection"]>, "custom">;
|
|
16
|
+
export declare const redactors: Record<RedactorKeys, BasicRedactor>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EmailRedactorWithMetrics } from "./email.js";
|
|
2
|
+
import { IpRedactorWithMetrics } from "./ip.js";
|
|
3
|
+
import { getMetric } from "../../../metrics.js";
|
|
4
|
+
import { PpsnRedactorWithMetrics } from "./ppsn.js";
|
|
5
|
+
const metricCounter = getMetric("counter", {
|
|
6
|
+
meterName: "o11y",
|
|
7
|
+
metricName: "o11y_pii_redaction",
|
|
8
|
+
});
|
|
9
|
+
export const redactors = {
|
|
10
|
+
email: new EmailRedactorWithMetrics(metricCounter),
|
|
11
|
+
ip: new IpRedactorWithMetrics(metricCounter),
|
|
12
|
+
ppsn: new PpsnRedactorWithMetrics(metricCounter),
|
|
13
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Counter } from "@opentelemetry/api";
|
|
2
|
+
import type { PIISource, RedactionMetric } from "./index.js";
|
|
3
|
+
import { IpRedactor, type StringKind } from "../../../../../sdk-core/index.js";
|
|
4
|
+
export declare class IpRedactorWithMetrics extends IpRedactor {
|
|
5
|
+
protected _counterRedactionMetric: Counter<RedactionMetric>;
|
|
6
|
+
constructor(metric: Counter<RedactionMetric>);
|
|
7
|
+
protected exportMetrics(context: ReturnType<typeof this.redact>["context"], source: PIISource, kind: StringKind): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { IpRedactor } from "../../../../../sdk-core/index.js";
|
|
2
|
+
export class IpRedactorWithMetrics extends IpRedactor {
|
|
3
|
+
_counterRedactionMetric;
|
|
4
|
+
constructor(metric) {
|
|
5
|
+
super();
|
|
6
|
+
this._counterRedactionMetric = metric;
|
|
7
|
+
}
|
|
8
|
+
exportMetrics(context, source, kind) {
|
|
9
|
+
const { counters } = context;
|
|
10
|
+
Object.entries(counters).forEach(([type, counter]) => {
|
|
11
|
+
if (counter > 0) {
|
|
12
|
+
this._counterRedactionMetric.add(counter, {
|
|
13
|
+
pii_type: type,
|
|
14
|
+
redaction_source: source,
|
|
15
|
+
pii_format: kind,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PIISource, RedactionMetric } from "./index.js";
|
|
2
|
+
import type { Counter } from "@opentelemetry/api";
|
|
3
|
+
import { PpsnRedactor, type StringKind } from "../../../../../sdk-core/index.js";
|
|
4
|
+
export declare class PpsnRedactorWithMetrics extends PpsnRedactor {
|
|
5
|
+
protected _counterRedactionMetric: Counter<RedactionMetric>;
|
|
6
|
+
constructor(metric: Counter<RedactionMetric>);
|
|
7
|
+
protected exportMetrics(context: ReturnType<typeof this.redact>["context"], source: PIISource, kind: StringKind): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PpsnRedactor, } from "../../../../../sdk-core/index.js";
|
|
2
|
+
export class PpsnRedactorWithMetrics extends PpsnRedactor {
|
|
3
|
+
_counterRedactionMetric;
|
|
4
|
+
constructor(metric) {
|
|
5
|
+
super();
|
|
6
|
+
this._counterRedactionMetric = metric;
|
|
7
|
+
}
|
|
8
|
+
exportMetrics(context, source, kind) {
|
|
9
|
+
const { redactedCounter } = context;
|
|
10
|
+
if (redactedCounter === 0)
|
|
11
|
+
return;
|
|
12
|
+
this._counterRedactionMetric.add(redactedCounter, {
|
|
13
|
+
pii_type: "ppsn",
|
|
14
|
+
redaction_source: source,
|
|
15
|
+
pii_format: kind,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Counter, Gauge, Histogram, MetricOptions, ObservableCounter, ObservableGauge, ObservableUpDownCounter, UpDownCounter, Attributes } from "@opentelemetry/api";
|
|
1
|
+
import { type Counter, type Gauge, type Histogram, type MetricOptions, type ObservableCounter, type ObservableGauge, type ObservableUpDownCounter, type UpDownCounter, type Attributes } from "@opentelemetry/api";
|
|
2
2
|
type MetricTypeMap<TAttributes extends Attributes> = {
|
|
3
3
|
counter: Counter<TAttributes>;
|
|
4
4
|
histogram: Histogram<TAttributes>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SdkLogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
-
import { Context } from "@opentelemetry/api";
|
|
3
|
-
import { SignalAttributeValue } from "../index.js";
|
|
1
|
+
import type { SdkLogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
+
import type { Context } from "@opentelemetry/api";
|
|
3
|
+
import type { SignalAttributeValue } from "../index.js";
|
|
4
4
|
export declare class EnrichLogProcessor implements LogRecordProcessor {
|
|
5
5
|
private _spanAttributes?;
|
|
6
6
|
constructor(spanAttributes?: Record<string, SignalAttributeValue | (() => SignalAttributeValue)>);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Context } from "@opentelemetry/api";
|
|
2
|
-
import { ReadableSpan, Span, SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
3
|
-
import { SignalAttributeValue } from "../index.js";
|
|
1
|
+
import type { Context } from "@opentelemetry/api";
|
|
2
|
+
import type { ReadableSpan, Span, SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
3
|
+
import type { SignalAttributeValue } from "../index.js";
|
|
4
4
|
export declare class EnrichSpanProcessor implements SpanProcessor {
|
|
5
5
|
private _spanAttributes;
|
|
6
6
|
constructor(spanAttributes?: Record<string, SignalAttributeValue | (() => SignalAttributeValue)>);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Context } from "@opentelemetry/api";
|
|
2
|
+
import { LogRecordProcessor, SdkLogRecord } from "@opentelemetry/sdk-logs";
|
|
3
|
+
export declare class NextJsLogProcessor implements LogRecordProcessor {
|
|
4
|
+
onEmit(logRecord: SdkLogRecord, _context?: Context): void;
|
|
5
|
+
shutdown(): Promise<void>;
|
|
6
|
+
forceFlush(): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SeverityNumber } from "@opentelemetry/api-logs";
|
|
2
|
+
export class NextJsLogProcessor {
|
|
3
|
+
onEmit(logRecord, _context) {
|
|
4
|
+
try {
|
|
5
|
+
if (typeof logRecord.body === "object" &&
|
|
6
|
+
logRecord.body !== null &&
|
|
7
|
+
"error" in logRecord.body) {
|
|
8
|
+
const error = logRecord.body.error;
|
|
9
|
+
if (error &&
|
|
10
|
+
typeof error.digest === "string" &&
|
|
11
|
+
error.digest.includes("NEXT_REDIRECT")) {
|
|
12
|
+
logRecord.setBody({
|
|
13
|
+
message: error.digest,
|
|
14
|
+
});
|
|
15
|
+
logRecord.setSeverityNumber(SeverityNumber.INFO);
|
|
16
|
+
logRecord.setSeverityText("INFO");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
console.error("Error processing log record:", err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
shutdown() {
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
}
|
|
27
|
+
forceFlush() {
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}
|
|
30
|
+
}
|