@effect/opentelemetry 4.0.0-beta.7 → 4.0.0-beta.70

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/src/Tracer.ts CHANGED
@@ -1,18 +1,36 @@
1
1
  /**
2
- * @since 1.0.0
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
- * @since 1.0.0
24
- * @category Services
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 ServiceMap.Service<
46
+ export class OtelTracer extends Context.Service<
27
47
  OtelTracer,
28
48
  Otel.Tracer
29
49
  >()("@effect/opentelemetry/Tracer") {}
30
50
 
31
51
  /**
32
- * @since 1.0.0
33
- * @category Services
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 ServiceMap.Service<
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
- * @since 1.0.0
42
- * @category Services
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 ServiceMap.Service<
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
- * @since 1.0.0
51
- * @category Services
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 ServiceMap.Service<
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
- * @since 1.0.0
64
- * @category Constructors
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
- * @since 1.0.0
95
- * @category Constructors
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
- let annotations = ServiceMap.empty()
104
-
105
- if (options.traceFlags !== undefined) {
106
- annotations = ServiceMap.add(annotations, OtelTraceFlags, options.traceFlags)
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
- if (typeof options.traceState === "string") {
110
- try {
111
- const traceState = Otel.createTraceState(options.traceState)
112
- annotations = ServiceMap.add(annotations, OtelTraceState, traceState)
113
- } catch {
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
- } else if (options.traceState) {
117
- annotations = ServiceMap.add(annotations, OtelTraceState, options.traceState)
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
- * @since 1.0.0
135
- * @category Layers
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
- * @since 1.0.0
144
- * @category Layers
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,38 @@ export const layerTracer: Layer.Layer<OtelTracer, never, OtelTracerProvider | Re
156
192
  )
157
193
 
158
194
  /**
159
- * @since 1.0.0
160
- * @category Layers
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
- * @since 1.0.0
168
- * @category Layers
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
- * @since 1.0.0
176
- * @category Layers
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
- * @since 1.0.0
182
- * @category Layers
223
+ * Layer that creates an OpenTelemetry tracer from a provider and resource, then installs it as the Effect tracer.
224
+ *
225
+ * @category layers
226
+ * @since 4.0.0
183
227
  */
