@effect/opentelemetry 4.0.0-beta.1 → 4.0.0-beta.100
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/dist/NodeSdk.d.ts +89 -17
- package/dist/NodeSdk.d.ts.map +1 -1
- package/dist/NodeSdk.js +31 -8
- package/dist/NodeSdk.js.map +1 -1
- package/dist/OtelLogger.d.ts +99 -0
- package/dist/OtelLogger.d.ts.map +1 -0
- package/dist/OtelLogger.js +139 -0
- package/dist/OtelLogger.js.map +1 -0
- package/dist/{Metrics.d.ts → OtelMetrics.d.ts} +45 -21
- package/dist/OtelMetrics.d.ts.map +1 -0
- package/dist/{Metrics.js → OtelMetrics.js} +27 -12
- package/dist/OtelMetrics.js.map +1 -0
- package/dist/OtelTracer.d.ts +186 -0
- package/dist/OtelTracer.d.ts.map +1 -0
- package/dist/{Tracer.js → OtelTracer.js} +129 -72
- package/dist/OtelTracer.js.map +1 -0
- package/dist/Resource.d.ts +57 -13
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +48 -13
- package/dist/Resource.js.map +1 -1
- package/dist/WebSdk.d.ts +82 -13
- package/dist/WebSdk.d.ts.map +1 -1
- package/dist/WebSdk.js +28 -7
- package/dist/WebSdk.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/internal/attributes.js +5 -0
- package/dist/internal/attributes.js.map +1 -1
- package/dist/internal/metrics.js +5 -5
- package/dist/internal/metrics.js.map +1 -1
- package/package.json +22 -18
- package/src/NodeSdk.ts +90 -18
- package/src/OtelLogger.ts +193 -0
- package/src/{Metrics.ts → OtelMetrics.ts} +45 -21
- package/src/{Tracer.ts → OtelTracer.ts} +161 -101
- package/src/Resource.ts +58 -14
- package/src/WebSdk.ts +83 -14
- package/src/index.ts +12 -12
- package/src/internal/attributes.ts +7 -0
- package/src/internal/metrics.ts +7 -7
- package/dist/Logger.d.ts +0 -48
- package/dist/Logger.d.ts.map +0 -1
- package/dist/Logger.js +0 -76
- package/dist/Logger.js.map +0 -1
- package/dist/Metrics.d.ts.map +0 -1
- package/dist/Metrics.js.map +0 -1
- package/dist/Tracer.d.ts +0 -129
- package/dist/Tracer.d.ts.map +0 -1
- package/dist/Tracer.js.map +0 -1
- package/src/Logger.ts +0 -124
|
@@ -1,18 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Bridges Effect tracing into OpenTelemetry by installing an Effect `Tracer`
|
|
3
|
+
* that creates OpenTelemetry spans, records attributes, events, links, errors,
|
|
4
|
+
* and status, and keeps OpenTelemetry context active while traced effects run.
|
|
5
|
+
* Use this module when an application already has an OpenTelemetry
|
|
6
|
+
* `TracerProvider`, or when the Node and Web SDK layers should expose Effect
|
|
7
|
+
* spans to OTLP, console, or other OpenTelemetry-compatible exporters.
|
|
8
|
+
*
|
|
9
|
+
* The layer constructors wire Effect's tracer service to either the global
|
|
10
|
+
* OpenTelemetry tracer provider or an explicitly provided `OtelTracer`. This
|
|
11
|
+
* module does not create exporters or span processors by itself, so spans are
|
|
12
|
+
* exported only when the provider has been configured by the application or by
|
|
13
|
+
* the Node/Web SDK layers. Parentage is taken from Effect spans first and can
|
|
14
|
+
* also attach to the active OpenTelemetry context, while `makeExternalSpan` and
|
|
15
|
+
* `withSpanContext` are the entry points for continuing an incoming remote
|
|
16
|
+
* trace. Preserve `traceFlags` and `traceState` when building external spans;
|
|
17
|
+
* otherwise sampling defaults to sampled and trace state cannot be propagated.
|
|
18
|
+
*
|
|
19
|
+
* @since 4.0.0
|
|
3
20
|
*/
|
|
4
21
|
import * as Otel from "@opentelemetry/api"
|
|
5
22
|
import * as OtelSemConv from "@opentelemetry/semantic-conventions"
|
|
6
23
|
import * as Cause from "effect/Cause"
|
|
7
24
|
import type * as Clock from "effect/Clock"
|
|
25
|
+
import * as Context from "effect/Context"
|
|
8
26
|
import * as Effect from "effect/Effect"
|
|
9
27
|
import * as Exit from "effect/Exit"
|
|
10
28
|
import { constTrue, dual } from "effect/Function"
|
|
11
29
|
import * as Layer from "effect/Layer"
|
|
30
|
+
import * as Option from "effect/Option"
|
|
12
31
|
import * as Predicate from "effect/Predicate"
|
|
13
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
14
32
|
import * as Tracer from "effect/Tracer"
|
|
15
|
-
import { recordToAttributes, unknownToAttributeValue } from "./internal/attributes.ts"
|
|
33
|
+
import { nanosToHrTime, recordToAttributes, unknownToAttributeValue } from "./internal/attributes.ts"
|
|
16
34
|
import { Resource } from "./Resource.ts"
|
|
17
35
|
|
|
18
36
|
// =============================================================================
|
|
@@ -20,37 +38,45 @@ import { Resource } from "./Resource.ts"
|
|
|
20
38
|
// =============================================================================
|
|
21
39
|
|
|
22
40
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
41
|
+
* Context service containing the OpenTelemetry `Tracer` used to create spans for Effect tracing.
|
|
42
|
+
*
|
|
43
|
+
* @category services
|
|
44
|
+
* @since 4.0.0
|
|
25
45
|
*/
|
|
26
|
-
export class OtelTracer extends
|
|
46
|
+
export class OtelTracer extends Context.Service<
|
|
27
47
|
OtelTracer,
|
|
28
48
|
Otel.Tracer
|
|
29
49
|
>()("@effect/opentelemetry/Tracer") {}
|
|
30
50
|
|
|
31
51
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
52
|
+
* Context service containing the OpenTelemetry `TracerProvider` used to obtain tracers.
|
|
53
|
+
*
|
|
54
|
+
* @category services
|
|
55
|
+
* @since 4.0.0
|
|
34
56
|
*/
|
|
35
|
-
export class OtelTracerProvider extends
|
|
57
|
+
export class OtelTracerProvider extends Context.Service<
|
|
36
58
|
OtelTracerProvider,
|
|
37
59
|
Otel.TracerProvider
|
|
38
60
|
>()("@effect/opentelemetry/Tracer/OtelTracerProvider") {}
|
|
39
61
|
|
|
40
62
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
63
|
+
* Context service containing OpenTelemetry trace flags used when constructing external span contexts.
|
|
64
|
+
*
|
|
65
|
+
* @category services
|
|
66
|
+
* @since 4.0.0
|
|
43
67
|
*/
|
|
44
|
-
export class OtelTraceFlags extends
|
|
68
|
+
export class OtelTraceFlags extends Context.Service<
|
|
45
69
|
OtelTraceFlags,
|
|
46
70
|
Otel.TraceFlags
|
|
47
71
|
>()("@effect/opentelemetry/Tracer/OtelTraceFlags") {}
|
|
48
72
|
|
|
49
73
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
74
|
+
* Context service containing OpenTelemetry trace state used when constructing external span contexts.
|
|
75
|
+
*
|
|
76
|
+
* @category services
|
|
77
|
+
* @since 4.0.0
|
|
52
78
|
*/
|
|
53
|
-
export class OtelTraceState extends
|
|
79
|
+
export class OtelTraceState extends Context.Service<
|
|
54
80
|
OtelTraceState,
|
|
55
81
|
Otel.TraceState
|
|
56
82
|
>()("@effect/opentelemetry/Tracer/OtelTraceState") {}
|
|
@@ -60,8 +86,10 @@ export class OtelTraceState extends ServiceMap.Service<
|
|
|
60
86
|
// =============================================================================
|
|
61
87
|
|
|
62
88
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
89
|
+
* Creates an Effect `Tracer` implementation backed by the configured OpenTelemetry tracer.
|
|
90
|
+
*
|
|
91
|
+
* @category constructors
|
|
92
|
+
* @since 4.0.0
|
|
65
93
|
*/
|
|
66
94
|
export const make: Effect.Effect<Tracer.Tracer, never, OtelTracer> = Effect.map(
|
|
67
95
|
Effect.service(OtelTracer),
|
|
@@ -91,8 +119,10 @@ export const make: Effect.Effect<Tracer.Tracer, never, OtelTracer> = Effect.map(
|
|
|
91
119
|
)
|
|
92
120
|
|
|
93
121
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
122
|
+
* Creates an Effect external span from an OpenTelemetry span context, preserving trace flags and trace state when provided.
|
|
123
|
+
*
|
|
124
|
+
* @category constructors
|
|
125
|
+
* @since 4.0.0
|
|
96
126
|
*/
|
|
97
127
|
export const makeExternalSpan = (options: {
|
|
98
128
|
readonly traceId: string
|
|
@@ -100,22 +130,24 @@ export const makeExternalSpan = (options: {
|
|
|
100
130
|
readonly traceFlags?: number | undefined
|
|
101
131
|
readonly traceState?: string | Otel.TraceState | undefined
|
|
102
132
|
}): Tracer.ExternalSpan => {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
133
|
+
const annotations = Context.mutate(Context.empty(), (annotations) => {
|
|
134
|
+
let next = annotations
|
|
135
|
+
if (options.traceFlags !== undefined) {
|
|
136
|
+
next = Context.add(next, OtelTraceFlags, options.traceFlags)
|
|
137
|
+
}
|
|
108
138
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
139
|
+
if (typeof options.traceState === "string") {
|
|
140
|
+
try {
|
|
141
|
+
next = Context.add(next, OtelTraceState, Otel.createTraceState(options.traceState))
|
|
142
|
+
} catch {
|
|
143
|
+
//
|
|
144
|
+
}
|
|
145
|
+
} else if (options.traceState) {
|
|
146
|
+
next = Context.add(next, OtelTraceState, options.traceState)
|
|
115
147
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
148
|
+
|
|
149
|
+
return next
|
|
150
|
+
})
|
|
119
151
|
|
|
120
152
|
return {
|
|
121
153
|
_tag: "ExternalSpan",
|
|
@@ -131,8 +163,10 @@ export const makeExternalSpan = (options: {
|
|
|
131
163
|
// =============================================================================
|
|
132
164
|
|
|
133
165
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
166
|
+
* Layer that provides the current global OpenTelemetry tracer provider.
|
|
167
|
+
*
|
|
168
|
+
* @category layers
|
|
169
|
+
* @since 4.0.0
|
|
136
170
|
*/
|
|
137
171
|
export const layerGlobalProvider: Layer.Layer<OtelTracerProvider> = Layer.sync(
|
|
138
172
|
OtelTracerProvider,
|
|
@@ -140,8 +174,10 @@ export const layerGlobalProvider: Layer.Layer<OtelTracerProvider> = Layer.sync(
|
|
|
140
174
|
)
|
|
141
175
|
|
|
142
176
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
177
|
+
* Layer that creates an OpenTelemetry tracer from the provided tracer provider and resource metadata.
|
|
178
|
+
*
|
|
179
|
+
* @category layers
|
|
180
|
+
* @since 4.0.0
|
|
145
181
|
*/
|
|
146
182
|
export const layerTracer: Layer.Layer<OtelTracer, never, OtelTracerProvider | Resource> = Layer.effect(
|
|
147
183
|
OtelTracer,
|
|
@@ -156,30 +192,47 @@ export const layerTracer: Layer.Layer<OtelTracer, never, OtelTracerProvider | Re
|
|
|
156
192
|
)
|
|
157
193
|
|
|
158
194
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
195
|
+
* Layer that creates an OpenTelemetry tracer from the global tracer provider and the current resource.
|
|
196
|
+
*
|
|
197
|
+
* @category layers
|
|
198
|
+
* @since 4.0.0
|
|
161
199
|
*/
|
|
162
200
|
export const layerGlobalTracer: Layer.Layer<OtelTracer, never, Resource> = layerTracer.pipe(
|
|
163
201
|
Layer.provide(layerGlobalProvider)
|
|
164
202
|
)
|
|
165
203
|
|
|
166
204
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
205
|
+
* Layer that installs an Effect tracer backed by the global OpenTelemetry tracer provider.
|
|
206
|
+
*
|
|
207
|
+
* @category layers
|
|
208
|
+
* @since 4.0.0
|
|
169
209
|
*/
|
|
170
210
|
export const layerGlobal: Layer.Layer<OtelTracer, never, Resource> = Layer.effect(Tracer.Tracer, make).pipe(
|
|
171
211
|
Layer.provideMerge(layerGlobalTracer)
|
|
172
212
|
)
|
|
173
213
|
|
|
174
214
|
/**
|
|
175
|
-
*
|
|
176
|
-
*
|
|
215
|
+
* Layer that installs the Effect tracer using an `OtelTracer` already provided in the environment.
|
|
216
|
+
*
|
|
217
|
+
* @category layers
|
|
218
|
+
* @since 4.0.0
|
|
177
219
|
*/
|
|
178
220
|
export const layerWithoutOtelTracer: Layer.Layer<never, never, OtelTracer> = Layer.effect(Tracer.Tracer, make)
|
|
179
221
|
|
|
180
222
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
223
|
+
* Layer that creates an OpenTelemetry tracer from a provider and resource, then installs it as the Effect tracer.
|
|
224
|
+
*
|
|
225
|
+
* **When to use**
|
|
226
|
+
*
|
|
227
|
+
* Use when you already provide an `OtelTracerProvider` and a `Resource`, and
|
|
228
|
+
* want Effect spans backed by a tracer derived from them.
|
|
229
|
+
*
|
|
230
|
+
* @see {@link layerTracer} for creating only the OpenTelemetry tracer service
|
|
231
|
+
* @see {@link layerGlobal} for installing the Effect tracer from the global provider
|
|
232
|
+
* @see {@link layerWithoutOtelTracer} for installing an already-provided `OtelTracer`
|
|
233
|
+
*
|
|
234
|
+
* @category layers
|
|
235
|
+
* @since 4.0.0
|
|
183
236
|
*/
|
|
184
237
|
export const layer: Layer.Layer<OtelTracer, never, OtelTracerProvider | Resource> = layerWithoutOtelTracer.pipe(
|
|
185
238
|
Layer.provideMerge(layerTracer)
|
|
@@ -193,16 +246,17 @@ const bigint1e6 = BigInt(1_000_000)
|
|
|
193
246
|
const bigint1e9 = BigInt(1_000_000_000)
|
|
194
247
|
|
|
195
248
|
/**
|
|
196
|
-
*
|
|
249
|
+
* Gets the current OpenTelemetry span.
|
|
197
250
|
*
|
|
198
|
-
*
|
|
199
|
-
* `NodeSdk.layer`, etc.) and the lightweight OTLP module (`OtlpTracer.layer`).
|
|
251
|
+
* **Details**
|
|
200
252
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
253
|
+
* This accessor works with both the official OpenTelemetry API, such as
|
|
254
|
+
* `Tracer.layer` and `NodeSdk.layer`, and the lightweight OTLP module, such as
|
|
255
|
+
* `OtlpTracer.layer`. When using OTLP, the returned span is a wrapper that
|
|
256
|
+
* conforms to the OpenTelemetry `Span` interface.
|
|
203
257
|
*
|
|
204
|
-
* @since 1.0.0
|
|
205
258
|
* @category accessors
|
|
259
|
+
* @since 4.0.0
|
|
206
260
|
*/
|
|
207
261
|
export const currentOtelSpan: Effect.Effect<Otel.Span, Cause.NoSuchElementError> = Effect.clockWith((clock) =>
|
|
208
262
|
Effect.map(Effect.currentSpan, (span) =>
|
|
@@ -275,7 +329,9 @@ const makeOtelSpan = (span: Tracer.Span, clock: Clock.Clock): Otel.Span => {
|
|
|
275
329
|
recordException(exception, timeInput) {
|
|
276
330
|
const time = convertOtelTimeInput(timeInput, clock)
|
|
277
331
|
const cause = Cause.fail(exception)
|
|
278
|
-
const error = Cause.prettyErrors(cause
|
|
332
|
+
const error = Cause.prettyErrors(cause, {
|
|
333
|
+
includeCauseInStack: true
|
|
334
|
+
})[0]
|
|
279
335
|
span.event(error.message, time, {
|
|
280
336
|
"exception.type": error.name,
|
|
281
337
|
"exception.message": error.message,
|
|
@@ -299,35 +355,41 @@ const convertOtelTimeInput = (input: Otel.TimeInput | undefined, clock: Clock.Cl
|
|
|
299
355
|
}
|
|
300
356
|
|
|
301
357
|
/**
|
|
302
|
-
*
|
|
358
|
+
* Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
|
|
303
359
|
*
|
|
304
|
-
*
|
|
305
|
-
* attach to a parent span.
|
|
360
|
+
* **When to use**
|
|
306
361
|
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
362
|
+
* Use when you need an effect to continue a trace from a parent span context
|
|
363
|
+
* produced by OpenTelemetry instrumentation outside Effect.
|
|
364
|
+
*
|
|
365
|
+
* @category propagation
|
|
366
|
+
* @since 4.0.0
|
|
309
367
|
*/
|
|
310
368
|
export const withSpanContext: {
|
|
311
369
|
/**
|
|
312
|
-
*
|
|
370
|
+
* Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
|
|
371
|
+
*
|
|
372
|
+
* **When to use**
|
|
313
373
|
*
|
|
314
|
-
*
|
|
315
|
-
*
|
|
374
|
+
* Use when you need an effect to continue a trace from a parent span context
|
|
375
|
+
* produced by OpenTelemetry instrumentation outside Effect.
|
|
316
376
|
*
|
|
317
|
-
* @
|
|
318
|
-
* @
|
|
377
|
+
* @category propagation
|
|
378
|
+
* @since 4.0.0
|
|
319
379
|
*/
|
|
320
380
|
(spanContext: Otel.SpanContext): <A, E, R>(
|
|
321
381
|
self: Effect.Effect<A, E, R>
|
|
322
382
|
) => Effect.Effect<A, E, Exclude<R, Tracer.ParentSpan>>
|
|
323
383
|
/**
|
|
324
|
-
*
|
|
384
|
+
* Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
|
|
325
385
|
*
|
|
326
|
-
*
|
|
327
|
-
* attach to a parent span.
|
|
386
|
+
* **When to use**
|
|
328
387
|
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
388
|
+
* Use when you need an effect to continue a trace from a parent span context
|
|
389
|
+
* produced by OpenTelemetry instrumentation outside Effect.
|
|
390
|
+
*
|
|
391
|
+
* @category propagation
|
|
392
|
+
* @since 4.0.0
|
|
331
393
|
*/
|
|
332
394
|
<A, E, R>(self: Effect.Effect<A, E, R>, spanContext: Otel.SpanContext): Effect.Effect<A, E, Exclude<R, Tracer.ParentSpan>>
|
|
333
395
|
} = dual(2, <A, E, R>(
|
|
@@ -356,14 +418,14 @@ export class OtelSpan implements Tracer.Span {
|
|
|
356
418
|
|
|
357
419
|
readonly name: string
|
|
358
420
|
readonly kind: Tracer.SpanKind
|
|
359
|
-
readonly annotations:
|
|
421
|
+
readonly annotations: Context.Context<never>
|
|
360
422
|
readonly links: Array<Tracer.SpanLink>
|
|
361
423
|
readonly span: Otel.Span
|
|
362
424
|
readonly spanId: string
|
|
363
425
|
readonly traceId: string
|
|
364
426
|
readonly attributes = new Map<string, unknown>()
|
|
365
427
|
readonly sampled: boolean
|
|
366
|
-
readonly parent: Tracer.AnySpan
|
|
428
|
+
readonly parent: Option.Option<Tracer.AnySpan>
|
|
367
429
|
status: Tracer.SpanStatus
|
|
368
430
|
|
|
369
431
|
constructor(
|
|
@@ -378,9 +440,9 @@ export class OtelSpan implements Tracer.Span {
|
|
|
378
440
|
this.links = options.links
|
|
379
441
|
this.kind = options.kind
|
|
380
442
|
const active = contextApi.active()
|
|
381
|
-
this.parent = options.
|
|
382
|
-
getOtelParent(traceApi, active, options.annotations)
|
|
383
|
-
|
|
443
|
+
this.parent = options.root !== true
|
|
444
|
+
? Option.orElse(options.parent, () => getOtelParent(traceApi, active, options.annotations))
|
|
445
|
+
: options.parent
|
|
384
446
|
this.span = tracer.startSpan(
|
|
385
447
|
options.name,
|
|
386
448
|
{
|
|
@@ -393,7 +455,9 @@ export class OtelSpan implements Tracer.Span {
|
|
|
393
455
|
: undefined as any,
|
|
394
456
|
kind: kindMap[this.kind]
|
|
395
457
|
},
|
|
396
|
-
|
|
458
|
+
Option.isSome(this.parent) ?
|
|
459
|
+
populateContext(active, this.parent.value, options.annotations) :
|
|
460
|
+
Otel.trace.deleteSpan(active)
|
|
397
461
|
)
|
|
398
462
|
const spanContext = this.span.spanContext()
|
|
399
463
|
this.spanId = spanContext.spanId
|
|
@@ -439,7 +503,9 @@ export class OtelSpan implements Tracer.Span {
|
|
|
439
503
|
this.span.setAttribute("span.label", "⚠︎ Interrupted")
|
|
440
504
|
this.span.setAttribute("status.interrupted", true)
|
|
441
505
|
} else {
|
|
442
|
-
const errors = Cause.prettyErrors(exit.cause
|
|
506
|
+
const errors = Cause.prettyErrors(exit.cause, {
|
|
507
|
+
includeCauseInStack: true
|
|
508
|
+
})
|
|
443
509
|
if (errors.length > 0) {
|
|
444
510
|
for (const error of errors) {
|
|
445
511
|
this.span.recordException(error, hrTime)
|
|
@@ -469,30 +535,24 @@ export class OtelSpan implements Tracer.Span {
|
|
|
469
535
|
const isSampled = (traceFlags: Otel.TraceFlags): boolean =>
|
|
470
536
|
(traceFlags & Otel.TraceFlags.SAMPLED) === Otel.TraceFlags.SAMPLED
|
|
471
537
|
|
|
472
|
-
const nanosToHrTime = (timestamp: bigint): Otel.HrTime => {
|
|
473
|
-
return [Number(timestamp / bigint1e9), Number(timestamp % bigint1e9)]
|
|
474
|
-
}
|
|
475
|
-
|
|
476
538
|
const getOtelParent = (
|
|
477
539
|
tracer: Otel.TraceAPI,
|
|
478
540
|
context: Otel.Context,
|
|
479
|
-
annotations:
|
|
480
|
-
): Tracer.AnySpan
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
return
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
})
|
|
490
|
-
: undefined
|
|
541
|
+
annotations: Context.Context<never>
|
|
542
|
+
): Option.Option<Tracer.AnySpan> => {
|
|
543
|
+
const otelParent = tracer.getSpan(context)?.spanContext()
|
|
544
|
+
if (!otelParent) return Option.none()
|
|
545
|
+
return Option.some(Tracer.externalSpan({
|
|
546
|
+
spanId: otelParent.spanId,
|
|
547
|
+
traceId: otelParent.traceId,
|
|
548
|
+
sampled: (otelParent.traceFlags & 1) === 1,
|
|
549
|
+
annotations
|
|
550
|
+
}))
|
|
491
551
|
}
|
|
492
552
|
|
|
493
553
|
const makeSpanContext = (
|
|
494
554
|
span: Tracer.AnySpan,
|
|
495
|
-
annotations?:
|
|
555
|
+
annotations?: Context.Context<never>
|
|
496
556
|
): Otel.SpanContext => {
|
|
497
557
|
const traceFlags = makeTraceFlags(span, annotations)
|
|
498
558
|
const traceState = makeTraceState(span, annotations)!
|
|
@@ -507,27 +567,27 @@ const makeSpanContext = (
|
|
|
507
567
|
|
|
508
568
|
const makeTraceFlags = (
|
|
509
569
|
span: Tracer.AnySpan,
|
|
510
|
-
annotations:
|
|
570
|
+
annotations: Context.Context<never> | undefined
|
|
511
571
|
): Otel.TraceFlags => {
|
|
512
572
|
let traceFlags: Otel.TraceFlags | undefined
|
|
513
573
|
if (Predicate.isNotUndefined(annotations)) {
|
|
514
574
|
traceFlags = extractTraceService(span, annotations, OtelTraceFlags)
|
|
515
575
|
if (Predicate.isUndefined(traceFlags)) {
|
|
516
|
-
traceFlags =
|
|
576
|
+
traceFlags = Context.getOrUndefined(span.annotations, OtelTraceFlags)
|
|
517
577
|
}
|
|
518
578
|
}
|
|
519
|
-
return traceFlags ?? Otel.TraceFlags.SAMPLED
|
|
579
|
+
return traceFlags ?? (span.sampled ? Otel.TraceFlags.SAMPLED : Otel.TraceFlags.NONE)
|
|
520
580
|
}
|
|
521
581
|
|
|
522
582
|
const makeTraceState = (
|
|
523
583
|
span: Tracer.AnySpan,
|
|
524
|
-
annotations:
|
|
584
|
+
annotations: Context.Context<never> | undefined
|
|
525
585
|
): Otel.TraceState | undefined => {
|
|
526
586
|
let traceState: Otel.TraceState | undefined
|
|
527
587
|
if (Predicate.isNotUndefined(annotations)) {
|
|
528
588
|
traceState = extractTraceService(span, annotations, OtelTraceState)
|
|
529
589
|
if (Predicate.isUndefined(traceState)) {
|
|
530
|
-
traceState =
|
|
590
|
+
traceState = Context.getOrUndefined(span.annotations, OtelTraceState)
|
|
531
591
|
}
|
|
532
592
|
}
|
|
533
593
|
return traceState
|
|
@@ -535,20 +595,20 @@ const makeTraceState = (
|
|
|
535
595
|
|
|
536
596
|
const extractTraceService = <I, S>(
|
|
537
597
|
parent: Tracer.AnySpan,
|
|
538
|
-
annotations:
|
|
539
|
-
service:
|
|
598
|
+
annotations: Context.Context<never>,
|
|
599
|
+
service: Context.Service<I, S>
|
|
540
600
|
) => {
|
|
541
|
-
const instance =
|
|
601
|
+
const instance = Context.getOrUndefined(annotations, service)
|
|
542
602
|
if (Predicate.isNotUndefined(instance)) {
|
|
543
603
|
return instance
|
|
544
604
|
}
|
|
545
|
-
return
|
|
605
|
+
return Context.getOrUndefined(parent.annotations, service)
|
|
546
606
|
}
|
|
547
607
|
|
|
548
608
|
const populateContext = (
|
|
549
609
|
context: Otel.Context,
|
|
550
610
|
span: Tracer.AnySpan,
|
|
551
|
-
annotations?:
|
|
611
|
+
annotations?: Context.Context<never> | undefined
|
|
552
612
|
): Otel.Context =>
|
|
553
613
|
span instanceof OtelSpan ?
|
|
554
614
|
Otel.trace.setSpan(context, span.span) :
|
package/src/Resource.ts
CHANGED
|
@@ -1,27 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* OpenTelemetry resource service and layers.
|
|
3
|
+
*
|
|
4
|
+
* An OpenTelemetry resource identifies the process or service that emits spans,
|
|
5
|
+
* metrics, and logs. This module stores that resource in Effect context and
|
|
6
|
+
* provides layers for creating it from explicit service metadata, from
|
|
7
|
+
* `OTEL_SERVICE_NAME` and `OTEL_RESOURCE_ATTRIBUTES`, or as an empty resource.
|
|
8
|
+
* It also includes `configToAttributes` for turning service metadata into raw
|
|
9
|
+
* OpenTelemetry attributes.
|
|
10
|
+
*
|
|
11
|
+
* @since 4.0.0
|
|
3
12
|
*/
|
|
4
13
|
import type * as OtelApi from "@opentelemetry/api"
|
|
5
14
|
import * as Resources from "@opentelemetry/resources"
|
|
6
15
|
import * as OtelSemConv from "@opentelemetry/semantic-conventions"
|
|
7
16
|
import * as Arr from "effect/Array"
|
|
8
17
|
import * as Config from "effect/Config"
|
|
18
|
+
import * as Context from "effect/Context"
|
|
9
19
|
import * as Effect from "effect/Effect"
|
|
10
20
|
import * as Layer from "effect/Layer"
|
|
11
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
12
21
|
|
|
13
22
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
23
|
+
* Service tag for OpenTelemetry metadata attached to emitted telemetry.
|
|
24
|
+
*
|
|
25
|
+
* **When to use**
|
|
26
|
+
*
|
|
27
|
+
* Use to provide process, service, and deployment metadata that should be
|
|
28
|
+
* attached to spans, metrics, and logs.
|
|
29
|
+
*
|
|
30
|
+
* @category services
|
|
31
|
+
* @since 4.0.0
|
|
16
32
|
*/
|
|
17
|
-
export class Resource extends
|
|
33
|
+
export class Resource extends Context.Service<
|
|
18
34
|
Resource,
|
|
19
35
|
Resources.Resource
|
|
20
36
|
>()("@effect/opentelemetry/Resource") {}
|
|
21
37
|
|
|
22
38
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
39
|
+
* Creates a `Resource` layer from service metadata and additional OpenTelemetry attributes.
|
|
40
|
+
*
|
|
41
|
+
* @category layers
|
|
42
|
+
* @since 4.0.0
|
|
25
43
|
*/
|
|
26
44
|
export const layer = (config: {
|
|
27
45
|
readonly serviceName: string
|
|
@@ -34,8 +52,30 @@ export const layer = (config: {
|
|
|
34
52
|
)
|
|
35
53
|
|
|
36
54
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
55
|
+
* Converts resource configuration into OpenTelemetry attributes, adding service name, optional service version, and telemetry SDK metadata.
|
|
56
|
+
*
|
|
57
|
+
* **When to use**
|
|
58
|
+
*
|
|
59
|
+
* Use to turn explicit service metadata into a raw OpenTelemetry attribute map
|
|
60
|
+
* for lower-level resource construction or merging with environment-derived
|
|
61
|
+
* attributes via `layerFromEnv`.
|
|
62
|
+
*
|
|
63
|
+
* **Details**
|
|
64
|
+
*
|
|
65
|
+
* The returned record copies `attributes` first, then sets `service.name`,
|
|
66
|
+
* `telemetry.sdk.name`, and `telemetry.sdk.language`. `service.version` is
|
|
67
|
+
* included only when `serviceVersion` is provided.
|
|
68
|
+
*
|
|
69
|
+
* **Gotchas**
|
|
70
|
+
*
|
|
71
|
+
* Custom values for `service.name` and `telemetry.sdk.*` are overwritten by this
|
|
72
|
+
* helper. An empty `serviceVersion` is treated as absent.
|
|
73
|
+
*
|
|
74
|
+
* @see {@link layer} for creating a `Resource` layer from explicit metadata
|
|
75
|
+
* @see {@link layerFromEnv} for merging attributes with OpenTelemetry environment variables
|
|
76
|
+
*
|
|
77
|
+
* @category configuration
|
|
78
|
+
* @since 4.0.0
|
|
39
79
|
*/
|
|
40
80
|
export const configToAttributes = (options: {
|
|
41
81
|
readonly serviceName: string
|
|
@@ -57,8 +97,10 @@ export const configToAttributes = (options: {
|
|
|
57
97
|
}
|
|
58
98
|
|
|
59
99
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
100
|
+
* Creates a `Resource` layer from OpenTelemetry environment variables, optionally merging additional attributes.
|
|
101
|
+
*
|
|
102
|
+
* @category layers
|
|
103
|
+
* @since 4.0.0
|
|
62
104
|
*/
|
|
63
105
|
export const layerFromEnv = (
|
|
64
106
|
additionalAttributes?:
|
|
@@ -70,7 +112,7 @@ export const layerFromEnv = (
|
|
|
70
112
|
Effect.gen(function*() {
|
|
71
113
|
const serviceName = yield* Config.option(Config.string("OTEL_SERVICE_NAME"))
|
|
72
114
|
const attributes = yield* Config.string("OTEL_RESOURCE_ATTRIBUTES").pipe(
|
|
73
|
-
Config.withDefault(
|
|
115
|
+
Config.withDefault(""),
|
|
74
116
|
Config.map((s) => {
|
|
75
117
|
const attrs = s.split(",")
|
|
76
118
|
return Arr.reduce(attrs, {} as OtelApi.Attributes, (acc, attr) => {
|
|
@@ -94,8 +136,10 @@ export const layerFromEnv = (
|
|
|
94
136
|
)
|
|
95
137
|
|
|
96
138
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
139
|
+
* Layer that provides an empty OpenTelemetry resource.
|
|
140
|
+
*
|
|
141
|
+
* @category layers
|
|
142
|
+
* @since 4.0.0
|
|
99
143
|
*/
|
|
100
144
|
export const layerEmpty = Layer.succeed(
|
|
101
145
|
Resource,
|