@atrim/instrument-node 0.7.1-dev.14fdea7.20260109021705 → 0.7.1-dev.764c183.20260110203528
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 +2 -1
- package/target/dist/index.cjs +19 -0
- package/target/dist/index.cjs.map +1 -1
- package/target/dist/index.js +19 -0
- package/target/dist/index.js.map +1 -1
- package/target/dist/integrations/effect/auto/index.cjs +146 -52
- package/target/dist/integrations/effect/auto/index.cjs.map +1 -1
- package/target/dist/integrations/effect/auto/index.d.cts +20 -1
- package/target/dist/integrations/effect/auto/index.d.ts +20 -1
- package/target/dist/integrations/effect/auto/index.js +146 -52
- package/target/dist/integrations/effect/auto/index.js.map +1 -1
- package/target/dist/integrations/effect/index.cjs +19 -0
- package/target/dist/integrations/effect/index.cjs.map +1 -1
- package/target/dist/integrations/effect/index.js +19 -0
- package/target/dist/integrations/effect/index.js.map +1 -1
|
@@ -4,14 +4,14 @@ var effect = require('effect');
|
|
|
4
4
|
var opentelemetry = require('@effect/opentelemetry');
|
|
5
5
|
var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
|
|
6
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');
|
|
7
10
|
var FileSystem = require('@effect/platform/FileSystem');
|
|
8
11
|
var HttpClient = require('@effect/platform/HttpClient');
|
|
9
12
|
var HttpClientRequest = require('@effect/platform/HttpClientRequest');
|
|
10
13
|
var yaml = require('yaml');
|
|
11
14
|
var zod = require('zod');
|
|
12
|
-
var OtelApi = require('@opentelemetry/api');
|
|
13
|
-
var resources = require('@opentelemetry/resources');
|
|
14
|
-
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
15
15
|
var path = require('path');
|
|
16
16
|
|
|
17
17
|
function _interopNamespace(e) {
|
|
@@ -32,9 +32,9 @@ function _interopNamespace(e) {
|
|
|
32
32
|
return Object.freeze(n);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
|
|
35
36
|
var HttpClient__namespace = /*#__PURE__*/_interopNamespace(HttpClient);
|
|
36
37
|
var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
|
|
37
|
-
var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
|
|
38
38
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
39
39
|
|
|
40
40
|
var __defProp = Object.defineProperty;
|
|
@@ -107,6 +107,25 @@ var AutoInstrumentationConfigSchema = zod.z.object({
|
|
|
107
107
|
// Naming rules (first match wins)
|
|
108
108
|
rules: zod.z.array(SpanNamingRuleSchema).default([])
|
|
109
109
|
}).default({}),
|
|
110
|
+
// Span relationship configuration for forked fibers
|
|
111
|
+
// Controls how child fiber spans relate to their parent/forking context
|
|
112
|
+
span_relationships: zod.z.object({
|
|
113
|
+
// Relationship type between forked fiber spans and their parent context
|
|
114
|
+
// - 'parent-child': Use parent-child relationship (default, traditional tracing)
|
|
115
|
+
// Parent span shows child as nested. Works well with most observability tools.
|
|
116
|
+
// - 'span-links': Use span links (semantically correct for async forks per OTel spec)
|
|
117
|
+
// Fibers get independent traces linked to parent. Better for long-running fibers.
|
|
118
|
+
// - 'both': Create parent-child AND add span links
|
|
119
|
+
// Maximum visibility but may create redundant data.
|
|
120
|
+
type: zod.z.enum(["parent-child", "span-links", "both"]).default("parent-child"),
|
|
121
|
+
// Custom attributes to add to span links (only used when type includes links)
|
|
122
|
+
link_attributes: zod.z.object({
|
|
123
|
+
// Link type identifier
|
|
124
|
+
"link.type": zod.z.string().default("fork"),
|
|
125
|
+
// Custom attributes (key-value pairs)
|
|
126
|
+
custom: zod.z.record(zod.z.string()).optional()
|
|
127
|
+
}).optional()
|
|
128
|
+
}).default({}),
|
|
110
129
|
// Pattern-based filtering
|
|
111
130
|
filter: zod.z.object({
|
|
112
131
|
// Only trace spans matching these patterns (empty = trace all)
|
|
@@ -550,6 +569,9 @@ var defaultAutoTracingConfig = {
|
|
|
550
569
|
infer_from_source: true,
|
|
551
570
|
rules: []
|
|
552
571
|
},
|
|
572
|
+
span_relationships: {
|
|
573
|
+
type: "parent-child"
|
|
574
|
+
},
|
|
553
575
|
filter: {
|
|
554
576
|
include: [],
|
|
555
577
|
exclude: []
|
|
@@ -817,42 +839,85 @@ var AutoTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
|
|
|
817
839
|
if (!this.shouldTrace(spanName)) {
|
|
818
840
|
return;
|
|
819
841
|
}
|
|
842
|
+
const relationshipType = this.config.span_relationships?.type ?? "parent-child";
|
|
843
|
+
const useParentChild = relationshipType === "parent-child" || relationshipType === "both";
|
|
844
|
+
const useSpanLinks = relationshipType === "span-links" || relationshipType === "both";
|
|
820
845
|
let parentContext = OtelApi__namespace.ROOT_CONTEXT;
|
|
821
846
|
let parentFiberId;
|
|
847
|
+
let spanLinks = [];
|
|
822
848
|
const maybeEffectParentSpan = effect.Context.getOption(_context, effect.Tracer.ParentSpan);
|
|
823
849
|
if (effect.Option.isSome(maybeEffectParentSpan)) {
|
|
824
850
|
const effectSpan = maybeEffectParentSpan.value;
|
|
825
|
-
logger.log(
|
|
851
|
+
logger.log(
|
|
852
|
+
`@atrim/auto-trace: Found ParentSpan - traceId=${effectSpan.traceId.slice(0, 8)}..., spanId=${effectSpan.spanId.slice(0, 8)}...`
|
|
853
|
+
);
|
|
826
854
|
const otelSpanContext = {
|
|
827
855
|
traceId: effectSpan.traceId,
|
|
828
856
|
spanId: effectSpan.spanId,
|
|
829
857
|
traceFlags: effectSpan.sampled ? OtelApi__namespace.TraceFlags.SAMPLED : OtelApi__namespace.TraceFlags.NONE,
|
|
830
858
|
isRemote: false
|
|
831
859
|
};
|
|
832
|
-
|
|
833
|
-
|
|
860
|
+
if (useParentChild) {
|
|
861
|
+
const wrappedSpan = OtelApi__namespace.trace.wrapSpanContext(otelSpanContext);
|
|
862
|
+
parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, wrappedSpan);
|
|
863
|
+
}
|
|
864
|
+
if (useSpanLinks) {
|
|
865
|
+
const linkAttributes = this.getLinkAttributes();
|
|
866
|
+
spanLinks.push({
|
|
867
|
+
context: otelSpanContext,
|
|
868
|
+
attributes: linkAttributes
|
|
869
|
+
});
|
|
870
|
+
logger.log(`@atrim/auto-trace: Added span link to parent (${relationshipType})`);
|
|
871
|
+
}
|
|
834
872
|
} else if (effect.Option.isSome(parent)) {
|
|
835
873
|
parentFiberId = parent.value.id().id;
|
|
836
874
|
const parentSpan = this.fiberSpans.get(parent.value);
|
|
837
875
|
if (parentSpan) {
|
|
838
|
-
|
|
876
|
+
if (useParentChild) {
|
|
877
|
+
parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, parentSpan);
|
|
878
|
+
}
|
|
879
|
+
if (useSpanLinks) {
|
|
880
|
+
const linkAttributes = this.getLinkAttributes();
|
|
881
|
+
spanLinks.push({
|
|
882
|
+
context: parentSpan.spanContext(),
|
|
883
|
+
attributes: linkAttributes
|
|
884
|
+
});
|
|
885
|
+
}
|
|
839
886
|
} else if (this._rootSpan) {
|
|
840
|
-
|
|
887
|
+
if (useParentChild) {
|
|
888
|
+
parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, this._rootSpan);
|
|
889
|
+
}
|
|
890
|
+
if (useSpanLinks) {
|
|
891
|
+
const linkAttributes = this.getLinkAttributes();
|
|
892
|
+
spanLinks.push({
|
|
893
|
+
context: this._rootSpan.spanContext(),
|
|
894
|
+
attributes: linkAttributes
|
|
895
|
+
});
|
|
896
|
+
}
|
|
841
897
|
}
|
|
842
898
|
} else if (this._rootSpan) {
|
|
843
|
-
|
|
899
|
+
if (useParentChild) {
|
|
900
|
+
parentContext = OtelApi__namespace.trace.setSpan(OtelApi__namespace.ROOT_CONTEXT, this._rootSpan);
|
|
901
|
+
}
|
|
902
|
+
if (useSpanLinks) {
|
|
903
|
+
const linkAttributes = this.getLinkAttributes();
|
|
904
|
+
spanLinks.push({
|
|
905
|
+
context: this._rootSpan.spanContext(),
|
|
906
|
+
attributes: linkAttributes
|
|
907
|
+
});
|
|
908
|
+
}
|
|
844
909
|
}
|
|
845
910
|
if (effect.Option.isSome(parent)) {
|
|
846
911
|
parentFiberId = parent.value.id().id;
|
|
847
912
|
}
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
);
|
|
913
|
+
const spanOptions = {
|
|
914
|
+
kind: OtelApi__namespace.SpanKind.INTERNAL,
|
|
915
|
+
attributes: this.getInitialAttributes(fiber, sourceInfo, parentFiberId)
|
|
916
|
+
};
|
|
917
|
+
if (spanLinks.length > 0) {
|
|
918
|
+
spanOptions.links = spanLinks;
|
|
919
|
+
}
|
|
920
|
+
const span = this.tracer.startSpan(spanName, spanOptions, parentContext);
|
|
856
921
|
logger.log(`@atrim/auto-trace: Created span "${spanName}" for fiber ${fiber.id().id}`);
|
|
857
922
|
this.fiberSpans.set(fiber, span);
|
|
858
923
|
this.fiberStartTimes.set(fiber, process.hrtime.bigint());
|
|
@@ -862,8 +927,12 @@ var AutoTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
|
|
|
862
927
|
* Called when a fiber completes (success or failure)
|
|
863
928
|
*/
|
|
864
929
|
onEnd(exit, fiber) {
|
|
930
|
+
logger.log(`@atrim/auto-trace: onEnd called for fiber ${fiber.id().id}`);
|
|
865
931
|
const span = this.fiberSpans.get(fiber);
|
|
866
932
|
if (!span) {
|
|
933
|
+
logger.log(
|
|
934
|
+
`@atrim/auto-trace: No span found for fiber ${fiber.id().id} (skipped or filtered)`
|
|
935
|
+
);
|
|
867
936
|
return;
|
|
868
937
|
}
|
|
869
938
|
const startTime = this.fiberStartTimes.get(fiber);
|
|
@@ -887,10 +956,26 @@ var AutoTracingSupervisor = class extends effect.Supervisor.AbstractSupervisor {
|
|
|
887
956
|
span.setAttribute("effect.fiber.failed", true);
|
|
888
957
|
}
|
|
889
958
|
span.end();
|
|
959
|
+
logger.log(`@atrim/auto-trace: Ended span for fiber ${fiber.id().id}`);
|
|
890
960
|
this.fiberSpans.delete(fiber);
|
|
891
961
|
this.fiberStartTimes.delete(fiber);
|
|
892
962
|
this.activeFiberCount--;
|
|
893
963
|
}
|
|
964
|
+
/**
|
|
965
|
+
* Get attributes for span links from config
|
|
966
|
+
*/
|
|
967
|
+
getLinkAttributes() {
|
|
968
|
+
const linkConfig = this.config.span_relationships?.link_attributes;
|
|
969
|
+
const attrs = {
|
|
970
|
+
"link.type": linkConfig?.["link.type"] ?? "fork"
|
|
971
|
+
};
|
|
972
|
+
if (linkConfig?.custom) {
|
|
973
|
+
for (const [key, value] of Object.entries(linkConfig.custom)) {
|
|
974
|
+
attrs[key] = value;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return attrs;
|
|
978
|
+
}
|
|
894
979
|
/**
|
|
895
980
|
* Check if a span name should be traced based on filter patterns
|
|
896
981
|
*/
|
|
@@ -1062,7 +1147,9 @@ var createExporterLayer = (exporterConfig, serviceName, serviceVersion) => {
|
|
|
1062
1147
|
};
|
|
1063
1148
|
if (config.headers) {
|
|
1064
1149
|
exporterConfig2.headers = config.headers;
|
|
1065
|
-
logger.log(
|
|
1150
|
+
logger.log(
|
|
1151
|
+
`@atrim/auto-trace: Using custom headers: ${Object.keys(config.headers).join(", ")}`
|
|
1152
|
+
);
|
|
1066
1153
|
}
|
|
1067
1154
|
return new exporterTraceOtlpHttp.OTLPTraceExporter(exporterConfig2);
|
|
1068
1155
|
};
|
|
@@ -1155,7 +1242,9 @@ var createEffectTracingLayer = () => {
|
|
|
1155
1242
|
};
|
|
1156
1243
|
if (exporterConfig.headers) {
|
|
1157
1244
|
otlpConfig.headers = exporterConfig.headers;
|
|
1158
|
-
logger.log(
|
|
1245
|
+
logger.log(
|
|
1246
|
+
`@atrim/auto-trace: Using custom headers: ${Object.keys(exporterConfig.headers).join(", ")}`
|
|
1247
|
+
);
|
|
1159
1248
|
}
|
|
1160
1249
|
const exporter = new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
|
|
1161
1250
|
if (exporterConfig.processor === "simple") {
|
|
@@ -1203,6 +1292,9 @@ var createCombinedTracingLayer = () => {
|
|
|
1203
1292
|
infer_from_source: true,
|
|
1204
1293
|
rules: []
|
|
1205
1294
|
},
|
|
1295
|
+
span_relationships: {
|
|
1296
|
+
type: "parent-child"
|
|
1297
|
+
},
|
|
1206
1298
|
filter: { include: [], exclude: [] },
|
|
1207
1299
|
performance: { sampling_rate: 1, min_duration: "0ms", max_concurrent: 0 },
|
|
1208
1300
|
metadata: { fiber_info: true, source_location: true, parent_fiber: true }
|
|
@@ -1214,10 +1306,10 @@ var createCombinedTracingLayer = () => {
|
|
|
1214
1306
|
logger.log('@atrim/auto-trace: Exporter type is "none", using empty layer');
|
|
1215
1307
|
return effect.Layer.empty;
|
|
1216
1308
|
}
|
|
1217
|
-
const
|
|
1309
|
+
const createSpanExporter = () => {
|
|
1218
1310
|
if (exporterConfig.type === "console") {
|
|
1219
|
-
logger.log("@atrim/auto-trace: Using ConsoleSpanExporter
|
|
1220
|
-
return new sdkTraceBase.
|
|
1311
|
+
logger.log("@atrim/auto-trace: Using ConsoleSpanExporter");
|
|
1312
|
+
return new sdkTraceBase.ConsoleSpanExporter();
|
|
1221
1313
|
}
|
|
1222
1314
|
const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
|
|
1223
1315
|
logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
|
|
@@ -1226,10 +1318,15 @@ var createCombinedTracingLayer = () => {
|
|
|
1226
1318
|
};
|
|
1227
1319
|
if (exporterConfig.headers) {
|
|
1228
1320
|
otlpConfig.headers = exporterConfig.headers;
|
|
1229
|
-
logger.log(
|
|
1321
|
+
logger.log(
|
|
1322
|
+
`@atrim/auto-trace: Using custom headers: ${Object.keys(exporterConfig.headers).join(", ")}`
|
|
1323
|
+
);
|
|
1230
1324
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1325
|
+
return new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
|
|
1326
|
+
};
|
|
1327
|
+
const createSpanProcessor = () => {
|
|
1328
|
+
const exporter = createSpanExporter();
|
|
1329
|
+
if (exporterConfig.processor === "simple" || exporterConfig.type === "console") {
|
|
1233
1330
|
logger.log("@atrim/auto-trace: Using SimpleSpanProcessor");
|
|
1234
1331
|
return new sdkTraceBase.SimpleSpanProcessor(exporter);
|
|
1235
1332
|
}
|
|
@@ -1243,34 +1340,31 @@ var createCombinedTracingLayer = () => {
|
|
|
1243
1340
|
maxExportBatchSize: batchConfig.max_export_batch_size
|
|
1244
1341
|
});
|
|
1245
1342
|
};
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
logger.log("@atrim/auto-trace: Got TracerProvider from NodeSdk layer");
|
|
1258
|
-
const supervisor = createAutoTracingSupervisor(autoConfig, tracerProvider.value);
|
|
1259
|
-
logger.log("@atrim/auto-trace: Combined layer created");
|
|
1260
|
-
logger.log(" - HTTP requests: auto-traced via Effect platform");
|
|
1261
|
-
logger.log(" - Forked fibers: auto-traced via Supervisor");
|
|
1262
|
-
return effect.Supervisor.addSupervisor(supervisor);
|
|
1263
|
-
} else {
|
|
1264
|
-
logger.log("@atrim/auto-trace: WARNING: No TracerProvider found, creating supervisor without it");
|
|
1265
|
-
const supervisor = createAutoTracingSupervisor(autoConfig);
|
|
1266
|
-
logger.log("@atrim/auto-trace: Combined layer created (fallback)");
|
|
1267
|
-
logger.log(" - HTTP requests: auto-traced via Effect platform");
|
|
1268
|
-
logger.log(" - Forked fibers: auto-traced via Supervisor");
|
|
1269
|
-
return effect.Supervisor.addSupervisor(supervisor);
|
|
1270
|
-
}
|
|
1343
|
+
const globalProviderLayer = effect.Layer.effectDiscard(
|
|
1344
|
+
effect.Effect.sync(() => {
|
|
1345
|
+
const provider = new sdkTraceBase.BasicTracerProvider({
|
|
1346
|
+
resource: resources.resourceFromAttributes({
|
|
1347
|
+
[semanticConventions.ATTR_SERVICE_NAME]: serviceName,
|
|
1348
|
+
[semanticConventions.ATTR_SERVICE_VERSION]: serviceVersion
|
|
1349
|
+
}),
|
|
1350
|
+
spanProcessors: [createSpanProcessor()]
|
|
1351
|
+
});
|
|
1352
|
+
OtelApi__namespace.trace.setGlobalTracerProvider(provider);
|
|
1353
|
+
logger.log("@atrim/auto-trace: Global TracerProvider registered");
|
|
1271
1354
|
})
|
|
1272
1355
|
);
|
|
1273
|
-
|
|
1356
|
+
const resourceLayer = opentelemetry.Resource.layer({
|
|
1357
|
+
serviceName,
|
|
1358
|
+
serviceVersion
|
|
1359
|
+
});
|
|
1360
|
+
const effectTracerLayer = opentelemetry.Tracer.layerGlobal;
|
|
1361
|
+
const supervisor = createAutoTracingSupervisor(autoConfig);
|
|
1362
|
+
const supervisorLayer = effect.Supervisor.addSupervisor(supervisor);
|
|
1363
|
+
logger.log("@atrim/auto-trace: Combined layer created");
|
|
1364
|
+
logger.log(" - HTTP requests: auto-traced via Effect platform (global provider)");
|
|
1365
|
+
logger.log(" - Forked fibers: auto-traced via Supervisor (global provider)");
|
|
1366
|
+
const tracerWithResource = effectTracerLayer.pipe(effect.Layer.provide(resourceLayer));
|
|
1367
|
+
return effect.Layer.mergeAll(globalProviderLayer, effect.Layer.discard(tracerWithResource), supervisorLayer);
|
|
1274
1368
|
})
|
|
1275
1369
|
);
|
|
1276
1370
|
};
|