184
228
  export const layer: Layer.Layer<OtelTracer, never, OtelTracerProvider | Resource> = layerWithoutOtelTracer.pipe(
185
229
  Layer.provideMerge(layerTracer)
@@ -193,16 +237,17 @@ const bigint1e6 = BigInt(1_000_000)
193
237
  const bigint1e9 = BigInt(1_000_000_000)
194
238
 
195
239
  /**
196
- * Get the current OpenTelemetry span.
240
+ * Gets the current OpenTelemetry span.
197
241
  *
198
- * Works with both the official OpenTelemetry API (via `Tracer.layer`,
199
- * `NodeSdk.layer`, etc.) and the lightweight OTLP module (`OtlpTracer.layer`).
242
+ * **Details**
200
243
  *
201
- * When using OTLP, the returned span is a wrapper that conforms to the
202
- * OpenTelemetry `Span` interface.
244
+ * This accessor works with both the official OpenTelemetry API, such as
245
+ * `Tracer.layer` and `NodeSdk.layer`, and the lightweight OTLP module, such as
246
+ * `OtlpTracer.layer`. When using OTLP, the returned span is a wrapper that
247
+ * conforms to the OpenTelemetry `Span` interface.
203
248
  *
204
- * @since 1.0.0
205
249
  * @category accessors
250
+ * @since 4.0.0
206
251
  */
207
252
  export const currentOtelSpan: Effect.Effect<Otel.Span, Cause.NoSuchElementError> = Effect.clockWith((clock) =>
208
253
  Effect.map(Effect.currentSpan, (span) =>
@@ -299,35 +344,41 @@ const convertOtelTimeInput = (input: Otel.TimeInput | undefined, clock: Clock.Cl
299
344
  }
300
345
 
301
346
  /**
302
- * Set the effect's parent span from the given opentelemetry `SpanContext`.
347
+ * Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
303
348
  *
304
- * This is handy when you set up OpenTelemetry outside of Effect and want to
305
- * attach to a parent span.
349
+ * **When to use**
306
350
  *
307
- * @since 1.0.0
308
- * @category Propagation
351
+ * Use this when OpenTelemetry instrumentation outside Effect has already
352
+ * produced a parent span context and an effect should continue that trace.
353
+ *
354
+ * @category propagation
355
+ * @since 4.0.0
309
356
  */
310
357
  export const withSpanContext: {
311
358
  /**
312
- * Set the effect's parent span from the given opentelemetry `SpanContext`.
359
+ * Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
360
+ *
361
+ * **When to use**
313
362
  *
314
- * This is handy when you set up OpenTelemetry outside of Effect and want to
315
- * attach to a parent span.
363
+ * Use this when OpenTelemetry instrumentation outside Effect has already
364
+ * produced a parent span context and an effect should continue that trace.
316
365
  *
317
- * @since 1.0.0
318
- * @category Propagation
366
+ * @category propagation
367
+ * @since 4.0.0
319
368
  */
320
369
  (spanContext: Otel.SpanContext): <A, E, R>(
321
370
  self: Effect.Effect<A, E, R>
322
371
  ) => Effect.Effect<A, E, Exclude<R, Tracer.ParentSpan>>
323
372
  /**
324
- * Set the effect's parent span from the given opentelemetry `SpanContext`.
373
+ * Sets an effect's parent span from the given OpenTelemetry `SpanContext`.
325
374
  *
326
- * This is handy when you set up OpenTelemetry outside of Effect and want to
327
- * attach to a parent span.
375
+ * **When to use**
328
376
  *
329
- * @since 1.0.0
330
- * @category Propagation
377
+ * Use this when OpenTelemetry instrumentation outside Effect has already
378
+ * produced a parent span context and an effect should continue that trace.
379
+ *
380
+ * @category propagation
381
+ * @since 4.0.0
331
382
  */
332
383
  <A, E, R>(self: Effect.Effect<A, E, R>, spanContext: Otel.SpanContext): Effect.Effect<A, E, Exclude<R, Tracer.ParentSpan>>
333
384
  } = dual(2, <A, E, R>(
@@ -356,14 +407,14 @@ export class OtelSpan implements Tracer.Span {
356
407
 
357
408
  readonly name: string
358
409
  readonly kind: Tracer.SpanKind
359
- readonly annotations: ServiceMap.ServiceMap<never>
410
+ readonly annotations: Context.Context<never>
360
411
  readonly links: Array<Tracer.SpanLink>
361
412
  readonly span: Otel.Span
362
413
  readonly spanId: string
363
414
  readonly traceId: string
364
415
  readonly attributes = new Map<string, unknown>()
365
416
  readonly sampled: boolean
366
- readonly parent: Tracer.AnySpan | undefined
417
+ readonly parent: Option.Option<Tracer.AnySpan>
367
418
  status: Tracer.SpanStatus
368
419
 
369
420
  constructor(
@@ -378,9 +429,9 @@ export class OtelSpan implements Tracer.Span {
378
429
  this.links = options.links
379
430
  this.kind = options.kind
380
431
  const active = contextApi.active()
381
- this.parent = options.parent ?? (options?.root !== true) ?
382
- getOtelParent(traceApi, active, options.annotations) :
383
- undefined
432
+ this.parent = options.root !== true
433
+ ? Option.orElse(options.parent, () => getOtelParent(traceApi, active, options.annotations))
434
+ : options.parent
384
435
  this.span = tracer.startSpan(
385
436
  options.name,
386
437
  {
@@ -393,7 +444,9 @@ export class OtelSpan implements Tracer.Span {
393
444
  : undefined as any,
394
445
  kind: kindMap[this.kind]
395
446
  },
396
- this.parent ? populateContext(active, this.parent, options.annotations) : Otel.trace.deleteSpan(active)
447
+ Option.isSome(this.parent) ?
448
+ populateContext(active, this.parent.value, options.annotations) :
449
+ Otel.trace.deleteSpan(active)
397
450
  )
398
451
  const spanContext = this.span.spanContext()
399
452
  this.spanId = spanContext.spanId
@@ -469,30 +522,24 @@ export class OtelSpan implements Tracer.Span {
469
522
  const isSampled = (traceFlags: Otel.TraceFlags): boolean =>
470
523
  (traceFlags & Otel.TraceFlags.SAMPLED) === Otel.TraceFlags.SAMPLED
471
524
 
472
- const nanosToHrTime = (timestamp: bigint): Otel.HrTime => {
473
- return [Number(timestamp / bigint1e9), Number(timestamp % bigint1e9)]
474
- }
475
-
476
525
  const getOtelParent = (
477
526
  tracer: Otel.TraceAPI,
478
527
  context: Otel.Context,
479
- annotations: ServiceMap.ServiceMap<never>
480
- ): Tracer.AnySpan | undefined => {
481
- const active = tracer.getSpan(context)
482
- const otelParent = active ? active.spanContext() : undefined
483
- return otelParent
484
- ? Tracer.externalSpan({
485
- spanId: otelParent.spanId,
486
- traceId: otelParent.traceId,
487
- sampled: (otelParent.traceFlags & 1) === 1,
488
- annotations
489
- })
490
- : undefined
528
+ annotations: Context.Context<never>
529
+ ): Option.Option<Tracer.AnySpan> => {
530
+ const otelParent = tracer.getSpan(context)?.spanContext()
531
+ if (!otelParent) return Option.none()
532
+ return Option.some(Tracer.externalSpan({
533
+ spanId: otelParent.spanId,
534
+ traceId: otelParent.traceId,
535
+ sampled: (otelParent.traceFlags & 1) === 1,
536
+ annotations
537
+ }))
491
538
  }
492
539
 
493
540
  const makeSpanContext = (
494
541
  span: Tracer.AnySpan,
495
- annotations?: ServiceMap.ServiceMap<never>
542
+ annotations?: Context.Context<never>
496
543
  ): Otel.SpanContext => {
497
544
  const traceFlags = makeTraceFlags(span, annotations)
498
545
  const traceState = makeTraceState(span, annotations)!
@@ -507,13 +554,13 @@ const makeSpanContext = (
507
554
 
508
555
  const makeTraceFlags = (
509
556
  span: Tracer.AnySpan,
510
- annotations: ServiceMap.ServiceMap<never> | undefined
557
+ annotations: Context.Context<never> | undefined
511
558
  ): Otel.TraceFlags => {
512
559
  let traceFlags: Otel.TraceFlags | undefined
513
560
  if (Predicate.isNotUndefined(annotations)) {
514
561
  traceFlags = extractTraceService(span, annotations, OtelTraceFlags)
515
562
  if (Predicate.isUndefined(traceFlags)) {
516
- traceFlags = ServiceMap.getOrUndefined(span.annotations, OtelTraceFlags)
563
+ traceFlags = Context.getOrUndefined(span.annotations, OtelTraceFlags)
517
564
  }
518
565
  }
519
566
  return traceFlags ?? Otel.TraceFlags.SAMPLED
@@ -521,13 +568,13 @@ const makeTraceFlags = (
521
568
 
522
569
  const makeTraceState = (
523
570
  span: Tracer.AnySpan,
524
- annotations: ServiceMap.ServiceMap<never> | undefined
571
+ annotations: Context.Context<never> | undefined
525
572
  ): Otel.TraceState | undefined => {
526
573
  let traceState: Otel.TraceState | undefined
527
574
  if (Predicate.isNotUndefined(annotations)) {
528
575
  traceState = extractTraceService(span, annotations, OtelTraceState)
529
576
  if (Predicate.isUndefined(traceState)) {
530
- traceState = ServiceMap.getOrUndefined(span.annotations, OtelTraceState)
577
+ traceState = Context.getOrUndefined(span.annotations, OtelTraceState)
531
578
  }
532
579
  }
533
580
  return traceState
@@ -535,20 +582,20 @@ const makeTraceState = (
535
582
 
536
583
  const extractTraceService = <I, S>(
537
584
  parent: Tracer.AnySpan,
538
- annotations: ServiceMap.ServiceMap<never>,
539
- service: ServiceMap.Service<I, S>
585
+ annotations: Context.Context<never>,
586
+ service: Context.Service<I, S>
540
587
  ) => {
541
- const instance = ServiceMap.getOrUndefined(annotations, service)
588
+ const instance = Context.getOrUndefined(annotations, service)
542
589
  if (Predicate.isNotUndefined(instance)) {
543
590
  return instance
544
591
  }
545
- return ServiceMap.getOrUndefined(parent.annotations, service)
592
+ return Context.getOrUndefined(parent.annotations, service)
546
593
  }
547
594
 
548
595
  const populateContext = (
549
596
  context: Otel.Context,
550
597
  span: Tracer.AnySpan,
551
- annotations?: ServiceMap.ServiceMap<never> | undefined
598
+ annotations?: Context.Context<never> | undefined
552
599
  ): Otel.Context =>
553
600
  span instanceof OtelSpan ?
554
601
  Otel.trace.setSpan(context, span.span) :
package/src/WebSdk.ts CHANGED
@@ -1,5 +1,31 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Provides an Effect layer for configuring OpenTelemetry in browser
3
+ * applications. The module builds a shared resource from explicit service
4
+ * metadata and wires Effect tracing, metrics, and logging into OpenTelemetry
5
+ * SDK providers when span processors, metric readers, or log record processors
6
+ * are supplied.
7
+ *
8
+ * Use this module in client-side applications that need Effect spans, metrics,
9
+ * and logs exported from browser runtimes, such as single-page apps,
10
+ * multi-page apps with hydrated Effect code, frontend workers, or UI flows
11
+ * that should be correlated with backend traces. Telemetry is enabled only for
12
+ * the configured signal types, so tracing, metrics, and logging can be
13
+ * installed independently from the same layer.
14
+ *
15
+ * Browser SDKs cannot rely on process environment resource configuration, so
16
+ * provide stable service metadata explicitly and use resource attributes for
17
+ * application, release, deployment, or page-shell identity rather than
18
+ * per-event data. This module does not create exporters; supply
19
+ * browser-compatible processors, readers, and exporters yourself, and make sure
20
+ * their endpoints are reachable from the browser with the required CORS and
21
+ * authentication behavior. The layer is scoped: tracer providers are
22
+ * force-flushed and shut down when the scope is released, while metric readers
23
+ * and logger providers follow their respective layer lifecycles. Keep the
24
+ * scope alive for the lifetime of the browser application and release it during
25
+ * application teardown when possible so batched exporters and periodic metric
26
+ * readers can deliver buffered telemetry before the page is unloaded.
27
+ *
28
+ * @since 4.0.0
3
29
  */
4
30
  import type * as Otel from "@opentelemetry/api"
5
31
  import type { LoggerProviderConfig, LogRecordProcessor } from "@opentelemetry/sdk-logs"
@@ -17,8 +43,10 @@ import * as Resource from "./Resource.ts"
17
43
  import * as Tracer from "./Tracer.ts"
18
44
 
19
45
  /**
20
- * @since 1.0.0
21
- * @category Models
46
+ * Configuration for the Web OpenTelemetry layer, including resource metadata and optional tracing, metrics, and logging settings.
47
+ *
48
+ * @category models
49
+ * @since 4.0.0
22
50
  */
23
51
  export interface Configuration {
24
52
  readonly spanProcessor?: SpanProcessor | ReadonlyArray<SpanProcessor> | undefined
@@ -36,8 +64,10 @@ export interface Configuration {
36
64
  }
37
65
 
38
66
  /**
39
- * @since 1.0.0
40
- * @category Layers
67
+ * Creates a scoped Web OpenTelemetry tracer provider from one or more span processors and shuts it down when the layer is released.
68
+ *
69
+ * @category layers
70
+ * @since 4.0.0
41
71
  */
42
72
  export const layerTracerProvider = (
43
73
  processor: SpanProcessor | NonEmptyReadonlyArray<SpanProcessor>,
@@ -65,18 +95,24 @@ export const layerTracerProvider = (
65
95
  )
66
96
 
67
97
  /**
68
- * @since 1.0.0
69
- * @category Layers
98
+ * Creates a Web OpenTelemetry layer from configuration, providing the resource and enabling tracing, metrics, and logging when configured.
99
+ *
100
+ * @category layers
101
+ * @since 4.0.0
70
102
  */
71
103
  export const layer: {
72
104
  /**
73
- * @since 1.0.0
74
- * @category Layers
105
+ * Creates a Web OpenTelemetry layer from configuration, providing the resource and enabling tracing, metrics, and logging when configured.
106
+ *
107
+ * @category layers
108
+ * @since 4.0.0
75
109
  */
76
110
  (evaluate: LazyArg<Configuration>): Layer.Layer<Resource.Resource>
77
111
  /**
78
- * @since 1.0.0
79
- * @category Layers
112
+ * Creates a Web OpenTelemetry layer from configuration, providing the resource and enabling tracing, metrics, and logging when configured.
113
+ *
114
+ * @category layers
115
+ * @since 4.0.0
80
116
  */
81
117
  <E, R>(evaluate: Effect.Effect<Configuration, E, R>): Layer.Layer<Resource.Resource, E, R>
82
118
  } = (