@atrim/instrument-node 0.4.0 → 0.5.0-c05e3a1-20251119131235
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -7
- package/target/dist/index.cjs +317 -264
- package/target/dist/index.cjs.map +1 -1
- package/target/dist/index.d.cts +163 -142
- package/target/dist/index.d.ts +163 -142
- package/target/dist/index.js +292 -258
- package/target/dist/index.js.map +1 -1
- package/target/dist/integrations/effect/index.cjs +234 -192
- package/target/dist/integrations/effect/index.cjs.map +1 -1
- package/target/dist/integrations/effect/index.d.cts +17 -1
- package/target/dist/integrations/effect/index.d.ts +17 -1
- package/target/dist/integrations/effect/index.js +233 -193
- package/target/dist/integrations/effect/index.js.map +1 -1
|
@@ -4,10 +4,12 @@ var effect = require('effect');
|
|
|
4
4
|
var Otlp = require('@effect/opentelemetry/Otlp');
|
|
5
5
|
var platform = require('@effect/platform');
|
|
6
6
|
var api = require('@opentelemetry/api');
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var FileSystem = require('@effect/platform/FileSystem');
|
|
8
|
+
var HttpClient = require('@effect/platform/HttpClient');
|
|
9
|
+
var HttpClientRequest = require('@effect/platform/HttpClientRequest');
|
|
9
10
|
var yaml = require('yaml');
|
|
10
11
|
var zod = require('zod');
|
|
12
|
+
var platformNode = require('@effect/platform-node');
|
|
11
13
|
|
|
12
14
|
function _interopNamespace(e) {
|
|
13
15
|
if (e && e.__esModule) return e;
|
|
@@ -28,6 +30,8 @@ function _interopNamespace(e) {
|
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
var Otlp__namespace = /*#__PURE__*/_interopNamespace(Otlp);
|
|
33
|
+
var HttpClient__namespace = /*#__PURE__*/_interopNamespace(HttpClient);
|
|
34
|
+
var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
|
|
31
35
|
|
|
32
36
|
// src/integrations/effect/effect-tracer.ts
|
|
33
37
|
var __defProp = Object.defineProperty;
|
|
@@ -66,7 +70,20 @@ var HttpFilteringConfigSchema = zod.z.object({
|
|
|
66
70
|
// Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
|
|
67
71
|
ignore_incoming_paths: zod.z.array(zod.z.string()).optional(),
|
|
68
72
|
// Require parent span for outgoing requests (prevents root spans for HTTP calls)
|
|
69
|
-
require_parent_for_outgoing_spans: zod.z.boolean().optional()
|
|
73
|
+
require_parent_for_outgoing_spans: zod.z.boolean().optional(),
|
|
74
|
+
// Trace context propagation configuration
|
|
75
|
+
// Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
|
|
76
|
+
propagate_trace_context: zod.z.object({
|
|
77
|
+
// Strategy for trace propagation
|
|
78
|
+
// - "all": Propagate to all cross-origin requests (may cause CORS errors)
|
|
79
|
+
// - "none": Never propagate trace headers
|
|
80
|
+
// - "same-origin": Only propagate to same-origin requests (default, safe)
|
|
81
|
+
// - "patterns": Propagate based on include_urls patterns
|
|
82
|
+
strategy: zod.z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
|
|
83
|
+
// URL patterns to include when strategy is "patterns"
|
|
84
|
+
// Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
|
|
85
|
+
include_urls: zod.z.array(zod.z.string()).optional()
|
|
86
|
+
}).optional()
|
|
70
87
|
});
|
|
71
88
|
var InstrumentationConfigSchema = zod.z.object({
|
|
72
89
|
version: zod.z.string(),
|
|
@@ -84,233 +101,183 @@ var InstrumentationConfigSchema = zod.z.object({
|
|
|
84
101
|
http: HttpFilteringConfigSchema.optional()
|
|
85
102
|
});
|
|
86
103
|
(class extends effect.Data.TaggedError("ConfigError") {
|
|
104
|
+
get message() {
|
|
105
|
+
return this.reason;
|
|
106
|
+
}
|
|
87
107
|
});
|
|
88
108
|
var ConfigUrlError = class extends effect.Data.TaggedError("ConfigUrlError") {
|
|
109
|
+
get message() {
|
|
110
|
+
return this.reason;
|
|
111
|
+
}
|
|
89
112
|
};
|
|
90
113
|
var ConfigValidationError = class extends effect.Data.TaggedError("ConfigValidationError") {
|
|
114
|
+
get message() {
|
|
115
|
+
return this.reason;
|
|
116
|
+
}
|
|
91
117
|
};
|
|
92
118
|
var ConfigFileError = class extends effect.Data.TaggedError("ConfigFileError") {
|
|
119
|
+
get message() {
|
|
120
|
+
return this.reason;
|
|
121
|
+
}
|
|
93
122
|
};
|
|
94
123
|
(class extends effect.Data.TaggedError("ServiceDetectionError") {
|
|
124
|
+
get message() {
|
|
125
|
+
return this.reason;
|
|
126
|
+
}
|
|
95
127
|
});
|
|
96
128
|
(class extends effect.Data.TaggedError("InitializationError") {
|
|
129
|
+
get message() {
|
|
130
|
+
return this.reason;
|
|
131
|
+
}
|
|
97
132
|
});
|
|
98
133
|
(class extends effect.Data.TaggedError("ExportError") {
|
|
134
|
+
get message() {
|
|
135
|
+
return this.reason;
|
|
136
|
+
}
|
|
99
137
|
});
|
|
100
138
|
(class extends effect.Data.TaggedError("ShutdownError") {
|
|
139
|
+
get message() {
|
|
140
|
+
return this.reason;
|
|
141
|
+
}
|
|
101
142
|
});
|
|
102
143
|
var SECURITY_DEFAULTS = {
|
|
103
144
|
maxConfigSize: 1e6,
|
|
104
145
|
// 1MB
|
|
105
|
-
requestTimeout: 5e3
|
|
106
|
-
|
|
107
|
-
// Only HTTPS for remote configs
|
|
108
|
-
cacheTimeout: 3e5
|
|
109
|
-
// 5 minutes
|
|
146
|
+
requestTimeout: 5e3
|
|
147
|
+
// 5 seconds
|
|
110
148
|
};
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
126
|
-
{ pattern: "^health\\.", description: "Health checks" }
|
|
127
|
-
]
|
|
128
|
-
},
|
|
129
|
-
effect: {
|
|
130
|
-
auto_extract_metadata: true
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
var validateConfigEffect = (rawConfig) => effect.Effect.try({
|
|
135
|
-
try: () => InstrumentationConfigSchema.parse(rawConfig),
|
|
136
|
-
catch: (error) => new ConfigValidationError({
|
|
137
|
-
reason: "Invalid configuration schema",
|
|
138
|
-
cause: error
|
|
139
|
-
})
|
|
140
|
-
});
|
|
141
|
-
var loadConfigFromFileEffect = (filePath) => effect.Effect.gen(function* () {
|
|
142
|
-
const fileContents = yield* effect.Effect.try({
|
|
143
|
-
try: () => fs.readFileSync(filePath, "utf8"),
|
|
144
|
-
catch: (error) => new ConfigFileError({
|
|
145
|
-
reason: `Failed to read config file at ${filePath}`,
|
|
149
|
+
var ConfigLoader = class extends effect.Context.Tag("ConfigLoader")() {
|
|
150
|
+
};
|
|
151
|
+
var parseYamlContent = (content, uri) => effect.Effect.gen(function* () {
|
|
152
|
+
const parsed = yield* effect.Effect.try({
|
|
153
|
+
try: () => yaml.parse(content),
|
|
154
|
+
catch: (error) => new ConfigValidationError({
|
|
155
|
+
reason: uri ? `Failed to parse YAML from ${uri}` : "Failed to parse YAML",
|
|
156
|
+
cause: error
|
|
157
|
+
})
|
|
158
|
+
});
|
|
159
|
+
return yield* effect.Effect.try({
|
|
160
|
+
try: () => InstrumentationConfigSchema.parse(parsed),
|
|
161
|
+
catch: (error) => new ConfigValidationError({
|
|
162
|
+
reason: uri ? `Invalid configuration schema from ${uri}` : "Invalid configuration schema",
|
|
146
163
|
cause: error
|
|
147
164
|
})
|
|
148
165
|
});
|
|
149
|
-
|
|
166
|
+
});
|
|
167
|
+
var loadFromFileWithFs = (fs, path, uri) => effect.Effect.gen(function* () {
|
|
168
|
+
const content = yield* fs.readFileString(path).pipe(
|
|
169
|
+
effect.Effect.mapError(
|
|
170
|
+
(error) => new ConfigFileError({
|
|
171
|
+
reason: `Failed to read config file at ${uri}`,
|
|
172
|
+
cause: error
|
|
173
|
+
})
|
|
174
|
+
)
|
|
175
|
+
);
|
|
176
|
+
if (content.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
150
177
|
return yield* effect.Effect.fail(
|
|
151
178
|
new ConfigFileError({
|
|
152
179
|
reason: `Config file exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
153
180
|
})
|
|
154
181
|
);
|
|
155
182
|
}
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
rawConfig = yaml.parse(fileContents);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
return yield* effect.Effect.fail(
|
|
161
|
-
new ConfigValidationError({
|
|
162
|
-
reason: "Invalid YAML syntax",
|
|
163
|
-
cause: error
|
|
164
|
-
})
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
return yield* validateConfigEffect(rawConfig);
|
|
183
|
+
return yield* parseYamlContent(content, uri);
|
|
168
184
|
});
|
|
169
|
-
var
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
185
|
+
var loadFromHttpWithClient = (client, url) => effect.Effect.scoped(
|
|
186
|
+
effect.Effect.gen(function* () {
|
|
187
|
+
if (url.startsWith("http://")) {
|
|
188
|
+
return yield* effect.Effect.fail(
|
|
189
|
+
new ConfigUrlError({
|
|
190
|
+
reason: "Insecure protocol: only HTTPS URLs are allowed"
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
const request = HttpClientRequest__namespace.get(url).pipe(
|
|
195
|
+
HttpClientRequest__namespace.setHeaders({
|
|
196
|
+
Accept: "application/yaml, text/yaml, application/x-yaml"
|
|
178
197
|
})
|
|
179
198
|
);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
const response = yield* client.execute(request).pipe(
|
|
200
|
+
effect.Effect.timeout(`${SECURITY_DEFAULTS.requestTimeout} millis`),
|
|
201
|
+
effect.Effect.mapError((error) => {
|
|
202
|
+
if (error._tag === "TimeoutException") {
|
|
203
|
+
return new ConfigUrlError({
|
|
204
|
+
reason: `Config fetch timeout after ${SECURITY_DEFAULTS.requestTimeout}ms from ${url}`
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return new ConfigUrlError({
|
|
208
|
+
reason: `Failed to load config from URL: ${url}`,
|
|
209
|
+
cause: error
|
|
210
|
+
});
|
|
185
211
|
})
|
|
186
212
|
);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
if (response.status >= 400) {
|
|
214
|
+
return yield* effect.Effect.fail(
|
|
215
|
+
new ConfigUrlError({
|
|
216
|
+
reason: `HTTP ${response.status} from ${url}`
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
const text = yield* response.text.pipe(
|
|
221
|
+
effect.Effect.mapError(
|
|
222
|
+
(error) => new ConfigUrlError({
|
|
223
|
+
reason: `Failed to read response body from ${url}`,
|
|
224
|
+
cause: error
|
|
225
|
+
})
|
|
226
|
+
)
|
|
227
|
+
);
|
|
228
|
+
if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
229
|
+
return yield* effect.Effect.fail(
|
|
230
|
+
new ConfigUrlError({
|
|
231
|
+
reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
232
|
+
})
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return yield* parseYamlContent(text, url);
|
|
236
|
+
})
|
|
237
|
+
);
|
|
238
|
+
var makeConfigLoader = effect.Effect.gen(function* () {
|
|
239
|
+
const fs = yield* effect.Effect.serviceOption(FileSystem.FileSystem);
|
|
240
|
+
const http = yield* HttpClient__namespace.HttpClient;
|
|
241
|
+
const loadFromUriUncached = (uri) => effect.Effect.gen(function* () {
|
|
242
|
+
if (uri.startsWith("file://")) {
|
|
243
|
+
const path = uri.slice(7);
|
|
244
|
+
if (fs._tag === "None") {
|
|
245
|
+
return yield* effect.Effect.fail(
|
|
246
|
+
new ConfigFileError({
|
|
247
|
+
reason: "FileSystem not available (browser environment?)",
|
|
248
|
+
cause: { uri }
|
|
210
249
|
})
|
|
211
250
|
);
|
|
212
251
|
}
|
|
213
|
-
return
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
return yield* loadFromFileWithFs(fs.value, path, uri);
|
|
253
|
+
}
|
|
254
|
+
if (uri.startsWith("http://") || uri.startsWith("https://")) {
|
|
255
|
+
return yield* loadFromHttpWithClient(http, uri);
|
|
256
|
+
}
|
|
257
|
+
if (fs._tag === "Some") {
|
|
258
|
+
return yield* loadFromFileWithFs(fs.value, uri, uri);
|
|
259
|
+
} else {
|
|
260
|
+
return yield* loadFromHttpWithClient(http, uri);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
const loadFromUriCached = yield* effect.Effect.cachedFunction(loadFromUriUncached);
|
|
264
|
+
return ConfigLoader.of({
|
|
265
|
+
loadFromUri: loadFromUriCached,
|
|
266
|
+
loadFromInline: (content) => effect.Effect.gen(function* () {
|
|
267
|
+
if (typeof content === "string") {
|
|
268
|
+
return yield* parseYamlContent(content);
|
|
269
|
+
}
|
|
270
|
+
return yield* effect.Effect.try({
|
|
271
|
+
try: () => InstrumentationConfigSchema.parse(content),
|
|
272
|
+
catch: (error) => new ConfigValidationError({
|
|
273
|
+
reason: "Invalid configuration schema",
|
|
274
|
+
cause: error
|
|
275
|
+
})
|
|
276
|
+
});
|
|
236
277
|
})
|
|
237
278
|
});
|
|
238
|
-
if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
239
|
-
return yield* effect.Effect.fail(
|
|
240
|
-
new ConfigUrlError({
|
|
241
|
-
reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
242
|
-
})
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
let rawConfig;
|
|
246
|
-
try {
|
|
247
|
-
rawConfig = yaml.parse(text);
|
|
248
|
-
} catch (error) {
|
|
249
|
-
return yield* effect.Effect.fail(
|
|
250
|
-
new ConfigValidationError({
|
|
251
|
-
reason: "Invalid YAML syntax",
|
|
252
|
-
cause: error
|
|
253
|
-
})
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
return yield* validateConfigEffect(rawConfig);
|
|
257
|
-
});
|
|
258
|
-
var makeConfigCache = () => effect.Cache.make({
|
|
259
|
-
capacity: 100,
|
|
260
|
-
timeToLive: effect.Duration.minutes(5),
|
|
261
|
-
lookup: (url) => fetchAndParseConfig(url)
|
|
262
|
-
});
|
|
263
|
-
var cacheInstance = null;
|
|
264
|
-
var getCache = effect.Effect.gen(function* () {
|
|
265
|
-
if (!cacheInstance) {
|
|
266
|
-
cacheInstance = yield* makeConfigCache();
|
|
267
|
-
}
|
|
268
|
-
return cacheInstance;
|
|
269
|
-
});
|
|
270
|
-
var loadConfigFromUrlEffect = (url, cacheTimeout = SECURITY_DEFAULTS.cacheTimeout) => effect.Effect.gen(function* () {
|
|
271
|
-
if (cacheTimeout === 0) {
|
|
272
|
-
return yield* fetchAndParseConfig(url);
|
|
273
|
-
}
|
|
274
|
-
const cache = yield* getCache;
|
|
275
|
-
return yield* cache.get(url);
|
|
276
279
|
});
|
|
277
|
-
var
|
|
278
|
-
if (options.config) {
|
|
279
|
-
return yield* validateConfigEffect(options.config);
|
|
280
|
-
}
|
|
281
|
-
const envConfigPath = process.env.ATRIM_INSTRUMENTATION_CONFIG;
|
|
282
|
-
if (envConfigPath) {
|
|
283
|
-
if (envConfigPath.startsWith("http://") || envConfigPath.startsWith("https://")) {
|
|
284
|
-
return yield* loadConfigFromUrlEffect(envConfigPath, options.cacheTimeout);
|
|
285
|
-
}
|
|
286
|
-
return yield* loadConfigFromFileEffect(envConfigPath);
|
|
287
|
-
}
|
|
288
|
-
if (options.configUrl) {
|
|
289
|
-
return yield* loadConfigFromUrlEffect(options.configUrl, options.cacheTimeout);
|
|
290
|
-
}
|
|
291
|
-
if (options.configPath) {
|
|
292
|
-
return yield* loadConfigFromFileEffect(options.configPath);
|
|
293
|
-
}
|
|
294
|
-
const defaultPath = path.join(process.cwd(), "instrumentation.yaml");
|
|
295
|
-
const exists = yield* effect.Effect.sync(() => fs.existsSync(defaultPath));
|
|
296
|
-
if (exists) {
|
|
297
|
-
return yield* loadConfigFromFileEffect(defaultPath);
|
|
298
|
-
}
|
|
299
|
-
return getDefaultConfig();
|
|
300
|
-
});
|
|
301
|
-
async function loadConfig(options = {}) {
|
|
302
|
-
return effect.Effect.runPromise(
|
|
303
|
-
loadConfigEffect(options).pipe(
|
|
304
|
-
// Convert typed errors to regular Error with reason message for backward compatibility
|
|
305
|
-
effect.Effect.mapError((error) => {
|
|
306
|
-
const message = error.reason;
|
|
307
|
-
const newError = new Error(message);
|
|
308
|
-
newError.cause = error.cause;
|
|
309
|
-
return newError;
|
|
310
|
-
})
|
|
311
|
-
)
|
|
312
|
-
);
|
|
313
|
-
}
|
|
280
|
+
var ConfigLoaderLive = effect.Layer.effect(ConfigLoader, makeConfigLoader);
|
|
314
281
|
var PatternMatcher = class {
|
|
315
282
|
constructor(config) {
|
|
316
283
|
__publicField(this, "ignorePatterns", []);
|
|
@@ -458,13 +425,88 @@ var Logger = class {
|
|
|
458
425
|
}
|
|
459
426
|
};
|
|
460
427
|
var logger = new Logger();
|
|
428
|
+
var NodeConfigLoaderLive = ConfigLoaderLive.pipe(
|
|
429
|
+
effect.Layer.provide(effect.Layer.mergeAll(platformNode.NodeContext.layer, platform.FetchHttpClient.layer))
|
|
430
|
+
);
|
|
431
|
+
var cachedLoaderPromise = null;
|
|
432
|
+
function getCachedLoader() {
|
|
433
|
+
if (!cachedLoaderPromise) {
|
|
434
|
+
cachedLoaderPromise = effect.Effect.runPromise(
|
|
435
|
+
effect.Effect.gen(function* () {
|
|
436
|
+
return yield* ConfigLoader;
|
|
437
|
+
}).pipe(effect.Effect.provide(NodeConfigLoaderLive))
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
return cachedLoaderPromise;
|
|
441
|
+
}
|
|
442
|
+
async function loadConfig(uri, options) {
|
|
443
|
+
if (options?.cacheTimeout === 0) {
|
|
444
|
+
const program = effect.Effect.gen(function* () {
|
|
445
|
+
const loader2 = yield* ConfigLoader;
|
|
446
|
+
return yield* loader2.loadFromUri(uri);
|
|
447
|
+
});
|
|
448
|
+
return effect.Effect.runPromise(program.pipe(effect.Effect.provide(NodeConfigLoaderLive)));
|
|
449
|
+
}
|
|
450
|
+
const loader = await getCachedLoader();
|
|
451
|
+
return effect.Effect.runPromise(loader.loadFromUri(uri));
|
|
452
|
+
}
|
|
453
|
+
async function loadConfigFromInline(content) {
|
|
454
|
+
const loader = await getCachedLoader();
|
|
455
|
+
return effect.Effect.runPromise(loader.loadFromInline(content));
|
|
456
|
+
}
|
|
457
|
+
function getDefaultConfig() {
|
|
458
|
+
return {
|
|
459
|
+
version: "1.0",
|
|
460
|
+
instrumentation: {
|
|
461
|
+
enabled: true,
|
|
462
|
+
logging: "on",
|
|
463
|
+
description: "Default instrumentation configuration",
|
|
464
|
+
instrument_patterns: [
|
|
465
|
+
{ pattern: "^app\\.", enabled: true, description: "Application operations" },
|
|
466
|
+
{ pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
|
|
467
|
+
{ pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
|
|
468
|
+
],
|
|
469
|
+
ignore_patterns: [
|
|
470
|
+
{ pattern: "^test\\.", description: "Test utilities" },
|
|
471
|
+
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
472
|
+
{ pattern: "^health\\.", description: "Health checks" }
|
|
473
|
+
]
|
|
474
|
+
},
|
|
475
|
+
effect: {
|
|
476
|
+
auto_extract_metadata: true
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
async function loadConfigWithOptions(options = {}) {
|
|
481
|
+
const loadOptions = options.cacheTimeout !== void 0 ? { cacheTimeout: options.cacheTimeout } : void 0;
|
|
482
|
+
if (options.config) {
|
|
483
|
+
return loadConfigFromInline(options.config);
|
|
484
|
+
}
|
|
485
|
+
const envConfigPath = process.env.ATRIM_INSTRUMENTATION_CONFIG;
|
|
486
|
+
if (envConfigPath) {
|
|
487
|
+
return loadConfig(envConfigPath, loadOptions);
|
|
488
|
+
}
|
|
489
|
+
if (options.configUrl) {
|
|
490
|
+
return loadConfig(options.configUrl, loadOptions);
|
|
491
|
+
}
|
|
492
|
+
if (options.configPath) {
|
|
493
|
+
return loadConfig(options.configPath, loadOptions);
|
|
494
|
+
}
|
|
495
|
+
const { existsSync } = await import('fs');
|
|
496
|
+
const { join } = await import('path');
|
|
497
|
+
const defaultPath = join(process.cwd(), "instrumentation.yaml");
|
|
498
|
+
if (existsSync(defaultPath)) {
|
|
499
|
+
return loadConfig(defaultPath, loadOptions);
|
|
500
|
+
}
|
|
501
|
+
return getDefaultConfig();
|
|
502
|
+
}
|
|
461
503
|
|
|
462
504
|
// src/integrations/effect/effect-tracer.ts
|
|
463
505
|
function createEffectInstrumentation(options = {}) {
|
|
464
506
|
return effect.Layer.unwrapEffect(
|
|
465
507
|
effect.Effect.gen(function* () {
|
|
466
508
|
const config = yield* effect.Effect.tryPromise({
|
|
467
|
-
try: () =>
|
|
509
|
+
try: () => loadConfigWithOptions(options),
|
|
468
510
|
catch: (error) => ({
|
|
469
511
|
_tag: "ConfigError",
|
|
470
512
|
message: error instanceof Error ? error.message : String(error)
|