autotel 6.3.0 → 6.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/auto.cjs +1 -1
  2. package/dist/auto.js +1 -1
  3. package/dist/{canonical-log-line-processor-mKABvGP0.js → canonical-log-line-processor-B0vq_QR6.js} +3 -1
  4. package/dist/{canonical-log-line-processor-DOjb6Kxy.cjs → canonical-log-line-processor-DxtBGZIi.cjs} +3 -1
  5. package/dist/correlation-id.cjs +1 -1
  6. package/dist/correlation-id.js +1 -1
  7. package/dist/decorators.cjs +1 -1
  8. package/dist/decorators.d.cts +1 -1
  9. package/dist/decorators.d.ts +1 -1
  10. package/dist/decorators.js +1 -1
  11. package/dist/event.cjs +1 -1
  12. package/dist/event.js +1 -1
  13. package/dist/{functional-DCBhFool.js → functional-0o9xSedq.js} +221 -283
  14. package/dist/functional-AT22vCw6.d.ts +389 -0
  15. package/dist/functional-e6jw5zQj.d.cts +389 -0
  16. package/dist/{functional-TbnG2lu7.cjs → functional-qZxRcIBp.cjs} +221 -283
  17. package/dist/functional.cjs +1 -1
  18. package/dist/functional.d.cts +2 -432
  19. package/dist/functional.d.ts +2 -432
  20. package/dist/functional.js +1 -1
  21. package/dist/http.cjs +1 -1
  22. package/dist/http.js +1 -1
  23. package/dist/index.cjs +3 -3
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +3 -3
  27. package/dist/{init-BneZ7WJ8.cjs → init-BnxHAi2M.cjs} +19 -10
  28. package/dist/{init-Qn4gIW1i.js → init-BxfZ3Vbw.js} +19 -10
  29. package/dist/{init-CfVWN4ND.d.cts → init-Cc7-vvzj.d.cts} +18 -0
  30. package/dist/{init-C1i2_2zl.d.ts → init-CsODvlau.d.ts} +18 -0
  31. package/dist/instrumentation.cjs +1 -1
  32. package/dist/instrumentation.js +1 -1
  33. package/dist/messaging.cjs +1 -1
  34. package/dist/messaging.js +1 -1
  35. package/dist/policy-CbpP4tFH.d.cts +147 -0
  36. package/dist/policy-CbpP4tFH.d.ts +147 -0
  37. package/dist/policy.cjs +0 -0
  38. package/dist/policy.d.cts +2 -0
  39. package/dist/policy.d.ts +2 -0
  40. package/dist/policy.js +0 -0
  41. package/dist/processors.cjs +1 -1
  42. package/dist/processors.js +1 -1
  43. package/dist/semantic-helpers.cjs +1 -1
  44. package/dist/semantic-helpers.js +1 -1
  45. package/dist/webhook.cjs +1 -1
  46. package/dist/webhook.js +1 -1
  47. package/dist/workflow-distributed.cjs +1 -1
  48. package/dist/workflow-distributed.js +1 -1
  49. package/dist/workflow.cjs +1 -1
  50. package/dist/workflow.js +1 -1
  51. package/dist/yaml-config.cjs +1 -0
  52. package/dist/yaml-config.d.cts +3 -1
  53. package/dist/yaml-config.d.ts +3 -1
  54. package/dist/yaml-config.js +1 -0
  55. package/package.json +6 -1
@@ -4,11 +4,12 @@ import { AUTOTEL_SAMPLING_RATE, resolveSamplingPreset, samplingPresets } from ".
4
4
  import { n as safeRequire, t as requireModule } from "./node-require-vROmTeJ8.js";
5
5
  import { TailSamplingSpanProcessor } from "./tail-sampling-processor.js";
6
6
  import { FilteringSpanProcessor } from "./filtering-span-processor.js";
7
+ import { PolicyLogRecordProcessor, policySpanFilter, setPolicies, watchPolicyFile } from "./policy.js";
7
8
  import { SpanNameNormalizingProcessor } from "./span-name-normalizer.js";
8
9
  import { AttributeRedactingProcessor, REDACTOR_PRESETS, normalizeAttributeRedactorConfig } from "./attribute-redacting-processor.js";
9
10
  import { t as PrettyConsoleExporter } from "./pretty-console-exporter-DqKl_q9z.js";
10
11
  import { loadYamlConfig } from "./yaml-config.js";
11
- import { t as CanonicalLogLineProcessor } from "./canonical-log-line-processor-mKABvGP0.js";
12
+ import { t as CanonicalLogLineProcessor } from "./canonical-log-line-processor-B0vq_QR6.js";
12
13
  import { r as recordStructuredError } from "./structured-error-9--cxBay.js";
13
14
  import { resetMetrics } from "./metric.js";
14
15
  import { NodeSDK } from "@opentelemetry/sdk-node";
