@atrim/instrument-node 0.4.0-c3ef89c-20251118193817 → 0.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.
@@ -5,13 +5,38 @@ var sdkNode = require('@opentelemetry/sdk-node');
5
5
  var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
6
6
  var autoInstrumentationsNode = require('@opentelemetry/auto-instrumentations-node');
7
7
  var api = require('@opentelemetry/api');
8
- var instrumentCore = require('@atrim/instrument-core');
8
+ var FileSystem = require('@effect/platform/FileSystem');
9
+ var HttpClient = require('@effect/platform/HttpClient');
10
+ var HttpClientRequest = require('@effect/platform/HttpClientRequest');
11
+ var yaml = require('yaml');
12
+ var zod = require('zod');
9
13
  var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
10
14
  var promises = require('fs/promises');
11
15
  var path = require('path');
12
16
  var platformNode = require('@effect/platform-node');
13
17
  var platform = require('@effect/platform');
14
18
 
19
+ function _interopNamespace(e) {
20
+ if (e && e.__esModule) return e;
21
+ var n = Object.create(null);
22
+ if (e) {
23
+ Object.keys(e).forEach(function (k) {
24
+ if (k !== 'default') {
25
+ var d = Object.getOwnPropertyDescriptor(e, k);
26
+ Object.defineProperty(n, k, d.get ? d : {
27
+ enumerable: true,
28
+ get: function () { return e[k]; }
29
+ });
30
+ }
31
+ });
32
+ }
33
+ n.default = e;
34
+ return Object.freeze(n);
35
+ }
36
+
37
+ var HttpClient__namespace = /*#__PURE__*/_interopNamespace(HttpClient);
38
+ var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
39
+
15
40
  var __defProp = Object.defineProperty;
16
41
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
42
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -21,11 +46,401 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
21
46
  throw Error('Dynamic require of "' + x + '" is not supported');
22
47
  });
