@atrim/instrument-node 0.5.0 → 0.5.1-1451fcf-20260105212505
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 +97 -269
- package/package.json +20 -19
- package/target/dist/index.cjs +149 -60
- package/target/dist/index.cjs.map +1 -1
- package/target/dist/index.d.cts +28 -13
- package/target/dist/index.d.ts +28 -13
- package/target/dist/index.js +148 -60
- package/target/dist/index.js.map +1 -1
- package/target/dist/integrations/effect/index.cjs +301 -130
- package/target/dist/integrations/effect/index.cjs.map +1 -1
- package/target/dist/integrations/effect/index.d.cts +205 -36
- package/target/dist/integrations/effect/index.d.ts +205 -36
- package/target/dist/integrations/effect/index.js +298 -132
- package/target/dist/integrations/effect/index.js.map +1 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { Data, Context, Effect, Layer, FiberSet as FiberSet$1,
|
|
1
|
+
import { Data, Context, Effect, Layer, Tracer, FiberSet as FiberSet$1, Fiber, Option, FiberId } from 'effect';
|
|
2
|
+
import * as OtelTracer from '@effect/opentelemetry/Tracer';
|
|
3
|
+
import * as Resource from '@effect/opentelemetry/Resource';
|
|
2
4
|
import * as Otlp from '@effect/opentelemetry/Otlp';
|
|
3
5
|
import { FetchHttpClient } from '@effect/platform';
|
|
4
6
|
import { TraceFlags, trace, context } from '@opentelemetry/api';
|
|
7
|
+
import { TELEMETRY_SDK_LANGUAGE_VALUE_NODEJS, ATTR_TELEMETRY_SDK_NAME, ATTR_TELEMETRY_SDK_LANGUAGE } from '@opentelemetry/semantic-conventions';
|
|
5
8
|
import { FileSystem } from '@effect/platform/FileSystem';
|
|
6
9
|
import * as HttpClient from '@effect/platform/HttpClient';
|
|
7
10
|
import * as HttpClientRequest from '@effect/platform/HttpClientRequest';
|
|
8
11
|
import { parse } from 'yaml';
|
|
9
12
|
import { z } from 'zod';
|
|
10
|
-
import { NodeContext } from '@effect/platform-node';
|
|
11
13
|
|
|
12
14
|
// src/integrations/effect/effect-tracer.ts
|
|
13
15
|
var __defProp = Object.defineProperty;
|
|
@@ -46,7 +48,20 @@ var HttpFilteringConfigSchema = z.object({
|
|
|
46
48
|
// Patterns to ignore for incoming HTTP requests (string patterns only in YAML)
|
|
47
49
|
ignore_incoming_paths: z.array(z.string()).optional(),
|
|
48
50
|
// Require parent span for outgoing requests (prevents root spans for HTTP calls)
|
|
49
|
-
require_parent_for_outgoing_spans: z.boolean().optional()
|
|
51
|
+
require_parent_for_outgoing_spans: z.boolean().optional(),
|
|
52
|
+
// Trace context propagation configuration
|
|
53
|
+
// Controls which cross-origin requests receive W3C Trace Context headers (traceparent, tracestate)
|
|
54
|
+
propagate_trace_context: z.object({
|
|
55
|
+
// Strategy for trace propagation
|
|
56
|
+
// - "all": Propagate to all cross-origin requests (may cause CORS errors)
|
|
57
|
+
// - "none": Never propagate trace headers
|
|
58
|
+
// - "same-origin": Only propagate to same-origin requests (default, safe)
|
|
59
|
+
// - "patterns": Propagate based on include_urls patterns
|
|
60
|
+
strategy: z.enum(["all", "none", "same-origin", "patterns"]).default("same-origin"),
|
|
61
|
+
// URL patterns to include when strategy is "patterns"
|
|
62
|
+
// Supports regex patterns (e.g., "^https://api\\.myapp\\.com")
|
|
63
|
+
include_urls: z.array(z.string()).optional()
|
|
64
|
+
}).optional()
|
|
50
65
|
});
|
|
51
66
|
var InstrumentationConfigSchema = z.object({
|
|
52
67
|
version: z.string(),
|
|
@@ -58,11 +73,50 @@ var InstrumentationConfigSchema = z.object({
|
|
|
58
73
|
ignore_patterns: z.array(PatternConfigSchema)
|
|
59
74
|
}),
|
|
60
75
|
effect: z.object({
|
|
76
|
+
// Enable/disable Effect tracing entirely
|
|
77
|
+
// When false, EffectInstrumentationLive returns Layer.empty
|
|
78
|
+
enabled: z.boolean().default(true),
|
|
79
|
+
// Exporter mode:
|
|
80
|
+
// - "unified": Use global TracerProvider from Node SDK (recommended, enables filtering)
|
|
81
|
+
// - "standalone": Use Effect's own OTLP exporter (bypasses Node SDK filtering)
|
|
82
|
+
exporter: z.enum(["unified", "standalone"]).default("unified"),
|
|
61
83
|
auto_extract_metadata: z.boolean(),
|
|
62
84
|
auto_isolation: AutoIsolationConfigSchema.optional()
|
|
63
85
|
}).optional(),
|
|
64
86
|
http: HttpFilteringConfigSchema.optional()
|
|
65
87
|
});
|
|
88
|
+
var defaultConfig = {
|
|
89
|
+
version: "1.0",
|
|
90
|
+
instrumentation: {
|
|
91
|
+
enabled: true,
|
|
92
|
+
logging: "on",
|
|
93
|
+
description: "Default instrumentation configuration",
|
|
94
|
+
instrument_patterns: [
|
|
95
|
+
{ pattern: "^app\\.", enabled: true, description: "Application operations" },
|
|
96
|
+
{ pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
|
|
97
|
+
{ pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
|
|
98
|
+
],
|
|
99
|
+
ignore_patterns: [
|
|
100
|
+
{ pattern: "^test\\.", description: "Test utilities" },
|
|
101
|
+
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
102
|
+
{ pattern: "^health\\.", description: "Health checks" }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
effect: {
|
|
106
|
+
enabled: true,
|
|
107
|
+
exporter: "unified",
|
|
108
|
+
auto_extract_metadata: true
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
function parseAndValidateConfig(content) {
|
|
112
|
+
let parsed;
|
|
113
|
+
if (typeof content === "string") {
|
|
114
|
+
parsed = parse(content);
|
|
115
|
+
} else {
|
|
116
|
+
parsed = content;
|
|
117
|
+
}
|
|
118
|
+
return InstrumentationConfigSchema.parse(parsed);
|
|
119
|
+
}
|
|
66
120
|
(class extends Data.TaggedError("ConfigError") {
|
|
67
121
|
get message() {
|
|
68
122
|
return this.reason;
|
|
@@ -240,7 +294,7 @@ var makeConfigLoader = Effect.gen(function* () {
|
|
|
240
294
|
})
|
|
241
295
|
});
|
|
242
296
|
});
|
|
243
|
-
|
|
297
|
+
Layer.effect(ConfigLoader, makeConfigLoader);
|
|
244
298
|
var PatternMatcher = class {
|
|
245
299
|
constructor(config) {
|
|
246
300
|
__publicField(this, "ignorePatterns", []);
|
|
@@ -388,83 +442,73 @@ var Logger = class {
|
|
|
388
442
|
}
|
|
389
443
|
};
|
|
390
444
|
var logger = new Logger();
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}).pipe(Effect.provide(NodeConfigLoaderLive))
|
|
401
|
-
);
|
|
445
|
+
async function loadFromFile(filePath) {
|
|
446
|
+
const { readFile } = await import('fs/promises');
|
|
447
|
+
const content = await readFile(filePath, "utf-8");
|
|
448
|
+
return parseAndValidateConfig(content);
|
|
449
|
+
}
|
|
450
|
+
async function loadFromUrl(url) {
|
|
451
|
+
const response = await fetch(url);
|
|
452
|
+
if (!response.ok) {
|
|
453
|
+
throw new Error(`Failed to fetch config from ${url}: ${response.statusText}`);
|
|
402
454
|
}
|
|
403
|
-
|
|
455
|
+
const content = await response.text();
|
|
456
|
+
return parseAndValidateConfig(content);
|
|
404
457
|
}
|
|
405
|
-
async function loadConfig(uri,
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return
|
|
458
|
+
async function loadConfig(uri, _options) {
|
|
459
|
+
if (uri.startsWith("http://") || uri.startsWith("https://")) {
|
|
460
|
+
return loadFromUrl(uri);
|
|
461
|
+
}
|
|
462
|
+
if (uri.startsWith("file://")) {
|
|
463
|
+
const filePath = uri.slice(7);
|
|
464
|
+
return loadFromFile(filePath);
|
|
412
465
|
}
|
|
413
|
-
|
|
414
|
-
return Effect.runPromise(loader.loadFromUri(uri));
|
|
466
|
+
return loadFromFile(uri);
|
|
415
467
|
}
|
|
416
468
|
async function loadConfigFromInline(content) {
|
|
417
|
-
|
|
418
|
-
return Effect.runPromise(loader.loadFromInline(content));
|
|
419
|
-
}
|
|
420
|
-
function getDefaultConfig() {
|
|
421
|
-
return {
|
|
422
|
-
version: "1.0",
|
|
423
|
-
instrumentation: {
|
|
424
|
-
enabled: true,
|
|
425
|
-
logging: "on",
|
|
426
|
-
description: "Default instrumentation configuration",
|
|
427
|
-
instrument_patterns: [
|
|
428
|
-
{ pattern: "^app\\.", enabled: true, description: "Application operations" },
|
|
429
|
-
{ pattern: "^http\\.server\\.", enabled: true, description: "HTTP server operations" },
|
|
430
|
-
{ pattern: "^http\\.client\\.", enabled: true, description: "HTTP client operations" }
|
|
431
|
-
],
|
|
432
|
-
ignore_patterns: [
|
|
433
|
-
{ pattern: "^test\\.", description: "Test utilities" },
|
|
434
|
-
{ pattern: "^internal\\.", description: "Internal operations" },
|
|
435
|
-
{ pattern: "^health\\.", description: "Health checks" }
|
|
436
|
-
]
|
|
437
|
-
},
|
|
438
|
-
effect: {
|
|
439
|
-
auto_extract_metadata: true
|
|
440
|
-
}
|
|
441
|
-
};
|
|
469
|
+
return parseAndValidateConfig(content);
|
|
442
470
|
}
|
|
443
471
|
async function loadConfigWithOptions(options = {}) {
|
|
444
|
-
const loadOptions = options.cacheTimeout !== void 0 ? { cacheTimeout: options.cacheTimeout } : void 0;
|
|
445
472
|
if (options.config) {
|
|
446
473
|
return loadConfigFromInline(options.config);
|
|
447
474
|
}
|
|
448
475
|
const envConfigPath = process.env.ATRIM_INSTRUMENTATION_CONFIG;
|
|
449
476
|
if (envConfigPath) {
|
|
450
|
-
return loadConfig(envConfigPath
|
|
477
|
+
return loadConfig(envConfigPath);
|
|
451
478
|
}
|
|
452
479
|
if (options.configUrl) {
|
|
453
|
-
return loadConfig(options.configUrl
|
|
480
|
+
return loadConfig(options.configUrl);
|
|
454
481
|
}
|
|
455
482
|
if (options.configPath) {
|
|
456
|
-
return loadConfig(options.configPath
|
|
483
|
+
return loadConfig(options.configPath);
|
|
457
484
|
}
|
|
458
485
|
const { existsSync } = await import('fs');
|
|
459
486
|
const { join } = await import('path');
|
|
460
487
|
const defaultPath = join(process.cwd(), "instrumentation.yaml");
|
|
461
488
|
if (existsSync(defaultPath)) {
|
|
462
|
-
return loadConfig(defaultPath
|
|
489
|
+
return loadConfig(defaultPath);
|
|
463
490
|
}
|
|
464
|
-
return
|
|
491
|
+
return defaultConfig;
|
|
465
492
|
}
|
|
466
493
|
|
|
467
494
|
// src/integrations/effect/effect-tracer.ts
|
|
495
|
+
var SDK_NAME = "@effect/opentelemetry";
|
|
496
|
+
var ATTR_TELEMETRY_EXPORTER_MODE = "telemetry.exporter.mode";
|
|
497
|
+
var ATTR_EFFECT_INSTRUMENTED = "effect.instrumented";
|
|
498
|
+
var EffectAttributeTracerLayer = Layer.effect(
|
|
499
|
+
Tracer.Tracer,
|
|
500
|
+
Effect.gen(function* () {
|
|
501
|
+
const baseTracer = yield* OtelTracer.make;
|
|
502
|
+
return Tracer.make({
|
|
503
|
+
span: (name, parent, context2, links, startTime, kind, options) => {
|
|
504
|
+
const span = baseTracer.span(name, parent, context2, links, startTime, kind, options);
|
|
505
|
+
span.attribute(ATTR_EFFECT_INSTRUMENTED, true);
|
|
506
|
+
return span;
|
|
507
|
+
},
|
|
508
|
+
context: (f, fiber) => baseTracer.context(f, fiber)
|
|
509
|
+
});
|
|
510
|
+
}).pipe(Effect.provide(OtelTracer.layerGlobalTracer))
|
|
511
|
+
);
|
|
468
512
|
function createEffectInstrumentation(options = {}) {
|
|
469
513
|
return Layer.unwrapEffect(
|
|
470
514
|
Effect.gen(function* () {
|
|
@@ -475,106 +519,228 @@ function createEffectInstrumentation(options = {}) {
|
|
|
475
519
|
message: error instanceof Error ? error.message : String(error)
|
|
476
520
|
})
|
|
477
521
|
});
|
|
522
|
+
const effectEnabled = process.env.OTEL_EFFECT_ENABLED !== "false" && (config.effect?.enabled ?? true);
|
|
523
|
+
if (!effectEnabled) {
|
|
524
|
+
logger.log("@atrim/instrumentation/effect: Effect tracing disabled via config");
|
|
525
|
+
return Layer.empty;
|
|
526
|
+
}
|
|
478
527
|
yield* Effect.sync(() => {
|
|
479
528
|
const loggingLevel = config.instrumentation.logging || "on";
|
|
480
529
|
logger.setLevel(loggingLevel);
|
|
481
530
|
});
|
|
482
531
|
yield* Effect.sync(() => initializePatternMatcher(config));
|
|
483
|
-
const otlpEndpoint = options.otlpEndpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
|
|
484
532
|
const serviceName = options.serviceName || process.env.OTEL_SERVICE_NAME || "effect-service";
|
|
485
533
|
const serviceVersion = options.serviceVersion || process.env.npm_package_version || "1.0.0";
|
|
486
|
-
const
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
534
|
+
const exporterMode = options.exporterMode ?? config.effect?.exporter ?? "unified";
|
|
535
|
+
const resourceAttributes = {
|
|
536
|
+
"platform.component": "effect",
|
|
537
|
+
[ATTR_TELEMETRY_SDK_LANGUAGE]: TELEMETRY_SDK_LANGUAGE_VALUE_NODEJS,
|
|
538
|
+
[ATTR_TELEMETRY_SDK_NAME]: SDK_NAME,
|
|
539
|
+
[ATTR_TELEMETRY_EXPORTER_MODE]: exporterMode
|
|
540
|
+
};
|
|
541
|
+
if (exporterMode === "standalone") {
|
|
542
|
+
const otlpEndpoint = options.otlpEndpoint || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
|
|
543
|
+
logger.log("Effect OpenTelemetry instrumentation (standalone)");
|
|
544
|
+
logger.log(` Service: ${serviceName}`);
|
|
545
|
+
logger.log(` Endpoint: ${otlpEndpoint}`);
|
|
546
|
+
logger.log(" WARNING: Standalone mode bypasses Node SDK filtering");
|
|
547
|
+
return Otlp.layer({
|
|
548
|
+
baseUrl: otlpEndpoint,
|
|
549
|
+
resource: {
|
|
550
|
+
serviceName,
|
|
551
|
+
serviceVersion,
|
|
552
|
+
attributes: resourceAttributes
|
|
553
|
+
},
|
|
554
|
+
// Bridge Effect context to OpenTelemetry global context
|
|
555
|
+
tracerContext: (f, span) => {
|
|
556
|
+
if (span._tag !== "Span") {
|
|
557
|
+
return f();
|
|
558
|
+
}
|
|
559
|
+
const spanContext = {
|
|
560
|
+
traceId: span.traceId,
|
|
561
|
+
spanId: span.spanId,
|
|
562
|
+
traceFlags: span.sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
|
|
563
|
+
};
|
|
564
|
+
const otelSpan = trace.wrapSpanContext(spanContext);
|
|
565
|
+
return context.with(trace.setSpan(context.active(), otelSpan), f);
|
|
509
566
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
567
|
+
}).pipe(Layer.provide(FetchHttpClient.layer));
|
|
568
|
+
} else {
|
|
569
|
+
logger.log("Effect OpenTelemetry instrumentation (unified)");
|
|
570
|
+
logger.log(` Service: ${serviceName}`);
|
|
571
|
+
logger.log(" Using global TracerProvider for span export");
|
|
572
|
+
return EffectAttributeTracerLayer.pipe(
|
|
573
|
+
Layer.provide(
|
|
574
|
+
Resource.layer({
|
|
575
|
+
serviceName,
|
|
576
|
+
serviceVersion,
|
|
577
|
+
attributes: resourceAttributes
|
|
578
|
+
})
|
|
579
|
+
)
|
|
580
|
+
);
|
|
521
581
|
}
|
|
522
|
-
return otlpLayer;
|
|
523
582
|
})
|
|
524
583
|
).pipe(Layer.orDie);
|
|
525
584
|
}
|
|
526
585
|
var EffectInstrumentationLive = Effect.sync(() => {
|
|
527
|
-
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://localhost:4318";
|
|
528
586
|
const serviceName = process.env.OTEL_SERVICE_NAME || "effect-service";
|
|
529
587
|
const serviceVersion = process.env.npm_package_version || "1.0.0";
|
|
530
588
|
logger.minimal(`@atrim/instrumentation/effect: Effect tracing enabled (${serviceName})`);
|
|
531
|
-
logger.log("
|
|
532
|
-
logger.log(`
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
return f();
|
|
548
|
-
}
|
|
549
|
-
const spanContext = {
|
|
550
|
-
traceId: span.traceId,
|
|
551
|
-
spanId: span.spanId,
|
|
552
|
-
traceFlags: span.sampled ? TraceFlags.SAMPLED : TraceFlags.NONE
|
|
553
|
-
};
|
|
554
|
-
const otelSpan = trace.wrapSpanContext(spanContext);
|
|
555
|
-
return context.with(trace.setSpan(context.active(), otelSpan), f);
|
|
556
|
-
}
|
|
557
|
-
}).pipe(Layer.provide(FetchHttpClient.layer));
|
|
589
|
+
logger.log("Effect OpenTelemetry tracer (unified)");
|
|
590
|
+
logger.log(` Service: ${serviceName}`);
|
|
591
|
+
return EffectAttributeTracerLayer.pipe(
|
|
592
|
+
Layer.provide(
|
|
593
|
+
Resource.layer({
|
|
594
|
+
serviceName,
|
|
595
|
+
serviceVersion,
|
|
596
|
+
attributes: {
|
|
597
|
+
"platform.component": "effect",
|
|
598
|
+
[ATTR_TELEMETRY_SDK_LANGUAGE]: TELEMETRY_SDK_LANGUAGE_VALUE_NODEJS,
|
|
599
|
+
[ATTR_TELEMETRY_SDK_NAME]: SDK_NAME,
|
|
600
|
+
[ATTR_TELEMETRY_EXPORTER_MODE]: "unified"
|
|
601
|
+
}
|
|
602
|
+
})
|
|
603
|
+
)
|
|
604
|
+
);
|
|
558
605
|
}).pipe(Layer.unwrapEffect);
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
606
|
+
function annotateUser(userId, email, username) {
|
|
607
|
+
const attributes = {
|
|
608
|
+
"user.id": userId
|
|
609
|
+
};
|
|
610
|
+
if (email) attributes["user.email"] = email;
|
|
611
|
+
if (username) attributes["user.name"] = username;
|
|
612
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
562
613
|
}
|
|
563
|
-
function annotateDataSize(
|
|
614
|
+
function annotateDataSize(bytes, items, compressionRatio) {
|
|
615
|
+
const attributes = {
|
|
616
|
+
"data.size.bytes": bytes,
|
|
617
|
+
"data.size.items": items
|
|
618
|
+
};
|
|
619
|
+
if (compressionRatio !== void 0) {
|
|
620
|
+
attributes["data.compression.ratio"] = compressionRatio;
|
|
621
|
+
}
|
|
622
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
564
623
|
}
|
|
565
|
-
function annotateBatch(
|
|
624
|
+
function annotateBatch(totalItems, batchSize, successCount, failureCount) {
|
|
625
|
+
const attributes = {
|
|
626
|
+
"batch.size": batchSize,
|
|
627
|
+
"batch.total_items": totalItems,
|
|
628
|
+
"batch.count": Math.ceil(totalItems / batchSize)
|
|
629
|
+
};
|
|
630
|
+
if (successCount !== void 0) {
|
|
631
|
+
attributes["batch.success_count"] = successCount;
|
|
632
|
+
}
|
|
633
|
+
if (failureCount !== void 0) {
|
|
634
|
+
attributes["batch.failure_count"] = failureCount;
|
|
635
|
+
}
|
|
636
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
566
637
|
}
|
|
567
|
-
function annotateLLM(
|
|
638
|
+
function annotateLLM(model, provider, tokens) {
|
|
639
|
+
const attributes = {
|
|
640
|
+
"llm.model": model,
|
|
641
|
+
"llm.provider": provider
|
|
642
|
+
};
|
|
643
|
+
if (tokens) {
|
|
644
|
+
if (tokens.prompt !== void 0) attributes["llm.tokens.prompt"] = tokens.prompt;
|
|
645
|
+
if (tokens.completion !== void 0) attributes["llm.tokens.completion"] = tokens.completion;
|
|
646
|
+
if (tokens.total !== void 0) attributes["llm.tokens.total"] = tokens.total;
|
|
647
|
+
}
|
|
648
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
649
|
+
}
|
|
650
|
+
function annotateQuery(query, duration, rowCount, database) {
|
|
651
|
+
const attributes = {
|
|
652
|
+
"db.statement": query.length > 1e3 ? query.substring(0, 1e3) + "..." : query
|
|
653
|
+
};
|
|
654
|
+
if (duration !== void 0) attributes["db.duration.ms"] = duration;
|
|
655
|
+
if (rowCount !== void 0) attributes["db.row_count"] = rowCount;
|
|
656
|
+
if (database) attributes["db.name"] = database;
|
|
657
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
658
|
+
}
|
|
659
|
+
function annotateHttpRequest(method, url, statusCode, contentLength) {
|
|
660
|
+
const attributes = {
|
|
661
|
+
"http.method": method,
|
|
662
|
+
"http.url": url
|
|
663
|
+
};
|
|
664
|
+
if (statusCode !== void 0) attributes["http.status_code"] = statusCode;
|
|
665
|
+
if (contentLength !== void 0) attributes["http.response.content_length"] = contentLength;
|
|
666
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
667
|
+
}
|
|
668
|
+
function annotateError(error, recoverable, errorType) {
|
|
669
|
+
const errorMessage = typeof error === "string" ? error : error.message;
|
|
670
|
+
const errorStack = typeof error === "string" ? void 0 : error.stack;
|
|
671
|
+
const attributes = {
|
|
672
|
+
"error.message": errorMessage,
|
|
673
|
+
"error.recoverable": recoverable
|
|
674
|
+
};
|
|
675
|
+
if (errorType) attributes["error.type"] = errorType;
|
|
676
|
+
if (errorStack) attributes["error.stack"] = errorStack;
|
|
677
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
568
678
|
}
|
|
569
|
-
function
|
|
679
|
+
function annotatePriority(priority, reason) {
|
|
680
|
+
const attributes = {
|
|
681
|
+
"operation.priority": priority
|
|
682
|
+
};
|
|
683
|
+
if (reason) attributes["operation.priority.reason"] = reason;
|
|
684
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
570
685
|
}
|
|
571
|
-
function
|
|
686
|
+
function annotateCache(hit, key, ttl) {
|
|
687
|
+
const attributes = {
|
|
688
|
+
"cache.hit": hit,
|
|
689
|
+
"cache.key": key
|
|
690
|
+
};
|
|
691
|
+
if (ttl !== void 0) attributes["cache.ttl.seconds"] = ttl;
|
|
692
|
+
return Effect.annotateCurrentSpan(attributes);
|
|
572
693
|
}
|
|
573
|
-
function
|
|
694
|
+
function extractEffectMetadata() {
|
|
695
|
+
return Effect.gen(function* () {
|
|
696
|
+
const metadata = {};
|
|
697
|
+
const currentFiber = Fiber.getCurrentFiber();
|
|
698
|
+
if (Option.isSome(currentFiber)) {
|
|
699
|
+
const fiber = currentFiber.value;
|
|
700
|
+
const fiberId = fiber.id();
|
|
701
|
+
metadata["effect.fiber.id"] = FiberId.threadName(fiberId);
|
|
702
|
+
const status = yield* Fiber.status(fiber);
|
|
703
|
+
if (status._tag) {
|
|
704
|
+
metadata["effect.fiber.status"] = status._tag;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
const parentSpanResult = yield* Effect.currentSpan.pipe(
|
|
708
|
+
Effect.option
|
|
709
|
+
// Convert NoSuchElementException to Option
|
|
710
|
+
);
|
|
711
|
+
if (Option.isSome(parentSpanResult)) {
|
|
712
|
+
const parentSpan = parentSpanResult.value;
|
|
713
|
+
metadata["effect.operation.nested"] = true;
|
|
714
|
+
metadata["effect.operation.root"] = false;
|
|
715
|
+
if (parentSpan.spanId) {
|
|
716
|
+
metadata["effect.parent.span.id"] = parentSpan.spanId;
|
|
717
|
+
}
|
|
718
|
+
if (parentSpan.name) {
|
|
719
|
+
metadata["effect.parent.span.name"] = parentSpan.name;
|
|
720
|
+
}
|
|
721
|
+
if (parentSpan.traceId) {
|
|
722
|
+
metadata["effect.parent.trace.id"] = parentSpan.traceId;
|
|
723
|
+
}
|
|
724
|
+
} else {
|
|
725
|
+
metadata["effect.operation.nested"] = false;
|
|
726
|
+
metadata["effect.operation.root"] = true;
|
|
727
|
+
}
|
|
728
|
+
return metadata;
|
|
729
|
+
});
|
|
574
730
|
}
|
|
575
|
-
function
|
|
731
|
+
function autoEnrichSpan() {
|
|
732
|
+
return Effect.gen(function* () {
|
|
733
|
+
const metadata = yield* extractEffectMetadata();
|
|
734
|
+
yield* Effect.annotateCurrentSpan(metadata);
|
|
735
|
+
});
|
|
576
736
|
}
|
|
577
|
-
function
|
|
737
|
+
function withAutoEnrichedSpan(spanName, options) {
|
|
738
|
+
return (self) => {
|
|
739
|
+
return Effect.gen(function* () {
|
|
740
|
+
yield* autoEnrichSpan();
|
|
741
|
+
return yield* self;
|
|
742
|
+
}).pipe(Effect.withSpan(spanName, options));
|
|
743
|
+
};
|
|
578
744
|
}
|
|
579
745
|
var createLogicalParentLink = (parentSpan, useSpanLinks) => {
|
|
580
746
|
if (!useSpanLinks) {
|
|
@@ -701,6 +867,6 @@ var FiberSet = {
|
|
|
701
867
|
runWithSpan
|
|
702
868
|
};
|
|
703
869
|
|
|
704
|
-
export { EffectInstrumentationLive, FiberSet, annotateBatch, annotateCache, annotateDataSize, annotateError, annotateHttpRequest, annotateLLM, annotatePriority, annotateQuery, annotateSpawnedTasks, annotateUser, createEffectInstrumentation, runIsolated, runWithSpan };
|
|
870
|
+
export { EffectInstrumentationLive, FiberSet, annotateBatch, annotateCache, annotateDataSize, annotateError, annotateHttpRequest, annotateLLM, annotatePriority, annotateQuery, annotateSpawnedTasks, annotateUser, autoEnrichSpan, createEffectInstrumentation, extractEffectMetadata, runIsolated, runWithSpan, withAutoEnrichedSpan };
|
|
705
871
|
//# sourceMappingURL=index.js.map
|
|
706
872
|
//# sourceMappingURL=index.js.map
|