@atrim/instrument-node 0.7.1-dev.14fdea7.20260108220010 → 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.
@@ -1,16 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  var effect = require('effect');
4
- var OtelApi = require('@opentelemetry/api');
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;
@@ -162,6 +163,9 @@ var ExporterConfigSchema = zod.z.object({
162
163
  // OTLP endpoint URL (for type: otlp)
163
164
  // Defaults to OTEL_EXPORTER_OTLP_ENDPOINT env var or http://localhost:4318
164
165
  endpoint: zod.z.string().optional(),
166
+ // Custom headers to send with OTLP requests (for type: otlp)
167
+ // Useful for authentication (x-api-key, Authorization, etc.)
168
+ headers: zod.z.record(zod.z.string()).optional(),
165
169
  // Span processor type
166
170
  // - 'batch': Batch spans for export (production, lower overhead)
167
171
  // - 'simple': Export immediately (development, no batching delay)
@@ -488,121 +492,6 @@ var Logger = class {
488
492
  }
489
493
  };
490
494
  var logger = new Logger();
491
- var compiledRulesCache = /* @__PURE__ */ new WeakMap();
492
- function compileNamingRules(rules) {
493
- const cached = compiledRulesCache.get(rules);
494
- if (cached) return cached;
495
- const compiled = rules.map((rule) => ({
496
- original: rule,
497
- filePattern: rule.match.file ? new RegExp(rule.match.file) : void 0,
498
- functionPattern: rule.match.function ? new RegExp(rule.match.function) : void 0,
499
- modulePattern: rule.match.module ? new RegExp(rule.match.module) : void 0
500
- }));
501
- compiledRulesCache.set(rules, compiled);
502
- return compiled;
503
- }
504
- function extractModuleName(filePath) {
505
- const basename2 = path__namespace.basename(filePath, path__namespace.extname(filePath));
506
- return basename2.replace(/\.(service|controller|handler|util|helper|model|repo|repository)$/i, "").replace(/(Service|Controller|Handler|Util|Helper|Model|Repo|Repository)$/i, "");
507
- }
508
- function applyTemplate(template, variables, matchGroups) {
509
- let result = template;
510
- for (const [key, value] of Object.entries(variables)) {
511
- result = result.replace(new RegExp(`\\{${key}\\}`, "g"), value);
512
- }
513
- if (matchGroups) {
514
- result = result.replace(
515
- /\{match:(\w+):(\d+)\}/g,
516
- (_fullMatch, field, index) => {
517
- const groups = matchGroups.get(field);
518
- const idx = parseInt(index, 10);
519
- if (groups && groups[idx]) {
520
- return groups[idx];
521
- }
522
- return "";
523
- }
524
- );
525
- }
526
- return result;
527
- }
528
- function findMatchingRule(sourceInfo, config) {
529
- const rules = config.span_naming?.rules;
530
- if (!rules || rules.length === 0) return void 0;
531
- const compiledRules = compileNamingRules(rules);
532
- for (const rule of compiledRules) {
533
- const matchGroups = /* @__PURE__ */ new Map();
534
- let allMatched = true;
535
- if (rule.filePattern) {
536
- if (sourceInfo?.file) {
537
- const match = sourceInfo.file.match(rule.filePattern);
538
- if (match) {
539
- matchGroups.set("file", match.slice(1));
540
- } else {
541
- allMatched = false;
542
- }
543
- } else {
544
- allMatched = false;
545
- }
546
- }
547
- if (rule.functionPattern && allMatched) {
548
- if (sourceInfo?.function) {
549
- const match = sourceInfo.function.match(rule.functionPattern);
550
- if (match) {
551
- matchGroups.set("function", match.slice(1));
552
- } else {
553
- allMatched = false;
554
- }
555
- } else {
556
- allMatched = false;
557
- }
558
- }
559
- if (rule.modulePattern && allMatched) {
560
- const moduleName = sourceInfo?.file ? extractModuleName(sourceInfo.file) : "";
561
- if (moduleName) {
562
- const match = moduleName.match(rule.modulePattern);
563
- if (match) {
564
- matchGroups.set("module", match.slice(1));
565
- } else {
566
- allMatched = false;
567
- }
568
- } else {
569
- allMatched = false;
570
- }
571
- }
572
- if (allMatched) {
573
- return { rule, matchGroups };
574
- }
575
- }
576
- return void 0;
577
- }
578
- function inferSpanName(fiberId, sourceInfo, config) {
579
- const variables = {
580
- fiber_id: String(fiberId),
581
- function: sourceInfo?.function || "anonymous",
582
- module: sourceInfo?.file ? extractModuleName(sourceInfo.file) : "unknown",
583
- file: sourceInfo?.file || "unknown",
584
- line: sourceInfo?.line ? String(sourceInfo.line) : "0",
585
- operator: "gen"
586
- // Default operator, could be enhanced with more context
587
- };
588
- const match = findMatchingRule(sourceInfo, config);
589
- if (match) {
590
- return applyTemplate(match.rule.original.name, variables, match.matchGroups);
591
- }
592
- const defaultTemplate = config.span_naming?.default || "effect.fiber.{fiber_id}";
593
- return applyTemplate(defaultTemplate, variables);
594
- }
595
- function sanitizeSpanName(name) {
596
- if (!name) return "effect.fiber.unknown";
597
- let sanitized = name.replace(/[^a-zA-Z0-9._-]/g, "_");
598
- sanitized = sanitized.replace(/_+/g, "_");
599
- sanitized = sanitized.replace(/^_+|_+$/g, "");
600
- if (!sanitized) return "effect.fiber.unknown";
601
- if (sanitized.length > 256) {
602
- sanitized = sanitized.substring(0, 256);
603
- }
604
- return sanitized;
605
- }
606
495
  async function loadFromFile(filePath) {
607
496
  const { readFile } = await import('fs/promises');
608
497
  const content = await readFile(filePath, "utf-8");
@@ -723,6 +612,182 @@ var loadFullConfig = (options) => effect.Effect.gen(function* () {
723
612
  return config;
724
613
  });
725
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
+
726
791
  // src/integrations/effect/auto/supervisor.ts
727
792
  var AutoTracingEnabled = effect.FiberRef.unsafeMake(true);
728
793
  var AutoTracingSpanName = effect.FiberRef.unsafeMake(effect.Option.none());
@@ -1023,9 +1088,14 @@ var createExporterLayer = (exporterConfig, serviceName, serviceVersion) => {
1023
1088
  }
1024
1089
  const endpoint = config.endpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
1025
1090
  logger.log(`@atrim/auto-trace: Using OTLPTraceExporter (${endpoint})`);
1026
- return new exporterTraceOtlpHttp.OTLPTraceExporter({
1091
+ const exporterConfig2 = {
1027
1092
  url: `${endpoint}/v1/traces`
1028
- });
1093
+ };
1094
+ if (config.headers) {
1095
+ exporterConfig2.headers = config.headers;
1096
+ logger.log(`@atrim/auto-trace: Using custom headers: ${Object.keys(config.headers).join(", ")}`);
1097
+ }
1098
+ return new exporterTraceOtlpHttp.OTLPTraceExporter(exporterConfig2);
1029
1099
  };
1030
1100
  const createSpanProcessor = () => {
1031
1101
  const exporter = createSpanExporter();
@@ -1093,9 +1163,11 @@ exports.AutoTracingEnabled = AutoTracingEnabled;
1093
1163
  exports.AutoTracingLive = AutoTracingLive;
1094
1164
  exports.AutoTracingSpanName = AutoTracingSpanName;
1095
1165
  exports.AutoTracingSupervisor = AutoTracingSupervisor;
1166
+ exports.EffectTracingLive = EffectTracingLive;
1096
1167
  exports.FullAutoTracingLive = FullAutoTracingLive;
1097
1168
  exports.createAutoTracingLayer = createAutoTracingLayer;
1098
1169
  exports.createAutoTracingSupervisor = createAutoTracingSupervisor;
1170
+ exports.createEffectTracingLayer = createEffectTracingLayer;
1099
1171
  exports.createFullAutoTracingLayer = createFullAutoTracingLayer;
1100
1172
  exports.defaultAutoTracingConfig = defaultAutoTracingConfig;
1101
1173
  exports.inferSpanName = inferSpanName;