23
48
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
49
+ var __defProp2 = Object.defineProperty;
50
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
51
+ var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
52
+ var PatternConfigSchema = zod.z.object({
53
+ pattern: zod.z.string(),
54
+ enabled: zod.z.boolean().optional(),
55
+ description: zod.z.string().optional()
56
+ });
57
+ var AutoIsolationConfigSchema = zod.z.object({
58
+ // Global enable/disable for auto-isolation
59
+ enabled: zod.z.boolean().default(false),
60
+ // Which operators to auto-isolate
61
+ operators: zod.z.object({
62
+ fiberset_run: zod.z.boolean().default(true),
63
+ effect_fork: zod.z.boolean().default(true),
64
+ effect_fork_daemon: zod.z.boolean().default(true),
65
+ effect_fork_in: zod.z.boolean().default(false)
66
+ }).default({}),
67
+ // Virtual parent tracking configuration
68
+ tracking: zod.z.object({
69
+ use_span_links: zod.z.boolean().default(true),
70
+ use_attributes: zod.z.boolean().default(true),
71
+ capture_logical_parent: zod.z.boolean().default(true)
72
+ }).default({}),
73
+ // Span categorization
74
+ attributes: zod.z.object({
75
+ category: zod.z.string().default("background_task"),
76
+ add_metadata: zod.z.boolean().default(true)
77
+ }).default({})
78
+ });
79
+ var HttpFilteringConfigSchema = zod.z.object({
80
+ // Patterns to ignore for outgoing HTTP requests (string patterns only in YAML)
81
+ ignore_outgoing_urls: zod.z.array(zod.z.string()).optional(),
82
+ // Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
83
+ ignore_incoming_paths: zod.z.array(zod.z.string()).optional(),
84
+ // Require parent span for outgoing requests (prevents root spans for HTTP calls)
85
+ require_parent_for_outgoing_spans: zod.z.boolean().optional()
86
+ });
87
+ var InstrumentationConfigSchema = zod.z.object({
88
+ version: zod.z.string(),
89
+ instrumentation: zod.z.object({
90
+ enabled: zod.z.boolean(),
91
+ description: zod.z.string().optional(),
92
+ logging: zod.z.enum(["on", "off", "minimal"]).optional().default("on"),
93
+ instrument_patterns: zod.z.array(PatternConfigSchema),
94
+ ignore_patterns: zod.z.array(PatternConfigSchema)
95
+ }),
96
+ effect: zod.z.object({
97
+ auto_extract_metadata: zod.z.boolean(),
98
+ auto_isolation: AutoIsolationConfigSchema.optional()
99
+ }).optional(),
100
+ http: HttpFilteringConfigSchema.optional()
101
+ });
102
+ (class extends effect.Data.TaggedError("ConfigError") {
103
+ get message() {
104
+ return this.reason;
105
+ }
106
+ });
107
+ var ConfigUrlError = class extends effect.Data.TaggedError("ConfigUrlError") {
108
+ get message() {
109
+ return this.reason;
110
+ }
111
+ };
112
+ var ConfigValidationError = class extends effect.Data.TaggedError("ConfigValidationError") {
113
+ get message() {
114
+ return this.reason;
115
+ }
116
+ };
117
+ var ConfigFileError = class extends effect.Data.TaggedError("ConfigFileError") {
118
+ get message() {
119
+ return this.reason;
120
+ }
121
+ };
122
+ (class extends effect.Data.TaggedError("ServiceDetectionError") {
123
+ get message() {
124
+ return this.reason;
125
+ }
126
+ });
127
+ (class extends effect.Data.TaggedError("InitializationError") {
128
+ get message() {
129
+ return this.reason;
130
+ }
131
+ });
132
+ (class extends effect.Data.TaggedError("ExportError") {
133
+ get message() {
134
+ return this.reason;
135
+ }
136
+ });
137
+ (class extends effect.Data.TaggedError("ShutdownError") {
138
+ get message() {
139
+ return this.reason;
140
+ }
141
+ });
142
+ var SECURITY_DEFAULTS = {
143
+ maxConfigSize: 1e6,
144
+ // 1MB
145
+ requestTimeout: 5e3
146
+ // 5 seconds
147
+ };
148
+ var ConfigLoader = class extends effect.Context.Tag("ConfigLoader")() {
149
+ };
150
+ var parseYamlContent = (content, uri) => effect.Effect.gen(function* () {
151
+ const parsed = yield* effect.Effect.try({
152
+ try: () => yaml.parse(content),
153
+ catch: (error) => new ConfigValidationError({
154
+ reason: uri ? `Failed to parse YAML from ${uri}` : "Failed to parse YAML",
155
+ cause: error
156
+ })
157
+ });
158
+ return yield* effect.Effect.try({
159
+ try: () => InstrumentationConfigSchema.parse(parsed),
160
+ catch: (error) => new ConfigValidationError({
161
+ reason: uri ? `Invalid configuration schema from ${uri}` : "Invalid configuration schema",
162
+ cause: error
163
+ })
164
+ });
165
+ });
166
+ var loadFromFileWithFs = (fs, path, uri) => effect.Effect.gen(function* () {
167
+ const content = yield* fs.readFileString(path).pipe(
168
+ effect.Effect.mapError(
169
+ (error) => new ConfigFileError({
170
+ reason: `Failed to read config file at ${uri}`,
171
+ cause: error
172
+ })
173
+ )
174
+ );
175
+ if (content.length > SECURITY_DEFAULTS.maxConfigSize) {
176
+ return yield* effect.Effect.fail(
177
+ new ConfigFileError({
178
+ reason: `Config file exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
179
+ })
180
+ );
181
+ }
182
+ return yield* parseYamlContent(content, uri);
183
+ });
184
+ var loadFromHttpWithClient = (client, url) => effect.Effect.scoped(
185
+ effect.Effect.gen(function* () {
186
+ if (url.startsWith("http://")) {
187
+ return yield* effect.Effect.fail(
188
+ new ConfigUrlError({
189
+ reason: "Insecure protocol: only HTTPS URLs are allowed"
190
+ })
191
+ );
192
+ }
193
+ const request = HttpClientRequest__namespace.get(url).pipe(
194
+ HttpClientRequest__namespace.setHeaders({
195
+ Accept: "application/yaml, text/yaml, application/x-yaml"
196
+ })
197
+ );
198
+ const response = yield* client.execute(request).pipe(
199
+ effect.Effect.timeout(`${SECURITY_DEFAULTS.requestTimeout} millis`),
200
+ effect.Effect.mapError((error) => {
201
+ if (error._tag === "TimeoutException") {
202
+ return new ConfigUrlError({
203
+ reason: `Config fetch timeout after ${SECURITY_DEFAULTS.requestTimeout}ms from ${url}`
204
+ });
205
+ }
206
+ return new ConfigUrlError({
207
+ reason: `Failed to load config from URL: ${url}`,
208
+ cause: error
209
+ });
210
+ })
211
+ );
212
+ if (response.status >= 400) {
213
+ return yield* effect.Effect.fail(
214
+ new ConfigUrlError({
215
+ reason: `HTTP ${response.status} from ${url}`
216
+ })
217
+ );
218
+ }
219
+ const text = yield* response.text.pipe(
220
+ effect.Effect.mapError(
221
+ (error) => new ConfigUrlError({
222
+ reason: `Failed to read response body from ${url}`,
223
+ cause: error
224
+ })
225
+ )
226
+ );
227
+ if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
228
+ return yield* effect.Effect.fail(
229
+ new ConfigUrlError({
230
+ reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
231
+ })
232
+ );
233
+ }
234
+ return yield* parseYamlContent(text, url);
235
+ })
236
+ );
237
+ var makeConfigLoader = effect.Effect.gen(function* () {
238
+ const fs = yield* effect.Effect.serviceOption(FileSystem.FileSystem);
239
+ const http = yield* HttpClient__namespace.HttpClient;
240
+ const loadFromUriUncached = (uri) => effect.Effect.gen(function* () {
241
+ if (uri.startsWith("file://")) {
242
+ const path = uri.slice(7);
243
+ if (fs._tag === "None") {
244
+ return yield* effect.Effect.fail(
245
+ new ConfigFileError({
246
+ reason: "FileSystem not available (browser environment?)",
247
+ cause: { uri }
248
+ })
249
+ );
250
+ }
251
+ return yield* loadFromFileWithFs(fs.value, path, uri);
252
+ }
253
+ if (uri.startsWith("http://") || uri.startsWith("https://")) {
254
+ return yield* loadFromHttpWithClient(http, uri);
255
+ }
256
+ if (fs._tag === "Some") {
257
+ return yield* loadFromFileWithFs(fs.value, uri, uri);
258
+ } else {
259
+ return yield* loadFromHttpWithClient(http, uri);
260
+ }
261
+ });
262
+ const loadFromUriCached = yield* effect.Effect.cachedFunction(loadFromUriUncached);
263
+ return ConfigLoader.of({
264
+ loadFromUri: loadFromUriCached,
265
+ loadFromInline: (content) => effect.Effect.gen(function* () {
266
+ if (typeof content === "string") {
267
+ return yield* parseYamlContent(content);
268
+ }
269
+ return yield* effect.Effect.try({
270
+ try: () => InstrumentationConfigSchema.parse(content),
271
+ catch: (error) => new ConfigValidationError({
272
+ reason: "Invalid configuration schema",
273
+ cause: error
274
+ })
275
+ });
276
+ })
277
+ });
278
+ });
279
+ var ConfigLoaderLive = effect.Layer.effect(ConfigLoader, makeConfigLoader);
280
+ var PatternMatcher = class {
281
+ constructor(config) {
282
+ __publicField2(this, "ignorePatterns", []);
283
+ __publicField2(this, "instrumentPatterns", []);
284
+ __publicField2(this, "enabled", true);
285
+ this.enabled = config.instrumentation.enabled;
286
+ this.ignorePatterns = config.instrumentation.ignore_patterns.map((p) => this.compilePattern(p));
287
+ this.instrumentPatterns = config.instrumentation.instrument_patterns.filter((p) => p.enabled !== false).map((p) => this.compilePattern(p));
288
+ }
289
+ /**
290
+ * Compile a pattern configuration into a RegExp
291
+ */
292
+ compilePattern(pattern) {
293
+ try {
294
+ const compiled = {
295
+ regex: new RegExp(pattern.pattern),
296
+ enabled: pattern.enabled !== false
297
+ };
298
+ if (pattern.description !== void 0) {
299
+ compiled.description = pattern.description;
300
+ }
301
+ return compiled;
302
+ } catch (error) {
303
+ throw new Error(
304
+ `Failed to compile pattern "${pattern.pattern}": ${error instanceof Error ? error.message : String(error)}`
305
+ );
306
+ }
307
+ }
308
+ /**
309
+ * Check if a span should be instrumented
310
+ *
311
+ * Returns true if the span should be created, false otherwise.
312
+ *
313
+ * Logic:
314
+ * 1. If instrumentation disabled globally, return false
315
+ * 2. Check ignore patterns - if any match, return false
316
+ * 3. Check instrument patterns - if any match, return true
317
+ * 4. Default: return true (fail-open - create span if no patterns match)
318
+ */
319
+ shouldInstrument(spanName) {
320
+ if (!this.enabled) {
321
+ return false;
322
+ }
323
+ for (const pattern of this.ignorePatterns) {
324
+ if (pattern.regex.test(spanName)) {
325
+ return false;
326
+ }
327
+ }
328
+ for (const pattern of this.instrumentPatterns) {
329
+ if (pattern.enabled && pattern.regex.test(spanName)) {
330
+ return true;
331
+ }
332
+ }
333
+ return true;
334
+ }
335
+ /**
336
+ * Get statistics about pattern matching (for debugging/monitoring)
337
+ */
338
+ getStats() {
339
+ return {
340
+ enabled: this.enabled,
341
+ ignorePatternCount: this.ignorePatterns.length,
342
+ instrumentPatternCount: this.instrumentPatterns.filter((p) => p.enabled).length
343
+ };
344
+ }
345
+ };
346
+ var globalMatcher = null;
347
+ function initializePatternMatcher(config) {
348
+ globalMatcher = new PatternMatcher(config);
349
+ }
350
+ function shouldInstrumentSpan(spanName) {
351
+ if (!globalMatcher) {
352
+ return true;
353
+ }
354
+ return globalMatcher.shouldInstrument(spanName);
355
+ }
356
+ function getPatternMatcher() {
357
+ return globalMatcher;
358
+ }
359
+ var Logger = class {
360
+ constructor() {
361
+ __publicField2(this, "level", "on");
362
+ __publicField2(this, "hasLoggedMinimal", false);
363
+ }
364
+ /**
365
+ * Set the logging level
366
+ */
367
+ setLevel(level) {
368
+ this.level = level;
369
+ this.hasLoggedMinimal = false;
370
+ }
371
+ /**
372
+ * Get the current logging level
373
+ */
374
+ getLevel() {
375
+ return this.level;
376
+ }
377
+ /**
378
+ * Log a minimal initialization message (only shown once in minimal mode)
379
+ */
380
+ minimal(message) {
381
+ if (this.level === "off") {
382
+ return;
383
+ }
384
+ if (this.level === "minimal" && !this.hasLoggedMinimal) {
385
+ console.log(message);
386
+ this.hasLoggedMinimal = true;
387
+ return;
388
+ }
389
+ if (this.level === "on") {
390
+ console.log(message);
391
+ }
392
+ }
393
+ /**
394
+ * Log an informational message
395
+ */
396
+ log(...args) {
397
+ if (this.level === "on") {
398
+ console.log(...args);
399
+ }
400
+ }
401
+ /**
402
+ * Log a warning message (shown in minimal mode)
403
+ */
404
+ warn(...args) {
405
+ if (this.level !== "off") {
406
+ console.warn(...args);
407
+ }
408
+ }
409
+ /**
410
+ * Log an error message (shown in minimal mode)
411
+ */
412
+ error(...args) {
413
+ if (this.level !== "off") {
414
+ console.error(...args);
415
+ }
416
+ }
417
+ /**
418
+ * Check if full logging is enabled
419
+ */
420
+ isEnabled() {
421
+ return this.level === "on";
422
+ }
423
+ /**
424
+ * Check if minimal logging is enabled
425
+ */
426
+ isMinimal() {
427
+ return this.level === "minimal";
428
+ }
429
+ /**
430
+ * Check if logging is completely disabled
431
+ */
432
+ isDisabled() {
433
+ return this.level === "off";
434
+ }
435
+ };
436
+ var logger = new Logger();
437
+
438
+ // src/core/span-processor.ts
24
439
  var PatternSpanProcessor = class {
25
440
  constructor(config, wrappedProcessor) {
26
441
  __publicField(this, "matcher");
27
442
  __publicField(this, "wrappedProcessor");
28
- this.matcher = new instrumentCore.PatternMatcher(config);
443
+ this.matcher = new PatternMatcher(config);
29
444
  this.wrappedProcessor = wrappedProcessor;
30
445
  }
31
446
  /**
@@ -98,6 +513,8 @@ function getOtlpEndpoint(options = {}) {
98
513
  const endpoint = options.endpoint || process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || DEFAULT_OTLP_ENDPOINT;
99
514
  return normalizeEndpoint(endpoint);
100
515
  }
516
+
517
+ // src/core/safe-exporter.ts
101
518
  var SafeSpanExporter = class {
102
519
  // Log errors max once per minute
103
520
  constructor(exporter) {
@@ -134,7 +551,7 @@ var SafeSpanExporter = class {
134
551
  try {
135
552
  await this.exporter.shutdown();
136
553
  } catch (error) {
137
- instrumentCore.logger.error(
554
+ logger.error(
138
555
  "@atrim/instrumentation: Error during exporter shutdown (non-critical):",
139
556
  error instanceof Error ? error.message : String(error)
140
557
  );
@@ -163,14 +580,14 @@ var SafeSpanExporter = class {
163
580
  if (shouldLog) {
164
581
  const errorMessage = error instanceof Error ? error.message : String(error);
165
582
  if (this.isConnectionError(error)) {
166
- instrumentCore.logger.warn(`@atrim/instrumentation: Unable to export spans - collector not available`);
167
- instrumentCore.logger.warn(` Error: ${errorMessage}`);
168
- instrumentCore.logger.warn(` Spans will be dropped. Ensure OTEL collector is running.`);
583
+ logger.warn(`@atrim/instrumentation: Unable to export spans - collector not available`);
584
+ logger.warn(` Error: ${errorMessage}`);
585
+ logger.warn(` Spans will be dropped. Ensure OTEL collector is running.`);
169
586
  } else {
170
- instrumentCore.logger.error("@atrim/instrumentation: Span export failed:", errorMessage);
587
+ logger.error("@atrim/instrumentation: Span export failed:", errorMessage);
171
588
  }
172
589
  if (this.errorCount > 1) {
173
- instrumentCore.logger.warn(` (${this.errorCount} errors total, throttled to 1/min)`);
590
+ logger.warn(` (${this.errorCount} errors total, throttled to 1/min)`);
174
591
  }
175
592
  this.lastErrorTime = now;
176
593
  this.errorCount = 0;
@@ -197,21 +614,21 @@ var SafeSpanExporter = class {
197
614
  return false;
198
615
  }
199
616
  };
200
- var ConfigError = class extends effect.Data.TaggedError("ConfigError") {
617
+ var ConfigError2 = class extends effect.Data.TaggedError("ConfigError") {
201
618
  };
202
- var ConfigUrlError = class extends effect.Data.TaggedError("ConfigUrlError") {
619
+ var ConfigUrlError2 = class extends effect.Data.TaggedError("ConfigUrlError") {
203
620
  };
204
- var ConfigValidationError = class extends effect.Data.TaggedError("ConfigValidationError") {
621
+ var ConfigValidationError2 = class extends effect.Data.TaggedError("ConfigValidationError") {
205
622
  };
206
- var ConfigFileError = class extends effect.Data.TaggedError("ConfigFileError") {
623
+ var ConfigFileError2 = class extends effect.Data.TaggedError("ConfigFileError") {
207
624
  };
208
- var ServiceDetectionError = class extends effect.Data.TaggedError("ServiceDetectionError") {
625
+ var ServiceDetectionError2 = class extends effect.Data.TaggedError("ServiceDetectionError") {
209
626
  };
210
- var InitializationError = class extends effect.Data.TaggedError("InitializationError") {
627
+ var InitializationError2 = class extends effect.Data.TaggedError("InitializationError") {
211
628
  };
212
- var ExportError = class extends effect.Data.TaggedError("ExportError") {
629
+ var ExportError2 = class extends effect.Data.TaggedError("ExportError") {
213
630
  };
214
- var ShutdownError = class extends effect.Data.TaggedError("ShutdownError") {
631
+ var ShutdownError2 = class extends effect.Data.TaggedError("ShutdownError") {
215
632
  };
216
633
 
217
634
  // src/core/service-detector.ts
@@ -228,7 +645,7 @@ var detectServiceInfo = effect.Effect.gen(
228
645
  const packageJsonPath = path.join(process.cwd(), "package.json");
229
646
  const packageJsonContent = yield* effect.Effect.tryPromise({
230
647
  try: () => promises.readFile(packageJsonPath, "utf-8"),
231
- catch: (error) => new ServiceDetectionError({
648
+ catch: (error) => new ServiceDetectionError2({
232
649
  reason: `Failed to read package.json at ${packageJsonPath}`,
233
650
  cause: error
234
651
  })
@@ -238,7 +655,7 @@ var detectServiceInfo = effect.Effect.gen(
238
655
  parsed = JSON.parse(packageJsonContent);
239
656
  } catch (error) {
240
657
  yield* effect.Effect.fail(
241
- new ServiceDetectionError({
658
+ new ServiceDetectionError2({
242
659
  reason: "Invalid JSON in package.json",
243
660
  cause: error
244
661
  })
@@ -254,7 +671,7 @@ var detectServiceInfo = effect.Effect.gen(
254
671
  }
255
672
  }
256
673
  return yield* effect.Effect.fail(
257
- new ServiceDetectionError({
674
+ new ServiceDetectionError2({
258
675
  reason: 'package.json exists but has no "name" field'
259
676
  })
260
677
  );
@@ -285,7 +702,7 @@ async function getServiceNameAsync() {
285
702
  async function getServiceVersionAsync() {
286
703
  return effect.Effect.runPromise(getServiceVersion);
287
704
  }
288
- var NodeConfigLoaderLive = instrumentCore.ConfigLoaderLive.pipe(
705
+ var NodeConfigLoaderLive = ConfigLoaderLive.pipe(
289
706
  effect.Layer.provide(effect.Layer.mergeAll(platformNode.NodeContext.layer, platform.FetchHttpClient.layer))
290
707
  );
291
708
  var cachedLoaderPromise = null;
@@ -293,7 +710,7 @@ function getCachedLoader() {
293
710
  if (!cachedLoaderPromise) {
294
711
  cachedLoaderPromise = effect.Effect.runPromise(
295
712
  effect.Effect.gen(function* () {
296
- return yield* instrumentCore.ConfigLoader;
713
+ return yield* ConfigLoader;
297
714
  }).pipe(effect.Effect.provide(NodeConfigLoaderLive))
298
715
  );
299
716
  }
@@ -305,7 +722,7 @@ function _resetConfigLoaderCache() {
305
722
  async function loadConfig(uri, options) {
306
723
  if (options?.cacheTimeout === 0) {
307
724
  const program = effect.Effect.gen(function* () {
308
- const loader2 = yield* instrumentCore.ConfigLoader;
725
+ const loader2 = yield* ConfigLoader;
309
726
  return yield* loader2.loadFromUri(uri);
310
727
  });
311
728
  return effect.Effect.runPromise(program.pipe(effect.Effect.provide(NodeConfigLoaderLive)));
@@ -375,7 +792,7 @@ function buildHttpInstrumentationConfig(options, config, _otlpEndpoint) {
375
792
  ...programmaticPatterns.map((p) => typeof p === "string" ? new RegExp(p) : p),
376
793
  ...yamlPatterns.map((p) => new RegExp(p))
377
794
  ];
378
- instrumentCore.logger.log(`HTTP filtering: ${allOutgoingPatterns.length} outgoing patterns configured`);
795
+ logger.log(`HTTP filtering: ${allOutgoingPatterns.length} outgoing patterns configured`);
379
796
  if (options.http?.ignoreOutgoingRequestHook) {
380
797
  httpConfig.ignoreOutgoingRequestHook = options.http.ignoreOutgoingRequestHook;
381
798
  } else if (allOutgoingPatterns.length > 0) {
@@ -444,9 +861,9 @@ function shouldEnableAutoInstrumentation(explicitValue, hasWebFramework) {
444
861
  }
445
862
  const isEffect = isEffectProject();
446
863
  if (isEffect && !hasWebFramework) {
447
- instrumentCore.logger.log("@atrim/instrumentation: Detected Effect-TS without web framework");
448
- instrumentCore.logger.log(" - Auto-instrumentation disabled by default");
449
- instrumentCore.logger.log(" - Effect.withSpan() will create spans");
864
+ logger.log("@atrim/instrumentation: Detected Effect-TS without web framework");
865
+ logger.log(" - Auto-instrumentation disabled by default");
866
+ logger.log(" - Effect.withSpan() will create spans");
450
867
  return false;
451
868
  }
452
869
  return true;
@@ -484,11 +901,11 @@ function isTracingAlreadyInitialized() {
484
901
  }
485
902
  async function initializeSdk(options = {}) {
486
903
  if (sdkInstance) {
487
- instrumentCore.logger.warn("@atrim/instrumentation: SDK already initialized. Returning existing instance.");
904
+ logger.warn("@atrim/instrumentation: SDK already initialized. Returning existing instance.");
488
905
  return sdkInstance;
489
906
  }
490
907
  if (initializationPromise) {
491
- instrumentCore.logger.log(
908
+ logger.log(
492
909
  "@atrim/instrumentation: SDK already initialized, waiting for initialization to complete..."
493
910
  );
494
911
  return initializationPromise;
@@ -504,18 +921,18 @@ async function initializeSdk(options = {}) {
504
921
  async function performInitialization(options) {
505
922
  const config = await loadConfigWithOptions(options);
506
923
  const loggingLevel = config.instrumentation.logging || "on";
507
- instrumentCore.logger.setLevel(loggingLevel);
924
+ logger.setLevel(loggingLevel);
508
925
  const alreadyInitialized = isTracingAlreadyInitialized();
509
926
  if (alreadyInitialized) {
510
- instrumentCore.logger.log("@atrim/instrumentation: Detected existing OpenTelemetry initialization.");
511
- instrumentCore.logger.log(" - Skipping NodeSDK setup");
512
- instrumentCore.logger.log(" - Setting up pattern-based filtering only");
513
- instrumentCore.logger.log("");
514
- instrumentCore.initializePatternMatcher(config);
515
- instrumentCore.logger.log("@atrim/instrumentation: Pattern filtering initialized");
516
- instrumentCore.logger.log(" \u26A0\uFE0F Note: Pattern filtering will only work with manual spans");
517
- instrumentCore.logger.log(" \u26A0\uFE0F Auto-instrumentation must be configured separately");
518
- instrumentCore.logger.log("");
927
+ logger.log("@atrim/instrumentation: Detected existing OpenTelemetry initialization.");
928
+ logger.log(" - Skipping NodeSDK setup");
929
+ logger.log(" - Setting up pattern-based filtering only");
930
+ logger.log("");
931
+ initializePatternMatcher(config);
932
+ logger.log("@atrim/instrumentation: Pattern filtering initialized");
933
+ logger.log(" \u26A0\uFE0F Note: Pattern filtering will only work with manual spans");
934
+ logger.log(" \u26A0\uFE0F Auto-instrumentation must be configured separately");
935
+ logger.log("");
519
936
  return null;
520
937
  }
521
938
  const serviceInfo = await detectServiceInfoAsync();
@@ -551,7 +968,7 @@ async function performInitialization(options) {
551
968
  "@opentelemetry/instrumentation-dns": { enabled: false }
552
969
  })
553
970
  );
554
- instrumentCore.logger.log(`Auto-instrumentation: ${instrumentations.length} instrumentations enabled`);
971
+ logger.log(`Auto-instrumentation: ${instrumentations.length} instrumentations enabled`);
555
972
  }
556
973
  if (options.instrumentations) {
557
974
  instrumentations.push(...options.instrumentations);
@@ -559,14 +976,14 @@ async function performInitialization(options) {
559
976
  if (!enableAutoInstrumentation && instrumentations.length === 0) {
560
977
  const wasExplicit = options.autoInstrument === false;
561
978
  const detectionMessage = wasExplicit ? "@atrim/instrumentation: Auto-instrumentation: disabled" : "@atrim/instrumentation: Pure Effect-TS app detected (auto-detected)";
562
- instrumentCore.logger.log(detectionMessage);
563
- instrumentCore.logger.log(" - Skipping NodeSDK setup");
564
- instrumentCore.logger.log(" - Pattern matching configured from instrumentation.yaml");
979
+ logger.log(detectionMessage);
980
+ logger.log(" - Skipping NodeSDK setup");
981
+ logger.log(" - Pattern matching configured from instrumentation.yaml");
565
982
  if (!wasExplicit) {
566
- instrumentCore.logger.log(" - Use EffectInstrumentationLive for tracing");
983
+ logger.log(" - Use EffectInstrumentationLive for tracing");
567
984
  }
568
- instrumentCore.logger.log("");
569
- instrumentCore.initializePatternMatcher(config);
985
+ logger.log("");
986
+ initializePatternMatcher(config);
570
987
  return null;
571
988
  }
572
989
  const sdkConfig = {
@@ -602,14 +1019,14 @@ function resetSdk() {
602
1019
  }
603
1020
  function registerShutdownHandlers(sdk) {
604
1021
  const shutdown = async (signal) => {
605
- instrumentCore.logger.log(`
1022
+ logger.log(`
606
1023
  @atrim/instrumentation: Received ${signal}, shutting down gracefully...`);
607
1024
  try {
608
1025
  await sdk.shutdown();
609
- instrumentCore.logger.log("@atrim/instrumentation: Shutdown complete");
1026
+ logger.log("@atrim/instrumentation: Shutdown complete");
610
1027
  process.exit(0);
611
1028
  } catch (error) {
612
- instrumentCore.logger.error(
1029
+ logger.error(
613
1030
  "@atrim/instrumentation: Error during shutdown:",
614
1031
  error instanceof Error ? error.message : String(error)
615
1032
  );
@@ -619,60 +1036,62 @@ function registerShutdownHandlers(sdk) {
619
1036
  process.on("SIGTERM", () => shutdown("SIGTERM"));
620
1037
  process.on("SIGINT", () => shutdown("SIGINT"));
621
1038
  process.on("uncaughtException", async (error) => {
622
- instrumentCore.logger.error("@atrim/instrumentation: Uncaught exception:", error);
1039
+ logger.error("@atrim/instrumentation: Uncaught exception:", error);
623
1040
  await sdk.shutdown();
624
1041
  process.exit(1);
625
1042
  });
626
1043
  process.on("unhandledRejection", async (reason) => {
627
- instrumentCore.logger.error("@atrim/instrumentation: Unhandled rejection:", reason);
1044
+ logger.error("@atrim/instrumentation: Unhandled rejection:", reason);
628
1045
  await sdk.shutdown();
629
1046
  process.exit(1);
630
1047
  });
631
1048
  }
632
1049
  function logInitialization(config, serviceName, serviceVersion, options, autoInstrumentEnabled) {
633
- instrumentCore.logger.minimal("@atrim/instrumentation: SDK initialized successfully");
634
- instrumentCore.logger.log(` - Service: ${serviceName}${serviceVersion ? ` v${serviceVersion}` : ""}`);
1050
+ logger.minimal("@atrim/instrumentation: SDK initialized successfully");
1051
+ logger.log(` - Service: ${serviceName}${serviceVersion ? ` v${serviceVersion}` : ""}`);
635
1052
  if (config.instrumentation.enabled) {
636
1053
  const instrumentCount = config.instrumentation.instrument_patterns.filter(
637
1054
  (p) => p.enabled !== false
638
1055
  ).length;
639
1056
  const ignoreCount = config.instrumentation.ignore_patterns.length;
640
- instrumentCore.logger.log(` - Pattern filtering: enabled`);
641
- instrumentCore.logger.log(` - Instrument patterns: ${instrumentCount}`);
642
- instrumentCore.logger.log(` - Ignore patterns: ${ignoreCount}`);
1057
+ logger.log(` - Pattern filtering: enabled`);
1058
+ logger.log(` - Instrument patterns: ${instrumentCount}`);
1059
+ logger.log(` - Ignore patterns: ${ignoreCount}`);
643
1060
  } else {
644
- instrumentCore.logger.log(` - Pattern filtering: disabled`);
1061
+ logger.log(` - Pattern filtering: disabled`);
645
1062
  }
646
1063
  const autoInstrumentLabel = autoInstrumentEnabled ? "enabled" : "disabled";
647
1064
  const autoDetected = options.autoInstrument === void 0 ? " (auto-detected)" : "";
648
- instrumentCore.logger.log(` - Auto-instrumentation: ${autoInstrumentLabel}${autoDetected}`);
1065
+ logger.log(` - Auto-instrumentation: ${autoInstrumentLabel}${autoDetected}`);
649
1066
  if (options.instrumentations && options.instrumentations.length > 0) {
650
- instrumentCore.logger.log(` - Custom instrumentations: ${options.instrumentations.length}`);
1067
+ logger.log(` - Custom instrumentations: ${options.instrumentations.length}`);
651
1068
  }
652
1069
  const endpoint = options.otlp?.endpoint || process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318/v1/traces";
653
- instrumentCore.logger.log(` - OTLP endpoint: ${endpoint}`);
654
- instrumentCore.logger.log("");
1070
+ logger.log(` - OTLP endpoint: ${endpoint}`);
1071
+ logger.log("");
655
1072
  }
1073
+
1074
+ // src/api.ts
656
1075
  async function initializeInstrumentation(options = {}) {
657
1076
  const sdk = await initializeSdk(options);
658
1077
  if (sdk) {
659
1078
  const config = await loadConfigWithOptions(options);
660
- instrumentCore.initializePatternMatcher(config);
1079
+ initializePatternMatcher(config);
661
1080
  }
662
1081
  return sdk;
663
1082
  }
664
1083
  async function initializePatternMatchingOnly(options = {}) {
665
1084
  const config = await loadConfigWithOptions(options);
666
- instrumentCore.initializePatternMatcher(config);
667
- instrumentCore.logger.log("@atrim/instrumentation: Pattern matching initialized (legacy mode)");
668
- instrumentCore.logger.log(
1085
+ initializePatternMatcher(config);
1086
+ logger.log("@atrim/instrumentation: Pattern matching initialized (legacy mode)");
1087
+ logger.log(
669
1088
  " Note: NodeSDK is not initialized. Use initializeInstrumentation() for complete setup."
670
1089
  );
671
1090
  }
672
1091
  var initializeInstrumentationEffect = (options = {}) => effect.Effect.gen(function* () {
673
1092
  const sdk = yield* effect.Effect.tryPromise({
674
1093
  try: () => initializeSdk(options),
675
- catch: (error) => new InitializationError({
1094
+ catch: (error) => new InitializationError2({
676
1095
  reason: "SDK initialization failed",
677
1096
  cause: error
678
1097
  })
@@ -680,14 +1099,14 @@ var initializeInstrumentationEffect = (options = {}) => effect.Effect.gen(functi
680
1099
  if (sdk) {
681
1100
  yield* effect.Effect.tryPromise({
682
1101
  try: () => loadConfigWithOptions(options),
683
- catch: (error) => new ConfigError({
1102
+ catch: (error) => new ConfigError2({
684
1103
  reason: "Failed to load config for pattern matcher",
685
1104
  cause: error
686
1105
  })
687
1106
  }).pipe(
688
1107
  effect.Effect.tap(
689
1108
  (config) => effect.Effect.sync(() => {
690
- instrumentCore.initializePatternMatcher(config);
1109
+ initializePatternMatcher(config);
691
1110
  })
692
1111
  )
693
1112
  );
@@ -697,15 +1116,15 @@ var initializeInstrumentationEffect = (options = {}) => effect.Effect.gen(functi
697
1116
  var initializePatternMatchingOnlyEffect = (options = {}) => effect.Effect.gen(function* () {
698
1117
  const config = yield* effect.Effect.tryPromise({
699
1118
  try: () => loadConfigWithOptions(options),
700
- catch: (error) => new ConfigError({
1119
+ catch: (error) => new ConfigError2({
701
1120
  reason: "Failed to load configuration",
702
1121
  cause: error
703
1122
  })
704
1123
  });
705
1124
  yield* effect.Effect.sync(() => {
706
- instrumentCore.initializePatternMatcher(config);
707
- instrumentCore.logger.log("@atrim/instrumentation: Pattern matching initialized (legacy mode)");
708
- instrumentCore.logger.log(
1125
+ initializePatternMatcher(config);
1126
+ logger.log("@atrim/instrumentation: Pattern matching initialized (legacy mode)");
1127
+ logger.log(
709
1128
  " Note: NodeSDK is not initialized. Use initializeInstrumentation() for complete setup."
710
1129
  );
711
1130
  });
@@ -805,27 +1224,16 @@ function suppressShutdownErrors() {
805
1224
  });
806
1225
  }
807
1226
 
808
- Object.defineProperty(exports, "PatternMatcher", {
809
- enumerable: true,
810
- get: function () { return instrumentCore.PatternMatcher; }
811
- });
812
- Object.defineProperty(exports, "getPatternMatcher", {
813
- enumerable: true,
814
- get: function () { return instrumentCore.getPatternMatcher; }
815
- });
816
- Object.defineProperty(exports, "shouldInstrumentSpan", {
817
- enumerable: true,
818
- get: function () { return instrumentCore.shouldInstrumentSpan; }
819
- });
820
- exports.ConfigError = ConfigError;
821
- exports.ConfigFileError = ConfigFileError;
822
- exports.ConfigUrlError = ConfigUrlError;
823
- exports.ConfigValidationError = ConfigValidationError;
824
- exports.ExportError = ExportError;
825
- exports.InitializationError = InitializationError;
1227
+ exports.ConfigError = ConfigError2;
1228
+ exports.ConfigFileError = ConfigFileError2;
1229
+ exports.ConfigUrlError = ConfigUrlError2;
1230
+ exports.ConfigValidationError = ConfigValidationError2;
1231
+ exports.ExportError = ExportError2;
1232
+ exports.InitializationError = InitializationError2;
1233
+ exports.PatternMatcher = PatternMatcher;
826
1234
  exports.PatternSpanProcessor = PatternSpanProcessor;
827
- exports.ServiceDetectionError = ServiceDetectionError;
828
- exports.ShutdownError = ShutdownError;
1235
+ exports.ServiceDetectionError = ServiceDetectionError2;
1236
+ exports.ShutdownError = ShutdownError2;
829
1237
  exports.annotateCacheOperation = annotateCacheOperation;
830
1238
  exports.annotateDbQuery = annotateDbQuery;
831
1239
  exports.annotateHttpRequest = annotateHttpRequest;
@@ -834,6 +1242,7 @@ exports.createOtlpExporter = createOtlpExporter;
834
1242
  exports.detectServiceInfo = detectServiceInfoAsync;
835
1243
  exports.detectServiceInfoEffect = detectServiceInfo;
836
1244
  exports.getOtlpEndpoint = getOtlpEndpoint;
1245
+ exports.getPatternMatcher = getPatternMatcher;
837
1246
  exports.getSdkInstance = getSdkInstance;
838
1247
  exports.getServiceInfoWithFallback = getServiceInfoWithFallback;
839
1248
  exports.getServiceName = getServiceNameAsync;
@@ -852,6 +1261,7 @@ exports.markSpanSuccess = markSpanSuccess;
852
1261
  exports.recordException = recordException;
853
1262
  exports.resetSdk = resetSdk;
854
1263
  exports.setSpanAttributes = setSpanAttributes;
1264
+ exports.shouldInstrumentSpan = shouldInstrumentSpan;
855
1265
  exports.shutdownSdk = shutdownSdk;
856
1266
  exports.suppressShutdownErrors = suppressShutdownErrors;
857
1267
  //# sourceMappingURL=index.cjs.map