@atrim/instrument-node 0.7.1-dev.14fdea7.20260108224013 → 0.7.1-dev.14fdea7.20260108231232
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 +1 -1
- package/target/dist/integrations/effect/auto/index.cjs +183 -119
- package/target/dist/integrations/effect/auto/index.cjs.map +1 -1
- package/target/dist/integrations/effect/auto/index.d.cts +79 -1
- package/target/dist/integrations/effect/auto/index.d.ts +79 -1
- package/target/dist/integrations/effect/auto/index.js +182 -120
- package/target/dist/integrations/effect/auto/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atrim/instrument-node",
|
|
3
|
-
"version": "0.7.1-dev.14fdea7.
|
|
3
|
+
"version": "0.7.1-dev.14fdea7.20260108231232",
|
|
4
4
|
"description": "OpenTelemetry instrumentation for Node.js with centralized YAML configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var effect = require('effect');
|
|
4
|
-
var
|
|
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
7
|
var FileSystem = require('@effect/platform/FileSystem');
|
|
10
8
|
var HttpClient = require('@effect/platform/HttpClient');
|
|
11
9
|
var HttpClientRequest = require('@effect/platform/HttpClientRequest');
|
|
12
10
|
var yaml = require('yaml');
|
|
13
11
|
var zod = require('zod');
|
|
12
|
+
var OtelApi = require('@opentelemetry/api');
|
|
13
|
+
var resources = require('@opentelemetry/resources');
|
|
14
|
+
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
14
15
|
var path = require('path');
|
|
15
16
|
|
|
16
17
|
function _interopNamespace(e) {
|
|
@@ -31,9 +32,9 @@ function _interopNamespace(e) {
|
|
|
31
32
|
return Object.freeze(n);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
|
|
35
35
|
var HttpClient__namespace = /*#__PURE__*/_interopNamespace(HttpClient);
|
|
36
36
|
var HttpClientRequest__namespace = /*#__PURE__*/_interopNamespace(HttpClientRequest);
|
|
37
|
+
var OtelApi__namespace = /*#__PURE__*/_interopNamespace(OtelApi);
|
|
37
38
|
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
38
39
|
|
|
39
40
|
var __defProp = Object.defineProperty;
|
|
@@ -491,121 +492,6 @@ var Logger = class {
|
|
|
491
492
|
}
|
|
492
493
|
};
|
|
493
494
|
var logger = new Logger();
|
|
494
|
-
var compiledRulesCache = /* @__PURE__ */ new WeakMap();
|
|
495
|
-
function compileNamingRules(rules) {
|
|
496
|
-
const cached = compiledRulesCache.get(rules);
|
|
497
|
-
if (cached) return cached;
|
|
498
|
-
const compiled = rules.map((rule) => ({
|
|
499
|
-
original: rule,
|
|
500
|
-
filePattern: rule.match.file ? new RegExp(rule.match.file) : void 0,
|
|
501
|
-
functionPattern: rule.match.function ? new RegExp(rule.match.function) : void 0,
|
|
502
|
-
modulePattern: rule.match.module ? new RegExp(rule.match.module) : void 0
|
|
503
|
-
}));
|
|
504
|
-
compiledRulesCache.set(rules, compiled);
|
|
505
|
-
return compiled;
|
|
506
|
-
}
|
|
507
|
-
function extractModuleName(filePath) {
|
|
508
|
-
const basename2 = path__namespace.basename(filePath, path__namespace.extname(filePath));
|
|
509
|
-
return basename2.replace(/\.(service|controller|handler|util|helper|model|repo|repository)$/i, "").replace(/(Service|Controller|Handler|Util|Helper|Model|Repo|Repository)$/i, "");
|
|
510
|
-
}
|
|
511
|
-
function applyTemplate(template, variables, matchGroups) {
|
|
512
|
-
let result = template;
|
|
513
|
-
for (const [key, value] of Object.entries(variables)) {
|
|
514
|
-
result = result.replace(new RegExp(`\\{${key}\\}`, "g"), value);
|
|
515
|
-
}
|
|
516
|
-
if (matchGroups) {
|
|
517
|
-
result = result.replace(
|
|
518
|
-
/\{match:(\w+):(\d+)\}/g,
|
|
519
|
-
(_fullMatch, field, index) => {
|
|
520
|
-
const groups = matchGroups.get(field);
|
|
521
|
-
const idx = parseInt(index, 10);
|
|
522
|
-
if (groups && groups[idx]) {
|
|
523
|
-
return groups[idx];
|
|
524
|
-
}
|
|
525
|
-
return "";
|
|
526
|
-
}
|
|
527
|
-
);
|
|
528
|
-
}
|
|
529
|
-
return result;
|
|
530
|
-
}
|
|
531
|
-
function findMatchingRule(sourceInfo, config) {
|
|
532
|
-
const rules = config.span_naming?.rules;
|
|
533
|
-
if (!rules || rules.length === 0) return void 0;
|
|
534
|
-
const compiledRules = compileNamingRules(rules);
|
|
535
|
-
for (const rule of compiledRules) {
|
|
536
|
-
const matchGroups = /* @__PURE__ */ new Map();
|
|
537
|
-
let allMatched = true;
|
|
538
|
-
if (rule.filePattern) {
|
|
539
|
-
if (sourceInfo?.file) {
|
|
540
|
-
const match = sourceInfo.file.match(rule.filePattern);
|
|
541
|
-
if (match) {
|
|
542
|
-
matchGroups.set("file", match.slice(1));
|
|
543
|
-
} else {
|
|
544
|
-
allMatched = false;
|
|
545
|
-
}
|
|
546
|
-
} else {
|
|
547
|
-
allMatched = false;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (rule.functionPattern && allMatched) {
|
|
551
|
-
if (sourceInfo?.function) {
|
|
552
|
-
const match = sourceInfo.function.match(rule.functionPattern);
|
|
553
|
-
if (match) {
|
|
554
|
-
matchGroups.set("function", match.slice(1));
|
|
555
|
-
} else {
|
|
556
|
-
allMatched = false;
|
|
557
|
-
}
|
|
558
|
-
} else {
|
|
559
|
-
allMatched = false;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
if (rule.modulePattern && allMatched) {
|
|
563
|
-
const moduleName = sourceInfo?.file ? extractModuleName(sourceInfo.file) : "";
|
|
564
|
-
if (moduleName) {
|
|
565
|
-
const match = moduleName.match(rule.modulePattern);
|
|
566
|
-
if (match) {
|
|
567
|
-
matchGroups.set("module", match.slice(1));
|
|
568
|
-
} else {
|
|
569
|
-
allMatched = false;
|
|
570
|
-
}
|
|
571
|
-
} else {
|
|
572
|
-
allMatched = false;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
if (allMatched) {
|
|
576
|
-
return { rule, matchGroups };
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
return void 0;
|
|
580
|
-
}
|
|
581
|
-
function inferSpanName(fiberId, sourceInfo, config) {
|
|
582
|
-
const variables = {
|
|
583
|
-
fiber_id: String(fiberId),
|
|
584
|
-
function: sourceInfo?.function || "anonymous",
|
|
585
|
-
module: sourceInfo?.file ? extractModuleName(sourceInfo.file) : "unknown",
|
|
586
|
-
file: sourceInfo?.file || "unknown",
|
|
587
|
-
line: sourceInfo?.line ? String(sourceInfo.line) : "0",
|
|
588
|
-
operator: "gen"
|
|
589
|
-
// Default operator, could be enhanced with more context
|
|
590
|
-
};
|
|
591
|
-
const match = findMatchingRule(sourceInfo, config);
|
|
592
|
-
if (match) {
|
|
593
|
-
return applyTemplate(match.rule.original.name, variables, match.matchGroups);
|
|
594
|
-
}
|
|
595
|
-
const defaultTemplate = config.span_naming?.default || "effect.fiber.{fiber_id}";
|
|
596
|
-
return applyTemplate(defaultTemplate, variables);
|
|
597
|
-
}
|
|
598
|
-
function sanitizeSpanName(name) {
|
|
599
|
-
if (!name) return "effect.fiber.unknown";
|
|
600
|
-
let sanitized = name.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
601
|
-
sanitized = sanitized.replace(/_+/g, "_");
|
|
602
|
-
sanitized = sanitized.replace(/^_+|_+$/g, "");
|
|
603
|
-
if (!sanitized) return "effect.fiber.unknown";
|
|
604
|
-
if (sanitized.length > 256) {
|
|
605
|
-
sanitized = sanitized.substring(0, 256);
|
|
606
|
-
}
|
|
607
|
-
return sanitized;
|
|
608
|
-
}
|
|
609
495
|
async function loadFromFile(filePath) {
|
|
610
496
|
const { readFile } = await import('fs/promises');
|
|
611
497
|
const content = await readFile(filePath, "utf-8");
|
|
@@ -726,6 +612,182 @@ var loadFullConfig = (options) => effect.Effect.gen(function* () {
|
|
|
726
612
|
return config;
|
|
727
613
|
});
|
|
728
614
|
|
|
615
|
+
// src/integrations/effect/auto/effect-tracing.ts
|
|
616
|
+
var createEffectTracingLayer = () => {
|
|
617
|
+
return effect.Layer.unwrapEffect(
|
|
618
|
+
effect.Effect.gen(function* () {
|
|
619
|
+
const config = yield* loadFullConfig();
|
|
620
|
+
const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
|
|
621
|
+
const serviceVersion = process.env.npm_package_version || "1.0.0";
|
|
622
|
+
const exporterConfig = config.effect?.exporter_config ?? {
|
|
623
|
+
type: "otlp",
|
|
624
|
+
processor: "batch"
|
|
625
|
+
};
|
|
626
|
+
logger.log("@atrim/auto-trace: Effect-native tracing enabled");
|
|
627
|
+
logger.log(` Service: ${serviceName}`);
|
|
628
|
+
logger.log(` Exporter: ${exporterConfig.type}`);
|
|
629
|
+
if (exporterConfig.type === "none") {
|
|
630
|
+
logger.log('@atrim/auto-trace: Exporter type is "none", using empty layer');
|
|
631
|
+
return effect.Layer.empty;
|
|
632
|
+
}
|
|
633
|
+
const createSpanProcessor = () => {
|
|
634
|
+
if (exporterConfig.type === "console") {
|
|
635
|
+
logger.log("@atrim/auto-trace: Using ConsoleSpanExporter with SimpleSpanProcessor");
|
|
636
|
+
return new sdkTraceBase.SimpleSpanProcessor(new sdkTraceBase.ConsoleSpanExporter());
|
|
637
|
+
}
|
|
638
|
+
const endpoint = exporterConfig.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
|
|
639
|
+
logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
|
|
640
|
+
const otlpConfig = {
|
|
641
|
+
url: `${endpoint}/v1/traces`
|
|
642
|
+
};
|
|
643
|
+
if (exporterConfig.headers) {
|
|
644
|
+
otlpConfig.headers = exporterConfig.headers;
|
|
645
|
+
logger.log(`@atrim/auto-trace: Using custom headers: ${Object.keys(exporterConfig.headers).join(", ")}`);
|
|
646
|
+
}
|
|
647
|
+
const exporter = new exporterTraceOtlpHttp.OTLPTraceExporter(otlpConfig);
|
|
648
|
+
if (exporterConfig.processor === "simple") {
|
|
649
|
+
logger.log("@atrim/auto-trace: Using SimpleSpanProcessor");
|
|
650
|
+
return new sdkTraceBase.SimpleSpanProcessor(exporter);
|
|
651
|
+
}
|
|
652
|
+
const batchConfig = exporterConfig.batch ?? {
|
|
653
|
+
scheduled_delay_millis: 1e3,
|
|
654
|
+
max_export_batch_size: 100
|
|
655
|
+
};
|
|
656
|
+
logger.log("@atrim/auto-trace: Using BatchSpanProcessor");
|
|
657
|
+
return new sdkTraceBase.BatchSpanProcessor(exporter, {
|
|
658
|
+
scheduledDelayMillis: batchConfig.scheduled_delay_millis,
|
|
659
|
+
maxExportBatchSize: batchConfig.max_export_batch_size
|
|
660
|
+
});
|
|
661
|
+
};
|
|
662
|
+
const sdkLayer = opentelemetry.NodeSdk.layer(() => ({
|
|
663
|
+
resource: {
|
|
664
|
+
serviceName,
|
|
665
|
+
serviceVersion
|
|
666
|
+
},
|
|
667
|
+
spanProcessor: createSpanProcessor()
|
|
668
|
+
}));
|
|
669
|
+
logger.log("@atrim/auto-trace: NodeSdk layer created - HTTP requests will be auto-traced");
|
|
670
|
+
return effect.Layer.discard(sdkLayer);
|
|
671
|
+
})
|
|
672
|
+
);
|
|
673
|
+
};
|
|
674
|
+
var EffectTracingLive = createEffectTracingLayer();
|
|
675
|
+
var compiledRulesCache = /* @__PURE__ */ new WeakMap();
|
|
676
|
+
function compileNamingRules(rules) {
|
|
677
|
+
const cached = compiledRulesCache.get(rules);
|
|
678
|
+
if (cached) return cached;
|
|
679
|
+
const compiled = rules.map((rule) => ({
|
|
680
|
+
original: rule,
|
|
681
|
+
filePattern: rule.match.file ? new RegExp(rule.match.file) : void 0,
|
|
682
|
+
functionPattern: rule.match.function ? new RegExp(rule.match.function) : void 0,
|
|
683
|
+
modulePattern: rule.match.module ? new RegExp(rule.match.module) : void 0
|
|
684
|
+
}));
|
|
685
|
+
compiledRulesCache.set(rules, compiled);
|
|
686
|
+
return compiled;
|
|
687
|
+
}
|
|
688
|
+
function extractModuleName(filePath) {
|
|
689
|
+
const basename2 = path__namespace.basename(filePath, path__namespace.extname(filePath));
|
|
690
|
+
return basename2.replace(/\.(service|controller|handler|util|helper|model|repo|repository)$/i, "").replace(/(Service|Controller|Handler|Util|Helper|Model|Repo|Repository)$/i, "");
|
|
691
|
+
}
|
|
692
|
+
function applyTemplate(template, variables, matchGroups) {
|
|
693
|
+
let result = template;
|
|
694
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
695
|
+
result = result.replace(new RegExp(`\\{${key}\\}`, "g"), value);
|
|
696
|
+
}
|
|
697
|
+
if (matchGroups) {
|
|
698
|
+
result = result.replace(
|
|
699
|
+
/\{match:(\w+):(\d+)\}/g,
|
|
700
|
+
(_fullMatch, field, index) => {
|
|
701
|
+
const groups = matchGroups.get(field);
|
|
702
|
+
const idx = parseInt(index, 10);
|
|
703
|
+
if (groups && groups[idx]) {
|
|
704
|
+
return groups[idx];
|
|
705
|
+
}
|
|
706
|
+
return "";
|
|
707
|
+
}
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
return result;
|
|
711
|
+
}
|
|
712
|
+
function findMatchingRule(sourceInfo, config) {
|
|
713
|
+
const rules = config.span_naming?.rules;
|
|
714
|
+
if (!rules || rules.length === 0) return void 0;
|
|
715
|
+
const compiledRules = compileNamingRules(rules);
|
|
716
|
+
for (const rule of compiledRules) {
|
|
717
|
+
const matchGroups = /* @__PURE__ */ new Map();
|
|
718
|
+
let allMatched = true;
|
|
719
|
+
if (rule.filePattern) {
|
|
720
|
+
if (sourceInfo?.file) {
|
|
721
|
+
const match = sourceInfo.file.match(rule.filePattern);
|
|
722
|
+
if (match) {
|
|
723
|
+
matchGroups.set("file", match.slice(1));
|
|
724
|
+
} else {
|
|
725
|
+
allMatched = false;
|
|
726
|
+
}
|
|
727
|
+
} else {
|
|
728
|
+
allMatched = false;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (rule.functionPattern && allMatched) {
|
|
732
|
+
if (sourceInfo?.function) {
|
|
733
|
+
const match = sourceInfo.function.match(rule.functionPattern);
|
|
734
|
+
if (match) {
|
|
735
|
+
matchGroups.set("function", match.slice(1));
|
|
736
|
+
} else {
|
|
737
|
+
allMatched = false;
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
allMatched = false;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (rule.modulePattern && allMatched) {
|
|
744
|
+
const moduleName = sourceInfo?.file ? extractModuleName(sourceInfo.file) : "";
|
|
745
|
+
if (moduleName) {
|
|
746
|
+
const match = moduleName.match(rule.modulePattern);
|
|
747
|
+
if (match) {
|
|
748
|
+
matchGroups.set("module", match.slice(1));
|
|
749
|
+
} else {
|
|
750
|
+
allMatched = false;
|
|
751
|
+
}
|
|
752
|
+
} else {
|
|
753
|
+
allMatched = false;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
if (allMatched) {
|
|
757
|
+
return { rule, matchGroups };
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return void 0;
|
|
761
|
+
}
|
|
762
|
+
function inferSpanName(fiberId, sourceInfo, config) {
|
|
763
|
+
const variables = {
|
|
764
|
+
fiber_id: String(fiberId),
|
|
765
|
+
function: sourceInfo?.function || "anonymous",
|
|
766
|
+
module: sourceInfo?.file ? extractModuleName(sourceInfo.file) : "unknown",
|
|
767
|
+
file: sourceInfo?.file || "unknown",
|
|
768
|
+
line: sourceInfo?.line ? String(sourceInfo.line) : "0",
|
|
769
|
+
operator: "gen"
|
|
770
|
+
// Default operator, could be enhanced with more context
|
|
771
|
+
};
|
|
772
|
+
const match = findMatchingRule(sourceInfo, config);
|
|
773
|
+
if (match) {
|
|
774
|
+
return applyTemplate(match.rule.original.name, variables, match.matchGroups);
|
|
775
|
+
}
|
|
776
|
+
const defaultTemplate = config.span_naming?.default || "effect.fiber.{fiber_id}";
|
|
777
|
+
return applyTemplate(defaultTemplate, variables);
|
|
778
|
+
}
|
|
779
|
+
function sanitizeSpanName(name) {
|
|
780
|
+
if (!name) return "effect.fiber.unknown";
|
|
781
|
+
let sanitized = name.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
782
|
+
sanitized = sanitized.replace(/_+/g, "_");
|
|
783
|
+
sanitized = sanitized.replace(/^_+|_+$/g, "");
|
|
784
|
+
if (!sanitized) return "effect.fiber.unknown";
|
|
785
|
+
if (sanitized.length > 256) {
|
|
786
|
+
sanitized = sanitized.substring(0, 256);
|
|
787
|
+
}
|
|
788
|
+
return sanitized;
|
|
789
|
+
}
|
|
790
|
+
|
|
729
791
|
// src/integrations/effect/auto/supervisor.ts
|
|
730
792
|
var AutoTracingEnabled = effect.FiberRef.unsafeMake(true);
|
|
731
793
|
var AutoTracingSpanName = effect.FiberRef.unsafeMake(effect.Option.none());
|
|
@@ -1101,9 +1163,11 @@ exports.AutoTracingEnabled = AutoTracingEnabled;
|
|
|
1101
1163
|
exports.AutoTracingLive = AutoTracingLive;
|
|
1102
1164
|
exports.AutoTracingSpanName = AutoTracingSpanName;
|
|
1103
1165
|
exports.AutoTracingSupervisor = AutoTracingSupervisor;
|
|
1166
|
+
exports.EffectTracingLive = EffectTracingLive;
|
|
1104
1167
|
exports.FullAutoTracingLive = FullAutoTracingLive;
|
|
1105
1168
|
exports.createAutoTracingLayer = createAutoTracingLayer;
|
|
1106
1169
|
exports.createAutoTracingSupervisor = createAutoTracingSupervisor;
|
|
1170
|
+
exports.createEffectTracingLayer = createEffectTracingLayer;
|
|
1107
1171
|
exports.createFullAutoTracingLayer = createFullAutoTracingLayer;
|
|
1108
1172
|
exports.defaultAutoTracingConfig = defaultAutoTracingConfig;
|
|
1109
1173
|
exports.inferSpanName = inferSpanName;
|