@@ -544,11 +545,15 @@ function getContextStorage() {
544
545
  return contextStorage;
545
546
  }
546
547
  /**
547
- * Get the active context, checking our stored context first
548
- * This ensures baggage setters work with OpenTelemetry's propagation
548
+ * Get the active OTel context with the latest stored baggage overlaid.
549
+ * Span identity always comes from the active OTel scope.
549
550
  */
550
551
  function getActiveContextWithBaggage() {
551
- return contextStorage.getStore()?.value ?? context.active();
552
+ const activeContext = context.active();
553
+ const stored = contextStorage.getStore()?.value;
554
+ if (!stored) return activeContext;
555
+ const storedBaggage = propagation.getBaggage(stored);
556
+ return storedBaggage ? propagation.setBaggage(activeContext, storedBaggage) : activeContext;
552
557
  }
553
558
  /**
554
559
  * Set a value in AsyncLocalStorage, preferring enterWith() when available
@@ -628,15 +633,13 @@ function createTraceContext(span) {
628
633
  return baggage?.getEntry(key)?.value;
629
634
  },
630
635
  setBaggage(key, value) {
631
- const activeCtx = context.active();
632
- const currentContext = contextStorage.getStore()?.value ?? activeCtx;
636
+ const currentContext = getActiveContextWithBaggage();
633
637
  const updated = (propagation.getBaggage(currentContext) ?? propagation.createBaggage()).setEntry(key, { value });
634
638
  updateActiveContext(propagation.setBaggage(currentContext, updated));
635
639
  return value;
636
640
  },
637
641
  deleteBaggage(key) {
638
- const activeCtx = context.active();
639
- const currentContext = contextStorage.getStore()?.value ?? activeCtx;
642
+ const currentContext = getActiveContextWithBaggage();
640
643
  const baggage = propagation.getBaggage(currentContext);
641
644
  if (baggage) {
642
645
  const updated = baggage.removeEntry(key);
@@ -672,8 +675,7 @@ function createTraceContext(span) {
672
675
  return Object.keys(result).length > 0 ? result : void 0;
673
676
  }),
674
677
  setTypedBaggage: ((namespace, value) => {
675
- const activeCtx = context.active();
676
- const currentContext = contextStorage.getStore()?.value ?? activeCtx;
678
+ const currentContext = getActiveContextWithBaggage();
677
679
  let baggage = propagation.getBaggage(currentContext) ?? propagation.createBaggage();
678
680
  const prefix = namespace ? `${namespace}.` : "";
679
681
  for (const [key, val] of Object.entries(value)) if (val !== void 0) {
@@ -3177,6 +3179,12 @@ function init(cfg) {
3177
3179
  for (const subscriber of mergedConfig.subscribers) if (acceptsStringRedactor(subscriber)) subscriber.setStringRedactor(_stringRedactor);
3178
3180
  }
3179
3181
  if (mergedConfig.spanNameNormalizer && spanProcessors.length > 0) spanProcessors = spanProcessors.map((processor) => new SpanNameNormalizingProcessor(processor, { normalizer: mergedConfig.spanNameNormalizer }));
3182
+ if (mergedConfig.policies) {
3183
+ if (typeof mergedConfig.policies === "string") watchPolicyFile(mergedConfig.policies);
3184
+ else setPolicies(mergedConfig.policies);
3185
+ const userSpanFilter = mergedConfig.spanFilter;
3186
+ mergedConfig.spanFilter = userSpanFilter ? (span) => userSpanFilter(span) && policySpanFilter(span) : policySpanFilter;
3187
+ }
3180
3188
  if (mergedConfig.spanFilter && spanProcessors.length > 0) spanProcessors = spanProcessors.map((processor) => new FilteringSpanProcessor(processor, { filter: mergedConfig.spanFilter }));
3181
3189
  const metricReaders = [];
3182
3190
  if (configuredMetricReaders && configuredMetricReaders.length > 0) metricReaders.push(...configuredMetricReaders);
@@ -3215,6 +3223,7 @@ function init(cfg) {
3215
3223
  logRecordProcessors.push(...posthogProcessors);
3216
3224
  logger.info({}, "[autotel] PostHog OTLP logs configured");
3217
3225
  }
3226
+ if (mergedConfig.policies && logRecordProcessors) logRecordProcessors = logRecordProcessors.map((processor) => new PolicyLogRecordProcessor(processor));
3218
3227
  let finalInstrumentations = mergedConfig.instrumentations ? [...mergedConfig.instrumentations] : [];
3219
3228
  if (mergedConfig.autoInstrumentations !== void 0 && mergedConfig.autoInstrumentations !== false) {
3220
3229
  if (isESMMode()) logger.info({}, "[autotel] ESM mode detected. For auto-instrumentation to work:\n 1. Install @opentelemetry/auto-instrumentations-node as a direct dependency\n 2. Import autotel/register FIRST in your instrumentation file\n 3. Use getNodeAutoInstrumentations() directly instead of autoInstrumentations\n See: https://github.com/jagreehal/autotel#esm-setup");
@@ -3,6 +3,7 @@ import { s as Logger } from "./logger-CN4xpzMd.cjs";
3
3
  import { h as SamplingPreset, p as Sampler } from "./sampling-BR9fkSwx.cjs";
4
4
  import { a as EventSubscriber } from "./event-subscriber-CWh8sTGh.cjs";
5
5
  import { r as SpanFilterPredicate } from "./filtering-span-processor-BpDagWNa.cjs";
6
+ import { r as Policy } from "./policy-CbpP4tFH.cjs";
6
7
  import { r as SpanNameNormalizerConfig } from "./span-name-normalizer-CN1-8C76.cjs";
7
8
  import { t as CanonicalLogLineOptions } from "./canonical-log-line-processor-B4WgG-VS.cjs";
8
9
  import { SpanExporter, SpanProcessor } from "@opentelemetry/sdk-trace-base";
@@ -959,6 +960,23 @@ interface AutotelConfig {
959
960
  * ```
960
961
  */
