@atrim/instrument-node 0.8.1-dev.ae570af.20260116212440 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var effect = require('effect');
4
- var opentelemetry = require('@effect/opentelemetry');
5
- var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
6
- var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
7
- var resources = require('@opentelemetry/resources');
8
- var semanticConventions = require('@opentelemetry/semantic-conventions');
9
- var OtelApi = require('@opentelemetry/api');
10
4
  var FileSystem = require('@effect/platform/FileSystem');
11
5
  var HttpClient = require('@effect/platform/HttpClient');
12
6
  var HttpClientRequest = require('@effect/platform/HttpClientRequest');
@@ -15,6 +9,12 @@ var zod = require('zod');
15
9
  var fs = require('fs');
16
10
  var path2 = require('path');
17
11
  var TracerModule = require('effect/Tracer');
12
+ var opentelemetry = require('@effect/opentelemetry');
13
+ var OtelApi = require('@opentelemetry/api');
14
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
15
+ var exporterTraceOtlpHttp = require('@opentelemetry/exporter-trace-otlp-http');
16
+ var resources = require('@opentelemetry/resources');
17
+ var semanticConventions = require('@opentelemetry/semantic-conventions');
18
18
 
19
19
  function _interopNamespace(e) {
20
20
  if (e && e.__esModule) return e;
@@ -34,258 +34,36 @@ function _interopNamespace(e) {
34
34
  return Object.freeze(n);
35
35
  }
36
36
 
37
- var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
38
37
  var HttpClient__namespace = /*#__PURE__*/_interopNamespace(HttpClient);
39
38
  var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
40
39
  var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
41
40
  var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
42
41
  var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
43
42
  var TracerModule__namespace = /*#__PURE__*/_interopNamespace(TracerModule);
43
+ var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
44
44
 
45
45
  var __defProp = Object.defineProperty;
46
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
47
+ var __getOwnPropNames = Object.getOwnPropertyNames;
48
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
46
49
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
47
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
48
- var __defProp2 = Object.defineProperty;
49
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
50
- var __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
51
- var PatternConfigSchema = zod.z.object({
52
- pattern: zod.z.string(),
53
- enabled: zod.z.boolean().optional(),
54
- description: zod.z.string().optional()
55
- });
56
- var AutoIsolationConfigSchema = zod.z.object({
57
- // Global enable/disable for auto-isolation
58
- enabled: zod.z.boolean().default(false),
59
- // Which operators to auto-isolate
60
- operators: zod.z.object({
61
- fiberset_run: zod.z.boolean().default(true),
62
- effect_fork: zod.z.boolean().default(true),
63
- effect_fork_daemon: zod.z.boolean().default(true),
64
- effect_fork_in: zod.z.boolean().default(false)
65
- }).default({}),
66
- // Virtual parent tracking configuration
67
- tracking: zod.z.object({
68
- use_span_links: zod.z.boolean().default(true),
69
- use_attributes: zod.z.boolean().default(true),
70
- capture_logical_parent: zod.z.boolean().default(true)
71
- }).default({}),
72
- // Span categorization
73
- attributes: zod.z.object({
74
- category: zod.z.string().default("background_task"),
75
- add_metadata: zod.z.boolean().default(true)
76
- }).default({})
77
- });
78
- var SpanNamingRuleSchema = zod.z.object({
79
- // Match criteria (all specified criteria must match)
80
- match: zod.z.object({
81
- // Regex pattern to match file path
82
- file: zod.z.string().optional(),
83
- // Regex pattern to match function name
84
- function: zod.z.string().optional(),
85
- // Regex pattern to match module name
86
- module: zod.z.string().optional()
87
- }),
88
- // Span name template with variables:
89
- // {fiber_id} - Fiber ID
90
- // {function} - Function name
91
- // {module} - Module name
92
- // {file} - File path
93
- // {line} - Line number
94
- // {operator} - Effect operator (gen, all, forEach, etc.)
95
- // {match:field:N} - Captured regex group from match
96
- name: zod.z.string()
97
- });
98
- var AutoInstrumentationConfigSchema = zod.z.object({
99
- // Enable/disable auto-instrumentation
100
- enabled: zod.z.boolean().default(false),
101
- // Tracing granularity
102
- // - 'fiber': Trace at fiber creation (recommended, lower overhead)
103
- // - 'operator': Trace each Effect operator (higher granularity, more overhead)
104
- granularity: zod.z.enum(["fiber", "operator"]).default("fiber"),
105
- // Smart span naming configuration
106
- span_naming: zod.z.object({
107
- // Default span name template when no rules match
108
- default: zod.z.string().default("effect.fiber.{fiber_id}"),
109
- // Infer span names from source code (requires stack trace parsing)
110
- // Adds ~50-100μs overhead per fiber
111
- infer_from_source: zod.z.boolean().default(true),
112
- // Naming rules (first match wins)
113
- rules: zod.z.array(SpanNamingRuleSchema).default([])
114
- }).default({}),
115
- // Span relationship configuration for forked fibers
116
- // Controls how child fiber spans relate to their parent/forking context
117
- span_relationships: zod.z.object({
118
- // Relationship type between forked fiber spans and their parent context
119
- // - 'parent-child': Use parent-child relationship (default, traditional tracing)
120
- // Parent span shows child as nested. Works well with most observability tools.
121
- // - 'span-links': Use span links (semantically correct for async forks per OTel spec)
122
- // Fibers get independent traces linked to parent. Better for long-running fibers.
123
- // - 'both': Create parent-child AND add span links
124
- // Maximum visibility but may create redundant data.
125
- type: zod.z.enum(["parent-child", "span-links", "both"]).default("parent-child"),
126
- // Custom attributes to add to span links (only used when type includes links)
127
- link_attributes: zod.z.object({
128
- // Link type identifier
129
- "link.type": zod.z.string().default("fork"),
130
- // Custom attributes (key-value pairs)
131
- custom: zod.z.record(zod.z.string()).optional()
132
- }).optional()
133
- }).default({}),
134
- // Pattern-based filtering
135
- filter: zod.z.object({
136
- // Only trace spans matching these patterns (empty = trace all)
137
- include: zod.z.array(zod.z.string()).default([]),
138
- // Never trace spans matching these patterns
139
- exclude: zod.z.array(zod.z.string()).default([])
140
- }).default({}),
141
- // Performance controls
142
- performance: zod.z.object({
143
- // Sample rate (0.0 - 1.0)
144
- sampling_rate: zod.z.number().min(0).max(1).default(1),
145
- // Skip fibers shorter than this duration (e.g., "10ms", "100 millis")
146
- min_duration: zod.z.string().default("0ms"),
147
- // Maximum concurrent traced fibers (0 = unlimited)
148
- max_concurrent: zod.z.number().default(0)
149
- }).default({}),
150
- // Automatic metadata extraction
151
- metadata: zod.z.object({
152
- // Extract Effect fiber information
153
- fiber_info: zod.z.boolean().default(true),
154
- // Extract source location (file:line)
155
- source_location: zod.z.boolean().default(true),
156
- // Extract parent fiber information
157
- parent_fiber: zod.z.boolean().default(true)
158
- }).default({})
159
- });
160
- var OperationTracingConfigSchema = zod.z.object({
161
- // Enable/disable operation tracing
162
- enabled: zod.z.boolean().default(false),
163
- // Global span naming settings
164
- span_naming: zod.z.object({
165
- // Include source location (file:line) in span name
166
- // Default: true - produces "effect.all (index.ts:42)"
167
- // When false - produces "effect.all"
168
- include_location: zod.z.boolean().default(true),
169
- // Span name template with variables:
170
- // {op} - Operation name (all, forEach, retry, etc.)
171
- // {file} - Full file path
172
- // {filename} - Just the filename (basename)
173
- // {line} - Line number
174
- // {column} - Column number
175
- // Default: "effect.{op} ({filename}:{line})"
176
- template: zod.z.string().default("effect.{op} ({filename}:{line})")
177
- }).default({}),
178
- // Operations to trace
179
- operations: zod.z.array(
180
- zod.z.object({
181
- // Operation name: 'all', 'forEach', 'retry', etc.
182
- name: zod.z.string(),
183
- // Custom span name template (overrides global span_naming.template)
184
- // Supports same variables: {op}, {file}, {filename}, {line}, {column}
185
- span_name: zod.z.string().optional(),
186
- // Include item count in span attributes
187
- include_count: zod.z.boolean().default(true),
188
- // Include stack trace in span attributes
189
- include_stack: zod.z.boolean().default(true)
190
- })
191
- ).default([])
192
- });
193
- var HttpFilteringConfigSchema = zod.z.object({
194
- // Patterns to ignore for outgoing HTTP requests (string patterns only in YAML)
195
- ignore_outgoing_urls: zod.z.array(zod.z.string()).optional(),
196
- // Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
197
- ignore_incoming_paths: zod.z.array(zod.z.string()).optional(),
198
- // Require parent span for outgoing requests (prevents root spans for HTTP calls)
199
- require_parent_for_outgoing_spans: zod.z.boolean().optional(),
200
- // Trace context propagation configuration
201
- // Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
202
- propagate_trace_context: zod.z.object({
203
- // Strategy for trace propagation
204
- // - "all": Propagate to all cross-origin requests (may cause CORS errors)
205
- // - "none": Never propagate trace headers
206
- // - "same-origin": Only propagate to same-origin requests (default, safe)
207
- // - "patterns": Propagate based on include_urls patterns
208
- strategy: zod.z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
209
- // URL patterns to include when strategy is "patterns"
210
- // Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
211
- include_urls: zod.z.array(zod.z.string()).optional()
212
- }).optional()
213
- });
214
- var ExporterConfigSchema = zod.z.object({
215
- // Exporter type: 'otlp' | 'console' | 'none'
216
- // - 'otlp': Export to OTLP endpoint (production)
217
- // - 'console': Log spans to console (development)
218
- // - 'none': No export (disable tracing)
219
- type: zod.z.enum(["otlp", "console", "none"]).default("otlp"),
220
- // OTLP endpoint URL (for type: otlp)
221
- // Defaults to OTEL_EXPORTER_OTLP_ENDPOINT env var or http://localhost:4318
222
- endpoint: zod.z.string().optional(),
223
- // Custom headers to send with OTLP requests (for type: otlp)
224
- // Useful for authentication (x-api-key, Authorization, etc.)
225
- headers: zod.z.record(zod.z.string()).optional(),
226
- // Span processor type
227
- // - 'batch': Batch spans for export (production, lower overhead)
228
- // - 'simple': Export immediately (development, no batching delay)
229
- processor: zod.z.enum(["batch", "simple"]).default("batch"),
230
- // Batch processor settings (for processor: batch)
231
- batch: zod.z.object({
232
- // Max time to wait before exporting (milliseconds)
233
- scheduled_delay_millis: zod.z.number().default(1e3),
234
- // Max batch size
235
- max_export_batch_size: zod.z.number().default(100)
236
- }).optional()
237
- });
238
- var InstrumentationConfigSchema = zod.z.object({
239
- version: zod.z.string(),
240
- instrumentation: zod.z.object({
241
- enabled: zod.z.boolean(),
242
- description: zod.z.string().optional(),
243
- logging: zod.z.enum(["on", "off", "minimal"]).optional().default("on"),
244
- instrument_patterns: zod.z.array(PatternConfigSchema),
245
- ignore_patterns: zod.z.array(PatternConfigSchema)
246
- }),
247
- effect: zod.z.object({
248
- // Enable/disable Effect tracing entirely
249
- // When false, EffectInstrumentationLive returns Layer.empty
250
- enabled: zod.z.boolean().default(true),
251
- // Exporter mode (legacy - use exporter.type instead):
252
- // - "unified": Use global TracerProvider from Node SDK (recommended, enables filtering)
253
- // - "standalone": Use Effect's own OTLP exporter (bypasses Node SDK filtering)
254
- exporter: zod.z.enum(["unified", "standalone"]).default("unified"),
255
- // Exporter configuration (for auto-instrumentation)
256
- exporter_config: ExporterConfigSchema.optional(),
257
- auto_extract_metadata: zod.z.boolean(),
258
- auto_isolation: AutoIsolationConfigSchema.optional(),
259
- // Auto-instrumentation: automatic tracing of all Effect fibers
260
- auto_instrumentation: AutoInstrumentationConfigSchema.optional(),
261
- // Operation tracing: automatic tracing of Effect.all, Effect.forEach, etc.
262
- operation_tracing: OperationTracingConfigSchema.optional()
263
- }).optional(),
264
- http: HttpFilteringConfigSchema.optional()
265
- });
266
- var defaultConfig = {
267
- version: "1.0",
268
- instrumentation: {
269
- enabled: true,
270
- logging: "on",
271
- description: "Default instrumentation configuration",
272
- instrument_patterns: [
273
- { pattern: "^app\\.", enabled: true, description: "Application operations" },
274
- { pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
275
- { pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
276
- ],
277
- ignore_patterns: [
278
- { pattern: "^test\\.", description: "Test utilities" },
279
- { pattern: "^internal\\.", description: "Internal operations" },
280
- { pattern: "^health\\.", description: "Health checks" }
281
- ]
282
- },
283
- effect: {
284
- enabled: true,
285
- exporter: "unified",
286
- auto_extract_metadata: true
50
+ var __esm = (fn, res) => function __init() {
51
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
52
+ };
53
+ var __export = (target, all) => {
54
+ for (var name in all)
55
+ __defProp(target, name, { get: all[name], enumerable: true });
56
+ };
57
+ var __copyProps = (to, from, except, desc) => {
58
+ if (from && typeof from === "object" || typeof from === "function") {
59
+ for (let key of __getOwnPropNames(from))
60
+ if (!__hasOwnProp.call(to, key) && key !== except)
61
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
287
62
  }
63
+ return to;
288
64
  };
65
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
66
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
289
67
  function parseAndValidateConfig(content) {
290
68
  let parsed;
291
69
  if (typeof content === "string") {
@@ -295,262 +73,508 @@ function parseAndValidateConfig(content) {
295
73
  }
296
74
  return InstrumentationConfigSchema.parse(parsed);
297
75
  }
298
- (class extends effect.Data.TaggedError("ConfigError") {
299
- get message() {
300
- return this.reason;
301
- }
302
- });
303
- var ConfigUrlError = class extends effect.Data.TaggedError("ConfigUrlError") {
304
- get message() {
305
- return this.reason;
306
- }
307
- };
308
- var ConfigValidationError = class extends effect.Data.TaggedError("ConfigValidationError") {
309
- get message() {
310
- return this.reason;
311
- }
312
- };
313
- var ConfigFileError = class extends effect.Data.TaggedError("ConfigFileError") {
314
- get message() {
315
- return this.reason;
316
- }
317
- };
318
- (class extends effect.Data.TaggedError("ServiceDetectionError") {
319
- get message() {
320
- return this.reason;
321
- }
322
- });
323
- (class extends effect.Data.TaggedError("InitializationError") {
324
- get message() {
325
- return this.reason;
326
- }
327
- });
328
- (class extends effect.Data.TaggedError("ExportError") {
329
- get message() {
330
- return this.reason;
331
- }
332
- });
333
- (class extends effect.Data.TaggedError("ShutdownError") {
334
- get message() {
335
- return this.reason;
336
- }
337
- });
338
- var SECURITY_DEFAULTS = {
339
- maxConfigSize: 1e6,
340
- // 1MB
341
- requestTimeout: 5e3
342
- // 5 seconds
343
- };
344
- var ConfigLoader = class extends effect.Context.Tag("ConfigLoader")() {
345
- };
346
- var parseYamlContent = (content, uri) => effect.Effect.gen(function* () {
347
- const parsed = yield* effect.Effect.try({
348
- try: () => yaml.parse(content),
349
- catch: (error) => new ConfigValidationError({
350
- reason: uri ? `Failed to parse YAML from ${uri}` : "Failed to parse YAML",
351
- cause: error
352
- })
353
- });
354
- return yield* effect.Effect.try({
355
- try: () => InstrumentationConfigSchema.parse(parsed),
356
- catch: (error) => new ConfigValidationError({
357
- reason: uri ? `Invalid configuration schema from ${uri}` : "Invalid configuration schema",
358
- cause: error
359
- })
360
- });
361
- });
362
- var loadFromFileWithFs = (fs3, path3, uri) => effect.Effect.gen(function* () {
363
- const content = yield* fs3.readFileString(path3).pipe(
364
- effect.Effect.mapError(
365
- (error) => new ConfigFileError({
366
- reason: `Failed to read config file at ${uri}`,
367
- cause: error
368
- })
369
- )
370
- );
371
- if (content.length > SECURITY_DEFAULTS.maxConfigSize) {
372
- return yield* effect.Effect.fail(
373
- new ConfigFileError({
374
- reason: `Config file exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
375
- })
376
- );
377
- }
378
- return yield* parseYamlContent(content, uri);
379
- });
380
- var loadFromHttpWithClient = (client, url) => effect.Effect.scoped(
381
- effect.Effect.gen(function* () {
382
- if (url.startsWith("http://")) {
383
- return yield* effect.Effect.fail(
384
- new ConfigUrlError({
385
- reason: "Insecure protocol: only HTTPS URLs are allowed"
76
+ var __defProp2, __defNormalProp2, __publicField2, PatternConfigSchema, AutoIsolationConfigSchema, SpanNamingRuleSchema, AutoInstrumentationConfigSchema, OperationTracingConfigSchema, HttpFilteringConfigSchema, ExporterConfigSchema, InstrumentationConfigSchema, defaultConfig, ConfigUrlError, ConfigValidationError, ConfigFileError, SECURITY_DEFAULTS, ConfigLoader, parseYamlContent, loadFromFileWithFs, loadFromHttpWithClient, makeConfigLoader, Logger, logger;
77
+ var init_dist = __esm({
78
+ "../core/target/dist/index.js"() {
79
+ __defProp2 = Object.defineProperty;
80
+ __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
81
+ __publicField2 = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value);
82
+ PatternConfigSchema = zod.z.object({
83
+ pattern: zod.z.string(),
84
+ enabled: zod.z.boolean().optional(),
85
+ description: zod.z.string().optional()
86
+ });
87
+ AutoIsolationConfigSchema = zod.z.object({
88
+ // Global enable/disable for auto-isolation
89
+ enabled: zod.z.boolean().default(false),
90
+ // Which operators to auto-isolate
91
+ operators: zod.z.object({
92
+ fiberset_run: zod.z.boolean().default(true),
93
+ effect_fork: zod.z.boolean().default(true),
94
+ effect_fork_daemon: zod.z.boolean().default(true),
95
+ effect_fork_in: zod.z.boolean().default(false)
96
+ }).default({}),
97
+ // Virtual parent tracking configuration
98
+ tracking: zod.z.object({
99
+ use_span_links: zod.z.boolean().default(true),
100
+ use_attributes: zod.z.boolean().default(true),
101
+ capture_logical_parent: zod.z.boolean().default(true)
102
+ }).default({}),
103
+ // Span categorization
104
+ attributes: zod.z.object({
105
+ category: zod.z.string().default("background_task"),
106
+ add_metadata: zod.z.boolean().default(true)
107
+ }).default({})
108
+ });
109
+ SpanNamingRuleSchema = zod.z.object({
110
+ // Match criteria (all specified criteria must match)
111
+ match: zod.z.object({
112
+ // Regex pattern to match file path
113
+ file: zod.z.string().optional(),
114
+ // Regex pattern to match function name
115
+ function: zod.z.string().optional(),
116
+ // Regex pattern to match module name
117
+ module: zod.z.string().optional()
118
+ }),
119
+ // Span name template with variables:
120
+ // {fiber_id} - Fiber ID
121
+ // {function} - Function name
122
+ // {module} - Module name
123
+ // {file} - File path
124
+ // {line} - Line number
125
+ // {operator} - Effect operator (gen, all, forEach, etc.)
126
+ // {match:field:N} - Captured regex group from match
127
+ name: zod.z.string()
128
+ });
129
+ AutoInstrumentationConfigSchema = zod.z.object({
130
+ // Enable/disable auto-instrumentation
131
+ enabled: zod.z.boolean().default(false),
132
+ // Tracing granularity
133
+ // - 'fiber': Trace at fiber creation (recommended, lower overhead)
134
+ // - 'operator': Trace each Effect operator (higher granularity, more overhead)
135
+ granularity: zod.z.enum(["fiber", "operator"]).default("fiber"),
136
+ // Smart span naming configuration
137
+ span_naming: zod.z.object({
138
+ // Default span name template when no rules match
139
+ default: zod.z.string().default("effect.fiber.{fiber_id}"),
140
+ // Infer span names from source code (requires stack trace parsing)
141
+ // Adds ~50-100μs overhead per fiber
142
+ infer_from_source: zod.z.boolean().default(true),
143
+ // Naming rules (first match wins)
144
+ rules: zod.z.array(SpanNamingRuleSchema).default([])
145
+ }).default({}),
146
+ // Span relationship configuration for forked fibers
147
+ // Controls how child fiber spans relate to their parent/forking context
148
+ span_relationships: zod.z.object({
149
+ // Relationship type between forked fiber spans and their parent context
150
+ // - 'parent-child': Use parent-child relationship (default, traditional tracing)
151
+ // Parent span shows child as nested. Works well with most observability tools.
152
+ // - 'span-links': Use span links (semantically correct for async forks per OTel spec)
153
+ // Fibers get independent traces linked to parent. Better for long-running fibers.
154
+ // - 'both': Create parent-child AND add span links
155
+ // Maximum visibility but may create redundant data.
156
+ type: zod.z.enum(["parent-child", "span-links", "both"]).default("parent-child"),
157
+ // Custom attributes to add to span links (only used when type includes links)
158
+ link_attributes: zod.z.object({
159
+ // Link type identifier
160
+ "link.type": zod.z.string().default("fork"),
161
+ // Custom attributes (key-value pairs)
162
+ custom: zod.z.record(zod.z.string()).optional()
163
+ }).optional()
164
+ }).default({}),
165
+ // Pattern-based filtering
166
+ filter: zod.z.object({
167
+ // Only trace spans matching these patterns (empty = trace all)
168
+ include: zod.z.array(zod.z.string()).default([]),
169
+ // Never trace spans matching these patterns
170
+ exclude: zod.z.array(zod.z.string()).default([])
171
+ }).default({}),
172
+ // Performance controls
173
+ performance: zod.z.object({
174
+ // Sample rate (0.0 - 1.0)
175
+ sampling_rate: zod.z.number().min(0).max(1).default(1),
176
+ // Skip fibers shorter than this duration (e.g., "10ms", "100 millis")
177
+ min_duration: zod.z.string().default("0ms"),
178
+ // Maximum concurrent traced fibers (0 = unlimited)
179
+ max_concurrent: zod.z.number().default(0)
180
+ }).default({}),
181
+ // Automatic metadata extraction
182
+ metadata: zod.z.object({
183
+ // Extract Effect fiber information
184
+ fiber_info: zod.z.boolean().default(true),
185
+ // Extract source location (file:line)
186
+ source_location: zod.z.boolean().default(true),
187
+ // Extract parent fiber information
188
+ parent_fiber: zod.z.boolean().default(true)
189
+ }).default({})
190
+ });
191
+ OperationTracingConfigSchema = zod.z.object({
192
+ // Enable/disable operation tracing
193
+ enabled: zod.z.boolean().default(false),
194
+ // Global span naming settings
195
+ span_naming: zod.z.object({
196
+ // Include source location (file:line) in span name
197
+ // Default: true - produces "effect.all (index.ts:42)"
198
+ // When false - produces "effect.all"
199
+ include_location: zod.z.boolean().default(true),
200
+ // Span name template with variables:
201
+ // {op} - Operation name (all, forEach, retry, etc.)
202
+ // {file} - Full file path
203
+ // {filename} - Just the filename (basename)
204
+ // {line} - Line number
205
+ // {column} - Column number
206
+ // Default: "effect.{op} ({filename}:{line})"
207
+ template: zod.z.string().default("effect.{op} ({filename}:{line})")
208
+ }).default({}),
209
+ // Operations to trace
210
+ operations: zod.z.array(
211
+ zod.z.object({
212
+ // Operation name: 'all', 'forEach', 'retry', etc.
213
+ name: zod.z.string(),
214
+ // Custom span name template (overrides global span_naming.template)
215
+ // Supports same variables: {op}, {file}, {filename}, {line}, {column}
216
+ span_name: zod.z.string().optional(),
217
+ // Include item count in span attributes
218
+ include_count: zod.z.boolean().default(true),
219
+ // Include stack trace in span attributes
220
+ include_stack: zod.z.boolean().default(true)
386
221
  })
387
- );
388
- }
389
- const request = HttpClientRequest__namespace.get(url).pipe(
390
- HttpClientRequest__namespace.setHeaders({
391
- Accept: "application/yaml, text/yaml, application/x-yaml"
392
- })
393
- );
394
- const response = yield* client.execute(request).pipe(
395
- effect.Effect.timeout(`${SECURITY_DEFAULTS.requestTimeout} millis`),
396
- effect.Effect.mapError((error) => {
397
- if (error._tag === "TimeoutException") {
398
- return new ConfigUrlError({
399
- reason: `Config fetch timeout after ${SECURITY_DEFAULTS.requestTimeout}ms from ${url}`
400
- });
401
- }
402
- return new ConfigUrlError({
403
- reason: `Failed to load config from URL: ${url}`,
222
+ ).default([])
223
+ });
224
+ HttpFilteringConfigSchema = zod.z.object({
225
+ // Patterns to ignore for outgoing HTTP requests (string patterns only in YAML)
226
+ ignore_outgoing_urls: zod.z.array(zod.z.string()).optional(),
227
+ // Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
228
+ ignore_incoming_paths: zod.z.array(zod.z.string()).optional(),
229
+ // Require parent span for outgoing requests (prevents root spans for HTTP calls)
230
+ require_parent_for_outgoing_spans: zod.z.boolean().optional(),
231
+ // Trace context propagation configuration
232
+ // Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
233
+ propagate_trace_context: zod.z.object({
234
+ // Strategy for trace propagation
235
+ // - "all": Propagate to all cross-origin requests (may cause CORS errors)
236
+ // - "none": Never propagate trace headers
237
+ // - "same-origin": Only propagate to same-origin requests (default, safe)
238
+ // - "patterns": Propagate based on include_urls patterns
239
+ strategy: zod.z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
240
+ // URL patterns to include when strategy is "patterns"
241
+ // Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
242
+ include_urls: zod.z.array(zod.z.string()).optional()
243
+ }).optional()
244
+ });
245
+ ExporterConfigSchema = zod.z.object({
246
+ // Exporter type: 'otlp' | 'console' | 'none'
247
+ // - 'otlp': Export to OTLP endpoint (production)
248
+ // - 'console': Log spans to console (development)
249
+ // - 'none': No export (disable tracing)
250
+ type: zod.z.enum(["otlp", "console", "none"]).default("otlp"),
251
+ // OTLP endpoint URL (for type: otlp)
252
+ // Defaults to OTEL_EXPORTER_OTLP_ENDPOINT env var or http://localhost:4318
253
+ endpoint: zod.z.string().optional(),
254
+ // Custom headers to send with OTLP requests (for type: otlp)
255
+ // Useful for authentication (x-api-key, Authorization, etc.)
256
+ headers: zod.z.record(zod.z.string()).optional(),
257
+ // Span processor type
258
+ // - 'batch': Batch spans for export (production, lower overhead)
259
+ // - 'simple': Export immediately (development, no batching delay)
260
+ processor: zod.z.enum(["batch", "simple"]).default("batch"),
261
+ // Batch processor settings (for processor: batch)
262
+ batch: zod.z.object({
263
+ // Max time to wait before exporting (milliseconds)
264
+ scheduled_delay_millis: zod.z.number().default(1e3),
265
+ // Max batch size
266
+ max_export_batch_size: zod.z.number().default(100)
267
+ }).optional()
268
+ });
269
+ InstrumentationConfigSchema = zod.z.object({
270
+ version: zod.z.string(),
271
+ instrumentation: zod.z.object({
272
+ enabled: zod.z.boolean(),
273
+ description: zod.z.string().optional(),
274
+ logging: zod.z.enum(["on", "off", "minimal"]).optional().default("on"),
275
+ instrument_patterns: zod.z.array(PatternConfigSchema),
276
+ ignore_patterns: zod.z.array(PatternConfigSchema)
277
+ }),
278
+ effect: zod.z.object({
279
+ // Enable/disable Effect tracing entirely
280
+ // When false, EffectInstrumentationLive returns Layer.empty
281
+ enabled: zod.z.boolean().default(true),
282
+ // Exporter mode (legacy - use exporter.type instead):
283
+ // - "unified": Use global TracerProvider from Node SDK (recommended, enables filtering)
284
+ // - "standalone": Use Effect's own OTLP exporter (bypasses Node SDK filtering)
285
+ exporter: zod.z.enum(["unified", "standalone"]).default("unified"),
286
+ // Exporter configuration (for auto-instrumentation)
287
+ exporter_config: ExporterConfigSchema.optional(),
288
+ auto_extract_metadata: zod.z.boolean(),
289
+ auto_isolation: AutoIsolationConfigSchema.optional(),
290
+ // Auto-instrumentation: automatic tracing of all Effect fibers
291
+ auto_instrumentation: AutoInstrumentationConfigSchema.optional(),
292
+ // Operation tracing: automatic tracing of Effect.all, Effect.forEach, etc.
293
+ operation_tracing: OperationTracingConfigSchema.optional()
294
+ }).optional(),
295
+ http: HttpFilteringConfigSchema.optional()
296
+ });
297
+ defaultConfig = {
298
+ version: "1.0",
299
+ instrumentation: {
300
+ enabled: true,
301
+ logging: "on",
302
+ description: "Default instrumentation configuration",
303
+ instrument_patterns: [
304
+ { pattern: "^app\\.", enabled: true, description: "Application operations" },
305
+ { pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
306
+ { pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
307
+ ],
308
+ ignore_patterns: [
309
+ { pattern: "^test\\.", description: "Test utilities" },
310
+ { pattern: "^internal\\.", description: "Internal operations" },
311
+ { pattern: "^health\\.", description: "Health checks" }
312
+ ]
313
+ },
314
+ effect: {
315
+ enabled: true,
316
+ exporter: "unified",
317
+ auto_extract_metadata: true
318
+ }
319
+ };
320
+ (class extends effect.Data.TaggedError("ConfigError") {
321
+ get message() {
322
+ return this.reason;
323
+ }
324
+ });
325
+ ConfigUrlError = class extends effect.Data.TaggedError("ConfigUrlError") {
326
+ get message() {
327
+ return this.reason;
328
+ }
329
+ };
330
+ ConfigValidationError = class extends effect.Data.TaggedError("ConfigValidationError") {
331
+ get message() {
332
+ return this.reason;
333
+ }
334
+ };
335
+ ConfigFileError = class extends effect.Data.TaggedError("ConfigFileError") {
336
+ get message() {
337
+ return this.reason;
338
+ }
339
+ };
340
+ (class extends effect.Data.TaggedError("ServiceDetectionError") {
341
+ get message() {
342
+ return this.reason;
343
+ }
344
+ });
345
+ (class extends effect.Data.TaggedError("InitializationError") {
346
+ get message() {
347
+ return this.reason;
348
+ }
349
+ });
350
+ (class extends effect.Data.TaggedError("ExportError") {
351
+ get message() {
352
+ return this.reason;
353
+ }
354
+ });
355
+ (class extends effect.Data.TaggedError("ShutdownError") {
356
+ get message() {
357
+ return this.reason;
358
+ }
359
+ });
360
+ SECURITY_DEFAULTS = {
361
+ maxConfigSize: 1e6,
362
+ // 1MB
363
+ requestTimeout: 5e3
364
+ // 5 seconds
365
+ };
366
+ ConfigLoader = class extends effect.Context.Tag("ConfigLoader")() {
367
+ };
368
+ parseYamlContent = (content, uri) => effect.Effect.gen(function* () {
369
+ const parsed = yield* effect.Effect.try({
370
+ try: () => yaml.parse(content),
371
+ catch: (error) => new ConfigValidationError({
372
+ reason: uri ? `Failed to parse YAML from ${uri}` : "Failed to parse YAML",
404
373
  cause: error
405
- });
406
- })
407
- );
408
- if (response.status >= 400) {
409
- return yield* effect.Effect.fail(
410
- new ConfigUrlError({
411
- reason: `HTTP ${response.status} from ${url}`
412
374
  })
413
- );
414
- }
415
- const text = yield* response.text.pipe(
416
- effect.Effect.mapError(
417
- (error) => new ConfigUrlError({
418
- reason: `Failed to read response body from ${url}`,
375
+ });
376
+ return yield* effect.Effect.try({
377
+ try: () => InstrumentationConfigSchema.parse(parsed),
378
+ catch: (error) => new ConfigValidationError({
379
+ reason: uri ? `Invalid configuration schema from ${uri}` : "Invalid configuration schema",
419
380
  cause: error
420
381
  })
421
- )
422
- );
423
- if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
424
- return yield* effect.Effect.fail(
425
- new ConfigUrlError({
426
- reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
427
- })
382
+ });
383
+ });
384
+ loadFromFileWithFs = (fs2, path3, uri) => effect.Effect.gen(function* () {
385
+ const content = yield* fs2.readFileString(path3).pipe(
386
+ effect.Effect.mapError(
387
+ (error) => new ConfigFileError({
388
+ reason: `Failed to read config file at ${uri}`,
389
+ cause: error
390
+ })
391
+ )
428
392
  );
429
- }
430
- return yield* parseYamlContent(text, url);
431
- })
432
- );
433
- var makeConfigLoader = effect.Effect.gen(function* () {
434
- const fs3 = yield* effect.Effect.serviceOption(FileSystem.FileSystem);
435
- const http = yield* HttpClient__namespace.HttpClient;
436
- const loadFromUriUncached = (uri) => effect.Effect.gen(function* () {
437
- if (uri.startsWith("file://")) {
438
- const path3 = uri.slice(7);
439
- if (fs3._tag === "None") {
393
+ if (content.length > SECURITY_DEFAULTS.maxConfigSize) {
440
394
  return yield* effect.Effect.fail(
441
395
  new ConfigFileError({
442
- reason: "FileSystem not available (browser environment?)",
443
- cause: { uri }
396
+ reason: `Config file exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
444
397
  })
445
398
  );
446
399
  }
447
- return yield* loadFromFileWithFs(fs3.value, path3, uri);
448
- }
449
- if (uri.startsWith("http://") || uri.startsWith("https://")) {
450
- return yield* loadFromHttpWithClient(http, uri);
451
- }
452
- if (fs3._tag === "Some") {
453
- return yield* loadFromFileWithFs(fs3.value, uri, uri);
454
- } else {
455
- return yield* loadFromHttpWithClient(http, uri);
456
- }
457
- });
458
- const loadFromUriCached = yield* effect.Effect.cachedFunction(loadFromUriUncached);
459
- return ConfigLoader.of({
460
- loadFromUri: loadFromUriCached,
461
- loadFromInline: (content) => effect.Effect.gen(function* () {
462
- if (typeof content === "string") {
463
- return yield* parseYamlContent(content);
464
- }
465
- return yield* effect.Effect.try({
466
- try: () => InstrumentationConfigSchema.parse(content),
467
- catch: (error) => new ConfigValidationError({
468
- reason: "Invalid configuration schema",
469
- cause: error
400
+ return yield* parseYamlContent(content, uri);
401
+ });
402
+ loadFromHttpWithClient = (client, url) => effect.Effect.scoped(
403
+ effect.Effect.gen(function* () {
404
+ if (url.startsWith("http://")) {
405
+ return yield* effect.Effect.fail(
406
+ new ConfigUrlError({
407
+ reason: "Insecure protocol: only HTTPS URLs are allowed"
408
+ })
409
+ );
410
+ }
411
+ const request = HttpClientRequest__namespace.get(url).pipe(
412
+ HttpClientRequest__namespace.setHeaders({
413
+ Accept: "application/yaml, text/yaml, application/x-yaml"
414
+ })
415
+ );
416
+ const response = yield* client.execute(request).pipe(
417
+ effect.Effect.timeout(`${SECURITY_DEFAULTS.requestTimeout} millis`),
418
+ effect.Effect.mapError((error) => {
419
+ if (error._tag === "TimeoutException") {
420
+ return new ConfigUrlError({
421
+ reason: `Config fetch timeout after ${SECURITY_DEFAULTS.requestTimeout}ms from ${url}`
422
+ });
423
+ }
424
+ return new ConfigUrlError({
425
+ reason: `Failed to load config from URL: ${url}`,
426
+ cause: error
427
+ });
428
+ })
429
+ );
430
+ if (response.status >= 400) {
431
+ return yield* effect.Effect.fail(
432
+ new ConfigUrlError({
433
+ reason: `HTTP ${response.status} from ${url}`
434
+ })
435
+ );
436
+ }
437
+ const text = yield* response.text.pipe(
438
+ effect.Effect.mapError(
439
+ (error) => new ConfigUrlError({
440
+ reason: `Failed to read response body from ${url}`,
441
+ cause: error
442
+ })
443
+ )
444
+ );
445
+ if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
446
+ return yield* effect.Effect.fail(
447
+ new ConfigUrlError({
448
+ reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
449
+ })
450
+ );
451
+ }
452
+ return yield* parseYamlContent(text, url);
453
+ })
454
+ );
455
+ makeConfigLoader = effect.Effect.gen(function* () {
456
+ const fs2 = yield* effect.Effect.serviceOption(FileSystem.FileSystem);
457
+ const http = yield* HttpClient__namespace.HttpClient;
458
+ const loadFromUriUncached = (uri) => effect.Effect.gen(function* () {
459
+ if (uri.startsWith("file://")) {
460
+ const path3 = uri.slice(7);
461
+ if (fs2._tag === "None") {
462
+ return yield* effect.Effect.fail(
463
+ new ConfigFileError({
464
+ reason: "FileSystem not available (browser environment?)",
465
+ cause: { uri }
466
+ })
467
+ );
468
+ }
469
+ return yield* loadFromFileWithFs(fs2.value, path3, uri);
470
+ }
471
+ if (uri.startsWith("http://") || uri.startsWith("https://")) {
472
+ return yield* loadFromHttpWithClient(http, uri);
473
+ }
474
+ if (fs2._tag === "Some") {
475
+ return yield* loadFromFileWithFs(fs2.value, uri, uri);
476
+ } else {
477
+ return yield* loadFromHttpWithClient(http, uri);
478
+ }
479
+ });
480
+ const loadFromUriCached = yield* effect.Effect.cachedFunction(loadFromUriUncached);
481
+ return ConfigLoader.of({
482
+ loadFromUri: loadFromUriCached,
483
+ loadFromInline: (content) => effect.Effect.gen(function* () {
484
+ if (typeof content === "string") {
485
+ return yield* parseYamlContent(content);
486
+ }
487
+ return yield* effect.Effect.try({
488
+ try: () => InstrumentationConfigSchema.parse(content),
489
+ catch: (error) => new ConfigValidationError({
490
+ reason: "Invalid configuration schema",
491
+ cause: error
492
+ })
493
+ });
470
494
  })
471
495
  });
472
- })
473
- });
474
- });
475
- effect.Layer.effect(ConfigLoader, makeConfigLoader);
476
- var Logger = class {
477
- constructor() {
478
- __publicField2(this, "level", "on");
479
- __publicField2(this, "hasLoggedMinimal", false);
480
- }
481
- /**
482
- * Set the logging level
483
- */
484
- setLevel(level) {
485
- this.level = level;
486
- this.hasLoggedMinimal = false;
487
- }
488
- /**
489
- * Get the current logging level
490
- */
491
- getLevel() {
492
- return this.level;
493
- }
494
- /**
495
- * Log a minimal initialization message (only shown once in minimal mode)
496
- */
497
- minimal(message) {
498
- if (this.level === "off") {
499
- return;
500
- }
501
- if (this.level === "minimal" && !this.hasLoggedMinimal) {
502
- console.log(message);
503
- this.hasLoggedMinimal = true;
504
- return;
505
- }
506
- if (this.level === "on") {
507
- console.log(message);
508
- }
509
- }
510
- /**
511
- * Log an informational message
512
- */
513
- log(...args) {
514
- if (this.level === "on") {
515
- console.log(...args);
516
- }
517
- }
518
- /**
519
- * Log a warning message (shown in minimal mode)
520
- */
521
- warn(...args) {
522
- if (this.level !== "off") {
523
- console.warn(...args);
524
- }
525
- }
526
- /**
527
- * Log an error message (shown in minimal mode)
528
- */
529
- error(...args) {
530
- if (this.level !== "off") {
531
- console.error(...args);
532
- }
533
- }
534
- /**
535
- * Check if full logging is enabled
536
- */
537
- isEnabled() {
538
- return this.level === "on";
539
- }
540
- /**
541
- * Check if minimal logging is enabled
542
- */
543
- isMinimal() {
544
- return this.level === "minimal";
545
- }
546
- /**
547
- * Check if logging is completely disabled
548
- */
549
- isDisabled() {
550
- return this.level === "off";
496
+ });
497
+ effect.Layer.effect(ConfigLoader, makeConfigLoader);
498
+ Logger = class {
499
+ constructor() {
500
+ __publicField2(this, "level", "on");
501
+ __publicField2(this, "hasLoggedMinimal", false);
502
+ }
503
+ /**
504
+ * Set the logging level
505
+ */
506
+ setLevel(level) {
507
+ this.level = level;
508
+ this.hasLoggedMinimal = false;
509
+ }
510
+ /**
511
+ * Get the current logging level
512
+ */
513
+ getLevel() {
514
+ return this.level;
515
+ }
516
+ /**
517
+ * Log a minimal initialization message (only shown once in minimal mode)
518
+ */
519
+ minimal(message) {
520
+ if (this.level === "off") {
521
+ return;
522
+ }
523
+ if (this.level === "minimal" && !this.hasLoggedMinimal) {
524
+ console.log(message);
525
+ this.hasLoggedMinimal = true;
526
+ return;
527
+ }
528
+ if (this.level === "on") {
529
+ console.log(message);
530
+ }
531
+ }
532
+ /**
533
+ * Log an informational message
534
+ */
535
+ log(...args) {
536
+ if (this.level === "on") {
537
+ console.log(...args);
538
+ }
539
+ }
540
+ /**
541
+ * Log a warning message (shown in minimal mode)
542
+ */
543
+ warn(...args) {
544
+ if (this.level !== "off") {
545
+ console.warn(...args);
546
+ }
547
+ }
548
+ /**
549
+ * Log an error message (shown in minimal mode)
550
+ */
551
+ error(...args) {
552
+ if (this.level !== "off") {
553
+ console.error(...args);
554
+ }
555
+ }
556
+ /**
557
+ * Check if full logging is enabled
558
+ */
559
+ isEnabled() {
560
+ return this.level === "on";
561
+ }
562
+ /**
563
+ * Check if minimal logging is enabled
564
+ */
565
+ isMinimal() {
566
+ return this.level === "minimal";
567
+ }
568
+ /**
569
+ * Check if logging is completely disabled
570
+ */
571
+ isDisabled() {
572
+ return this.level === "off";
573
+ }
574
+ };
575
+ logger = new Logger();
551
576
  }
552
- };
553
- var logger = new Logger();
577
+ });
554
578
  async function loadFromFile(filePath) {
555
579
  const { readFile } = await import('fs/promises');
556
580
  const content = await readFile(filePath, "utf-8");
@@ -591,170 +615,589 @@ async function loadConfigWithOptions(options = {}) {
591
615
  if (options.configPath) {
592
616
  return loadConfig(options.configPath);
593
617
  }
594
- const { existsSync: existsSync3 } = await import('fs');
618
+ const { existsSync: existsSync2 } = await import('fs');
595
619
  const { join: join2 } = await import('path');
596
620
  const defaultPath = join2(process.cwd(), "instrumentation.yaml");
597
- if (existsSync3(defaultPath)) {
621
+ if (existsSync2(defaultPath)) {
598
622
  return loadConfig(defaultPath);
599
623
  }
600
624
  return defaultConfig;
601
625
  }
602
-
603
- // src/integrations/effect/auto/config.ts
604
- var defaultAutoTracingConfig = {
605
- enabled: false,
606
- granularity: "fiber",
607
- span_naming: {
608
- default: "effect.fiber.{fiber_id}",
609
- infer_from_source: true,
610
- rules: []
611
- },
612
- span_relationships: {
613
- type: "parent-child"
614
- },
615
- filter: {
616
- include: [],
617
- exclude: []
618
- },
619
- performance: {
620
- sampling_rate: 1,
621
- min_duration: "0ms",
622
- max_concurrent: 0
623
- },
624
- metadata: {
625
- fiber_info: true,
626
- source_location: true,
627
- parent_fiber: true
628
- }
629
- };
630
- var AutoTracingConfig = class extends effect.Context.Tag("AutoTracingConfig")() {
631
- };
632
- var loadAutoTracingConfig = (options) => effect.Effect.gen(function* () {
633
- const config = yield* effect.Effect.tryPromise({
634
- try: () => loadConfigWithOptions(options),
635
- catch: (error) => {
636
- logger.log(`@atrim/auto-trace: Failed to load config: ${error}`);
637
- return error;
638
- }
639
- }).pipe(effect.Effect.catchAll(() => effect.Effect.succeed(null)));
640
- if (!config) {
641
- logger.log("@atrim/auto-trace: No config found, using defaults");
642
- return defaultAutoTracingConfig;
626
+ var init_config_loader = __esm({
627
+ "src/core/config-loader.ts"() {
628
+ init_dist();
643
629
  }
644
- const autoConfig = config.effect?.auto_instrumentation;
645
- if (!autoConfig) {
646
- logger.log("@atrim/auto-trace: No auto_instrumentation config, using defaults");
647
- return defaultAutoTracingConfig;
648
- }
649
- const parsed = AutoInstrumentationConfigSchema.safeParse(autoConfig);
650
- if (!parsed.success) {
651
- logger.log(`@atrim/auto-trace: Invalid config, using defaults: ${parsed.error.message}`);
652
- return defaultAutoTracingConfig;
630
+ });
631
+ exports.defaultAutoTracingConfig = void 0; exports.AutoTracingConfig = void 0; exports.loadAutoTracingConfig = void 0; exports.loadAutoTracingConfigSync = void 0; exports.AutoTracingConfigLive = void 0; exports.AutoTracingConfigLayer = void 0; exports.loadFullConfigSync = void 0;
632
+ var init_config = __esm({
633
+ "src/integrations/effect/auto/config.ts"() {
634
+ init_dist();
635
+ init_config_loader();
636
+ exports.defaultAutoTracingConfig = {
637
+ enabled: false,
638
+ granularity: "fiber",
639
+ span_naming: {
640
+ default: "effect.fiber.{fiber_id}",
641
+ infer_from_source: true,
642
+ rules: []
643
+ },
644
+ span_relationships: {
645
+ type: "parent-child"
646
+ },
647
+ filter: {
648
+ include: [],
649
+ exclude: []
650
+ },
651
+ performance: {
652
+ sampling_rate: 1,
653
+ min_duration: "0ms",
654
+ max_concurrent: 0
655
+ },
656
+ metadata: {
657
+ fiber_info: true,
658
+ source_location: true,
659
+ parent_fiber: true
660
+ }
661
+ };
662
+ exports.AutoTracingConfig = class extends effect.Context.Tag("AutoTracingConfig")() {
663
+ };
664
+ exports.loadAutoTracingConfig = (options) => effect.Effect.gen(function* () {
665
+ const config = yield* effect.Effect.tryPromise({
666
+ try: () => loadConfigWithOptions(options),
667
+ catch: (error) => {
668
+ logger.log(`@atrim/auto-trace: Failed to load config: ${error}`);
669
+ return error;
670
+ }
671
+ }).pipe(effect.Effect.catchAll(() => effect.Effect.succeed(null)));
672
+ if (!config) {
673
+ logger.log("@atrim/auto-trace: No config found, using defaults");
674
+ return exports.defaultAutoTracingConfig;
675
+ }
676
+ const autoConfig = config.effect?.auto_instrumentation;
677
+ if (!autoConfig) {
678
+ logger.log("@atrim/auto-trace: No auto_instrumentation config, using defaults");
679
+ return exports.defaultAutoTracingConfig;
680
+ }
681
+ const parsed = AutoInstrumentationConfigSchema.safeParse(autoConfig);
682
+ if (!parsed.success) {
683
+ logger.log(`@atrim/auto-trace: Invalid config, using defaults: ${parsed.error.message}`);
684
+ return exports.defaultAutoTracingConfig;
685
+ }
686
+ logger.log("@atrim/auto-trace: Loaded config from instrumentation.yaml");
687
+ return parsed.data;
688
+ });
689
+ exports.loadAutoTracingConfigSync = () => {
690
+ return exports.defaultAutoTracingConfig;
691
+ };
692
+ exports.AutoTracingConfigLive = effect.Layer.effect(exports.AutoTracingConfig, exports.loadAutoTracingConfig());
693
+ exports.AutoTracingConfigLayer = (config) => effect.Layer.succeed(exports.AutoTracingConfig, config);
694
+ exports.loadFullConfigSync = () => {
695
+ const defaultPath = path2__namespace.join(process.cwd(), "instrumentation.yaml");
696
+ try {
697
+ if (fs__namespace.existsSync(defaultPath)) {
698
+ const content = fs__namespace.readFileSync(defaultPath, "utf-8");
699
+ const parsed = yaml__namespace.parse(content);
700
+ const result = InstrumentationConfigSchema.safeParse(parsed);
701
+ if (result.success) {
702
+ logger.log(`@atrim/auto-trace: Loaded config from ${defaultPath}`);
703
+ return result.data;
704
+ } else {
705
+ logger.log(`@atrim/auto-trace: Invalid config, using defaults: ${result.error.message}`);
706
+ return defaultConfig;
707
+ }
708
+ }
709
+ } catch (error) {
710
+ logger.log(`@atrim/auto-trace: Failed to load config: ${error}`);
711
+ }
712
+ logger.log("@atrim/auto-trace: No config found, using defaults");
713
+ return defaultConfig;
714
+ };
653
715
  }
654
- logger.log("@atrim/auto-trace: Loaded config from instrumentation.yaml");
655
- return parsed.data;
656
716
  });
657
- var loadAutoTracingConfigSync = () => {
658
- return defaultAutoTracingConfig;
659
- };
660
- var AutoTracingConfigLive = effect.Layer.effect(AutoTracingConfig, loadAutoTracingConfig());
661
- var AutoTracingConfigLayer = (config) => effect.Layer.succeed(AutoTracingConfig, config);
662
- var loadFullConfig = (options) => effect.Effect.gen(function* () {
663
- const config = yield* effect.Effect.tryPromise({
664
- try: () => loadConfigWithOptions(options),
665
- catch: (error) => {
666
- logger.log(`@atrim/auto-trace: Failed to load config: ${error}`);
667
- return error;
668
- }
669
- }).pipe(effect.Effect.catchAll(() => effect.Effect.succeed(null)));
670
- if (!config) {
671
- logger.log("@atrim/auto-trace: No config found, using defaults");
672
- return defaultConfig;
717
+ exports.AutoTracingEnabled = void 0; exports.AutoTracingSpanName = void 0; exports.withoutAutoTracing = void 0; exports.setSpanName = void 0;
718
+ var init_span_control = __esm({
719
+ "src/integrations/effect/auto/span-control.ts"() {
720
+ exports.AutoTracingEnabled = effect.FiberRef.unsafeMake(true);
721
+ exports.AutoTracingSpanName = effect.FiberRef.unsafeMake(effect.Option.none());
722
+ exports.withoutAutoTracing = (effect$1) => effect$1.pipe(effect.Effect.locally(exports.AutoTracingEnabled, false));
723
+ exports.setSpanName = (name) => (effect$1) => effect$1.pipe(effect.Effect.locally(exports.AutoTracingSpanName, effect.Option.some(name)));
673
724
  }
674
- return config;
675
725
  });
676
- var loadFullConfigSync = () => {
677
- const defaultPath = path2__namespace.join(process.cwd(), "instrumentation.yaml");
678
- try {
679
- if (fs__namespace.existsSync(defaultPath)) {
680
- const content = fs__namespace.readFileSync(defaultPath, "utf-8");
681
- const parsed = yaml__namespace.parse(content);
682
- const result = InstrumentationConfigSchema.safeParse(parsed);
683
- if (result.success) {
684
- logger.log(`@atrim/auto-trace: Loaded config from ${defaultPath}`);
685
- return result.data;
686
- } else {
687
- logger.log(`@atrim/auto-trace: Invalid config, using defaults: ${result.error.message}`);
688
- return defaultConfig;
689
- }
690
- }
691
- } catch (error) {
692
- logger.log(`@atrim/auto-trace: Failed to load config: ${error}`);
726
+
727
+ // src/integrations/effect/auto/unified-tracing-supervisor.ts
728
+ var unified_tracing_supervisor_exports = {};
729
+ __export(unified_tracing_supervisor_exports, {
730
+ AutoTracingEnabled: () => exports.AutoTracingEnabled,
731
+ AutoTracingSpanName: () => exports.AutoTracingSpanName,
732
+ UnifiedTracingLive: () => exports.UnifiedTracingLive,
733
+ UnifiedTracingSupervisor: () => exports.UnifiedTracingSupervisor,
734
+ createUnifiedTracingLayer: () => exports.createUnifiedTracingLayer,
735
+ enableOpSupervision: () => exports.enableOpSupervision,
736
+ flushAndShutdown: () => exports.flushAndShutdown,
737
+ forceFlush: () => exports.forceFlush,
738
+ setSpanName: () => exports.setSpanName,
739
+ withAutoTracing: () => exports.withAutoTracing,
740
+ withUnifiedTracing: () => exports.withUnifiedTracing,
741
+ withoutAutoTracing: () => exports.withoutAutoTracing
742
+ });
743
+ function getOperationMeta(effect) {
744
+ const trace2 = effect.trace;
745
+ if (trace2 && trace2._tag === "OperationMeta") {
746
+ return trace2;
693
747
  }
694
- logger.log("@atrim/auto-trace: No config found, using defaults");
695
- return defaultConfig;
696
- };
697
- var CapturedSourceLocation = effect.FiberRef.unsafeMake(void 0);
698
- function captureCallSite(skipFrames = 0) {
699
- const originalLimit = Error.stackTraceLimit;
700
- Error.stackTraceLimit = 10;
701
- const error = new Error();
702
- Error.stackTraceLimit = originalLimit;
703
- if (!error.stack) return void 0;
704
- const lines = error.stack.split("\n");
705
- const startIndex = 3 + skipFrames;
706
- for (let i = startIndex; i < lines.length; i++) {
707
- const line = lines[i];
708
- if (line === void 0) continue;
709
- if (line.includes("@atrim/instrument") || line.includes("node_modules/effect")) {
748
+ return void 0;
749
+ }
750
+ function parseSourceLocation(stack) {
751
+ const lines = stack.split("\n");
752
+ for (const line of lines.slice(1)) {
753
+ if (line.includes("node_modules") || line.includes("/effect/") || line.includes("fiberRuntime.ts") || line.includes("core.ts")) {
710
754
  continue;
711
755
  }
712
- const match = line.match(/at\s+(?:(.+?)\s+)?\(?(.+?):(\d+):(\d+)\)?/);
713
- if (match) {
714
- const [, funcName, filePath, lineNum, colNum] = match;
756
+ const match = line.match(/at\s+(?:.*?\s+\()?(.+):(\d+):(\d+)\)?/);
757
+ if (match && match[1] && match[2]) {
715
758
  return {
716
- function: funcName?.trim() ?? "anonymous",
717
- file: filePath ?? "unknown",
718
- line: parseInt(lineNum ?? "0", 10),
719
- column: parseInt(colNum ?? "0", 10)
759
+ file: match[1],
760
+ line: parseInt(match[2], 10),
761
+ ...match[3] ? { column: parseInt(match[3], 10) } : {}
720
762
  };
721
763
  }
722
764
  }
723
765
  return void 0;
724
766
  }
725
- var tracedFork = (effect$1) => {
726
- const callSite = captureCallSite();
727
- if (!callSite) {
728
- return effect.Effect.fork(effect$1);
729
- }
730
- return effect.FiberRef.set(CapturedSourceLocation, callSite).pipe(effect.Effect.zipRight(effect.Effect.fork(effect$1)));
731
- };
732
- var tracedForkDaemon = (effect$1) => {
733
- const callSite = captureCallSite();
734
- if (!callSite) {
735
- return effect.Effect.forkDaemon(effect$1);
767
+ function makeSourceKey(source) {
768
+ if (!source) return "unknown";
769
+ return `${source.file}:${source.line}`;
770
+ }
771
+ function formatLocation(source) {
772
+ if (!source) return "unknown";
773
+ const filename = source.file.split("/").pop() ?? source.file;
774
+ return `${filename}:${source.line}`;
775
+ }
776
+ function getGlobalProviderSetup() {
777
+ if (_globalProviderSetup === void 0) {
778
+ _globalProviderSetup = setupGlobalTracerProvider();
736
779
  }
737
- return effect.FiberRef.set(CapturedSourceLocation, callSite).pipe(
738
- effect.Effect.zipRight(effect.Effect.forkDaemon(effect$1))
739
- );
740
- };
741
-
742
- // src/integrations/effect/auto/patch-fork.ts
743
- var patchAttempted = false;
744
- function isEffectForkPatched() {
745
- return false;
780
+ return _globalProviderSetup;
746
781
  }
747
- function patchEffectFork() {
748
- if (patchAttempted) {
749
- return;
782
+ var currentSourceLocation; exports.UnifiedTracingSupervisor = void 0; var setupGlobalTracerProvider, _globalProviderSetup; exports.createUnifiedTracingLayer = void 0; exports.UnifiedTracingLive = void 0; exports.enableOpSupervision = void 0; exports.withUnifiedTracing = void 0; exports.withAutoTracing = void 0; exports.flushAndShutdown = void 0; exports.forceFlush = void 0;
783
+ var init_unified_tracing_supervisor = __esm({
784
+ "src/integrations/effect/auto/unified-tracing-supervisor.ts"() {
785
+ init_dist();
786
+ init_config();
787
+ init_span_control();
788
+ init_span_control();
789
+ currentSourceLocation = effect.GlobalValue.globalValue(
790
+ /* @__PURE__ */ Symbol.for("effect/FiberRef/currentSourceLocation"),
791
+ () => effect.FiberRef.unsafeMake(void 0)
792
+ );
793
+ exports.UnifiedTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
794
+ constructor(config) {
795
+ super();
796
+ this.config = config;
797
+ // ========== Fork span registry ==========
798
+ // Maps sourceKey -> pending fork span (for correlating with child fibers)
799
+ __publicField(this, "pendingForkSpans", /* @__PURE__ */ new Map());
800
+ // ========== Fiber tracking ==========
801
+ __publicField(this, "fiberSpans", /* @__PURE__ */ new WeakMap());
802
+ __publicField(this, "fiberContexts", /* @__PURE__ */ new WeakMap());
803
+ __publicField(this, "fiberStartTimes", /* @__PURE__ */ new WeakMap());
804
+ // ========== Operation tracking ==========
805
+ __publicField(this, "processedEffects", /* @__PURE__ */ new WeakSet());
806
+ __publicField(this, "configuredOps");
807
+ // ========== OTel ==========
808
+ __publicField(this, "_tracer", null);
809
+ __publicField(this, "activeFiberCount", 0);
810
+ const defaultOps = [
811
+ { name: "all", includeCount: true, includeStack: true },
812
+ { name: "forEach", includeCount: true, includeStack: true },
813
+ { name: "fork", includeStack: true }
814
+ ];
815
+ this.configuredOps = new Map(defaultOps.map((op) => [op.name, op]));
816
+ logger.log("@atrim/unified-tracing: Supervisor initialized");
817
+ logger.log(` Operations: ${Array.from(this.configuredOps.keys()).join(", ")}`);
818
+ }
819
+ get tracer() {
820
+ if (!this._tracer) {
821
+ this._tracer = OtelApi__namespace.trace.getTracer("@atrim/unified-tracing", "1.0.0");
822
+ }
823
+ return this._tracer;
824
+ }
825
+ get value() {
826
+ return effect.Effect.void;
827
+ }
828
+ // ==========================================================================
829
+ // onEffect - Operation-level tracing (Effect.all, Effect.forEach, Effect.fork)
830
+ // ==========================================================================
831
+ onEffect(fiber, effect) {
832
+ if (this.processedEffects.has(effect)) {
833
+ return;
834
+ }
835
+ const meta = getOperationMeta(effect);
836
+ if (!meta) {
837
+ return;
838
+ }
839
+ const opConfig = this.configuredOps.get(meta.op);
840
+ if (!opConfig) {
841
+ return;
842
+ }
843
+ this.processedEffects.add(effect);
844
+ const fiberId = fiber.id().id;
845
+ const location = parseSourceLocation(meta.capturedAt);
846
+ const sourceKey = makeSourceKey(location);
847
+ logger.log(`@atrim/unified-tracing: onEffect "${meta.op}" in fiber ${fiberId} at ${sourceKey}`);
848
+ const parentContext = this.resolveParentContext(fiber);
849
+ const spanName = location ? `effect.${meta.op} (${formatLocation(location)})` : `effect.${meta.op}`;
850
+ const span = this.tracer.startSpan(spanName, { kind: OtelApi__namespace.SpanKind.INTERNAL }, parentContext);
851
+ span.setAttribute("effect.operation", meta.op);
852
+ if (opConfig.includeCount && meta.count !== void 0) {
853
+ span.setAttribute("effect.item_count", meta.count);
854
+ }
855
+ if (opConfig.includeStack && location) {
856
+ span.setAttribute("code.filepath", location.file);
857
+ span.setAttribute("code.lineno", location.line);
858
+ if (location.column !== void 0) {
859
+ span.setAttribute("code.column", location.column);
860
+ }
861
+ }
862
+ logger.log(
863
+ `@atrim/unified-tracing: Created operation span "${spanName}" spanId=${span.spanContext().spanId}`
864
+ );
865
+ if (meta.op === "fork") {
866
+ const forkContext = OtelApi__namespace.trace.setSpan(parentContext, span);
867
+ this.pendingForkSpans.set(sourceKey, {
868
+ forkSpan: span,
869
+ forkContext,
870
+ timestamp: process.hrtime.bigint(),
871
+ spanEnded: false
872
+ });
873
+ logger.log(`@atrim/unified-tracing: Registered pending fork at ${sourceKey}`);
874
+ } else {
875
+ span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
876
+ span.end();
877
+ }
878
+ }
879
+ // ==========================================================================
880
+ // onStart - Fiber-level tracing
881
+ // ==========================================================================
882
+ onStart(_context, _effect, parent, fiber) {
883
+ const fiberId = fiber.id().id;
884
+ const fiberRefs = fiber.getFiberRefs();
885
+ const enabled = effect.FiberRefs.getOrDefault(fiberRefs, exports.AutoTracingEnabled);
886
+ if (!enabled) {
887
+ logger.log(`@atrim/unified-tracing: Auto-tracing disabled for fiber ${fiberId}`);
888
+ return;
889
+ }
890
+ const samplingRate = this.config.performance?.sampling_rate ?? 1;
891
+ if (samplingRate < 1 && Math.random() > samplingRate) {
892
+ return;
893
+ }
894
+ const nameOverride = effect.FiberRefs.getOrDefault(fiberRefs, exports.AutoTracingSpanName);
895
+ const sourceLocation = effect.FiberRefs.getOrDefault(fiberRefs, currentSourceLocation);
896
+ const sourceKey = makeSourceKey(sourceLocation);
897
+ logger.log(`@atrim/unified-tracing: onStart fiber ${fiberId} at ${sourceKey}`);
898
+ let parentContext;
899
+ const pendingFork = this.pendingForkSpans.get(sourceKey);
900
+ if (pendingFork) {
901
+ parentContext = pendingFork.forkContext;
902
+ logger.log(
903
+ `@atrim/unified-tracing: Matched fiber ${fiberId} to fork span at ${sourceKey} - using fork span as parent`
904
+ );
905
+ if (!pendingFork.spanEnded) {
906
+ pendingFork.forkSpan.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
907
+ pendingFork.forkSpan.end();
908
+ logger.log(`@atrim/unified-tracing: Ended fork span at ${sourceKey}`);
909
+ }
910
+ this.pendingForkSpans.delete(sourceKey);
911
+ } else {
912
+ parentContext = this.resolveParentContextFromFiberRefs(
913
+ fiberRefs,
914
+ _context,
915
+ parent
916
+ );
917
+ }
918
+ let spanName;
919
+ if (effect.Option.isSome(nameOverride)) {
920
+ spanName = nameOverride.value;
921
+ } else if (sourceLocation) {
922
+ spanName = `effect.fiber (${formatLocation(sourceLocation)})`;
923
+ } else {
924
+ spanName = `effect.fiber-${fiberId}`;
925
+ }
926
+ const span = this.tracer.startSpan(spanName, { kind: OtelApi__namespace.SpanKind.INTERNAL }, parentContext);
927
+ span.setAttribute("effect.auto_traced", true);
928
+ span.setAttribute("effect.fiber.id", fiberId);
929
+ if (sourceLocation) {
930
+ span.setAttribute("code.filepath", sourceLocation.file);
931
+ span.setAttribute("code.lineno", sourceLocation.line);
932
+ if (sourceLocation.column !== void 0) {
933
+ span.setAttribute("code.column", sourceLocation.column);
934
+ }
935
+ }
936
+ if (effect.Option.isSome(parent)) {
937
+ span.setAttribute("effect.fiber.parent_id", parent.value.id().id);
938
+ }
939
+ logger.log(
940
+ `@atrim/unified-tracing: Created fiber span "${spanName}" spanId=${span.spanContext().spanId}`
941
+ );
942
+ const newContext = OtelApi__namespace.trace.setSpan(parentContext, span);
943
+ this.fiberSpans.set(fiber, span);
944
+ this.fiberContexts.set(fiber, newContext);
945
+ this.fiberStartTimes.set(fiber, process.hrtime.bigint());
946
+ this.activeFiberCount++;
947
+ }
948
+ // ==========================================================================
949
+ // onEnd - Fiber completion
950
+ // ==========================================================================
951
+ onEnd(exit, fiber) {
952
+ const fiberId = fiber.id().id;
953
+ const span = this.fiberSpans.get(fiber);
954
+ if (!span) {
955
+ return;
956
+ }
957
+ const startTime = this.fiberStartTimes.get(fiber);
958
+ if (startTime) {
959
+ const duration = process.hrtime.bigint() - startTime;
960
+ const minDuration = this.parseMinDuration(this.config.performance?.min_duration);
961
+ if (minDuration > 0 && duration < minDuration) {
962
+ this.cleanup(fiber);
963
+ return;
964
+ }
965
+ }
966
+ if (effect.Exit.isSuccess(exit)) {
967
+ span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
968
+ } else {
969
+ span.setStatus({ code: OtelApi__namespace.SpanStatusCode.ERROR, message: "Fiber failed" });
970
+ span.setAttribute("effect.fiber.failed", true);
971
+ }
972
+ span.end();
973
+ logger.log(`@atrim/unified-tracing: Ended fiber span for fiber ${fiberId}`);
974
+ this.cleanup(fiber);
975
+ }
976
+ // ==========================================================================
977
+ // Helpers
978
+ // ==========================================================================
979
+ cleanup(fiber) {
980
+ this.fiberSpans.delete(fiber);
981
+ this.fiberContexts.delete(fiber);
982
+ this.fiberStartTimes.delete(fiber);
983
+ this.activeFiberCount--;
984
+ }
985
+ resolveParentContext(fiber) {
986
+ const fiberContext = fiber.currentContext;
987
+ const maybeParentSpan = effect.Context.getOption(fiberContext, effect.Tracer.ParentSpan);
988
+ if (effect.Option.isSome(maybeParentSpan)) {
989
+ const effectSpan = maybeParentSpan.value;
990
+ return OtelApi__namespace.trace.setSpan(
991
+ OtelApi__namespace.ROOT_CONTEXT,
992
+ OtelApi__namespace.trace.wrapSpanContext({
993
+ traceId: effectSpan.traceId,
994
+ spanId: effectSpan.spanId,
995
+ traceFlags: OtelApi__namespace.TraceFlags.SAMPLED
996
+ })
997
+ );
998
+ }
999
+ return OtelApi__namespace.ROOT_CONTEXT;
1000
+ }
1001
+ resolveParentContextFromFiberRefs(fiberRefs, context2, parent) {
1002
+ const inheritedCtx = effect.FiberRefs.getOrDefault(fiberRefs, TracerModule__namespace.currentOtelSpanContext);
1003
+ if (inheritedCtx) {
1004
+ const span = OtelApi__namespace.trace.getSpan(inheritedCtx);
1005
+ if (span) {
1006
+ logger.log(
1007
+ `@atrim/unified-tracing: Using inherited OTel context from FiberRef - spanId=${span.spanContext().spanId}`
1008
+ );
1009
+ }
1010
+ return inheritedCtx;
1011
+ }
1012
+ const maybeParentSpan = effect.Context.getOption(context2, effect.Tracer.ParentSpan);
1013
+ if (effect.Option.isSome(maybeParentSpan)) {
1014
+ const effectSpan = maybeParentSpan.value;
1015
+ logger.log(
1016
+ `@atrim/unified-tracing: Using Effect ParentSpan - traceId=${effectSpan.traceId.slice(0, 8)}..., spanId=${effectSpan.spanId.slice(0, 8)}...`
1017
+ );
1018
+ return OtelApi__namespace.trace.setSpan(
1019
+ OtelApi__namespace.ROOT_CONTEXT,
1020
+ OtelApi__namespace.trace.wrapSpanContext({
1021
+ traceId: effectSpan.traceId,
1022
+ spanId: effectSpan.spanId,
1023
+ traceFlags: OtelApi__namespace.TraceFlags.SAMPLED
1024
+ })
1025
+ );
1026
+ }
1027
+ const activeContext = OtelApi__namespace.context.active();
1028
+ const activeSpan = OtelApi__namespace.trace.getSpan(activeContext);
1029
+ if (activeSpan && activeSpan.spanContext().traceFlags === OtelApi__namespace.TraceFlags.SAMPLED) {
1030
+ logger.log(
1031
+ `@atrim/unified-tracing: Auto-bridging from active OTel context - spanId=${activeSpan.spanContext().spanId}`
1032
+ );
1033
+ return activeContext;
1034
+ }
1035
+ if (effect.Option.isSome(parent)) {
1036
+ const parentCtx = this.fiberContexts.get(parent.value);
1037
+ if (parentCtx) {
1038
+ logger.log(`@atrim/unified-tracing: Using parent fiber's context`);
1039
+ return parentCtx;
1040
+ }
1041
+ }
1042
+ return OtelApi__namespace.ROOT_CONTEXT;
1043
+ }
1044
+ parseMinDuration(duration) {
1045
+ if (!duration || duration === "0ms") return BigInt(0);
1046
+ const match = duration.match(/^(\d+)\s*(ms|millis|s|sec|seconds|us|micros)?$/i);
1047
+ if (!match) return BigInt(0);
1048
+ const value = parseInt(match[1] ?? "0", 10);
1049
+ const unit = (match[2] ?? "ms").toLowerCase();
1050
+ switch (unit) {
1051
+ case "us":
1052
+ case "micros":
1053
+ return BigInt(value) * BigInt(1e3);
1054
+ case "ms":
1055
+ case "millis":
1056
+ return BigInt(value) * BigInt(1e6);
1057
+ case "s":
1058
+ case "sec":
1059
+ case "seconds":
1060
+ return BigInt(value) * BigInt(1e9);
1061
+ default:
1062
+ return BigInt(value) * BigInt(1e6);
1063
+ }
1064
+ }
1065
+ };
1066
+ setupGlobalTracerProvider = () => {
1067
+ const config = exports.loadFullConfigSync();
1068
+ const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1069
+ const serviceVersion = process.env.npm_package_version || "1.0.0";
1070
+ const exporterConfig = config.effect?.exporter_config ?? {
1071
+ type: "otlp",
1072
+ processor: "batch"
1073
+ };
1074
+ logger.log("@atrim/unified-tracing: Setting up global TracerProvider");
1075
+ logger.log(` Service: ${serviceName}`);
1076
+ logger.log(` Exporter: ${exporterConfig.type}`);
1077
+ if (exporterConfig.type === "none") {
1078
+ logger.log('@atrim/unified-tracing: Exporter type is "none", skipping provider setup');
1079
+ return null;
1080
+ }
1081
+ let exporter;
1082
+ if (exporterConfig.type === "console") {
1083
+ exporter = new sdkTraceBase.ConsoleSpanExporter();
1084
+ } else {
1085
+ const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1086
+ const otlpConfig = {
1087
+ url: `${endpoint}/v1/traces`
1088
+ };
1089
+ if (exporterConfig.headers) {
1090
+ otlpConfig.headers = exporterConfig.headers;
1091
+ }
1092
+ exporter = new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
1093
+ }
1094
+ let spanProcessor;
1095
+ if (exporterConfig.processor === "simple" || exporterConfig.type === "console") {
1096
+ spanProcessor = new sdkTraceBase.SimpleSpanProcessor(exporter);
1097
+ } else {
1098
+ const batchConfig = exporterConfig.batch ?? {
1099
+ scheduled_delay_millis: 1e3,
1100
+ max_export_batch_size: 100
1101
+ };
1102
+ spanProcessor = new sdkTraceBase.BatchSpanProcessor(exporter, {
1103
+ scheduledDelayMillis: batchConfig.scheduled_delay_millis,
1104
+ maxExportBatchSize: batchConfig.max_export_batch_size
1105
+ });
1106
+ }
1107
+ const provider = new sdkTraceBase.BasicTracerProvider({
1108
+ resource: resources.resourceFromAttributes({
1109
+ [semanticConventions.ATTR_SERVICE_NAME]: serviceName,
1110
+ [semanticConventions.ATTR_SERVICE_VERSION]: serviceVersion
1111
+ }),
1112
+ spanProcessors: [spanProcessor]
1113
+ });
1114
+ OtelApi__namespace.trace.setGlobalTracerProvider(provider);
1115
+ logger.log("@atrim/unified-tracing: Global TracerProvider registered");
1116
+ return { provider, spanProcessor };
1117
+ };
1118
+ exports.createUnifiedTracingLayer = () => {
1119
+ const config = exports.loadFullConfigSync();
1120
+ const autoConfig = config.effect?.auto_instrumentation ?? {
1121
+ enabled: true,
1122
+ granularity: "fiber",
1123
+ span_naming: { default: "effect.{function}", infer_from_source: true, rules: [] },
1124
+ span_relationships: { type: "parent-child" },
1125
+ filter: { include: [], exclude: [] },
1126
+ performance: { sampling_rate: 1, min_duration: "0ms", max_concurrent: 0 },
1127
+ metadata: { fiber_info: true, source_location: true, parent_fiber: true }
1128
+ };
1129
+ if (!getGlobalProviderSetup()) {
1130
+ logger.log("@atrim/unified-tracing: No TracerProvider, using empty layer");
1131
+ return effect.Layer.empty;
1132
+ }
1133
+ const supervisor = new exports.UnifiedTracingSupervisor(autoConfig);
1134
+ const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
1135
+ const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1136
+ const serviceVersion = process.env.npm_package_version || "1.0.0";
1137
+ const resourceLayer = opentelemetry.Resource.layer({ serviceName, serviceVersion });
1138
+ const effectTracerLayer = opentelemetry.Tracer.layerGlobal;
1139
+ const tracerWithResource = effectTracerLayer.pipe(effect.Layer.provide(resourceLayer));
1140
+ const opSupervisionLayer = effect.Layer.effectDiscard(
1141
+ effect.Effect.patchRuntimeFlags(effect.RuntimeFlagsPatch.enable(effect.RuntimeFlags.OpSupervision))
1142
+ );
1143
+ return effect.Layer.mergeAll(
1144
+ effect.Layer.discard(tracerWithResource),
1145
+ effect.Layer.enableSourceCapture,
1146
+ supervisorLayer,
1147
+ opSupervisionLayer
1148
+ );
1149
+ };
1150
+ exports.UnifiedTracingLive = effect.Layer.suspend(
1151
+ () => exports.createUnifiedTracingLayer()
1152
+ );
1153
+ exports.enableOpSupervision = (effect$1) => effect.Effect.withRuntimeFlagsPatch(effect$1, effect.RuntimeFlagsPatch.enable(effect.RuntimeFlags.OpSupervision));
1154
+ exports.withUnifiedTracing = (effect$1) => effect$1.pipe(exports.enableOpSupervision, effect.Effect.provide(exports.UnifiedTracingLive));
1155
+ exports.withAutoTracing = (effect$1, config, rootSpanName) => {
1156
+ const autoConfig = config ?? {
1157
+ enabled: true,
1158
+ granularity: "fiber",
1159
+ span_naming: { default: "effect.{function}", infer_from_source: true, rules: [] },
1160
+ span_relationships: { type: "parent-child" },
1161
+ filter: { include: [], exclude: [] },
1162
+ performance: { sampling_rate: 1, min_duration: "0ms", max_concurrent: 0 },
1163
+ metadata: { fiber_info: true, source_location: true, parent_fiber: true }
1164
+ };
1165
+ const supervisor = new exports.UnifiedTracingSupervisor(autoConfig);
1166
+ const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
1167
+ const opSupervisionLayer = effect.Layer.effectDiscard(
1168
+ effect.Effect.patchRuntimeFlags(effect.RuntimeFlagsPatch.enable(effect.RuntimeFlags.OpSupervision))
1169
+ );
1170
+ const combinedLayer = effect.Layer.mergeAll(
1171
+ supervisorLayer,
1172
+ effect.Layer.enableSourceCapture,
1173
+ opSupervisionLayer
1174
+ );
1175
+ const wrappedEffect = rootSpanName ? effect$1.pipe(effect.Effect.withSpan(rootSpanName)) : effect$1;
1176
+ return wrappedEffect.pipe(effect.Effect.provide(combinedLayer));
1177
+ };
1178
+ exports.flushAndShutdown = async () => {
1179
+ const setup = getGlobalProviderSetup();
1180
+ if (setup?.provider) {
1181
+ logger.log("@atrim/unified-tracing: Flushing and shutting down TracerProvider...");
1182
+ await setup.provider.forceFlush();
1183
+ await setup.provider.shutdown();
1184
+ logger.log("@atrim/unified-tracing: TracerProvider shutdown complete");
1185
+ }
1186
+ };
1187
+ exports.forceFlush = async () => {
1188
+ const setup = getGlobalProviderSetup();
1189
+ if (setup?.provider) {
1190
+ logger.log("@atrim/unified-tracing: Force flushing TracerProvider...");
1191
+ await setup.provider.forceFlush();
1192
+ logger.log("@atrim/unified-tracing: Force flush complete");
1193
+ }
1194
+ };
750
1195
  }
751
- patchAttempted = true;
752
- logger.log("@atrim/auto-trace: Effect.fork auto-patching not available (ESM limitation)");
753
- logger.log("@atrim/auto-trace: Use tracedFork() for call-site capture");
754
- }
755
- function unpatchEffectFork() {
756
- patchAttempted = false;
757
- }
1196
+ });
1197
+
1198
+ // src/integrations/effect/auto/index.ts
1199
+ init_unified_tracing_supervisor();
1200
+ init_config();
758
1201
  var compiledRulesCache = /* @__PURE__ */ new WeakMap();
759
1202
  function compileNamingRules(rules) {
760
1203
  const cached = compiledRulesCache.get(rules);
@@ -875,1333 +1318,102 @@ function sanitizeSpanName(name) {
875
1318
  }
876
1319
  return sanitized;
877
1320
  }
878
-
879
- // src/integrations/effect/auto/supervisor.ts
880
- var AutoTracingEnabled = effect.FiberRef.unsafeMake(true);
881
- var AutoTracingSpanName = effect.FiberRef.unsafeMake(effect.Option.none());
882
- var AutoTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
883
- constructor(config, tracerProvider) {
884
- super();
885
- this.config = config;
886
- // WeakMap to associate fibers with their OTel spans
887
- __publicField(this, "fiberSpans", /* @__PURE__ */ new WeakMap());
888
- // WeakMap for fiber start times (for min_duration filtering)
889
- __publicField(this, "fiberStartTimes", /* @__PURE__ */ new WeakMap());
890
- // OpenTelemetry tracer - lazily initialized
891
- __publicField(this, "_tracer", null);
892
- // Optional TracerProvider (if provided, use this instead of global)
893
- __publicField(this, "tracerProvider", null);
894
- // Compiled filter patterns
895
- __publicField(this, "includePatterns");
896
- __publicField(this, "excludePatterns");
897
- // Active fiber count (for max_concurrent limiting)
898
- __publicField(this, "activeFiberCount", 0);
899
- // Root span for parent context (set by withAutoTracing)
900
- __publicField(this, "_rootSpan", null);
901
- if (tracerProvider) {
902
- this.tracerProvider = tracerProvider;
903
- logger.log("@atrim/auto-trace: Using provided TracerProvider");
904
- }
905
- this.includePatterns = (config.filter?.include || []).map((p) => new RegExp(p));
906
- this.excludePatterns = (config.filter?.exclude || []).map((p) => new RegExp(p));
907
- logger.log("@atrim/auto-trace: Supervisor initialized");
908
- logger.log(` Granularity: ${config.granularity || "fiber"}`);
909
- logger.log(` Sampling rate: ${config.performance?.sampling_rate ?? 1}`);
910
- logger.log(` Infer from source: ${config.span_naming?.infer_from_source ?? true}`);
911
- }
912
- /**
913
- * Set the root span for parent context propagation
914
- */
915
- setRootSpan(span) {
916
- this._rootSpan = span;
917
- }
918
- /**
919
- * Get the tracer lazily - uses provided TracerProvider if available, otherwise uses global
920
- */
921
- get tracer() {
922
- if (!this._tracer) {
923
- if (this.tracerProvider) {
924
- logger.log("@atrim/auto-trace: Getting tracer from provided TracerProvider");
925
- this._tracer = this.tracerProvider.getTracer("@atrim/auto-trace", "1.0.0");
926
- } else {
927
- logger.log("@atrim/auto-trace: Getting tracer from global API");
928
- this._tracer = OtelApi__namespace.trace.getTracer("@atrim/auto-trace", "1.0.0");
929
- }
930
- }
931
- return this._tracer;
932
- }
933
- /**
934
- * Returns the current value (void for this supervisor)
935
- */
936
- get value() {
937
- return effect.Effect.void;
938
- }
939
- /**
940
- * Called when a fiber starts executing
941
- */
942
- onStart(_context, _effect, parent, fiber) {
943
- logger.log(`@atrim/auto-trace: onStart called for fiber ${fiber.id().id}`);
944
- const fiberRefsValue = fiber.getFiberRefs();
945
- const enabled = effect.FiberRefs.getOrDefault(fiberRefsValue, AutoTracingEnabled);
946
- if (!enabled) {
947
- logger.log(`@atrim/auto-trace: Auto-tracing disabled for fiber ${fiber.id().id}`);
948
- return;
949
- }
950
- const samplingRate = this.config.performance?.sampling_rate ?? 1;
951
- if (samplingRate < 1 && Math.random() > samplingRate) {
952
- return;
953
- }
954
- const maxConcurrent = this.config.performance?.max_concurrent ?? 0;
955
- if (maxConcurrent > 0 && this.activeFiberCount >= maxConcurrent) {
956
- return;
957
- }
958
- const nameOverride = effect.FiberRefs.getOrDefault(fiberRefsValue, AutoTracingSpanName);
959
- let sourceInfo = effect.FiberRefs.getOrDefault(fiberRefsValue, CapturedSourceLocation);
960
- if (sourceInfo) {
961
- logger.log(`@atrim/auto-trace: Using captured source location for fiber ${fiber.id().id}`);
962
- logger.log(` function: ${sourceInfo.function}`);
963
- logger.log(` file: ${sourceInfo.file}`);
964
- logger.log(` line: ${sourceInfo.line}`);
965
- } else if (this.config.span_naming?.infer_from_source) {
966
- sourceInfo = this.parseStackTrace();
967
- if (sourceInfo) {
968
- logger.log(`@atrim/auto-trace: Inferred source from stack for fiber ${fiber.id().id}`);
969
- logger.log(` function: ${sourceInfo.function}`);
970
- logger.log(` file: ${sourceInfo.file}`);
971
- logger.log(` line: ${sourceInfo.line}`);
972
- } else {
973
- logger.log(`@atrim/auto-trace: No source info for fiber ${fiber.id().id}`);
974
- }
975
- }
976
- let spanName;
977
- if (effect.Option.isSome(nameOverride)) {
978
- spanName = nameOverride.value;
979
- } else {
980
- spanName = inferSpanName(fiber.id().id, sourceInfo, this.config);
981
- }
982
- if (!this.shouldTrace(spanName)) {
983
- return;
1321
+ var CapturedSourceLocation = effect.FiberRef.unsafeMake(void 0);
1322
+ function captureCallSite(skipFrames = 0) {
1323
+ const originalLimit = Error.stackTraceLimit;
1324
+ Error.stackTraceLimit = 10;
1325
+ const error = new Error();
1326
+ Error.stackTraceLimit = originalLimit;
1327
+ if (!error.stack) return void 0;
1328
+ const lines = error.stack.split("\n");
1329
+ const startIndex = 3 + skipFrames;
1330
+ for (let i = startIndex; i < lines.length; i++) {
1331
+ const line = lines[i];
1332
+ if (line === void 0) continue;
1333
+ if (line.includes("@atrim/instrument") || line.includes("node_modules/effect")) {
1334
+ continue;
984
1335
  }
985
- const relationshipType = this.config.span_relationships?.type ?? "parent-child";
986
- const useParentChild = relationshipType === "parent-child" || relationshipType === "both";
987
- const useSpanLinks = relationshipType === "span-links" || relationshipType === "both";
988
- let parentContext = OtelApi__namespace.ROOT_CONTEXT;
989
- let parentFiberId;
990
- let spanLinks = [];
991
- const maybeEffectParentSpan = effect.Context.getOption(_context, effect.Tracer.ParentSpan);
992
- if (effect.Option.isSome(maybeEffectParentSpan)) {
993
- const effectSpan = maybeEffectParentSpan.value;
994
- logger.log(
995
- `@atrim/auto-trace: Found ParentSpan - traceId=${effectSpan.traceId.slice(0, 8)}..., spanId=${effectSpan.spanId.slice(0, 8)}...`
996
- );
997
- const otelSpanContext = {
998
- traceId: effectSpan.traceId,
999
- spanId: effectSpan.spanId,
1000
- traceFlags: effectSpan.sampled ? OtelApi__namespace.TraceFlags.SAMPLED : OtelApi__namespace.TraceFlags.NONE,
1001
- isRemote: false
1336
+ const match = line.match(/at\s+(?:(.+?)\s+)?\(?(.+?):(\d+):(\d+)\)?/);
1337
+ if (match) {
1338
+ const [, funcName, filePath, lineNum, colNum] = match;
1339
+ return {
1340
+ function: funcName?.trim() ?? "anonymous",
1341
+ file: filePath ?? "unknown",
1342
+ line: parseInt(lineNum ?? "0", 10),
1343
+ column: parseInt(colNum ?? "0", 10)
1002
1344
  };
1003
- if (useParentChild) {
1004
- const wrappedSpan = OtelApi__namespace.trace.wrapSpanContext(otelSpanContext);
1005
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, wrappedSpan);
1006
- }
1007
- if (useSpanLinks) {
1008
- const linkAttributes = this.getLinkAttributes();
1009
- spanLinks.push({
1010
- context: otelSpanContext,
1011
- attributes: linkAttributes
1012
- });
1013
- logger.log(`@atrim/auto-trace: Added span link to parent (${relationshipType})`);
1014
- }
1015
- } else if (effect.Option.isSome(parent)) {
1016
- parentFiberId = parent.value.id().id;
1017
- const parentSpan = this.fiberSpans.get(parent.value);
1018
- if (parentSpan) {
1019
- if (useParentChild) {
1020
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, parentSpan);
1021
- }
1022
- if (useSpanLinks) {
1023
- const linkAttributes = this.getLinkAttributes();
1024
- spanLinks.push({
1025
- context: parentSpan.spanContext(),
1026
- attributes: linkAttributes
1027
- });
1028
- }
1029
- } else if (this._rootSpan) {
1030
- if (useParentChild) {
1031
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, this._rootSpan);
1032
- }
1033
- if (useSpanLinks) {
1034
- const linkAttributes = this.getLinkAttributes();
1035
- spanLinks.push({
1036
- context: this._rootSpan.spanContext(),
1037
- attributes: linkAttributes
1038
- });
1039
- }
1040
- }
1041
- } else if (this._rootSpan) {
1042
- if (useParentChild) {
1043
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, this._rootSpan);
1044
- }
1045
- if (useSpanLinks) {
1046
- const linkAttributes = this.getLinkAttributes();
1047
- spanLinks.push({
1048
- context: this._rootSpan.spanContext(),
1049
- attributes: linkAttributes
1050
- });
1051
- }
1052
- }
1053
- if (effect.Option.isSome(parent)) {
1054
- parentFiberId = parent.value.id().id;
1055
- }
1056
- const spanOptions = {
1057
- kind: OtelApi__namespace.SpanKind.INTERNAL,
1058
- attributes: this.getInitialAttributes(fiber, sourceInfo, parentFiberId)
1059
- };
1060
- if (spanLinks.length > 0) {
1061
- spanOptions.links = spanLinks;
1062
- }
1063
- const span = this.tracer.startSpan(spanName, spanOptions, parentContext);
1064
- logger.log(`@atrim/auto-trace: Created span "${spanName}" for fiber ${fiber.id().id}`);
1065
- this.fiberSpans.set(fiber, span);
1066
- this.fiberStartTimes.set(fiber, process.hrtime.bigint());
1067
- this.activeFiberCount++;
1068
- }
1069
- /**
1070
- * Called when a fiber completes (success or failure)
1071
- */
1072
- onEnd(exit, fiber) {
1073
- logger.log(`@atrim/auto-trace: onEnd called for fiber ${fiber.id().id}`);
1074
- const span = this.fiberSpans.get(fiber);
1075
- if (!span) {
1076
- logger.log(
1077
- `@atrim/auto-trace: No span found for fiber ${fiber.id().id} (skipped or filtered)`
1078
- );
1079
- return;
1080
- }
1081
- const startTime = this.fiberStartTimes.get(fiber);
1082
- if (startTime) {
1083
- const duration = process.hrtime.bigint() - startTime;
1084
- const minDuration = this.parseMinDuration(this.config.performance?.min_duration);
1085
- if (minDuration > 0 && duration < minDuration) {
1086
- this.fiberSpans.delete(fiber);
1087
- this.fiberStartTimes.delete(fiber);
1088
- this.activeFiberCount--;
1089
- return;
1090
- }
1091
- }
1092
- if (effect.Exit.isSuccess(exit)) {
1093
- span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
1094
- } else {
1095
- span.setStatus({
1096
- code: OtelApi__namespace.SpanStatusCode.ERROR,
1097
- message: "Fiber failed"
1098
- });
1099
- span.setAttribute("effect.fiber.failed", true);
1100
- }
1101
- span.end();
1102
- logger.log(`@atrim/auto-trace: Ended span for fiber ${fiber.id().id}`);
1103
- this.fiberSpans.delete(fiber);
1104
- this.fiberStartTimes.delete(fiber);
1105
- this.activeFiberCount--;
1106
- }
1107
- /**
1108
- * Get attributes for span links from config
1109
- */
1110
- getLinkAttributes() {
1111
- const linkConfig = this.config.span_relationships?.link_attributes;
1112
- const attrs = {
1113
- "link.type": linkConfig?.["link.type"] ?? "fork"
1114
- };
1115
- if (linkConfig?.custom) {
1116
- for (const [key, value] of Object.entries(linkConfig.custom)) {
1117
- attrs[key] = value;
1118
- }
1119
- }
1120
- return attrs;
1121
- }
1122
- /**
1123
- * Check if a span name should be traced based on filter patterns
1124
- */
1125
- shouldTrace(spanName) {
1126
- for (const pattern of this.excludePatterns) {
1127
- if (pattern.test(spanName)) {
1128
- return false;
1129
- }
1130
- }
1131
- if (this.includePatterns.length > 0) {
1132
- for (const pattern of this.includePatterns) {
1133
- if (pattern.test(spanName)) {
1134
- return true;
1135
- }
1136
- }
1137
- return false;
1138
- }
1139
- return true;
1140
- }
1141
- /**
1142
- * Get initial span attributes for a fiber
1143
- */
1144
- getInitialAttributes(fiber, sourceInfo, parentFiberId) {
1145
- const attrs = {
1146
- "effect.auto_traced": true
1147
- };
1148
- if (this.config.metadata?.fiber_info !== false) {
1149
- attrs["effect.fiber.id"] = fiber.id().id;
1150
- }
1151
- if (this.config.metadata?.source_location !== false && sourceInfo) {
1152
- attrs["code.function"] = sourceInfo.function;
1153
- attrs["code.filepath"] = sourceInfo.file;
1154
- attrs["code.lineno"] = sourceInfo.line;
1155
- attrs["code.column"] = sourceInfo.column;
1156
- }
1157
- if (this.config.metadata?.parent_fiber !== false && parentFiberId !== void 0) {
1158
- attrs["effect.fiber.parent_id"] = parentFiberId;
1159
1345
  }
1160
- return attrs;
1161
1346
  }
1162
- /**
1163
- * Parse stack trace to get source info
1164
- */
1165
- parseStackTrace() {
1166
- const stack = new Error().stack;
1167
- if (!stack) {
1168
- logger.log("@atrim/auto-trace: [parseStackTrace] No stack available");
1169
- return void 0;
1170
- }
1171
- const lines = stack.split("\n");
1172
- logger.log(`@atrim/auto-trace: [parseStackTrace] Stack has ${lines.length} lines`);
1173
- for (let i = 0; i < Math.min(10, lines.length); i++) {
1174
- logger.log(`@atrim/auto-trace: [stack ${i}] ${lines[i]}`);
1175
- }
1176
- for (let i = 3; i < lines.length; i++) {
1177
- const line = lines[i];
1178
- if (line === void 0) continue;
1179
- if (!line.includes("node_modules/effect") && !line.includes("@atrim/instrument") && !line.includes("auto/supervisor")) {
1180
- logger.log(`@atrim/auto-trace: [parseStackTrace] Found user frame: ${line}`);
1181
- const match = line.match(/at\s+(?:(.+?)\s+)?\(?(.+?):(\d+):(\d+)\)?/);
1182
- if (match) {
1183
- const [, funcName, filePath, lineNum, colNum] = match;
1184
- const sourceInfo = {
1185
- function: funcName ?? "anonymous",
1186
- file: filePath ?? "unknown",
1187
- line: parseInt(lineNum ?? "0", 10),
1188
- column: parseInt(colNum ?? "0", 10)
1189
- };
1190
- logger.log(
1191
- `@atrim/auto-trace: [parseStackTrace] Parsed: ${sourceInfo.function} at ${sourceInfo.file}:${sourceInfo.line}`
1192
- );
1193
- return sourceInfo;
1194
- }
1195
- }
1196
- }
1197
- logger.log("@atrim/auto-trace: [parseStackTrace] No user code frame found in stack");
1198
- return void 0;
1199
- }
1200
- /**
1201
- * Parse min_duration string to nanoseconds
1202
- */
1203
- parseMinDuration(duration) {
1204
- if (!duration || duration === "0ms") return BigInt(0);
1205
- const match = duration.match(/^(\d+)\s*(ms|millis|s|sec|seconds|us|micros)?$/i);
1206
- if (!match) return BigInt(0);
1207
- const value = parseInt(match[1] ?? "0", 10);
1208
- const unit = (match[2] ?? "ms").toLowerCase();
1209
- switch (unit) {
1210
- case "us":
1211
- case "micros":
1212
- return BigInt(value) * BigInt(1e3);
1213
- case "ms":
1214
- case "millis":
1215
- return BigInt(value) * BigInt(1e6);
1216
- case "s":
1217
- case "sec":
1218
- case "seconds":
1219
- return BigInt(value) * BigInt(1e9);
1220
- default:
1221
- return BigInt(value) * BigInt(1e6);
1222
- }
1347
+ return void 0;
1348
+ }
1349
+ var tracedFork = (effect$1) => {
1350
+ const callSite = captureCallSite();
1351
+ if (!callSite) {
1352
+ return effect.Effect.fork(effect$1);
1223
1353
  }
1354
+ return effect.FiberRef.set(CapturedSourceLocation, callSite).pipe(effect.Effect.zipRight(effect.Effect.fork(effect$1)));
1224
1355
  };
1225
- var createAutoTracingSupervisor = (config, tracerProvider) => {
1226
- return new AutoTracingSupervisor(config, tracerProvider);
1227
- };
1228
- var createAutoTracingLayer = (options) => {
1229
- return effect.Layer.unwrapEffect(
1230
- effect.Effect.gen(function* () {
1231
- const config = options?.config ?? (yield* loadAutoTracingConfig());
1232
- if (!config.enabled) {
1233
- logger.log("@atrim/auto-trace: Auto-tracing disabled via config");
1234
- return effect.Layer.empty;
1235
- }
1236
- patchEffectFork();
1237
- const supervisor = createAutoTracingSupervisor(config);
1238
- return effect.Supervisor.addSupervisor(supervisor);
1239
- })
1240
- );
1241
- };
1242
- var withAutoTracing = (effect$1, config, mainSpanName) => {
1243
- if (!config.enabled) {
1244
- logger.log("@atrim/auto-trace: Auto-tracing disabled via config");
1245
- return effect$1;
1356
+ var tracedForkDaemon = (effect$1) => {
1357
+ const callSite = captureCallSite();
1358
+ if (!callSite) {
1359
+ return effect.Effect.forkDaemon(effect$1);
1246
1360
  }
1247
- const supervisor = createAutoTracingSupervisor(config);
1248
- const tracer = OtelApi__namespace.trace.getTracer("@atrim/auto-trace", "1.0.0");
1249
- const spanName = mainSpanName ?? inferSpanName(0, void 0, config);
1250
- const mainSpan = tracer.startSpan(spanName, {
1251
- kind: OtelApi__namespace.SpanKind.INTERNAL,
1252
- attributes: {
1253
- "effect.auto_traced": true,
1254
- "effect.fiber.id": 0,
1255
- // Main fiber
1256
- "effect.main_fiber": true
1257
- }
1258
- });
1259
- supervisor.setRootSpan(mainSpan);
1260
- return effect.Effect.acquireUseRelease(
1261
- // Acquire: return the span (already started)
1262
- effect.Effect.succeed(mainSpan),
1263
- // Use: run the supervised effect
1264
- () => effect.Effect.supervised(supervisor)(effect$1),
1265
- // Release: end the span
1266
- (span, exit) => effect.Effect.sync(() => {
1267
- if (effect.Exit.isSuccess(exit)) {
1268
- span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
1269
- } else {
1270
- span.setStatus({
1271
- code: OtelApi__namespace.SpanStatusCode.ERROR,
1272
- message: "Effect failed"
1273
- });
1274
- }
1275
- span.end();
1276
- })
1361
+ return effect.FiberRef.set(CapturedSourceLocation, callSite).pipe(
1362
+ effect.Effect.zipRight(effect.Effect.forkDaemon(effect$1))
1277
1363
  );
1278
1364
  };
1279
- var AutoTracingLive = createAutoTracingLayer();
1280
- var withoutAutoTracing = (effect$1) => effect$1.pipe(effect.Effect.locally(AutoTracingEnabled, false));
1281
- var setSpanName = (name) => (effect$1) => effect$1.pipe(effect.Effect.locally(AutoTracingSpanName, effect.Option.some(name)));
1282
- var createExporterLayer = (exporterConfig, serviceName, serviceVersion) => {
1283
- const config = exporterConfig ?? {
1284
- type: "otlp",
1285
- processor: "batch",
1286
- batch: {
1287
- scheduled_delay_millis: 1e3,
1288
- max_export_batch_size: 100
1289
- }
1290
- };
1291
- if (config.type === "none") {
1292
- logger.log('@atrim/auto-trace: Exporter type is "none", no spans will be exported');
1293
- return effect.Layer.empty;
1294
- }
1295
- const createSpanExporter = () => {
1296
- if (config.type === "console") {
1297
- logger.log("@atrim/auto-trace: Using ConsoleSpanExporter");
1298
- return new sdkTraceBase.ConsoleSpanExporter();
1299
- }
1300
- const endpoint = config.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1301
- logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
1302
- const exporterConfig2 = {
1303
- url: `${endpoint}/v1/traces`
1304
- };
1305
- if (config.headers) {
1306
- exporterConfig2.headers = config.headers;
1307
- logger.log(
1308
- `@atrim/auto-trace: Using custom headers: ${Object.keys(config.headers).join(", ")}`
1309
- );
1310
- }
1311
- return new exporterTraceOtlpHttp.OTLPTraceExporter(exporterConfig2);
1312
- };
1313
- const createSpanProcessor = () => {
1314
- const exporter = createSpanExporter();
1315
- if (config.processor === "simple" || config.type === "console") {
1316
- logger.log("@atrim/auto-trace: Using SimpleSpanProcessor");
1317
- return new sdkTraceBase.SimpleSpanProcessor(exporter);
1318
- }
1319
- const batchConfig = config.batch ?? {
1320
- scheduled_delay_millis: 1e3,
1321
- max_export_batch_size: 100
1322
- };
1323
- logger.log("@atrim/auto-trace: Using BatchSpanProcessor");
1324
- return new sdkTraceBase.BatchSpanProcessor(exporter, {
1325
- scheduledDelayMillis: batchConfig.scheduled_delay_millis,
1326
- maxExportBatchSize: batchConfig.max_export_batch_size
1327
- });
1328
- };
1329
- return effect.Layer.effectDiscard(
1330
- effect.Effect.sync(() => {
1331
- const provider = new sdkTraceBase.BasicTracerProvider({
1332
- resource: resources.resourceFromAttributes({
1333
- [semanticConventions.ATTR_SERVICE_NAME]: serviceName,
1334
- [semanticConventions.ATTR_SERVICE_VERSION]: serviceVersion
1335
- }),
1336
- spanProcessors: [createSpanProcessor()]
1337
- });
1338
- OtelApi__namespace.trace.setGlobalTracerProvider(provider);
1339
- logger.log("@atrim/auto-trace: Global TracerProvider registered");
1340
- return () => {
1341
- provider.shutdown().catch((err) => {
1342
- logger.log(`@atrim/auto-trace: Error shutting down provider: ${err}`);
1343
- });
1344
- };
1345
- })
1346
- );
1347
- };
1348
- var createFullAutoTracingLayer = () => {
1349
- return effect.Layer.unwrapEffect(
1350
- effect.Effect.gen(function* () {
1351
- const config = yield* loadFullConfig();
1352
- const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1353
- const serviceVersion = process.env.npm_package_version || "1.0.0";
1354
- const autoConfig = config.effect?.auto_instrumentation;
1355
- if (!autoConfig?.enabled) {
1356
- logger.log("@atrim/auto-trace: Auto-instrumentation disabled via config");
1357
- return effect.Layer.empty;
1358
- }
1359
- patchEffectFork();
1360
- const exporterConfig = config.effect?.exporter_config;
1361
- logger.log("@atrim/auto-trace: Full auto-instrumentation enabled");
1362
- logger.log(` Service: ${serviceName}`);
1363
- logger.log(` Exporter: ${exporterConfig?.type ?? "otlp"}`);
1364
- const exporterLayer = createExporterLayer(exporterConfig, serviceName, serviceVersion);
1365
- const supervisor = createAutoTracingSupervisor(autoConfig);
1366
- const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
1367
- return effect.Layer.mergeAll(exporterLayer, supervisorLayer);
1368
- })
1369
- );
1370
- };
1371
- var FullAutoTracingLive = createFullAutoTracingLayer();
1372
1365
 
1373
- // src/integrations/effect/auto/effect-tracing.ts
1374
- var createEffectTracingLayer = () => {
1375
- return effect.Layer.unwrapEffect(
1376
- effect.Effect.gen(function* () {
1377
- const config = yield* loadFullConfig();
1378
- const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1379
- const serviceVersion = process.env.npm_package_version || "1.0.0";
1380
- const exporterConfig = config.effect?.exporter_config ?? {
1381
- type: "otlp",
1382
- processor: "batch"
1383
- };
1384
- logger.log("@atrim/auto-trace: Effect-native tracing enabled");
1385
- logger.log(` Service: ${serviceName}`);
1386
- logger.log(` Exporter: ${exporterConfig.type}`);
1387
- if (exporterConfig.type === "none") {
1388
- logger.log('@atrim/auto-trace: Exporter type is "none", using empty layer');
1389
- return effect.Layer.empty;
1390
- }
1391
- const createSpanProcessor = () => {
1392
- if (exporterConfig.type === "console") {
1393
- logger.log("@atrim/auto-trace: Using ConsoleSpanExporter with SimpleSpanProcessor");
1394
- return new sdkTraceBase.SimpleSpanProcessor(new sdkTraceBase.ConsoleSpanExporter());
1395
- }
1396
- const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1397
- logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
1398
- const otlpConfig = {
1399
- url: `${endpoint}/v1/traces`
1400
- };
1401
- if (exporterConfig.headers) {
1402
- otlpConfig.headers = exporterConfig.headers;
1403
- logger.log(
1404
- `@atrim/auto-trace: Using custom headers: ${Object.keys(exporterConfig.headers).join(", ")}`
1405
- );
1406
- }
1407
- const exporter = new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
1408
- if (exporterConfig.processor === "simple") {
1409
- logger.log("@atrim/auto-trace: Using SimpleSpanProcessor");
1410
- return new sdkTraceBase.SimpleSpanProcessor(exporter);
1411
- }
1412
- const batchConfig = exporterConfig.batch ?? {
1413
- scheduled_delay_millis: 1e3,
1414
- max_export_batch_size: 100
1415
- };
1416
- logger.log("@atrim/auto-trace: Using BatchSpanProcessor");
1417
- return new sdkTraceBase.BatchSpanProcessor(exporter, {
1418
- scheduledDelayMillis: batchConfig.scheduled_delay_millis,
1419
- maxExportBatchSize: batchConfig.max_export_batch_size
1420
- });
1421
- };
1422
- const sdkLayer = opentelemetry.NodeSdk.layer(() => ({
1423
- resource: {
1424
- serviceName,
1425
- serviceVersion
1426
- },
1427
- spanProcessor: createSpanProcessor()
1428
- }));
1429
- logger.log("@atrim/auto-trace: NodeSdk layer created - HTTP requests will be auto-traced");
1430
- return effect.Layer.discard(sdkLayer);
1431
- })
1432
- );
1433
- };
1434
- var EffectTracingLive = createEffectTracingLayer();
1435
- var createCombinedTracingLayer = () => {
1436
- return effect.Layer.unwrapEffect(
1437
- effect.Effect.gen(function* () {
1438
- const config = yield* loadFullConfig();
1439
- const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1440
- const serviceVersion = process.env.npm_package_version || "1.0.0";
1441
- const exporterConfig = config.effect?.exporter_config ?? {
1442
- type: "otlp",
1443
- processor: "batch"
1444
- };
1445
- const autoConfig = config.effect?.auto_instrumentation ?? {
1446
- enabled: true,
1447
- granularity: "fiber",
1448
- span_naming: {
1449
- default: "effect.{function}",
1450
- infer_from_source: true,
1451
- rules: []
1452
- },
1453
- span_relationships: {
1454
- type: "parent-child"
1455
- },
1456
- filter: { include: [], exclude: [] },
1457
- performance: { sampling_rate: 1, min_duration: "0ms", max_concurrent: 0 },
1458
- metadata: { fiber_info: true, source_location: true, parent_fiber: true }
1459
- };
1460
- logger.log("@atrim/auto-trace: Combined tracing enabled (HTTP + Fiber)");
1461
- logger.log(` Service: ${serviceName}`);
1462
- logger.log(` Exporter: ${exporterConfig.type}`);
1463
- if (exporterConfig.type === "none") {
1464
- logger.log('@atrim/auto-trace: Exporter type is "none", using empty layer');
1465
- return effect.Layer.empty;
1466
- }
1467
- const createSpanExporter = () => {
1468
- if (exporterConfig.type === "console") {
1469
- logger.log("@atrim/auto-trace: Using ConsoleSpanExporter");
1470
- return new sdkTraceBase.ConsoleSpanExporter();
1471
- }
1472
- const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1473
- logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
1474
- const otlpConfig = {
1475
- url: `${endpoint}/v1/traces`
1476
- };
1477
- if (exporterConfig.headers) {
1478
- otlpConfig.headers = exporterConfig.headers;
1479
- logger.log(
1480
- `@atrim/auto-trace: Using custom headers: ${Object.keys(exporterConfig.headers).join(", ")}`
1481
- );
1482
- }
1483
- return new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
1484
- };
1485
- const createSpanProcessor = () => {
1486
- const exporter = createSpanExporter();
1487
- if (exporterConfig.processor === "simple" || exporterConfig.type === "console") {
1488
- logger.log("@atrim/auto-trace: Using SimpleSpanProcessor");
1489
- return new sdkTraceBase.SimpleSpanProcessor(exporter);
1490
- }
1491
- const batchConfig = exporterConfig.batch ?? {
1492
- scheduled_delay_millis: 1e3,
1493
- max_export_batch_size: 100
1494
- };
1495
- logger.log("@atrim/auto-trace: Using BatchSpanProcessor");
1496
- return new sdkTraceBase.BatchSpanProcessor(exporter, {
1497
- scheduledDelayMillis: batchConfig.scheduled_delay_millis,
1498
- maxExportBatchSize: batchConfig.max_export_batch_size
1499
- });
1500
- };
1501
- const globalProviderLayer = effect.Layer.effectDiscard(
1502
- effect.Effect.sync(() => {
1503
- const provider = new sdkTraceBase.BasicTracerProvider({
1504
- resource: resources.resourceFromAttributes({
1505
- [semanticConventions.ATTR_SERVICE_NAME]: serviceName,
1506
- [semanticConventions.ATTR_SERVICE_VERSION]: serviceVersion
1507
- }),
1508
- spanProcessors: [createSpanProcessor()]
1509
- });
1510
- OtelApi__namespace.trace.setGlobalTracerProvider(provider);
1511
- logger.log("@atrim/auto-trace: Global TracerProvider registered");
1512
- })
1513
- );
1514
- const resourceLayer = opentelemetry.Resource.layer({
1515
- serviceName,
1516
- serviceVersion
1517
- });
1518
- const effectTracerLayer = opentelemetry.Tracer.layerGlobal;
1519
- const supervisor = createAutoTracingSupervisor(autoConfig);
1520
- const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
1521
- logger.log("@atrim/auto-trace: Combined layer created");
1522
- logger.log(" - HTTP requests: auto-traced via Effect platform (global provider)");
1523
- logger.log(" - Forked fibers: auto-traced via Supervisor (global provider)");
1524
- const tracerWithResource = effectTracerLayer.pipe(effect.Layer.provide(resourceLayer));
1525
- return effect.Layer.mergeAll(globalProviderLayer, effect.Layer.discard(tracerWithResource), supervisorLayer);
1526
- })
1527
- );
1528
- };
1529
- var CombinedTracingLive = createCombinedTracingLayer();
1530
- var currentSourceLocation = effect.GlobalValue.globalValue(
1531
- /* @__PURE__ */ Symbol.for("effect/FiberRef/currentSourceLocation"),
1532
- () => effect.FiberRef.unsafeMake(void 0)
1533
- );
1534
- var sourceFileCache = /* @__PURE__ */ new Map();
1535
- function extractFunctionNameFromSource(location) {
1536
- try {
1537
- let lines = sourceFileCache.get(location.file);
1538
- if (!lines) {
1539
- if (!fs__namespace.existsSync(location.file)) {
1540
- return void 0;
1541
- }
1542
- const content = fs__namespace.readFileSync(location.file, "utf-8");
1543
- lines = content.split("\n");
1544
- sourceFileCache.set(location.file, lines);
1545
- }
1546
- const lineIndex = location.line - 1;
1547
- if (lineIndex < 0 || lineIndex >= lines.length) {
1548
- return void 0;
1549
- }
1550
- const line = lines[lineIndex];
1551
- if (!line) return void 0;
1552
- const fromColumn = line.slice(location.column - 1);
1553
- const forkPattern = /(?:fork|forkDaemon|forkScoped|forkIn)\s*\(\s*([a-zA-Z_$][a-zA-Z0-9_$]*)/;
1554
- const match = fromColumn.match(forkPattern);
1555
- if (match && match[1]) {
1556
- return match[1];
1557
- }
1558
- const fullLinePattern = /(?:fork|forkDaemon|forkScoped|forkIn)\s*\(\s*([a-zA-Z_$][a-zA-Z0-9_$]*)/;
1559
- const fullMatch = line.match(fullLinePattern);
1560
- if (fullMatch && fullMatch[1]) {
1561
- return fullMatch[1];
1562
- }
1563
- return void 0;
1564
- } catch {
1565
- return void 0;
1566
- }
1567
- }
1568
- var AutoTracingEnabled2 = effect.FiberRef.unsafeMake(true);
1569
- var AutoTracingSpanName2 = effect.FiberRef.unsafeMake(effect.Option.none());
1570
- var SourceCaptureSupervisor = class extends effect.Supervisor.AbstractSupervisor {
1571
- constructor(config) {
1572
- super();
1573
- this.config = config;
1574
- // WeakMap to associate fibers with their OTel spans
1575
- __publicField(this, "fiberSpans", /* @__PURE__ */ new WeakMap());
1576
- // WeakMap to associate fibers with their OTel contexts (for child fiber lookups)
1577
- __publicField(this, "fiberContexts", /* @__PURE__ */ new WeakMap());
1578
- // WeakMap for fiber start times (for min_duration filtering)
1579
- __publicField(this, "fiberStartTimes", /* @__PURE__ */ new WeakMap());
1580
- // OpenTelemetry tracer - lazily initialized
1581
- __publicField(this, "_tracer", null);
1582
- // Active fiber count (for max_concurrent limiting)
1583
- __publicField(this, "activeFiberCount", 0);
1584
- // Default root span for fibers without a ParentSpan in their context
1585
- // This enables auto-instrumentation without requiring Effect.withSpan()
1586
- __publicField(this, "_rootSpan", null);
1587
- logger.log("@atrim/source-capture: Supervisor initialized (native source capture)");
1588
- logger.log(` Granularity: ${config.granularity || "fiber"}`);
1589
- logger.log(` Sampling rate: ${config.performance?.sampling_rate ?? 1}`);
1590
- }
1591
- /**
1592
- * Set the default root span for auto-instrumentation.
1593
- * Fibers without a ParentSpan will use this as their parent.
1594
- */
1595
- setRootSpan(span) {
1596
- this._rootSpan = span;
1597
- logger.log(`@atrim/source-capture: Root span set - spanId=${span.spanContext().spanId}`);
1598
- }
1599
- /**
1600
- * Get the root span (if set)
1601
- */
1602
- get rootSpan() {
1603
- return this._rootSpan;
1604
- }
1605
- /**
1606
- * Get the tracer lazily from global OTel API
1607
- */
1608
- get tracer() {
1609
- if (!this._tracer) {
1610
- logger.log("@atrim/source-capture: Getting tracer from global API");
1611
- this._tracer = OtelApi__namespace.trace.getTracer("@atrim/source-capture", "1.0.0");
1612
- }
1613
- return this._tracer;
1614
- }
1615
- /**
1616
- * Returns the current value (void for this supervisor)
1617
- */
1618
- get value() {
1619
- return effect.Effect.void;
1620
- }
1621
- /**
1622
- * Called when a fiber starts executing
1623
- */
1624
- onStart(_context, _effect, parent, fiber) {
1625
- const fiberId = fiber.id().id;
1626
- logger.log(`@atrim/source-capture: onStart called for fiber ${fiberId}`);
1627
- const fiberRefsValue = fiber.getFiberRefs();
1628
- const enabled = effect.FiberRefs.getOrDefault(fiberRefsValue, AutoTracingEnabled2);
1629
- if (!enabled) {
1630
- logger.log(`@atrim/source-capture: Auto-tracing disabled for fiber ${fiberId}`);
1631
- return;
1632
- }
1633
- const samplingRate = this.config.performance?.sampling_rate ?? 1;
1634
- if (samplingRate < 1 && Math.random() > samplingRate) {
1635
- return;
1636
- }
1637
- const maxConcurrent = this.config.performance?.max_concurrent ?? 0;
1638
- if (maxConcurrent > 0 && this.activeFiberCount >= maxConcurrent) {
1639
- return;
1640
- }
1641
- const nameOverride = effect.FiberRefs.getOrDefault(fiberRefsValue, AutoTracingSpanName2);
1642
- const nativeSourceLocation = effect.FiberRefs.getOrDefault(fiberRefsValue, currentSourceLocation);
1643
- if (nativeSourceLocation) {
1644
- logger.log(`@atrim/source-capture: Found native source location for fiber ${fiberId}`);
1645
- logger.log(` file: ${nativeSourceLocation.file}`);
1646
- logger.log(` line: ${nativeSourceLocation.line}`);
1647
- logger.log(` column: ${nativeSourceLocation.column}`);
1648
- logger.log(` functionName: ${nativeSourceLocation.functionName ?? "N/A"}`);
1649
- } else {
1650
- logger.log(
1651
- `@atrim/source-capture: No source location for fiber ${fiberId} (source capture may be disabled)`
1652
- );
1653
- }
1654
- let spanName;
1655
- let extractedFuncName;
1656
- if (effect.Option.isSome(nameOverride)) {
1657
- spanName = nameOverride.value;
1658
- } else if (nativeSourceLocation) {
1659
- extractedFuncName = extractFunctionNameFromSource(nativeSourceLocation);
1660
- const funcName = extractedFuncName ?? nativeSourceLocation.functionName ?? "anonymous";
1661
- const fileName = nativeSourceLocation.file.split("/").pop() ?? "unknown";
1662
- spanName = `effect.${funcName} (${fileName}:${nativeSourceLocation.line})`;
1663
- if (extractedFuncName) {
1664
- logger.log(
1665
- `@atrim/source-capture: Extracted function name "${extractedFuncName}" from source`
1666
- );
1667
- }
1668
- } else {
1669
- spanName = `effect.fiber-${fiberId}`;
1670
- }
1671
- let parentContext = OtelApi__namespace.ROOT_CONTEXT;
1672
- let parentFiberId;
1673
- const inheritedOtelContext = effect.FiberRefs.getOrDefault(
1674
- fiberRefsValue,
1675
- TracerModule__namespace.currentOtelSpanContext
1676
- );
1677
- if (inheritedOtelContext) {
1678
- parentContext = inheritedOtelContext;
1679
- const inheritedSpan = OtelApi__namespace.trace.getSpan(inheritedOtelContext);
1680
- if (inheritedSpan) {
1681
- const spanCtx = inheritedSpan.spanContext();
1682
- logger.log(
1683
- `@atrim/source-capture: Using inherited OTel context - traceId=${spanCtx.traceId}, spanId=${spanCtx.spanId}`
1684
- );
1685
- }
1686
- } else {
1687
- const maybeEffectParentSpan = effect.Context.getOption(_context, effect.Tracer.ParentSpan);
1688
- if (effect.Option.isSome(maybeEffectParentSpan)) {
1689
- const effectSpan = maybeEffectParentSpan.value;
1690
- logger.log(
1691
- `@atrim/source-capture: Found ParentSpan - traceId=${effectSpan.traceId}, spanId=${effectSpan.spanId}`
1692
- );
1693
- const otelSpanContext = {
1694
- traceId: effectSpan.traceId,
1695
- spanId: effectSpan.spanId,
1696
- traceFlags: effectSpan.sampled ? OtelApi__namespace.TraceFlags.SAMPLED : OtelApi__namespace.TraceFlags.NONE,
1697
- isRemote: false
1698
- };
1699
- const wrappedSpan = OtelApi__namespace.trace.wrapSpanContext(otelSpanContext);
1700
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, wrappedSpan);
1701
- } else if (effect.Option.isSome(parent)) {
1702
- parentFiberId = parent.value.id().id;
1703
- const parentOtelContext = this.fiberContexts.get(parent.value);
1704
- if (parentOtelContext) {
1705
- parentContext = parentOtelContext;
1706
- const parentSpan = OtelApi__namespace.trace.getSpan(parentOtelContext);
1707
- if (parentSpan) {
1708
- logger.log(
1709
- `@atrim/source-capture: Using parent fiber's OTel context - traceId=${parentSpan.spanContext().traceId}`
1710
- );
1711
- }
1712
- } else {
1713
- const parentSpan = this.fiberSpans.get(parent.value);
1714
- if (parentSpan) {
1715
- parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, parentSpan);
1716
- }
1717
- }
1718
- }
1719
- }
1720
- if (effect.Option.isSome(parent)) {
1721
- parentFiberId = parent.value.id().id;
1722
- }
1723
- const attributes = {
1724
- "effect.auto_traced": true,
1725
- "effect.source_capture": true,
1726
- "effect.fiber.id": fiberId
1727
- };
1728
- if (nativeSourceLocation) {
1729
- attributes["code.function"] = extractedFuncName ?? nativeSourceLocation.functionName ?? "anonymous";
1730
- attributes["code.filepath"] = nativeSourceLocation.file;
1731
- attributes["code.lineno"] = nativeSourceLocation.line;
1732
- attributes["code.column"] = nativeSourceLocation.column;
1733
- }
1734
- if (parentFiberId !== void 0) {
1735
- attributes["effect.fiber.parent_id"] = parentFiberId;
1736
- }
1737
- const span = this.tracer.startSpan(
1738
- spanName,
1739
- {
1740
- kind: OtelApi__namespace.SpanKind.INTERNAL,
1741
- attributes
1742
- },
1743
- parentContext
1744
- );
1745
- logger.log(`@atrim/source-capture: Created span "${spanName}" for fiber ${fiberId}`);
1746
- const newContext = OtelApi__namespace.trace.setSpan(parentContext, span);
1747
- this.fiberSpans.set(fiber, span);
1748
- this.fiberContexts.set(fiber, newContext);
1749
- this.fiberStartTimes.set(fiber, process.hrtime.bigint());
1750
- this.activeFiberCount++;
1751
- }
1752
- /**
1753
- * Called when a fiber completes (success or failure)
1754
- */
1755
- onEnd(exit, fiber) {
1756
- const fiberId = fiber.id().id;
1757
- logger.log(`@atrim/source-capture: onEnd called for fiber ${fiberId}`);
1758
- const span = this.fiberSpans.get(fiber);
1759
- if (!span) {
1760
- logger.log(`@atrim/source-capture: No span found for fiber ${fiberId} (skipped or filtered)`);
1761
- return;
1762
- }
1763
- const startTime = this.fiberStartTimes.get(fiber);
1764
- if (startTime) {
1765
- const duration = process.hrtime.bigint() - startTime;
1766
- const minDuration = this.parseMinDuration(this.config.performance?.min_duration);
1767
- if (minDuration > 0 && duration < minDuration) {
1768
- this.fiberSpans.delete(fiber);
1769
- this.fiberContexts.delete(fiber);
1770
- this.fiberStartTimes.delete(fiber);
1771
- this.activeFiberCount--;
1772
- return;
1773
- }
1774
- }
1775
- if (effect.Exit.isSuccess(exit)) {
1776
- span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
1777
- } else {
1778
- span.setStatus({
1779
- code: OtelApi__namespace.SpanStatusCode.ERROR,
1780
- message: "Fiber failed"
1781
- });
1782
- span.setAttribute("effect.fiber.failed", true);
1783
- }
1784
- span.end();
1785
- logger.log(`@atrim/source-capture: Ended span for fiber ${fiberId}`);
1786
- this.fiberSpans.delete(fiber);
1787
- this.fiberContexts.delete(fiber);
1788
- this.fiberStartTimes.delete(fiber);
1789
- this.activeFiberCount--;
1790
- }
1791
- /**
1792
- * Parse min_duration string to nanoseconds
1793
- */
1794
- parseMinDuration(duration) {
1795
- if (!duration || duration === "0ms") return BigInt(0);
1796
- const match = duration.match(/^(\d+)\s*(ms|millis|s|sec|seconds|us|micros)?$/i);
1797
- if (!match) return BigInt(0);
1798
- const value = parseInt(match[1] ?? "0", 10);
1799
- const unit = (match[2] ?? "ms").toLowerCase();
1800
- switch (unit) {
1801
- case "us":
1802
- case "micros":
1803
- return BigInt(value) * BigInt(1e3);
1804
- case "ms":
1805
- case "millis":
1806
- return BigInt(value) * BigInt(1e6);
1807
- case "s":
1808
- case "sec":
1809
- case "seconds":
1810
- return BigInt(value) * BigInt(1e9);
1811
- default:
1812
- return BigInt(value) * BigInt(1e6);
1813
- }
1814
- }
1815
- };
1816
- var setupGlobalTracerProvider = () => {
1817
- const config = loadFullConfigSync();
1818
- const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1819
- const serviceVersion = process.env.npm_package_version || "1.0.0";
1820
- const exporterConfig = config.effect?.exporter_config ?? {
1821
- type: "otlp",
1822
- processor: "batch"
1823
- };
1824
- logger.log("@atrim/source-capture: Setting up global TracerProvider");
1825
- logger.log(` Service: ${serviceName}`);
1826
- logger.log(` Exporter: ${exporterConfig.type}`);
1827
- if (exporterConfig.type === "none") {
1828
- logger.log('@atrim/source-capture: Exporter type is "none", skipping provider setup');
1829
- return null;
1830
- }
1831
- let exporter;
1832
- if (exporterConfig.type === "console") {
1833
- logger.log("@atrim/source-capture: Using ConsoleSpanExporter");
1834
- exporter = new sdkTraceBase.ConsoleSpanExporter();
1835
- } else {
1836
- const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1837
- logger.log(`@atrim/source-capture: Using OTLPTraceExporter (${endpoint})`);
1838
- const otlpConfig = {
1839
- url: `${endpoint}/v1/traces`
1840
- };
1841
- if (exporterConfig.headers) {
1842
- otlpConfig.headers = exporterConfig.headers;
1843
- logger.log(
1844
- `@atrim/source-capture: Using headers: ${Object.keys(exporterConfig.headers).join(", ")}`
1845
- );
1846
- }
1847
- exporter = new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
1848
- }
1849
- let spanProcessor;
1850
- if (exporterConfig.processor === "simple" || exporterConfig.type === "console") {
1851
- logger.log("@atrim/source-capture: Using SimpleSpanProcessor");
1852
- spanProcessor = new sdkTraceBase.SimpleSpanProcessor(exporter);
1853
- } else {
1854
- const batchConfig = exporterConfig.batch ?? {
1855
- scheduled_delay_millis: 1e3,
1856
- max_export_batch_size: 100
1857
- };
1858
- logger.log("@atrim/source-capture: Using BatchSpanProcessor");
1859
- spanProcessor = new sdkTraceBase.BatchSpanProcessor(exporter, {
1860
- scheduledDelayMillis: batchConfig.scheduled_delay_millis,
1861
- maxExportBatchSize: batchConfig.max_export_batch_size
1862
- });
1863
- }
1864
- const provider = new sdkTraceBase.BasicTracerProvider({
1865
- resource: resources.resourceFromAttributes({
1866
- [semanticConventions.ATTR_SERVICE_NAME]: serviceName,
1867
- [semanticConventions.ATTR_SERVICE_VERSION]: serviceVersion
1868
- }),
1869
- spanProcessors: [spanProcessor]
1870
- });
1871
- OtelApi__namespace.trace.setGlobalTracerProvider(provider);
1872
- logger.log("@atrim/source-capture: Global TracerProvider registered");
1873
- return { provider, spanProcessor };
1874
- };
1875
- var globalProviderSetup = setupGlobalTracerProvider();
1876
- var createSourceCaptureTracingLayer = () => {
1877
- const config = loadFullConfigSync();
1878
- const autoConfig = config.effect?.auto_instrumentation ?? {
1879
- enabled: true,
1880
- granularity: "fiber",
1881
- span_naming: {
1882
- default: "effect.{function}",
1883
- infer_from_source: true,
1884
- rules: []
1885
- },
1886
- span_relationships: {
1887
- type: "parent-child"
1888
- },
1889
- filter: { include: [], exclude: [] },
1890
- performance: { sampling_rate: 1, min_duration: "0ms", max_concurrent: 0 },
1891
- metadata: { fiber_info: true, source_location: true, parent_fiber: true }
1892
- };
1893
- if (!globalProviderSetup) {
1894
- logger.log("@atrim/source-capture: No TracerProvider, using empty layer");
1895
- return effect.Layer.empty;
1896
- }
1897
- const supervisor = new SourceCaptureSupervisor(autoConfig);
1898
- const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
1899
- logger.log("@atrim/source-capture: Creating layer");
1900
- logger.log(" - Source capture: ENABLED via Layer.enableSourceCapture");
1901
- logger.log(" - Effect.withSpan(): exports to OTel via our tracer");
1902
- logger.log(" - Forked fibers: auto-traced via SourceCaptureSupervisor");
1903
- const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
1904
- const serviceVersion = process.env.npm_package_version || "1.0.0";
1905
- const otelTracer = OtelApi__namespace.trace.getTracer(serviceName, serviceVersion);
1906
- logger.log(`@atrim/source-capture: Using tracer "${serviceName}" from our provider`);
1907
- const effectTracerLayer = opentelemetry.Tracer.layerWithoutOtelTracer.pipe(
1908
- effect.Layer.provide(effect.Layer.succeed(opentelemetry.Tracer.OtelTracer, otelTracer))
1909
- );
1910
- return effect.Layer.mergeAll(effectTracerLayer, effect.Layer.enableSourceCapture, supervisorLayer);
1911
- };
1912
- var SourceCaptureTracingLive = createSourceCaptureTracingLayer();
1913
- var withoutSourceCapture = (effect$1) => effect.Effect.withCaptureStackTraces(false)(effect$1);
1914
- var flushAndShutdown = async () => {
1915
- if (globalProviderSetup?.provider) {
1916
- logger.log("@atrim/source-capture: Flushing and shutting down TracerProvider...");
1917
- await globalProviderSetup.provider.forceFlush();
1918
- await globalProviderSetup.provider.shutdown();
1919
- logger.log("@atrim/source-capture: TracerProvider shutdown complete");
1920
- }
1921
- };
1922
- var forceFlush = async () => {
1923
- if (globalProviderSetup?.provider) {
1924
- logger.log("@atrim/source-capture: Force flushing TracerProvider...");
1925
- await globalProviderSetup.provider.forceFlush();
1926
- logger.log("@atrim/source-capture: Force flush complete");
1927
- }
1928
- };
1929
- var defaultSpanNaming = {
1930
- includeLocation: true,
1931
- template: "effect.{op} ({filename}:{line})"
1932
- };
1933
- function parseSourceLocation(stack) {
1934
- const lines = stack.split("\n");
1935
- for (const line of lines.slice(1)) {
1936
- if (line.includes("node_modules") || line.includes("/effect/") || line.includes("fiberRuntime.ts") || line.includes("core.ts")) {
1937
- continue;
1938
- }
1939
- const match = line.match(/at\s+(?:.*?\s+\()?(.+):(\d+):(\d+)\)?/);
1940
- if (match && match[1] && match[2]) {
1941
- return {
1942
- file: match[1],
1943
- line: parseInt(match[2], 10),
1944
- column: match[3] ? parseInt(match[3], 10) : void 0
1945
- };
1946
- }
1947
- }
1948
- return void 0;
1366
+ // src/integrations/effect/auto/patch-fork.ts
1367
+ init_dist();
1368
+ var patchAttempted = false;
1369
+ function isEffectForkPatched() {
1370
+ return false;
1949
1371
  }
1950
- function getOperationMeta(effect) {
1951
- const trace5 = effect.trace;
1952
- if (trace5 && trace5._tag === "OperationMeta") {
1953
- return trace5;
1372
+ function patchEffectFork() {
1373
+ if (patchAttempted) {
1374
+ return;
1954
1375
  }
1955
- return void 0;
1376
+ patchAttempted = true;
1377
+ logger.log("@atrim/auto-trace: Effect.fork auto-patching not available (ESM limitation)");
1378
+ logger.log("@atrim/auto-trace: Use tracedFork() for call-site capture");
1956
1379
  }
1957
- function applyTemplate2(template, vars) {
1958
- return template.replace(/\{op\}/g, vars.op).replace(/\{file\}/g, vars.file).replace(/\{filename\}/g, vars.filename).replace(/\{line\}/g, vars.line).replace(/\{column\}/g, vars.column);
1380
+ function unpatchEffectFork() {
1381
+ patchAttempted = false;
1959
1382
  }
1960
- var OperationTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
1961
- constructor(operations, spanNaming = defaultSpanNaming) {
1962
- super();
1963
- // Map of configured operations by name
1964
- __publicField(this, "configuredOps");
1965
- // Global span naming configuration
1966
- __publicField(this, "spanNaming");
1967
- // Track processed effects to avoid duplicate spans (using WeakSet for GC)
1968
- __publicField(this, "processedEffects", /* @__PURE__ */ new WeakSet());
1969
- // Track spans per fiber for proper lifecycle management
1970
- __publicField(this, "fiberSpans", /* @__PURE__ */ new WeakMap());
1971
- // OpenTelemetry tracer - lazily initialized
1972
- __publicField(this, "_tracer", null);
1973
- this.configuredOps = new Map(operations.map((op) => [op.name, op]));
1974
- this.spanNaming = spanNaming;
1975
- logger.log("@atrim/operation-tracing: Supervisor initialized");
1976
- logger.log(` Configured operations: ${Array.from(this.configuredOps.keys()).join(", ")}`);
1977
- }
1978
- /**
1979
- * Get the tracer lazily from global OTel API
1980
- */
1981
- get tracer() {
1982
- if (!this._tracer) {
1983
- this._tracer = OtelApi__namespace.trace.getTracer("@atrim/operation-tracing", "1.0.0");
1984
- }
1985
- return this._tracer;
1986
- }
1987
- /**
1988
- * Returns the current value (void for this supervisor)
1989
- */
1990
- get value() {
1991
- return effect.Effect.void;
1992
- }
1993
- /**
1994
- * Called for EVERY Effect operation when OpSupervision is enabled.
1995
- *
1996
- * This is the key hook for operation-level tracing. We check if the effect
1997
- * has OperationMeta and create a span if configured.
1998
- */
1999
- onEffect(fiber, effect$1) {
2000
- if (this.processedEffects.has(effect$1)) {
2001
- return;
2002
- }
2003
- const meta = getOperationMeta(effect$1);
2004
- if (!meta) {
2005
- return;
2006
- }
2007
- const config = this.configuredOps.get(meta.op);
2008
- if (!config) {
2009
- return;
2010
- }
2011
- this.processedEffects.add(effect$1);
2012
- const fiberId = fiber.id().id;
2013
- logger.log(`@atrim/operation-tracing: Found operation "${meta.op}" in fiber ${fiberId}`);
2014
- ({
2015
- "effect.operation": meta.op
2016
- });
2017
- if (config.includeCount && meta.count !== void 0) {
2018
- meta.count;
2019
- }
2020
- const location = config.includeStack ? parseSourceLocation(meta.capturedAt) : void 0;
2021
- if (config.includeStack && location) {
2022
- location.file;
2023
- location.line;
2024
- if (location.column !== void 0) {
2025
- location.column;
2026
- }
2027
- }
2028
- let spanName;
2029
- const templateVars = {
2030
- op: meta.op,
2031
- file: location?.file ?? "unknown",
2032
- filename: location?.file?.split("/").pop() ?? "unknown",
2033
- line: location?.line?.toString() ?? "0",
2034
- column: location?.column?.toString() ?? "0"
2035
- };
2036
- if (config.spanNameTemplate) {
2037
- spanName = applyTemplate2(config.spanNameTemplate, templateVars);
2038
- } else if (this.spanNaming.includeLocation && location) {
2039
- spanName = applyTemplate2(this.spanNaming.template, templateVars);
2040
- } else {
2041
- spanName = `effect.${meta.op}`;
2042
- }
2043
- let parentContext = OtelApi__namespace.ROOT_CONTEXT;
2044
- const fiberContext = fiber.currentContext;
2045
- const maybeEffectParentSpan = effect.Context.getOption(fiberContext, TracerModule__namespace.ParentSpan);
2046
- if (effect.Option.isSome(maybeEffectParentSpan)) {
2047
- const effectSpan = maybeEffectParentSpan.value;
2048
- parentContext = OtelApi__namespace.trace.setSpan(
2049
- OtelApi__namespace.ROOT_CONTEXT,
2050
- OtelApi__namespace.trace.wrapSpanContext({
2051
- traceId: effectSpan.traceId,
2052
- spanId: effectSpan.spanId,
2053
- traceFlags: OtelApi__namespace.TraceFlags.SAMPLED
2054
- })
2055
- );
2056
- logger.log(
2057
- `@atrim/operation-tracing: Using parent span traceId=${effectSpan.traceId.slice(0, 8)}...`
2058
- );
2059
- }
2060
- const span = this.tracer.startSpan(
2061
- spanName,
2062
- {
2063
- kind: OtelApi__namespace.SpanKind.INTERNAL
2064
- },
2065
- parentContext
2066
- );
2067
- span.setAttribute("effect.operation", meta.op);
2068
- if (config.includeCount && meta.count !== void 0) {
2069
- span.setAttribute("effect.item_count", meta.count);
2070
- }
2071
- if (config.includeStack && location) {
2072
- span.setAttribute("code.filepath", location.file);
2073
- span.setAttribute("code.lineno", location.line);
2074
- if (location.column !== void 0) {
2075
- span.setAttribute("code.column", location.column);
2076
- }
2077
- }
2078
- logger.log(
2079
- `@atrim/operation-tracing: Created span "${spanName}" - spanId=${span.spanContext().spanId}`
2080
- );
2081
- span.setStatus({ code: OtelApi__namespace.SpanStatusCode.OK });
2082
- span.end();
2083
- logger.log(`@atrim/operation-tracing: Ended span "${spanName}"`);
2084
- let spanMap = this.fiberSpans.get(fiber);
2085
- if (!spanMap) {
2086
- spanMap = /* @__PURE__ */ new Map();
2087
- this.fiberSpans.set(fiber, spanMap);
2088
- }
2089
- const spanKey = `${meta.op}-${meta.capturedAt.slice(0, 100)}`;
2090
- spanMap.set(spanKey, span);
2091
- }
2092
- /**
2093
- * Called when a fiber starts - we don't need this for operation tracing
2094
- */
2095
- onStart() {
2096
- }
2097
- /**
2098
- * Called when a fiber ends - end all spans for this fiber
2099
- */
2100
- onEnd(exit, fiber) {
2101
- const spanMap = this.fiberSpans.get(fiber);
2102
- if (!spanMap) {
2103
- return;
2104
- }
2105
- const isError = exit._tag === "Failure";
2106
- const fiberId = fiber.id().id;
2107
- for (const [_key, span] of spanMap) {
2108
- span.setStatus({
2109
- code: isError ? OtelApi__namespace.SpanStatusCode.ERROR : OtelApi__namespace.SpanStatusCode.OK
2110
- });
2111
- span.end();
2112
- logger.log(
2113
- `@atrim/operation-tracing: Ended span for fiber ${fiberId} (${isError ? "error" : "success"})`
2114
- );
2115
- }
2116
- this.fiberSpans.delete(fiber);
2117
- }
2118
- };
2119
- var defaultOperations = [
2120
- { name: "all", includeCount: true, includeStack: true },
2121
- { name: "forEach", includeCount: true, includeStack: true }
2122
- ];
2123
- var makeOperationTracingLayer = (operations = defaultOperations, spanNaming = defaultSpanNaming) => {
2124
- const supervisor = new OperationTracingSupervisor(operations, spanNaming);
2125
- return effect.Supervisor.addSupervisor(supervisor);
2126
- };
2127
- var enableOpSupervision = (effect$1) => effect.Effect.withRuntimeFlagsPatch(effect$1, effect.RuntimeFlagsPatch.enable(effect.RuntimeFlags.OpSupervision));
2128
- var loadOperationTracingLayer = () => effect.Layer.unwrapEffect(
2129
- effect.Effect.gen(function* () {
2130
- const config = yield* effect.Effect.tryPromise({
2131
- try: () => loadConfigWithOptions(),
2132
- catch: (error) => {
2133
- logger.log(`@atrim/operation-tracing: Failed to load config: ${error}`);
2134
- return error;
2135
- }
2136
- }).pipe(effect.Effect.catchAll(() => effect.Effect.succeed(null)));
2137
- const opTracingConfig = config?.effect?.operation_tracing;
2138
- if (opTracingConfig?.enabled === false) {
2139
- logger.log("@atrim/operation-tracing: Operation tracing disabled in config");
2140
- return effect.Layer.empty;
2141
- }
2142
- const spanNaming = {
2143
- includeLocation: opTracingConfig?.span_naming?.include_location ?? true,
2144
- template: opTracingConfig?.span_naming?.template ?? "effect.{op} ({filename}:{line})"
2145
- };
2146
- logger.log(
2147
- `@atrim/operation-tracing: Span naming - includeLocation=${spanNaming.includeLocation}, template="${spanNaming.template}"`
2148
- );
2149
- const operations = opTracingConfig?.operations ? opTracingConfig.operations.map((op) => ({
2150
- name: op.name,
2151
- ...op.span_name && { spanNameTemplate: op.span_name },
2152
- includeCount: op.include_count ?? true,
2153
- includeStack: op.include_stack ?? true
2154
- })) : defaultOperations;
2155
- const source = opTracingConfig?.operations ? "instrumentation.yaml" : "defaults";
2156
- logger.log(
2157
- `@atrim/operation-tracing: Loaded ${operations.length} operation configs from ${source}`
2158
- );
2159
- return makeOperationTracingLayer(operations, spanNaming);
2160
- })
2161
- );
2162
- var OperationTracingLive = loadOperationTracingLayer();
2163
- var withOperationTracing = (effect$1) => effect$1.pipe(enableOpSupervision, effect.Effect.provide(OperationTracingLive));
2164
1383
 
2165
- exports.AutoTracingConfig = AutoTracingConfig;
2166
- exports.AutoTracingConfigLayer = AutoTracingConfigLayer;
2167
- exports.AutoTracingConfigLive = AutoTracingConfigLive;
2168
- exports.AutoTracingEnabled = AutoTracingEnabled;
2169
- exports.AutoTracingLive = AutoTracingLive;
2170
- exports.AutoTracingSpanName = AutoTracingSpanName;
2171
- exports.AutoTracingSupervisor = AutoTracingSupervisor;
1384
+ // src/integrations/effect/auto/index.ts
1385
+ init_unified_tracing_supervisor();
1386
+ init_unified_tracing_supervisor();
1387
+ init_unified_tracing_supervisor();
1388
+ init_unified_tracing_supervisor();
1389
+ init_unified_tracing_supervisor();
1390
+ init_unified_tracing_supervisor();
1391
+ init_unified_tracing_supervisor();
1392
+ init_unified_tracing_supervisor();
1393
+ init_unified_tracing_supervisor();
1394
+ init_unified_tracing_supervisor();
1395
+ init_unified_tracing_supervisor();
1396
+ var createAutoTracingSupervisor = (config) => new (init_unified_tracing_supervisor(), __toCommonJS(unified_tracing_supervisor_exports)).UnifiedTracingSupervisor(config);
1397
+
1398
+ exports.AutoTracingLive = exports.UnifiedTracingLive;
1399
+ exports.AutoTracingSupervisor = exports.UnifiedTracingSupervisor;
2172
1400
  exports.CapturedSourceLocation = CapturedSourceLocation;
2173
- exports.CombinedTracingLive = CombinedTracingLive;
2174
- exports.EffectTracingLive = EffectTracingLive;
2175
- exports.FullAutoTracingLive = FullAutoTracingLive;
2176
- exports.OperationTracingLive = OperationTracingLive;
2177
- exports.OperationTracingSupervisor = OperationTracingSupervisor;
2178
- exports.SourceCaptureSupervisor = SourceCaptureSupervisor;
2179
- exports.SourceCaptureTracingLive = SourceCaptureTracingLive;
1401
+ exports.CombinedTracingLive = exports.UnifiedTracingLive;
1402
+ exports.FullAutoTracingLive = exports.UnifiedTracingLive;
1403
+ exports.OperationTracingLive = exports.UnifiedTracingLive;
1404
+ exports.SourceCaptureSupervisor = exports.UnifiedTracingSupervisor;
1405
+ exports.SourceCaptureTracingLive = exports.UnifiedTracingLive;
2180
1406
  exports.captureCallSite = captureCallSite;
2181
- exports.createAutoTracingLayer = createAutoTracingLayer;
1407
+ exports.createAutoTracingLayer = exports.createUnifiedTracingLayer;
2182
1408
  exports.createAutoTracingSupervisor = createAutoTracingSupervisor;
2183
- exports.createCombinedTracingLayer = createCombinedTracingLayer;
2184
- exports.createEffectTracingLayer = createEffectTracingLayer;
2185
- exports.createFullAutoTracingLayer = createFullAutoTracingLayer;
2186
- exports.createSourceCaptureTracingLayer = createSourceCaptureTracingLayer;
2187
- exports.defaultAutoTracingConfig = defaultAutoTracingConfig;
2188
- exports.enableOpSupervision = enableOpSupervision;
2189
- exports.flushAndShutdown = flushAndShutdown;
2190
- exports.forceFlush = forceFlush;
1409
+ exports.createFullAutoTracingLayer = exports.createUnifiedTracingLayer;
2191
1410
  exports.inferSpanName = inferSpanName;
2192
1411
  exports.isEffectForkPatched = isEffectForkPatched;
2193
- exports.loadAutoTracingConfig = loadAutoTracingConfig;
2194
- exports.loadAutoTracingConfigSync = loadAutoTracingConfigSync;
2195
- exports.makeOperationTracingLayer = makeOperationTracingLayer;
2196
1412
  exports.patchEffectFork = patchEffectFork;
2197
1413
  exports.sanitizeSpanName = sanitizeSpanName;
2198
- exports.setSpanName = setSpanName;
2199
1414
  exports.tracedFork = tracedFork;
2200
1415
  exports.tracedForkDaemon = tracedForkDaemon;
2201
1416
  exports.unpatchEffectFork = unpatchEffectFork;
2202
- exports.withAutoTracing = withAutoTracing;
2203
- exports.withOperationTracing = withOperationTracing;
2204
- exports.withoutAutoTracing = withoutAutoTracing;
2205
- exports.withoutSourceCapture = withoutSourceCapture;
1417
+ exports.withOperationTracing = exports.withUnifiedTracing;
2206
1418
  //# sourceMappingURL=index.cjs.map
2207
1419
  //# sourceMappingURL=index.cjs.map