@atrim/instrument-node 0.4.0 → 0.5.0-3a3dd2c-20251124202015
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/README.md +66 -0
- package/package.json +13 -7
- package/target/dist/index.cjs +310 -197
- package/target/dist/index.cjs.map +1 -1
- package/target/dist/index.d.cts +57 -3
- package/target/dist/index.d.ts +57 -3
- package/target/dist/index.js +288 -199
- package/target/dist/index.js.map +1 -1
- package/target/dist/integrations/effect/auto/index.cjs +276 -0
- package/target/dist/integrations/effect/auto/index.cjs.map +1 -0
- package/target/dist/integrations/effect/auto/index.d.cts +1513 -0
- package/target/dist/integrations/effect/auto/index.d.ts +1513 -0
- package/target/dist/integrations/effect/auto/index.js +264 -0
- package/target/dist/integrations/effect/auto/index.js.map +1 -0
- package/target/dist/integrations/effect/index.cjs +424 -206
- package/target/dist/integrations/effect/index.cjs.map +1 -1
- package/target/dist/integrations/effect/index.d.cts +204 -13
- package/target/dist/integrations/effect/index.d.ts +204 -13
- package/target/dist/integrations/effect/index.js +421 -208
- package/target/dist/integrations/effect/index.js.map +1 -1
package/target/dist/index.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { Data,
|
|
1
|
+
import { Data, Context, Effect, Layer } from 'effect';
|
|
2
2
|
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
3
3
|
import { SimpleSpanProcessor, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
4
4
|
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
|
|
5
5
|
import { trace } from '@opentelemetry/api';
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
6
|
+
import { FileSystem } from '@effect/platform/FileSystem';
|
|
7
|
+
import * as HttpClient from '@effect/platform/HttpClient';
|
|
8
|
+
import * as HttpClientRequest from '@effect/platform/HttpClientRequest';
|
|
8
9
|
import { parse } from 'yaml';
|
|
9
10
|
import { z } from 'zod';
|
|
10
11
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
11
12
|
import { readFile } from 'fs/promises';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { NodeContext } from '@effect/platform-node';
|
|
15
|
+
import { FetchHttpClient } from '@effect/platform';
|
|
12
16
|
|
|
13
17
|
var __defProp = Object.defineProperty;
|
|
14
18
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -49,13 +53,69 @@ var AutoIsolationConfigSchema = z.object({
|
|
|
49
53
|
add_metadata: z.boolean().default(true)
|
|
50
54
|
}).default({})
|
|
51
55
|
});
|
|
56
|
+
var SpanNamingRuleSchema = z.object({
|
|
57
|
+
// Match conditions (all specified conditions must match)
|
|
58
|
+
match: z.object({
|
|
59
|
+
// Match by file path pattern (regex)
|
|
60
|
+
file: z.string().optional(),
|
|
61
|
+
// Match by function name pattern (regex)
|
|
62
|
+
function: z.string().optional(),
|
|
63
|
+
// Match by operator type (gen, all, forEach, etc.)
|
|
64
|
+
operator: z.string().optional(),
|
|
65
|
+
// Match by call stack pattern (regex)
|
|
66
|
+
stack: z.string().optional(),
|
|
67
|
+
// Match by fiber annotation key
|
|
68
|
+
annotation: z.string().optional()
|
|
69
|
+
}),
|
|
70
|
+
// Name template with substitution variables
|
|
71
|
+
// Available: {operator}, {function}, {module}, {file}, {line}, {class}, {match:N}
|
|
72
|
+
name: z.string()
|
|
73
|
+
});
|
|
74
|
+
var AutoTracingConfigSchema = z.object({
|
|
75
|
+
// Global enable/disable for auto-tracing
|
|
76
|
+
enabled: z.boolean().default(true),
|
|
77
|
+
// Span naming configuration
|
|
78
|
+
span_naming: z.object({
|
|
79
|
+
// Default name template when no rules match
|
|
80
|
+
default: z.string().default("effect.{operator}"),
|
|
81
|
+
// Custom naming rules (applied in order, first match wins)
|
|
82
|
+
rules: z.array(SpanNamingRuleSchema).default([])
|
|
83
|
+
}).default({}),
|
|
84
|
+
// Pattern filtering
|
|
85
|
+
filter_patterns: z.object({
|
|
86
|
+
// Only trace spans matching these patterns
|
|
87
|
+
include: z.array(z.string()).default([]),
|
|
88
|
+
// Exclude spans matching these patterns (takes precedence)
|
|
89
|
+
exclude: z.array(z.string()).default([])
|
|
90
|
+
}).default({}),
|
|
91
|
+
// Sampling configuration
|
|
92
|
+
sampling: z.object({
|
|
93
|
+
// Sampling rate (0.0 to 1.0)
|
|
94
|
+
rate: z.number().min(0).max(1).default(1),
|
|
95
|
+
// Only trace effects with duration > this value
|
|
96
|
+
min_duration: z.string().default("0 millis")
|
|
97
|
+
}).default({})
|
|
98
|
+
});
|
|
52
99
|
var HttpFilteringConfigSchema = z.object({
|
|
53
100
|
// Patterns to ignore for outgoing HTTP requests (string patterns only in YAML)
|
|
54
101
|
ignore_outgoing_urls: z.array(z.string()).optional(),
|
|
55
102
|
// Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
|
|
56
103
|
ignore_incoming_paths: z.array(z.string()).optional(),
|
|
57
104
|
// Require parent span for outgoing requests (prevents root spans for HTTP calls)
|
|
58
|
-
require_parent_for_outgoing_spans: z.boolean().optional()
|
|
105
|
+
require_parent_for_outgoing_spans: z.boolean().optional(),
|
|
106
|
+
// Trace context propagation configuration
|
|
107
|
+
// Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
|
|
108
|
+
propagate_trace_context: z.object({
|
|
109
|
+
// Strategy for trace propagation
|
|
110
|
+
// - "all": Propagate to all cross-origin requests (may cause CORS errors)
|
|
111
|
+
// - "none": Never propagate trace headers
|
|
112
|
+
// - "same-origin": Only propagate to same-origin requests (default, safe)
|
|
113
|
+
// - "patterns": Propagate based on include_urls patterns
|
|
114
|
+
strategy: z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
|
|
115
|
+
// URL patterns to include when strategy is "patterns"
|
|
116
|
+
// Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
|
|
117
|
+
include_urls: z.array(z.string()).optional()
|
|
118
|
+
}).optional()
|
|
59
119
|
});
|
|
60
120
|
var InstrumentationConfigSchema = z.object({
|
|
61
121
|
version: z.string(),
|
|
@@ -68,238 +128,189 @@ var InstrumentationConfigSchema = z.object({
|
|
|
68
128
|
}),
|
|
69
129
|
effect: z.object({
|
|
70
130
|
auto_extract_metadata: z.boolean(),
|
|
71
|
-
auto_isolation: AutoIsolationConfigSchema.optional()
|
|
131
|
+
auto_isolation: AutoIsolationConfigSchema.optional(),
|
|
132
|
+
auto_tracing: AutoTracingConfigSchema.optional()
|
|
72
133
|
}).optional(),
|
|
73
134
|
http: HttpFilteringConfigSchema.optional()
|
|
74
135
|
});
|
|
75
136
|
(class extends Data.TaggedError("ConfigError") {
|
|
137
|
+
get message() {
|
|
138
|
+
return this.reason;
|
|
139
|
+
}
|
|
76
140
|
});
|
|
77
141
|
var ConfigUrlError = class extends Data.TaggedError("ConfigUrlError") {
|
|
142
|
+
get message() {
|
|
143
|
+
return this.reason;
|
|
144
|
+
}
|
|
78
145
|
};
|
|
79
146
|
var ConfigValidationError = class extends Data.TaggedError("ConfigValidationError") {
|
|
147
|
+
get message() {
|
|
148
|
+
return this.reason;
|
|
149
|
+
}
|
|
80
150
|
};
|
|
81
151
|
var ConfigFileError = class extends Data.TaggedError("ConfigFileError") {
|
|
152
|
+
get message() {
|
|
153
|
+
return this.reason;
|
|
154
|
+
}
|
|
82
155
|
};
|
|
83
156
|
(class extends Data.TaggedError("ServiceDetectionError") {
|
|
157
|
+
get message() {
|
|
158
|
+
return this.reason;
|
|
159
|
+
}
|
|
84
160
|
});
|
|
85
161
|
(class extends Data.TaggedError("InitializationError") {
|
|
162
|
+
get message() {
|
|
163
|
+
return this.reason;
|
|
164
|
+
}
|
|
86
165
|
});
|
|
87
166
|
(class extends Data.TaggedError("ExportError") {
|
|
167
|
+
get message() {
|
|
168
|
+
return this.reason;
|
|
169
|
+
}
|
|
88
170
|
});
|
|
89
171
|
(class extends Data.TaggedError("ShutdownError") {
|
|
172
|
+
get message() {
|
|
173
|
+
return this.reason;
|
|
174
|
+
}
|
|
90
175
|
});
|
|
91
176
|
var SECURITY_DEFAULTS = {
|
|
92
177
|
maxConfigSize: 1e6,
|
|
93
178
|
// 1MB
|
|
94
|
-
requestTimeout: 5e3
|
|
95
|
-
|
|
96
|
-
// Only HTTPS for remote configs
|
|
97
|
-
cacheTimeout: 3e5
|
|
98
|
-
// 5 minutes
|
|
179
|
+
requestTimeout: 5e3
|
|
180
|
+
// 5 seconds
|
|
99
181
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
115
|
-
{ pattern: "^health\\.", description: "Health checks" }
|
|
116
|
-
]
|
|
117
|
-
},
|
|
118
|
-
effect: {
|
|
119
|
-
auto_extract_metadata: true
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
var validateConfigEffect = (rawConfig) => Effect.try({
|
|
124
|
-
try: () => InstrumentationConfigSchema.parse(rawConfig),
|
|
125
|
-
catch: (error) => new ConfigValidationError({
|
|
126
|
-
reason: "Invalid configuration schema",
|
|
127
|
-
cause: error
|
|
128
|
-
})
|
|
129
|
-
});
|
|
130
|
-
var loadConfigFromFileEffect = (filePath) => Effect.gen(function* () {
|
|
131
|
-
const fileContents = yield* Effect.try({
|
|
132
|
-
try: () => readFileSync(filePath, "utf8"),
|
|
133
|
-
catch: (error) => new ConfigFileError({
|
|
134
|
-
reason: `Failed to read config file at ${filePath}`,
|
|
182
|
+
var ConfigLoader = class extends Context.Tag("ConfigLoader")() {
|
|
183
|
+
};
|
|
184
|
+
var parseYamlContent = (content, uri) => Effect.gen(function* () {
|
|
185
|
+
const parsed = yield* Effect.try({
|
|
186
|
+
try: () => parse(content),
|
|
187
|
+
catch: (error) => new ConfigValidationError({
|
|
188
|
+
reason: uri ? `Failed to parse YAML from ${uri}` : "Failed to parse YAML",
|
|
189
|
+
cause: error
|
|
190
|
+
})
|
|
191
|
+
});
|
|
192
|
+
return yield* Effect.try({
|
|
193
|
+
try: () => InstrumentationConfigSchema.parse(parsed),
|
|
194
|
+
catch: (error) => new ConfigValidationError({
|
|
195
|
+
reason: uri ? `Invalid configuration schema from ${uri}` : "Invalid configuration schema",
|
|
135
196
|
cause: error
|
|
136
197
|
})
|
|
137
198
|
});
|
|
138
|
-
|
|
199
|
+
});
|
|
200
|
+
var loadFromFileWithFs = (fs, path, uri) => Effect.gen(function* () {
|
|
201
|
+
const content = yield* fs.readFileString(path).pipe(
|
|
202
|
+
Effect.mapError(
|
|
203
|
+
(error) => new ConfigFileError({
|
|
204
|
+
reason: `Failed to read config file at ${uri}`,
|
|
205
|
+
cause: error
|
|
206
|
+
})
|
|
207
|
+
)
|
|
208
|
+
);
|
|
209
|
+
if (content.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
139
210
|
return yield* Effect.fail(
|
|
140
211
|
new ConfigFileError({
|
|
141
212
|
reason: `Config file exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
142
213
|
})
|
|
143
214
|
);
|
|
144
215
|
}
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
rawConfig = parse(fileContents);
|
|
148
|
-
} catch (error) {
|
|
149
|
-
return yield* Effect.fail(
|
|
150
|
-
new ConfigValidationError({
|
|
151
|
-
reason: "Invalid YAML syntax",
|
|
152
|
-
cause: error
|
|
153
|
-
})
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
return yield* validateConfigEffect(rawConfig);
|
|
216
|
+
return yield* parseYamlContent(content, uri);
|
|
157
217
|
});
|
|
158
|
-
var
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
218
|
+
var loadFromHttpWithClient = (client, url) => Effect.scoped(
|
|
219
|
+
Effect.gen(function* () {
|
|
220
|
+
if (url.startsWith("http://")) {
|
|
221
|
+
return yield* Effect.fail(
|
|
222
|
+
new ConfigUrlError({
|
|
223
|
+
reason: "Insecure protocol: only HTTPS URLs are allowed"
|
|
224
|
+
})
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const request = HttpClientRequest.get(url).pipe(
|
|
228
|
+
HttpClientRequest.setHeaders({
|
|
229
|
+
Accept: "application/yaml, text/yaml, application/x-yaml"
|
|
167
230
|
})
|
|
168
231
|
);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
232
|
+
const response = yield* client.execute(request).pipe(
|
|
233
|
+
Effect.timeout(`${SECURITY_DEFAULTS.requestTimeout} millis`),
|
|
234
|
+
Effect.mapError((error) => {
|
|
235
|
+
if (error._tag === "TimeoutException") {
|
|
236
|
+
return new ConfigUrlError({
|
|
237
|
+
reason: `Config fetch timeout after ${SECURITY_DEFAULTS.requestTimeout}ms from ${url}`
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
return new ConfigUrlError({
|
|
241
|
+
reason: `Failed to load config from URL: ${url}`,
|
|
242
|
+
cause: error
|
|
243
|
+
});
|
|
174
244
|
})
|
|
175
245
|
);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
246
|
+
if (response.status >= 400) {
|
|
247
|
+
return yield* Effect.fail(
|
|
248
|
+
new ConfigUrlError({
|
|
249
|
+
reason: `HTTP ${response.status} from ${url}`
|
|
250
|
+
})
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const text = yield* response.text.pipe(
|
|
254
|
+
Effect.mapError(
|
|
255
|
+
(error) => new ConfigUrlError({
|
|
256
|
+
reason: `Failed to read response body from ${url}`,
|
|
257
|
+
cause: error
|
|
258
|
+
})
|
|
259
|
+
)
|
|
260
|
+
);
|
|
261
|
+
if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
262
|
+
return yield* Effect.fail(
|
|
263
|
+
new ConfigUrlError({
|
|
264
|
+
reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
265
|
+
})
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return yield* parseYamlContent(text, url);
|
|
269
|
+
})
|
|
270
|
+
);
|
|
271
|
+
var makeConfigLoader = Effect.gen(function* () {
|
|
272
|
+
const fs = yield* Effect.serviceOption(FileSystem);
|
|
273
|
+
const http = yield* HttpClient.HttpClient;
|
|
274
|
+
const loadFromUriUncached = (uri) => Effect.gen(function* () {
|
|
275
|
+
if (uri.startsWith("file://")) {
|
|
276
|
+
const path = uri.slice(7);
|
|
277
|
+
if (fs._tag === "None") {
|
|
278
|
+
return yield* Effect.fail(
|
|
279
|
+
new ConfigFileError({
|
|
280
|
+
reason: "FileSystem not available (browser environment?)",
|
|
281
|
+
cause: { uri }
|
|
199
282
|
})
|
|
200
283
|
);
|
|
201
284
|
}
|
|
202
|
-
return
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
285
|
+
return yield* loadFromFileWithFs(fs.value, path, uri);
|
|
286
|
+
}
|
|
287
|
+
if (uri.startsWith("http://") || uri.startsWith("https://")) {
|
|
288
|
+
return yield* loadFromHttpWithClient(http, uri);
|
|
289
|
+
}
|
|
290
|
+
if (fs._tag === "Some") {
|
|
291
|
+
return yield* loadFromFileWithFs(fs.value, uri, uri);
|
|
292
|
+
} else {
|
|
293
|
+
return yield* loadFromHttpWithClient(http, uri);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
const loadFromUriCached = yield* Effect.cachedFunction(loadFromUriUncached);
|
|
297
|
+
return ConfigLoader.of({
|
|
298
|
+
loadFromUri: loadFromUriCached,
|
|
299
|
+
loadFromInline: (content) => Effect.gen(function* () {
|
|
300
|
+
if (typeof content === "string") {
|
|
301
|
+
return yield* parseYamlContent(content);
|
|
302
|
+
}
|
|
303
|
+
return yield* Effect.try({
|
|
304
|
+
try: () => InstrumentationConfigSchema.parse(content),
|
|
305
|
+
catch: (error) => new ConfigValidationError({
|
|
306
|
+
reason: "Invalid configuration schema",
|
|
307
|
+
cause: error
|
|
308
|
+
})
|
|
309
|
+
});
|
|
225
310
|
})
|
|
226
311
|
});
|
|
227
|
-
if (text.length > SECURITY_DEFAULTS.maxConfigSize) {
|
|
228
|
-
return yield* Effect.fail(
|
|
229
|
-
new ConfigUrlError({
|
|
230
|
-
reason: `Config exceeds maximum size of ${SECURITY_DEFAULTS.maxConfigSize} bytes`
|
|
231
|
-
})
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
let rawConfig;
|
|
235
|
-
try {
|
|
236
|
-
rawConfig = parse(text);
|
|
237
|
-
} catch (error) {
|
|
238
|
-
return yield* Effect.fail(
|
|
239
|
-
new ConfigValidationError({
|
|
240
|
-
reason: "Invalid YAML syntax",
|
|
241
|
-
cause: error
|
|
242
|
-
})
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
return yield* validateConfigEffect(rawConfig);
|
|
246
312
|
});
|
|
247
|
-
var
|
|
248
|
-
capacity: 100,
|
|
249
|
-
timeToLive: Duration.minutes(5),
|
|
250
|
-
lookup: (url) => fetchAndParseConfig(url)
|
|
251
|
-
});
|
|
252
|
-
var cacheInstance = null;
|
|
253
|
-
var getCache = Effect.gen(function* () {
|
|
254
|
-
if (!cacheInstance) {
|
|
255
|
-
cacheInstance = yield* makeConfigCache();
|
|
256
|
-
}
|
|
257
|
-
return cacheInstance;
|
|
258
|
-
});
|
|
259
|
-
var loadConfigFromUrlEffect = (url, cacheTimeout = SECURITY_DEFAULTS.cacheTimeout) => Effect.gen(function* () {
|
|
260
|
-
if (cacheTimeout === 0) {
|
|
261
|
-
return yield* fetchAndParseConfig(url);
|
|
262
|
-
}
|
|
263
|
-
const cache = yield* getCache;
|
|
264
|
-
return yield* cache.get(url);
|
|
265
|
-
});
|
|
266
|
-
var loadConfigEffect = (options = {}) => Effect.gen(function* () {
|
|
267
|
-
if (options.config) {
|
|
268
|
-
return yield* validateConfigEffect(options.config);
|
|
269
|
-
}
|
|
270
|
-
const envConfigPath = process.env.ATRIM_INSTRUMENTATION_CONFIG;
|
|
271
|
-
if (envConfigPath) {
|
|
272
|
-
if (envConfigPath.startsWith("http://") || envConfigPath.startsWith("https://")) {
|
|
273
|
-
return yield* loadConfigFromUrlEffect(envConfigPath, options.cacheTimeout);
|
|
274
|
-
}
|
|
275
|
-
return yield* loadConfigFromFileEffect(envConfigPath);
|
|
276
|
-
}
|
|
277
|
-
if (options.configUrl) {
|
|
278
|
-
return yield* loadConfigFromUrlEffect(options.configUrl, options.cacheTimeout);
|
|
279
|
-
}
|
|
280
|
-
if (options.configPath) {
|
|
281
|
-
return yield* loadConfigFromFileEffect(options.configPath);
|
|
282
|
-
}
|
|
283
|
-
const defaultPath = join(process.cwd(), "instrumentation.yaml");
|
|
284
|
-
const exists = yield* Effect.sync(() => existsSync(defaultPath));
|
|
285
|
-
if (exists) {
|
|
286
|
-
return yield* loadConfigFromFileEffect(defaultPath);
|
|
287
|
-
}
|
|
288
|
-
return getDefaultConfig();
|
|
289
|
-
});
|
|
290
|
-
async function loadConfig(options = {}) {
|
|
291
|
-
return Effect.runPromise(
|
|
292
|
-
loadConfigEffect(options).pipe(
|
|
293
|
-
// Convert typed errors to regular Error with reason message for backward compatibility
|
|
294
|
-
Effect.mapError((error) => {
|
|
295
|
-
const message = error.reason;
|
|
296
|
-
const newError = new Error(message);
|
|
297
|
-
newError.cause = error.cause;
|
|
298
|
-
return newError;
|
|
299
|
-
})
|
|
300
|
-
)
|
|
301
|
-
);
|
|
302
|
-
}
|
|
313
|
+
var ConfigLoaderLive = Layer.effect(ConfigLoader, makeConfigLoader);
|
|
303
314
|
var PatternMatcher = class {
|
|
304
315
|
constructor(config) {
|
|
305
316
|
__publicField2(this, "ignorePatterns", []);
|
|
@@ -725,6 +736,84 @@ async function getServiceNameAsync() {
|
|
|
725
736
|
async function getServiceVersionAsync() {
|
|
726
737
|
return Effect.runPromise(getServiceVersion);
|
|
727
738
|
}
|
|
739
|
+
var NodeConfigLoaderLive = ConfigLoaderLive.pipe(
|
|
740
|
+
Layer.provide(Layer.mergeAll(NodeContext.layer, FetchHttpClient.layer))
|
|
741
|
+
);
|
|
742
|
+
var cachedLoaderPromise = null;
|
|
743
|
+
function getCachedLoader() {
|
|
744
|
+
if (!cachedLoaderPromise) {
|
|
745
|
+
cachedLoaderPromise = Effect.runPromise(
|
|
746
|
+
Effect.gen(function* () {
|
|
747
|
+
return yield* ConfigLoader;
|
|
748
|
+
}).pipe(Effect.provide(NodeConfigLoaderLive))
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
return cachedLoaderPromise;
|
|
752
|
+
}
|
|
753
|
+
function _resetConfigLoaderCache() {
|
|
754
|
+
cachedLoaderPromise = null;
|
|
755
|
+
}
|
|
756
|
+
async function loadConfig(uri, options) {
|
|
757
|
+
if (options?.cacheTimeout === 0) {
|
|
758
|
+
const program = Effect.gen(function* () {
|
|
759
|
+
const loader2 = yield* ConfigLoader;
|
|
760
|
+
return yield* loader2.loadFromUri(uri);
|
|
761
|
+
});
|
|
762
|
+
return Effect.runPromise(program.pipe(Effect.provide(NodeConfigLoaderLive)));
|
|
763
|
+
}
|
|
764
|
+
const loader = await getCachedLoader();
|
|
765
|
+
return Effect.runPromise(loader.loadFromUri(uri));
|
|
766
|
+
}
|
|
767
|
+
async function loadConfigFromInline(content) {
|
|
768
|
+
const loader = await getCachedLoader();
|
|
769
|
+
return Effect.runPromise(loader.loadFromInline(content));
|
|
770
|
+
}
|
|
771
|
+
function getDefaultConfig() {
|
|
772
|
+
return {
|
|
773
|
+
version: "1.0",
|
|
774
|
+
instrumentation: {
|
|
775
|
+
enabled: true,
|
|
776
|
+
logging: "on",
|
|
777
|
+
description: "Default instrumentation configuration",
|
|
778
|
+
instrument_patterns: [
|
|
779
|
+
{ pattern: "^app\\.", enabled: true, description: "Application operations" },
|
|
780
|
+
{ pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
|
|
781
|
+
{ pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
|
|
782
|
+
],
|
|
783
|
+
ignore_patterns: [
|
|
784
|
+
{ pattern: "^test\\.", description: "Test utilities" },
|
|
785
|
+
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
786
|
+
{ pattern: "^health\\.", description: "Health checks" }
|
|
787
|
+
]
|
|
788
|
+
},
|
|
789
|
+
effect: {
|
|
790
|
+
auto_extract_metadata: true
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
async function loadConfigWithOptions(options = {}) {
|
|
795
|
+
const loadOptions = options.cacheTimeout !== void 0 ? { cacheTimeout: options.cacheTimeout } : void 0;
|
|
796
|
+
if (options.config) {
|
|
797
|
+
return loadConfigFromInline(options.config);
|
|
798
|
+
}
|
|
799
|
+
const envConfigPath = process.env.ATRIM_INSTRUMENTATION_CONFIG;
|
|
800
|
+
if (envConfigPath) {
|
|
801
|
+
return loadConfig(envConfigPath, loadOptions);
|
|
802
|
+
}
|
|
803
|
+
if (options.configUrl) {
|
|
804
|
+
return loadConfig(options.configUrl, loadOptions);
|
|
805
|
+
}
|
|
806
|
+
if (options.configPath) {
|
|
807
|
+
return loadConfig(options.configPath, loadOptions);
|
|
808
|
+
}
|
|
809
|
+
const { existsSync } = await import('fs');
|
|
810
|
+
const { join: join2 } = await import('path');
|
|
811
|
+
const defaultPath = join2(process.cwd(), "instrumentation.yaml");
|
|
812
|
+
if (existsSync(defaultPath)) {
|
|
813
|
+
return loadConfig(defaultPath, loadOptions);
|
|
814
|
+
}
|
|
815
|
+
return getDefaultConfig();
|
|
816
|
+
}
|
|
728
817
|
|
|
729
818
|
// src/core/sdk-initializer.ts
|
|
730
819
|
var sdkInstance = null;
|
|
@@ -864,7 +953,7 @@ async function initializeSdk(options = {}) {
|
|
|
864
953
|
}
|
|
865
954
|
}
|
|
866
955
|
async function performInitialization(options) {
|
|
867
|
-
const config = await
|
|
956
|
+
const config = await loadConfigWithOptions(options);
|
|
868
957
|
const loggingLevel = config.instrumentation.logging || "on";
|
|
869
958
|
logger.setLevel(loggingLevel);
|
|
870
959
|
const alreadyInitialized = isTracingAlreadyInitialized();
|
|
@@ -1020,13 +1109,13 @@ function logInitialization(config, serviceName, serviceVersion, options, autoIns
|
|
|
1020
1109
|
async function initializeInstrumentation(options = {}) {
|
|
1021
1110
|
const sdk = await initializeSdk(options);
|
|
1022
1111
|
if (sdk) {
|
|
1023
|
-
const config = await
|
|
1112
|
+
const config = await loadConfigWithOptions(options);
|
|
1024
1113
|
initializePatternMatcher(config);
|
|
1025
1114
|
}
|
|
1026
1115
|
return sdk;
|
|
1027
1116
|
}
|
|
1028
1117
|
async function initializePatternMatchingOnly(options = {}) {
|
|
1029
|
-
const config = await
|
|
1118
|
+
const config = await loadConfigWithOptions(options);
|
|
1030
1119
|
initializePatternMatcher(config);
|
|
1031
1120
|
logger.log("@atrim/instrumentation: Pattern matching initialized (legacy mode)");
|
|
1032
1121
|
logger.log(
|
|
@@ -1043,7 +1132,7 @@ var initializeInstrumentationEffect = (options = {}) => Effect.gen(function* ()
|
|
|
1043
1132
|
});
|
|
1044
1133
|
if (sdk) {
|
|
1045
1134
|
yield* Effect.tryPromise({
|
|
1046
|
-
try: () =>
|
|
1135
|
+
try: () => loadConfigWithOptions(options),
|
|
1047
1136
|
catch: (error) => new ConfigError2({
|
|
1048
1137
|
reason: "Failed to load config for pattern matcher",
|
|
1049
1138
|
cause: error
|
|
@@ -1060,7 +1149,7 @@ var initializeInstrumentationEffect = (options = {}) => Effect.gen(function* ()
|
|
|
1060
1149
|
});
|
|
1061
1150
|
var initializePatternMatchingOnlyEffect = (options = {}) => Effect.gen(function* () {
|
|
1062
1151
|
const config = yield* Effect.tryPromise({
|
|
1063
|
-
try: () =>
|
|
1152
|
+
try: () => loadConfigWithOptions(options),
|
|
1064
1153
|
catch: (error) => new ConfigError2({
|
|
1065
1154
|
reason: "Failed to load configuration",
|
|
1066
1155
|
cause: error
|
|
@@ -1169,6 +1258,6 @@ function suppressShutdownErrors() {
|
|
|
1169
1258
|
});
|
|
1170
1259
|
}
|
|
1171
1260
|
|
|
1172
|
-
export { ConfigError2 as ConfigError, ConfigFileError2 as ConfigFileError, ConfigUrlError2 as ConfigUrlError, ConfigValidationError2 as ConfigValidationError, ExportError2 as ExportError, InitializationError2 as InitializationError, PatternMatcher, PatternSpanProcessor, ServiceDetectionError2 as ServiceDetectionError, ShutdownError2 as ShutdownError, annotateCacheOperation, annotateDbQuery, annotateHttpRequest, createOtlpExporter, detectServiceInfoAsync as detectServiceInfo, detectServiceInfo as detectServiceInfoEffect, getOtlpEndpoint, getPatternMatcher, getSdkInstance, getServiceInfoWithFallback, getServiceNameAsync as getServiceName, getServiceName as getServiceNameEffect, getServiceVersionAsync as getServiceVersion, getServiceVersion as getServiceVersionEffect, initializeInstrumentation, initializeInstrumentationEffect, initializePatternMatchingOnly, initializePatternMatchingOnlyEffect, loadConfig, markSpanError, markSpanSuccess, recordException, resetSdk, setSpanAttributes, shouldInstrumentSpan, shutdownSdk, suppressShutdownErrors };
|
|
1261
|
+
export { ConfigError2 as ConfigError, ConfigFileError2 as ConfigFileError, ConfigUrlError2 as ConfigUrlError, ConfigValidationError2 as ConfigValidationError, ExportError2 as ExportError, InitializationError2 as InitializationError, PatternMatcher, PatternSpanProcessor, ServiceDetectionError2 as ServiceDetectionError, ShutdownError2 as ShutdownError, annotateCacheOperation, annotateDbQuery, annotateHttpRequest, _resetConfigLoaderCache as clearConfigCache, createOtlpExporter, detectServiceInfoAsync as detectServiceInfo, detectServiceInfo as detectServiceInfoEffect, getOtlpEndpoint, getPatternMatcher, getSdkInstance, getServiceInfoWithFallback, getServiceNameAsync as getServiceName, getServiceName as getServiceNameEffect, getServiceVersionAsync as getServiceVersion, getServiceVersion as getServiceVersionEffect, initializeInstrumentation, initializeInstrumentationEffect, initializePatternMatchingOnly, initializePatternMatchingOnlyEffect, loadConfig, loadConfigFromInline, loadConfigWithOptions, markSpanError, markSpanSuccess, recordException, resetSdk, setSpanAttributes, shouldInstrumentSpan, shutdownSdk, suppressShutdownErrors };
|
|
1173
1262
|
//# sourceMappingURL=index.js.map
|
|
1174
1263
|
//# sourceMappingURL=index.js.map
|