961
962
  spanFilter?: SpanFilterPredicate;
963
+ /**
964
+ * Telemetry Policies (experimental) — OTEP 4738.
965
+ *
966
+ * Portable, fail-open rules deciding what telemetry is kept and how it is
967
+ * transformed. Pass a path to a `.json` file or a directory of them (reloaded
968
+ * on change), or an inline array.
969
+ *
970
+ * Composes with `spanFilter`: a span must pass both.
971
+ *
972
+ * @example
973
+ * ```typescript
974
+ * init({ service: 'api', policies: './policies' })
975
+ * ```
976
+ *
977
+ * @see `autotel/policy` for the supported subset of policy stages.
978
+ */
979
+ policies?: string | Policy[];
962
980
  /**
963
981
  * Normalize span names to reduce cardinality from dynamic path segments.
964
982
  *
@@ -3,6 +3,7 @@ import { s as Logger } from "./logger-CN4xpzMd.js";
3
3
  import { h as SamplingPreset, p as Sampler } from "./sampling-CP3e7-Yr.js";
4
4
  import { a as EventSubscriber } from "./event-subscriber-CWh8sTGh.js";
5
5
  import { r as SpanFilterPredicate } from "./filtering-span-processor-BpDagWNa.js";
6
+ import { r as Policy } from "./policy-CbpP4tFH.js";
6
7
  import { r as SpanNameNormalizerConfig } from "./span-name-normalizer-CN1-8C76.js";
7
8
  import { t as CanonicalLogLineOptions } from "./canonical-log-line-processor-CL_J7gb5.js";
8
9
  import { NodeSDK, NodeSDKConfiguration } from "@opentelemetry/sdk-node";
@@ -959,6 +960,23 @@ interface AutotelConfig {
959
960
  * ```
960
961
  */
961
962
  spanFilter?: SpanFilterPredicate;
