@composed-di/instrumentation-core 0.6.0-alpha

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.
@@ -0,0 +1,4 @@
1
+ export * from './serviceInstrumentation';
2
+ export * from './instrument';
3
+ export * from './redaction';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./serviceInstrumentation"), exports);
18
+ __exportStar(require("./instrument"), exports);
19
+ __exportStar(require("./redaction"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAwC;AACxC,+CAA4B;AAC5B,8CAA2B"}
@@ -0,0 +1,72 @@
1
+ import { ServiceFactory, ServiceKey, ServiceModule } from '@composed-di/core';
2
+ import type { ServiceInstrumentation } from './serviceInstrumentation';
3
+ import type { RedactionRule } from './redaction';
4
+ type GenericFactory = ServiceFactory<unknown, readonly ServiceKey<any>[]>;
5
+ /**
6
+ * Configuration for {@link instrument}. Capture policy lives here, not in
7
+ * the ServiceInstrumentation implementations: what an implementation
8
+ * receives is exactly what it is allowed to record, so no implementation
9
+ * carries its own capture flags or redaction logic.
10
+ */
11
+ export interface InstrumentOptions {
12
+ /**
13
+ * The instrumentation notified of service lifecycle events and method
14
+ * calls.
15
+ */
16
+ instrumentation: ServiceInstrumentation;
17
+ /**
18
+ * Deliver method arguments to the instrumentation (as
19
+ * MethodCallContext.args). Off by default: arguments may be large or
20
+ * contain secrets, and they end up wherever the instrumentation exports
21
+ * them. When off, the instrumentation never sees the arguments at all.
22
+ */
23
+ captureArguments?: boolean;
24
+ /**
25
+ * Deliver method call return / resolved values to the instrumentation
26
+ * (as the success outcome's `value`). Off by default, for the same
27
+ * reasons as `captureArguments`. When off, the instrumentation never
28
+ * sees the values at all. Initialize and dispose outcomes never carry a
29
+ * value: the service instance is not useful information to report.
30
+ */
31
+ captureResults?: boolean;
32
+ /**
33
+ * Per-service redaction applied to whatever the capture flags let
34
+ * through: matched arguments and success values are blanked (or run
35
+ * through the rule's custom mask) before the instrumentation sees them.
36
+ * The capture flags are the primary gate — when capture is off there is
37
+ * nothing to redact, and rules cannot re-enable delivery.
38
+ */
39
+ redactionRules?: readonly RedactionRule<any>[];
40
+ }
41
+ /**
42
+ * Wraps service factories with instrumentation, so the given
43
+ * ServiceInstrumentation is notified when a service is initialized or
44
+ * disposed and when a method is called on a service instance, and may
45
+ * return an EventSpan per operation to observe its completion. Service
46
+ * instances are wrapped in a Proxy to observe method calls, and errors
47
+ * are rethrown after being reported, so behavior is otherwise unchanged.
48
+ *
49
+ * ServiceModule entries are flattened into their factories, so an
50
+ * already-built module can be instrumented as a whole. Compose the result
51
+ * with `ServiceModule.from`:
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * const module = ServiceModule.from(
56
+ * instrument([db, cache, api], {
57
+ * instrumentation: otel,
58
+ * captureArguments: true,
59
+ * captureResults: true,
60
+ * redactionRules: [redactionRule(VaultKey).redact('getSecret').build()],
61
+ * }),
62
+ * );
63
+ * ```
64
+ *
65
+ * @param entries - An array of ServiceModule or factory instances to wrap.
66
+ * @param options - The instrumentation to notify, plus the capture and
67
+ * redaction policy applied before anything reaches it.
68
+ * @return The wrapped factories, ready to be passed to ServiceModule.from.
69
+ */
70
+ export declare function instrument(entries: (ServiceModule | GenericFactory)[], options: InstrumentOptions): GenericFactory[];
71
+ export {};
72
+ //# sourceMappingURL=instrument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrument.d.ts","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC7E,OAAO,KAAK,EAGV,sBAAsB,EACvB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAEzE;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,eAAe,EAAE,sBAAsB,CAAA;IAEvC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAE1B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IAExB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,CAAA;CAC/C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,CAAC,aAAa,GAAG,cAAc,CAAC,EAAE,EAC3C,OAAO,EAAE,iBAAiB,GACzB,cAAc,EAAE,CAIlB"}
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.instrument = instrument;
13
+ const core_1 = require("@composed-di/core");
14
+ /**
15
+ * Wraps service factories with instrumentation, so the given
16
+ * ServiceInstrumentation is notified when a service is initialized or
17
+ * disposed and when a method is called on a service instance, and may
18
+ * return an EventSpan per operation to observe its completion. Service
19
+ * instances are wrapped in a Proxy to observe method calls, and errors
20
+ * are rethrown after being reported, so behavior is otherwise unchanged.
21
+ *
22
+ * ServiceModule entries are flattened into their factories, so an
23
+ * already-built module can be instrumented as a whole. Compose the result
24
+ * with `ServiceModule.from`:
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const module = ServiceModule.from(
29
+ * instrument([db, cache, api], {
30
+ * instrumentation: otel,
31
+ * captureArguments: true,
32
+ * captureResults: true,
33
+ * redactionRules: [redactionRule(VaultKey).redact('getSecret').build()],
34
+ * }),
35
+ * );
36
+ * ```
37
+ *
38
+ * @param entries - An array of ServiceModule or factory instances to wrap.
39
+ * @param options - The instrumentation to notify, plus the capture and
40
+ * redaction policy applied before anything reaches it.
41
+ * @return The wrapped factories, ready to be passed to ServiceModule.from.
42
+ */
43
+ function instrument(entries, options) {
44
+ return entries
45
+ .flatMap((e) => (e instanceof core_1.ServiceModule ? e.factories : [e]))
46
+ .map((factory) => makeObservable(options, factory));
47
+ }
48
+ function makeCapture(options, key) {
49
+ var _a, _b, _c;
50
+ const rule = (_a = options.redactionRules) === null || _a === void 0 ? void 0 : _a.find((r) => r.key === key);
51
+ const captureArguments = (_b = options.captureArguments) !== null && _b !== void 0 ? _b : false;
52
+ const captureResults = (_c = options.captureResults) !== null && _c !== void 0 ? _c : false;
53
+ return {
54
+ args: (functionName, args) => captureArguments
55
+ ? rule
56
+ ? rule.maskArgs(functionName, args)
57
+ : args
58
+ : undefined,
59
+ success: (functionName, value) => captureResults
60
+ ? {
61
+ type: 'success',
62
+ value: rule ? rule.maskResult(functionName, value) : value,
63
+ }
64
+ : { type: 'success' },
65
+ };
66
+ }
67
+ /**
68
+ * Wraps a given service factory with instrumentation to notify a
69
+ * ServiceInstrumentation of lifecycle events and method calls.
70
+ *
71
+ * For each of initialize, dispose, and method calls, the instrumentation
72
+ * is invoked at the start of the operation and may return an EventSpan
73
+ * whose `end` is called with the outcome when the operation finishes.
74
+ * Errors are rethrown after being reported.
75
+ *
76
+ * @param options The instrumentation to notify and the capture policy.
77
+ * @param delegate The original service factory to be instrumented.
78
+ * @return A new service factory that provides the same dependencies but includes event notification logic.
79
+ */
80
+ function makeObservable(options, delegate) {
81
+ const instrumentation = options.instrumentation;
82
+ const key = delegate.provides;
83
+ const capture = makeCapture(options, key);
84
+ return core_1.ServiceFactory.singleton({
85
+ scope: delegate.scope,
86
+ provides: delegate.provides,
87
+ dependsOn: delegate.dependsOn,
88
+ initialize: (...args) => __awaiter(this, void 0, void 0, function* () {
89
+ var _a;
90
+ const span = (_a = instrumentation.onInitialize) === null || _a === void 0 ? void 0 : _a.call(instrumentation, { key });
91
+ if (!span) {
92
+ return delegate.initialize(...args);
93
+ }
94
+ try {
95
+ const instance = yield span.run(() => delegate.initialize(...args));
96
+ span.end({ type: 'success' });
97
+ return observeMethodCalls(instance, instrumentation, key, capture);
98
+ }
99
+ catch (error) {
100
+ span.end({ type: 'failure', error });
101
+ throw error;
102
+ }
103
+ }),
104
+ dispose: () => {
105
+ var _a;
106
+ const dispose = delegate.dispose;
107
+ if (dispose) {
108
+ const span = (_a = instrumentation.onDispose) === null || _a === void 0 ? void 0 : _a.call(instrumentation, { key });
109
+ if (span) {
110
+ try {
111
+ span.run(dispose);
112
+ span.end({ type: 'success' });
113
+ }
114
+ catch (error) {
115
+ span.end({ type: 'failure', error });
116
+ throw error;
117
+ }
118
+ }
119
+ }
120
+ },
121
+ });
122
+ }
123
+ /**
124
+ * Wraps an object with a Proxy to notify the instrumentation of method calls.
125
+ *
126
+ * Methods returning a promise report their outcome when the promise
127
+ * settles, not when the method returns.
128
+ *
129
+ * @param thing The object whose method calls need to be observed.
130
+ * @param instrumentation The instrumentation notified of method call events.
131
+ * @param key The service key used to identify the service in events.
132
+ * @param capture The capture policy deciding what argument and result
133
+ * values (if any) are delivered with each event.
134
+ * @return A Proxy wrapping the input object, with all method calls being reported.
135
+ */
136
+ function observeMethodCalls(thing, instrumentation, key, capture) {
137
+ if (typeof thing !== 'object' || thing === null) {
138
+ return thing;
139
+ }
140
+ const className = classNameOf(thing);
141
+ return new Proxy(thing, {
142
+ get(target, prop) {
143
+ const value = Reflect.get(target, prop);
144
+ if (typeof value === 'function' && typeof prop === 'string') {
145
+ return (...args) => {
146
+ var _a;
147
+ const span = (_a = instrumentation.onMethodCall) === null || _a === void 0 ? void 0 : _a.call(instrumentation, {
148
+ key,
149
+ className,
150
+ functionName: prop,
151
+ args: capture.args(prop, args),
152
+ });
153
+ try {
154
+ const result = invokeWithin(span, () => value.apply(target, args));
155
+ if (result instanceof Promise) {
156
+ return result.then((resolved) => {
157
+ span === null || span === void 0 ? void 0 : span.end(capture.success(prop, resolved));
158
+ return resolved;
159
+ }, (error) => {
160
+ span === null || span === void 0 ? void 0 : span.end({ type: 'failure', error });
161
+ throw error;
162
+ });
163
+ }
164
+ span === null || span === void 0 ? void 0 : span.end(capture.success(prop, result));
165
+ return result;
166
+ }
167
+ catch (error) {
168
+ span === null || span === void 0 ? void 0 : span.end({ type: 'failure', error });
169
+ throw error;
170
+ }
171
+ };
172
+ }
173
+ return value;
174
+ },
175
+ });
176
+ }
177
+ /**
178
+ * Invokes an operation through the EventSpan's `run` wrapper when the
179
+ * instrumentation returned a span, so it can establish ambient state
180
+ * (tracing context) around the operation; invokes the operation directly
181
+ * otherwise.
182
+ *
183
+ * @param span The EventSpan returned by the instrumentation, if any.
184
+ * @param fn The thunk performing the operation.
185
+ * @returns The value returned by `fn`.
186
+ */
187
+ function invokeWithin(span, fn) {
188
+ return span ? span.run(fn) : fn();
189
+ }
190
+ /**
191
+ * Resolves the class name of a service instance, or undefined for values
192
+ * that are not instances of a named class (plain object literals,
193
+ * null-prototype objects).
194
+ *
195
+ * @param thing The service instance to inspect.
196
+ * @returns The constructor name, or undefined when there is none to report.
197
+ */
198
+ function classNameOf(thing) {
199
+ var _a;
200
+ const name = (_a = thing.constructor) === null || _a === void 0 ? void 0 : _a.name;
201
+ return name && name !== 'Object' ? name : undefined;
202
+ }
203
+ //# sourceMappingURL=instrument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrument.js","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import type { DisposeContext, EventSpan, InitializeContext, MethodCallContext, ServiceInstrumentation } from './serviceInstrumentation';
2
+ import type { ServiceKey } from '@composed-di/core';
3
+ /**
4
+ * The placeholder that replaces a redacted value when no custom
5
+ * transform is given for it.
6
+ */
7
+ export declare const REDACTED_VALUE = "[REDACTED]";
8
+ /**
9
+ * Custom masking for one included property, narrowed to the exact
10
+ * method named when {@link RedactionRuleBuilder.redact} is called.
11
+ * Omitting a side fully blanks it with {@link REDACTED_VALUE}; providing
12
+ * one lets you report a partial mask instead (e.g. the last 4 digits of
13
+ * a card number) — both always return a `string`, the masked
14
+ * representation to report in place of the real value.
15
+ */
16
+ export type Mask<T, K extends Extract<keyof T, string>> = T[K] extends (...args: infer A) => infer R ? {
17
+ maskArgs?: (...args: A) => string;
18
+ maskResult?: (result: R) => string;
19
+ } : never;
20
+ /**
21
+ * Marks a service — or specific properties of it — as sensitive, so the
22
+ * values flowing through its events are redacted. Returned by
23
+ * {@link RedactionRuleBuilder.build}, which is the only way to construct
24
+ * one — the `redactAll`/per-property merge logic lives entirely inside
25
+ * `maskArgs`/`maskResult`, so callers never need to know how a rule
26
+ * reached its decision, only what to do with it.
27
+ */
28
+ export interface RedactionRule<T> {
29
+ readonly key: ServiceKey<T>;
30
+ /**
31
+ * The args to report for a call to `functionName`: unchanged if not
32
+ * redacted, otherwise blanked or run through a custom `maskArgs`.
33
+ */
34
+ maskArgs(functionName: string, args: readonly unknown[]): readonly unknown[];
35
+ /**
36
+ * The value to report for a success outcome: unchanged if not
37
+ * redacted, otherwise blanked or run through a custom `maskResult`.
38
+ * Omit `functionName` to ask about the initialize result (the service
39
+ * instance itself), which only the rule's `redactAll` default touches.
40
+ */
41
+ maskResult(functionName: string | undefined, result: unknown): unknown;
42
+ }
43
+ /**
44
+ * Fluent, single-key rule builder returned by {@link redactionRule}.
45
+ * `redactAll`, `redact`, and `exclude` all merge into the same rule —
46
+ * call them in any combination, in any order; the more specific
47
+ * per-property calls (`redact`/`exclude`) always win over the blanket
48
+ * `redactAll` default for the properties they name.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const rules = [
53
+ * redactionRule(SecretClientKey)
54
+ * .redactAll()
55
+ * .build(), // whole service is sensitive
56
+ * redactionRule(BillingKey)
57
+ * .redactAll()
58
+ * .redact('chargeCard', { maskResult: (card) => `card ending in ${card.number.slice(-4)}` })
59
+ * .exclude('ping') // redact everything except this, with one custom mask
60
+ * .build(),
61
+ * redactionRule(VaultKey)
62
+ * .redact('getSecret')
63
+ * .build(), // only this call, nothing else
64
+ * ];
65
+ * ```
66
+ */
67
+ export declare class RedactionRuleBuilder<T> {
68
+ private readonly key;
69
+ private redactAllFlag;
70
+ private hasRedact;
71
+ private readonly overrides;
72
+ constructor(key: ServiceKey<T>);
73
+ /** Redacts every property, plus the initialize result, by default. */
74
+ redactAll(): this;
75
+ /**
76
+ * Marks one property (method) as redacted, with optional custom
77
+ * masking. Call repeatedly for several properties. Overrides
78
+ * `redactAll`/`exclude` for this specific property.
79
+ */
80
+ redact<K extends Extract<keyof T, string>>(name: K, mask?: Mask<T, K>): this;
81
+ /**
82
+ * Marks one or more properties as explicitly NOT redacted, overriding
83
+ * `redactAll` for just these.
84
+ */
85
+ exclude(...names: Extract<keyof T, string>[]): this;
86
+ build(): RedactionRule<any>;
87
+ }
88
+ export declare function redactionRule<T>(key: ServiceKey<T>): RedactionRuleBuilder<T>;
89
+ /**
90
+ * A ServiceInstrumentation decorator that redacts sensitive values before
91
+ * they reach the wrapped instrumentation. Works with any implementation via
92
+ * delegation: arguments in MethodCallContext and success values in
93
+ * EventOutcome are replaced (wholesale, or via a custom transform)
94
+ * before the delegate ever sees them — whatever it captures or exports
95
+ * is already scrubbed.
96
+ *
97
+ * Failure outcomes are passed through unchanged so error reporting keeps
98
+ * working; keep secrets out of error messages at the throwing site.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const listener = new RedactingEventListener(
103
+ * new OTELEventListener({ captureArguments: true, captureResults: true }),
104
+ * [
105
+ * redactionRule(SecretClientKey).redactAll().build(), // whole service is sensitive
106
+ * redactionRule(VaultKey).redact('getSecret').build(), // only this call
107
+ * redactionRule(HealthKey).redactAll().exclude('ping').build(), // everything but this call
108
+ * ],
109
+ * );
110
+ * ```
111
+ */
112
+ export declare class RedactingEventListener implements ServiceInstrumentation {
113
+ private readonly delegate;
114
+ private readonly rules;
115
+ constructor(delegate: ServiceInstrumentation, rules: readonly RedactionRule<any>[]);
116
+ onInitialize(context: InitializeContext): EventSpan | void;
117
+ onDispose(context: DisposeContext): EventSpan | void;
118
+ onMethodCall(context: MethodCallContext): EventSpan | void;
119
+ }
120
+ //# sourceMappingURL=redactingEventListener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redactingEventListener.d.ts","sourceRoot":"","sources":["../src/redactingEventListener.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAEd,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,cAAc,eAAe,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CACrE,GAAG,IAAI,EAAE,MAAM,CAAC,KACb,MAAM,CAAC,GACR;IACE,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;CACpC,GACD,KAAK,CAAC;AAeV;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAE5B;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,OAAO,EAAE,CAAC;IAE7E;;;;;OAKG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;CACxE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,oBAAoB,CAAC,CAAC;IAKrB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJhC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;gBAErC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IAE/C,sEAAsE;IACtE,SAAS,IAAI,IAAI;IAMjB;;;;OAIG;IACH,MAAM,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;IAM5E;;;OAGG;IACH,OAAO,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,GAAG,IAAI;IAOnD,KAAK,IAAI,aAAa,CAAC,GAAG,CAAC;CA0C5B;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAE5E;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,sBAAuB,YAAW,sBAAsB;IAEjE,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,QAAQ,EAAE,sBAAsB,EAChC,KAAK,EAAE,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE;IAGvD,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IAK1D,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI;IAKpD,YAAY,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;CAY3D"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedactingEventListener = exports.RedactionRuleBuilder = exports.REDACTED_VALUE = void 0;
4
+ exports.redactionRule = redactionRule;
5
+ /**
6
+ * The placeholder that replaces a redacted value when no custom
7
+ * transform is given for it.
8
+ */
9
+ exports.REDACTED_VALUE = '[REDACTED]';
10
+ /**
11
+ * Fluent, single-key rule builder returned by {@link redactionRule}.
12
+ * `redactAll`, `redact`, and `exclude` all merge into the same rule —
13
+ * call them in any combination, in any order; the more specific
14
+ * per-property calls (`redact`/`exclude`) always win over the blanket
15
+ * `redactAll` default for the properties they name.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const rules = [
20
+ * redactionRule(SecretClientKey)
21
+ * .redactAll()
22
+ * .build(), // whole service is sensitive
23
+ * redactionRule(BillingKey)
24
+ * .redactAll()
25
+ * .redact('chargeCard', { maskResult: (card) => `card ending in ${card.number.slice(-4)}` })
26
+ * .exclude('ping') // redact everything except this, with one custom mask
27
+ * .build(),
28
+ * redactionRule(VaultKey)
29
+ * .redact('getSecret')
30
+ * .build(), // only this call, nothing else
31
+ * ];
32
+ * ```
33
+ */
34
+ class RedactionRuleBuilder {
35
+ constructor(key) {
36
+ this.key = key;
37
+ this.redactAllFlag = false;
38
+ this.hasRedact = false;
39
+ this.overrides = {};
40
+ }
41
+ /** Redacts every property, plus the initialize result, by default. */
42
+ redactAll() {
43
+ this.redactAllFlag = true;
44
+ this.hasRedact = true;
45
+ return this;
46
+ }
47
+ /**
48
+ * Marks one property (method) as redacted, with optional custom
49
+ * masking. Call repeatedly for several properties. Overrides
50
+ * `redactAll`/`exclude` for this specific property.
51
+ */
52
+ redact(name, mask) {
53
+ this.overrides[name] = Object.assign({ redacted: true }, mask);
54
+ this.hasRedact = true;
55
+ return this;
56
+ }
57
+ /**
58
+ * Marks one or more properties as explicitly NOT redacted, overriding
59
+ * `redactAll` for just these.
60
+ */
61
+ exclude(...names) {
62
+ for (const name of names) {
63
+ this.overrides[name] = { redacted: false };
64
+ }
65
+ return this;
66
+ }
67
+ build() {
68
+ // `exclude` alone never redacts anything — at least one call to
69
+ // `redactAll`/`redact` is required for this rule to have any effect.
70
+ if (!this.hasRedact) {
71
+ throw new Error(`redactionRule(${this.key.name}) has no effect: call .redactAll() and/or .redact(...) ` +
72
+ 'before .build() — .exclude() alone never redacts anything.');
73
+ }
74
+ const redactAllFlag = this.redactAllFlag;
75
+ const overrides = this.overrides;
76
+ return {
77
+ key: this.key,
78
+ maskArgs(functionName, args) {
79
+ const override = overrides[functionName];
80
+ const redacted = override ? override.redacted : redactAllFlag;
81
+ if (!redacted) {
82
+ return args;
83
+ }
84
+ return (override === null || override === void 0 ? void 0 : override.maskArgs)
85
+ ? // A custom mask reports one string for the whole call,
86
+ // rather than a value per argument.
87
+ [override.maskArgs(...args)]
88
+ : // Replace each argument rather than the whole array, so the
89
+ // delegate still sees the call's arity.
90
+ args.map(() => exports.REDACTED_VALUE);
91
+ },
92
+ maskResult(functionName, result) {
93
+ const override = functionName === undefined ? undefined : overrides[functionName];
94
+ const redacted = override ? override.redacted : redactAllFlag;
95
+ if (!redacted) {
96
+ return result;
97
+ }
98
+ return (override === null || override === void 0 ? void 0 : override.maskResult)
99
+ ? override.maskResult(result)
100
+ : exports.REDACTED_VALUE;
101
+ },
102
+ };
103
+ }
104
+ }
105
+ exports.RedactionRuleBuilder = RedactionRuleBuilder;
106
+ function redactionRule(key) {
107
+ return new RedactionRuleBuilder(key);
108
+ }
109
+ /**
110
+ * A ServiceInstrumentation decorator that redacts sensitive values before
111
+ * they reach the wrapped instrumentation. Works with any implementation via
112
+ * delegation: arguments in MethodCallContext and success values in
113
+ * EventOutcome are replaced (wholesale, or via a custom transform)
114
+ * before the delegate ever sees them — whatever it captures or exports
115
+ * is already scrubbed.
116
+ *
117
+ * Failure outcomes are passed through unchanged so error reporting keeps
118
+ * working; keep secrets out of error messages at the throwing site.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * const listener = new RedactingEventListener(
123
+ * new OTELEventListener({ captureArguments: true, captureResults: true }),
124
+ * [
125
+ * redactionRule(SecretClientKey).redactAll().build(), // whole service is sensitive
126
+ * redactionRule(VaultKey).redact('getSecret').build(), // only this call
127
+ * redactionRule(HealthKey).redactAll().exclude('ping').build(), // everything but this call
128
+ * ],
129
+ * );
130
+ * ```
131
+ */
132
+ class RedactingEventListener {
133
+ constructor(delegate, rules) {
134
+ this.delegate = delegate;
135
+ this.rules = rules;
136
+ }
137
+ onInitialize(context) {
138
+ var _a, _b;
139
+ const rule = this.rules.find((r) => r.key === context.key);
140
+ return redactSpan((_b = (_a = this.delegate).onInitialize) === null || _b === void 0 ? void 0 : _b.call(_a, context), rule);
141
+ }
142
+ onDispose(context) {
143
+ var _a, _b;
144
+ // Dispose carries no arguments and no result value; nothing to redact.
145
+ return (_b = (_a = this.delegate).onDispose) === null || _b === void 0 ? void 0 : _b.call(_a, context);
146
+ }
147
+ onMethodCall(context) {
148
+ var _a, _b;
149
+ const rule = this.rules.find((r) => r.key === context.key);
150
+ const span = (_b = (_a = this.delegate).onMethodCall) === null || _b === void 0 ? void 0 : _b.call(_a, rule
151
+ ? Object.assign(Object.assign({}, context), { args: rule.maskArgs(context.functionName, context.args) }) : context);
152
+ return redactSpan(span, rule, context.functionName);
153
+ }
154
+ }
155
+ exports.RedactingEventListener = RedactingEventListener;
156
+ /**
157
+ * Wraps the delegate's EventSpan so success values are redacted before
158
+ * `end` sees them, by delegating to the rule's `maskResult`. `run` (and
159
+ * any future fields) pass through untouched. `functionName` is omitted
160
+ * for the initialize result (the instance itself).
161
+ */
162
+ function redactSpan(span, rule, functionName) {
163
+ if (!rule || !span) {
164
+ return span;
165
+ }
166
+ const end = span.end.bind(span);
167
+ return Object.assign(Object.assign({}, span), { end: (outcome) => end(outcome.type === 'success'
168
+ ? {
169
+ type: 'success',
170
+ value: rule.maskResult(functionName, outcome.value),
171
+ }
172
+ : outcome) });
173
+ }
174
+ //# sourceMappingURL=redactingEventListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redactingEventListener.js","sourceRoot":"","sources":["../src/redactingEventListener.ts"],"names":[],"mappings":"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"}