963
+ /**
964
+ * Telemetry Policies (experimental) — OTEP 4738.
965
+ *
966
+ * Portable, fail-open rules deciding what telemetry is kept and how it is
967
+ * transformed. Pass a path to a `.json` file or a directory of them (reloaded
968
+ * on change), or an inline array.
969
+ *
970
+ * Composes with `spanFilter`: a span must pass both.
971
+ *
972
+ * @example
973
+ * ```typescript
974
+ * init({ service: 'api', policies: './policies' })
975
+ * ```
976
+ *
977
+ * @see `autotel/policy` for the supported subset of policy stages.
978
+ */
979
+ policies?: string | Policy[];
962
980
  /**
963
981
  * Normalize span names to reduce cardinality from dynamic path segments.
964
982
  *
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_node_require = require('./node-require-PFqDihze.cjs');
3
- const require_init = require('./init-BneZ7WJ8.cjs');
3
+ const require_init = require('./init-BnxHAi2M.cjs');
4
4
  const require_tail_sampling_processor = require('./tail-sampling-processor.cjs');
5
5
  let _opentelemetry_sdk_node = require("@opentelemetry/sdk-node");
6
6
  let _opentelemetry_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
@@ -1,5 +1,5 @@
1
1
  import { n as safeRequire, t as requireModule } from "./node-require-vROmTeJ8.js";
2
- import { n as getLogger } from "./init-Qn4gIW1i.js";
2
+ import { n as getLogger } from "./init-BxfZ3Vbw.js";
3
3
  import { TailSamplingSpanProcessor } from "./tail-sampling-processor.js";
4
4
  import { NodeSDK } from "@opentelemetry/sdk-node";
5
5
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_sampling = require('./sampling.cjs');
3
- const require_functional = require('./functional-TbnG2lu7.cjs');
3
+ const require_functional = require('./functional-qZxRcIBp.cjs');
4
4
  const require_correlated_events = require('./correlated-events-kSwLo3mi.cjs');
5
5
  const require_trace_factory_validation = require('./trace-factory-validation-Dc8epn87.cjs');
6
6
  let _opentelemetry_api = require("@opentelemetry/api");
package/dist/messaging.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createLinkFromHeaders, extractLinksFromBatch } from "./sampling.js";
2
- import { c as withTracing } from "./functional-DCBhFool.js";
2
+ import { c as withTracing } from "./functional-0o9xSedq.js";
3
3
  import { t as emitCorrelatedEvent } from "./correlated-events-Bzh5y-UB.js";
4
4
  import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
5
5
  import { SpanKind, context, propagation } from "@opentelemetry/api";
@@ -0,0 +1,147 @@
1
+ import { ReadableSpan } from "@opentelemetry/sdk-trace-base";
2
+ import { Context } from "@opentelemetry/api";
3
+ import { LogRecordProcessor, SdkLogRecord } from "@opentelemetry/sdk-logs";
4
+ //#region src/policy.d.ts
5
+ /** A path into an attribute. `"ccn"` and `["ccn"]` are equivalent. */
6
+ type AttributePath = string | string[];
7
+ /**
8
+ * A single ANDed matcher. Exactly one field selector and exactly one match
9
+ * operator must be set. Regexes are RE2 in the spec but JS `RegExp` here —
10
+ * see {@link MAX_MATCH_LENGTH}.
11
+ */
12
+ interface PolicyMatcher {
13
+ log_field?: string;
14
+ trace_field?: string;
15
+ span_attribute?: AttributePath;
16
+ log_attribute?: AttributePath;
17
+ resource_attribute?: AttributePath;
18
+ scope_attribute?: AttributePath;
19
+ span_kind?: string;
20
+ span_status?: string;
21
+ exact?: string;
22
+ regex?: string;
23
+ exists?: boolean;
24
+ starts_with?: string;
25
+ ends_with?: string;
26
+ contains?: string;
27
+ negate?: boolean;
28
+ case_insensitive?: boolean;
29
+ }
30
+ /** A field targeted by a transform operation. */
31
+ interface PolicyField {
32
+ log_field?: string;
33
+ log_attribute?: AttributePath;
34
+ resource_attribute?: AttributePath;
35
+ scope_attribute?: AttributePath;
36
+ }
37
+ interface PolicyLogTransform {
38
+ remove?: PolicyField[];
39
+ redact?: Array<PolicyField & {
40
+ replacement?: string;
41
+ }>;
42
+ rename?: Array<PolicyField & {
43
+ to: string;
44
+ upsert?: boolean;
45
+ }>;
46
+ add?: Array<PolicyField & {
47
+ value: string;
48
+ upsert?: boolean;
49
+ }>;
50
+ }
51
+ interface PolicyLogTarget {
52
+ match: PolicyMatcher[];
53
+ /** `"all"` (default), `"none"`, or a percentage (`"5.0"` or `5`). */
54
+ keep?: string | number;
55
+ transform?: PolicyLogTransform;
56
+ }
57
+ interface PolicyTraceTarget {
58
+ match: PolicyMatcher[];
59
+ keep?: {
60
+ /** 0-100. Omitted means keep all matching spans. */
61
+ percentage?: number;
62
+ mode?: string;
63
+ sampling_precision?: number;
64
+ hash_seed?: number;
65
+ fail_closed?: boolean;
66
+ };
67
+ }
68
+ /** A telemetry policy. Exactly one target must be set. */
69
+ interface Policy {
70
+ id: string;
71
+ name?: string;
72
+ description?: string;
73
+ enabled?: boolean;
74
+ labels?: Record<string, string>;
75
+ trace?: PolicyTraceTarget;
76
+ log?: PolicyLogTarget;
77
+ /** Recognised so it can be reported unsupported rather than silently ignored. */
78
+ metric?: unknown;
79
+ }
80
+ /**
81
+ * Values longer than this are not regex-matched (the matcher yields no match).
82
+ *
83
+ * The spec mandates RE2 for cross-implementation consistency; Node's `RegExp`
84
+ * backtracks, so an untrusted log body plus a pathological pattern is a DoS.
85
+ * Capping input bounds the damage without pulling in an RE2 binding.
86
+ *
87
+ * ponytail: length cap instead of a real RE2 engine — swap in a linear-time
88
+ * matcher if policies ever run against fully untrusted patterns.
89
+ */
90
+ declare const MAX_MATCH_LENGTH = 4096;
91
+ /**
92
+ * Returns a reason string if the policy cannot be applied, or undefined if it can.
93
+ *
94
+ * Per spec an implementation MAY support a subset of stages but MUST skip the
95
+ * policy — never the telemetry — when it meets one it does not understand.
96
+ */
97
+ declare function unsupportedReason(policy: Policy): string | undefined;
98
+ /**
99
+ * Replace the active policy set.
100
+ *
101
+ * Disabled policies are dropped (spec: they MUST be treated as if they do not
102
+ * exist) and unsupported ones are skipped with a warning.
103
+ */
104
+ declare function setPolicies(policies: Policy[]): void;
105
+ /** The currently active (validated, enabled) policies. */
106
+ declare function getPolicies(): readonly Policy[];
107
+ declare function clearPolicies(): void;
108
+ /**
109
+ * A `SpanFilterPredicate` backed by the active policies. Returns true to keep.
110
+ *
111
+ * Fail-open: any error keeps the span.
112
+ */
113
+ declare function policySpanFilter(span: ReadableSpan): boolean;
114
+ /**
115
+ * Applies `log` policies — keep first, then transform (spec stage order).
116
+ *
117
+ * Fail-open: any error emits the record unmodified.
118
+ */
119
+ declare class PolicyLogRecordProcessor implements LogRecordProcessor {
120
+ private readonly wrapped;
121
+ constructor(wrapped: LogRecordProcessor);
122
+ onEmit(logRecord: SdkLogRecord, context?: Context): void;
123
+ shutdown(): Promise<void>;
124
+ forceFlush(): Promise<void>;
125
+ }
126
+ /** True when any active policy targets logs — used to skip wrapping otherwise. */
127
+ declare function hasLogPolicies(): boolean;
128
+ /**
129
+ * Load every policy from a `.json` file, or from every `.json` file in a
130
+ * directory.
131
+ *
132
+ * Fail-open: an unreadable or malformed file yields no policies from that file
133
+ * and warns; it never throws.
134
+ */
135
+ declare function loadPolicies(target: string): Policy[];
136
+ /**
137
+ * The file policy provider: load `target` now and reload on change.
138
+ *
139
+ * Policies are expected to change outside the lifecycle of the process, so the
140
+ * watcher is what makes them dynamic. The watcher is unref'd — it never holds
141
+ * the process open.
142
+ *
143
+ * @returns a function that stops watching
144
+ */
145
+ declare function watchPolicyFile(target: string): () => void;
146
+ //#endregion
147
+ export { watchPolicyFile as _, PolicyLogRecordProcessor as a, PolicyMatcher as c, getPolicies as d, hasLogPolicies as f, unsupportedReason as g, setPolicies as h, PolicyField as i, PolicyTraceTarget as l, policySpanFilter as m, MAX_MATCH_LENGTH as n, PolicyLogTarget as o, loadPolicies as p, Policy as r, PolicyLogTransform as s, AttributePath as t, clearPolicies as u };
@@ -0,0 +1,147 @@
1
+ import { ReadableSpan } from "@opentelemetry/sdk-trace-base";
2
+ import { Context } from "@opentelemetry/api";
3
+ import { LogRecordProcessor, SdkLogRecord } from "@opentelemetry/sdk-logs";
4
+ //#region src/policy.d.ts
5
+ /** A path into an attribute. `"ccn"` and `["ccn"]` are equivalent. */
6
+ type AttributePath = string | string[];
7
+ /**
8
+ * A single ANDed matcher. Exactly one field selector and exactly one match
9
+ * operator must be set. Regexes are RE2 in the spec but JS `RegExp` here —
10
+ * see {@link MAX_MATCH_LENGTH}.
11
+ */
12
+ interface PolicyMatcher {
13
+ log_field?: string;
14
+ trace_field?: string;
15
+ span_attribute?: AttributePath;
16
+ log_attribute?: AttributePath;
17
+ resource_attribute?: AttributePath;
18
+ scope_attribute?: AttributePath;
19
+ span_kind?: string;
20
+ span_status?: string;
21
+ exact?: string;
22
+ regex?: string;
23
+ exists?: boolean;
24
+ starts_with?: string;
25
+ ends_with?: string;
26
+ contains?: string;
27
+ negate?: boolean;
28
+ case_insensitive?: boolean;
29
+ }
30
+ /** A field targeted by a transform operation. */
31
+ interface PolicyField {
32
+ log_field?: string;
33
+ log_attribute?: AttributePath;
34
+ resource_attribute?: AttributePath;
35
+ scope_attribute?: AttributePath;
36
+ }
37
+ interface PolicyLogTransform {
38
+ remove?: PolicyField[];
39
+ redact?: Array<PolicyField & {
40
+ replacement?: string;
41
+ }>;
42
+ rename?: Array<PolicyField & {
43
+ to: string;
44
+ upsert?: boolean;
45
+ }>;
46
+ add?: Array<PolicyField & {
47
+ value: string;
48
+ upsert?: boolean;
49
+ }>;
50
+ }
51
+ interface PolicyLogTarget {
52
+ match: PolicyMatcher[];
53
+ /** `"all"` (default), `"none"`, or a percentage (`"5.0"` or `5`). */
54
+ keep?: string | number;
55
+ transform?: PolicyLogTransform;
56
+ }
57
+ interface PolicyTraceTarget {
58
+ match: PolicyMatcher[];
59
+ keep?: {
60
+ /** 0-100. Omitted means keep all matching spans. */
61
+ percentage?: number;
62
+ mode?: string;
63
+ sampling_precision?: number;
64
+ hash_seed?: number;
65
+ fail_closed?: boolean;
66
+ };
67
+ }
68
+ /** A telemetry policy. Exactly one target must be set. */
69
+ interface Policy {
70
+ id: string;
71
+ name?: string;
72
+ description?: string;
73
+ enabled?: boolean;
74
+ labels?: Record<string, string>;
75
+ trace?: PolicyTraceTarget;
76
+ log?: PolicyLogTarget;
77
+ /** Recognised so it can be reported unsupported rather than silently ignored. */
78
+ metric?: unknown;
79
+ }
80
+ /**
81
+ * Values longer than this are not regex-matched (the matcher yields no match).
82
+ *
83
+ * The spec mandates RE2 for cross-implementation consistency; Node's `RegExp`
84
+ * backtracks, so an untrusted log body plus a pathological pattern is a DoS.
85
+ * Capping input bounds the damage without pulling in an RE2 binding.
86
+ *
87
+ * ponytail: length cap instead of a real RE2 engine — swap in a linear-time
88
+ * matcher if policies ever run against fully untrusted patterns.
89
+ */
90
+ declare const MAX_MATCH_LENGTH = 4096;
91
+ /**
92
+ * Returns a reason string if the policy cannot be applied, or undefined if it can.
93
+ *
94
+ * Per spec an implementation MAY support a subset of stages but MUST skip the
95
+ * policy — never the telemetry — when it meets one it does not understand.
96
+ */
97
+ declare function unsupportedReason(policy: Policy): string | undefined;
98
+ /**
99
+ * Replace the active policy set.
100
+ *
101
+ * Disabled policies are dropped (spec: they MUST be treated as if they do not
102
+ * exist) and unsupported ones are skipped with a warning.
103
+ */
104
+ declare function setPolicies(policies: Policy[]): void;
105
+ /** The currently active (validated, enabled) policies. */
106
+ declare function getPolicies(): readonly Policy[];
107
+ declare function clearPolicies(): void;
108
+ /**
109
+ * A `SpanFilterPredicate` backed by the active policies. Returns true to keep.
110
+ *
111
+ * Fail-open: any error keeps the span.
112
+ */
113
+ declare function policySpanFilter(span: ReadableSpan): boolean;
114
+ /**
115
+ * Applies `log` policies — keep first, then transform (spec stage order).
116
+ *
117
+ * Fail-open: any error emits the record unmodified.
118
+ */
119
+ declare class PolicyLogRecordProcessor implements LogRecordProcessor {
120
+ private readonly wrapped;
121
+ constructor(wrapped: LogRecordProcessor);
122
+ onEmit(logRecord: SdkLogRecord, context?: Context): void;
123
+ shutdown(): Promise<void>;
124
+ forceFlush(): Promise<void>;
125
+ }
126
+ /** True when any active policy targets logs — used to skip wrapping otherwise. */
127
+ declare function hasLogPolicies(): boolean;
128
+ /**
129
+ * Load every policy from a `.json` file, or from every `.json` file in a
130
+ * directory.
131
+ *
132
+ * Fail-open: an unreadable or malformed file yields no policies from that file
133
+ * and warns; it never throws.
134
+ */
135
+ declare function loadPolicies(target: string): Policy[];
136
+ /**
137
+ * The file policy provider: load `target` now and reload on change.
138
+ *
139
+ * Policies are expected to change outside the lifecycle of the process, so the
140
+ * watcher is what makes them dynamic. The watcher is unref'd — it never holds
141
+ * the process open.
142
+ *
143
+ * @returns a function that stops watching
144
+ */
145
+ declare function watchPolicyFile(target: string): () => void;
146
+ //#endregion
147
+ export { watchPolicyFile as _, PolicyLogRecordProcessor as a, PolicyMatcher as c, getPolicies as d, hasLogPolicies as f, unsupportedReason as g, setPolicies as h, PolicyField as i, PolicyTraceTarget as l, policySpanFilter as m, MAX_MATCH_LENGTH as n, PolicyLogTarget as o, loadPolicies as p, Policy as r, PolicyLogTransform as s, AttributePath as t, clearPolicies as u };
Binary file
@@ -0,0 +1,2 @@
1
+ import { _ as watchPolicyFile, a as PolicyLogRecordProcessor, c as PolicyMatcher, d as getPolicies, f as hasLogPolicies, g as unsupportedReason, h as setPolicies, i as PolicyField, l as PolicyTraceTarget, m as policySpanFilter, n as MAX_MATCH_LENGTH, o as PolicyLogTarget, p as loadPolicies, r as Policy, s as PolicyLogTransform, t as AttributePath, u as clearPolicies } from "./policy-CbpP4tFH.cjs";
2
+ export { AttributePath, MAX_MATCH_LENGTH, Policy, PolicyField, PolicyLogRecordProcessor, PolicyLogTarget, PolicyLogTransform, PolicyMatcher, PolicyTraceTarget, clearPolicies, getPolicies, hasLogPolicies, loadPolicies, policySpanFilter, setPolicies, unsupportedReason, watchPolicyFile };
@@ -0,0 +1,2 @@
1
+ import { _ as watchPolicyFile, a as PolicyLogRecordProcessor, c as PolicyMatcher, d as getPolicies, f as hasLogPolicies, g as unsupportedReason, h as setPolicies, i as PolicyField, l as PolicyTraceTarget, m as policySpanFilter, n as MAX_MATCH_LENGTH, o as PolicyLogTarget, p as loadPolicies, r as Policy, s as PolicyLogTransform, t as AttributePath, u as clearPolicies } from "./policy-CbpP4tFH.js";
2
+ export { AttributePath, MAX_MATCH_LENGTH, Policy, PolicyField, PolicyLogRecordProcessor, PolicyLogTarget, PolicyLogTransform, PolicyMatcher, PolicyTraceTarget, clearPolicies, getPolicies, hasLogPolicies, loadPolicies, policySpanFilter, setPolicies, unsupportedReason, watchPolicyFile };
package/dist/policy.js ADDED
Binary file
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_canonical_log_line_processor = require('./canonical-log-line-processor-DOjb6Kxy.cjs');
2
+ const require_canonical_log_line_processor = require('./canonical-log-line-processor-DxtBGZIi.cjs');
3
3
  let _opentelemetry_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
4
4
 
5
5
  Object.defineProperty(exports, 'BatchSpanProcessor', {
@@ -1,4 +1,4 @@
1
- import { t as CanonicalLogLineProcessor } from "./canonical-log-line-processor-mKABvGP0.js";
1
+ import { t as CanonicalLogLineProcessor } from "./canonical-log-line-processor-B0vq_QR6.js";
2
2
  import { BatchSpanProcessor, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
3
3
 
4
4
  export { BatchSpanProcessor, CanonicalLogLineProcessor, SimpleSpanProcessor };
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_functional = require('./functional-TbnG2lu7.cjs');
2
+ const require_functional = require('./functional-qZxRcIBp.cjs');
3
3
  const require_trace_factory_validation = require('./trace-factory-validation-Dc8epn87.cjs');
4
4
  let _opentelemetry_api = require("@opentelemetry/api");
5
5
 
@@ -1,4 +1,4 @@
1
- import { c as withTracing } from "./functional-DCBhFool.js";
1
+ import { c as withTracing } from "./functional-0o9xSedq.js";
2
2
  import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
3
3
  import { SpanKind } from "@opentelemetry/api";
4
4
 
package/dist/webhook.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_structured_error = require('./structured-error-CHg7DoIQ.cjs');
3
- const require_functional = require('./functional-TbnG2lu7.cjs');
3
+ const require_functional = require('./functional-qZxRcIBp.cjs');
4
4
  const require_correlated_events = require('./correlated-events-kSwLo3mi.cjs');
5
5
  let _opentelemetry_api = require("@opentelemetry/api");
6
6
 
package/dist/webhook.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { r as recordStructuredError } from "./structured-error-9--cxBay.js";
2
- import { c as withTracing } from "./functional-DCBhFool.js";
2
+ import { c as withTracing } from "./functional-0o9xSedq.js";
3
3
  import { t as emitCorrelatedEvent } from "./correlated-events-Bzh5y-UB.js";
4
4
  import { SpanKind, trace } from "@opentelemetry/api";
5
5
 
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_functional = require('./functional-TbnG2lu7.cjs');
2
+ const require_functional = require('./functional-qZxRcIBp.cjs');
3
3
  const require_correlated_events = require('./correlated-events-kSwLo3mi.cjs');
4
4
  const require_business_baggage = require('./business-baggage.cjs');
5
5
  let _opentelemetry_api = require("@opentelemetry/api");
@@ -1,4 +1,4 @@
1
- import { c as withTracing } from "./functional-DCBhFool.js";
1
+ import { c as withTracing } from "./functional-0o9xSedq.js";
2
2
  import { t as emitCorrelatedEvent } from "./correlated-events-Bzh5y-UB.js";
3
3
  import { createSafeBaggageSchema } from "./business-baggage.js";
4
4
  import { SpanKind, context, propagation } from "@opentelemetry/api";
package/dist/workflow.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_rolldown_runtime = require('./rolldown-runtime-C_NdSu1c.cjs');
3
3
  const require_trace_helpers = require('./trace-helpers.cjs');
4
- const require_functional = require('./functional-TbnG2lu7.cjs');
4
+ const require_functional = require('./functional-qZxRcIBp.cjs');
5
5
  const require_correlated_events = require('./correlated-events-kSwLo3mi.cjs');
6
6
  const require_trace_factory_validation = require('./trace-factory-validation-Dc8epn87.cjs');
7
7
  let node_async_hooks = require("node:async_hooks");
package/dist/workflow.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { getActiveSpan } from "./trace-helpers.js";
2
- import { c as withTracing } from "./functional-DCBhFool.js";
2
+ import { c as withTracing } from "./functional-0o9xSedq.js";
3
3
  import { t as emitCorrelatedEvent } from "./correlated-events-Bzh5y-UB.js";
4
4
  import { t as assertTraceFactory } from "./trace-factory-validation-BjVAinz6.js";
5
5
  import * as nodeAsyncHooks from "node:async_hooks";
@@ -122,6 +122,7 @@ function yamlToAutotelConfig(yaml) {
122
122
  if (yaml.exporter?.destinations) config.destinations = yaml.exporter.destinations;
123
123
  if (yaml.resource) config.resourceAttributes = yaml.resource;
124
124
  if (yaml.autoInstrumentations) config.autoInstrumentations = yaml.autoInstrumentations;
125
+ if (yaml.policies) config.policies = yaml.policies;
125
126
  if (yaml.debug !== void 0) config.debug = yaml.debug;
126
127
  if (yaml.sampling?.preset) {
127
128
  warnOnIgnoredPresetOverrides(yaml.sampling);
@@ -1,5 +1,5 @@
1
1
  import { h as SamplingPreset } from "./sampling-BR9fkSwx.cjs";
2
- import { a as AutotelConfig, o as OtlpSignal } from "./init-CfVWN4ND.cjs";
2
+ import { a as AutotelConfig, o as OtlpSignal } from "./init-Cc7-vvzj.cjs";
3
3
  //#region src/yaml-config.d.ts
4
4
  /**
5
5
  * YAML config structure
@@ -35,6 +35,8 @@ interface YamlConfig {
35
35
  autoInstrumentations?: string[] | Record<string, {
36
36
  enabled?: boolean;
37
37
  }>;
38
+ /** Path to a policy `.json` file or a directory of them (OTEP 4738). */
39
+ policies?: string;
38
40
  debug?: boolean;
39
41
  }
40
42
  /**
@@ -1,5 +1,5 @@
1
1
  import { h as SamplingPreset } from "./sampling-CP3e7-Yr.js";
2
- import { a as AutotelConfig, o as OtlpSignal } from "./init-C1i2_2zl.js";
2
+ import { a as AutotelConfig, o as OtlpSignal } from "./init-CsODvlau.js";
3
3
  //#region src/yaml-config.d.ts
4
4
  /**
5
5
  * YAML config structure
@@ -35,6 +35,8 @@ interface YamlConfig {
35
35
  autoInstrumentations?: string[] | Record<string, {
36
36
  enabled?: boolean;
37
37
  }>;
38
+ /** Path to a policy `.json` file or a directory of them (OTEP 4738). */
39
+ policies?: string;
38
40
  debug?: boolean;
39
41
  }
40
42
  /**
@@ -118,6 +118,7 @@ function yamlToAutotelConfig(yaml) {
118
118
  if (yaml.exporter?.destinations) config.destinations = yaml.exporter.destinations;
119
119
  if (yaml.resource) config.resourceAttributes = yaml.resource;
120
120
  if (yaml.autoInstrumentations) config.autoInstrumentations = yaml.autoInstrumentations;
121
+ if (yaml.policies) config.policies = yaml.policies;
121
122
  if (yaml.debug !== void 0) config.debug = yaml.debug;
122
123
  if (yaml.sampling?.preset) {
123
124
  warnOnIgnoredPresetOverrides(yaml.sampling);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autotel",
3
- "version": "6.3.0",
3
+ "version": "6.4.1",
4
4
  "description": "Write Once, Observe Anywhere",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -110,6 +110,11 @@
110
110
  "import": "./dist/filtering-span-processor.js",
111
111
  "require": "./dist/filtering-span-processor.cjs"
112
112
  },
113
+ "./policy": {
114
+ "types": "./dist/policy.d.ts",
115
+ "import": "./dist/policy.js",
116
+ "require": "./dist/policy.cjs"
117
+ },
113
118
  "./span-name-normalizer": {
114
119
  "types": "./dist/span-name-normalizer.d.ts",
115
120
  "import": "./dist/span-name-normalizer.js",