@effect/opentelemetry 4.0.0-beta.99 → 4.0.0-rc.108

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.
Files changed (110) hide show
  1. package/AGENTS.md +381 -0
  2. package/CLAUDE.md +381 -0
  3. package/README.md +13 -2
  4. package/ai-docs/README.md +44 -0
  5. package/ai-docs/package.json +36 -0
  6. package/ai-docs/src/01_effect/01_basics/01_effect-gen.ts +30 -0
  7. package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +39 -0
  8. package/ai-docs/src/01_effect/01_basics/10_creating-effects.ts +74 -0
  9. package/ai-docs/src/01_effect/01_basics/index.md +5 -0
  10. package/ai-docs/src/01_effect/02_schema/10_schema-basics.ts +43 -0
  11. package/ai-docs/src/01_effect/02_schema/index.md +7 -0
  12. package/ai-docs/src/01_effect/03_services/01_service.ts +45 -0
  13. package/ai-docs/src/01_effect/03_services/10_reference.ts +10 -0
  14. package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +70 -0
  15. package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +66 -0
  16. package/ai-docs/src/01_effect/03_services/index.md +5 -0
  17. package/ai-docs/src/01_effect/04_errors/01_error-handling.ts +30 -0
  18. package/ai-docs/src/01_effect/04_errors/10_catch-tags.ts +24 -0
  19. package/ai-docs/src/01_effect/04_errors/20_reason-errors.ts +64 -0
  20. package/ai-docs/src/01_effect/04_errors/index.md +1 -0
  21. package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +105 -0
  22. package/ai-docs/src/01_effect/05_resources/20_layer-side-effects.ts +31 -0
  23. package/ai-docs/src/01_effect/05_resources/30_layer-map.ts +86 -0
  24. package/ai-docs/src/01_effect/05_resources/index.md +3 -0
  25. package/ai-docs/src/01_effect/06_running/10_run-main.ts +30 -0
  26. package/ai-docs/src/01_effect/06_running/20_layer-launch.ts +27 -0
  27. package/ai-docs/src/01_effect/06_running/index.md +1 -0
  28. package/ai-docs/src/01_effect/07_pubsub/10_pubsub.ts +56 -0
  29. package/ai-docs/src/01_effect/07_pubsub/index.md +3 -0
  30. package/ai-docs/src/03_stream/10_creating-streams.ts +103 -0
  31. package/ai-docs/src/03_stream/20_consuming-streams.ts +137 -0
  32. package/ai-docs/src/03_stream/30_encoding.ts +165 -0
  33. package/ai-docs/src/03_stream/index.md +4 -0
  34. package/ai-docs/src/04_integration/10_managed-runtime.ts +129 -0
  35. package/ai-docs/src/04_integration/index.md +5 -0
  36. package/ai-docs/src/05_batching/10_request-resolver.ts +89 -0
  37. package/ai-docs/src/05_batching/index.md +3 -0
  38. package/ai-docs/src/06_schedule/10_schedules.ts +110 -0
  39. package/ai-docs/src/06_schedule/index.md +3 -0
  40. package/ai-docs/src/07_datetime/10_creating-and-formatting.ts +30 -0
  41. package/ai-docs/src/07_datetime/20_time-zones.ts +44 -0
  42. package/ai-docs/src/07_datetime/index.md +5 -0
  43. package/ai-docs/src/08_observability/10_logging.ts +66 -0
  44. package/ai-docs/src/08_observability/20_otlp-tracing.ts +95 -0
  45. package/ai-docs/src/08_observability/index.md +7 -0
  46. package/ai-docs/src/09_testing/10_effect-tests.ts +55 -0
  47. package/ai-docs/src/09_testing/20_layer-tests.ts +138 -0
  48. package/ai-docs/src/09_testing/index.md +1 -0
  49. package/ai-docs/src/10_predicate/01_basics.ts +14 -0
  50. package/ai-docs/src/10_predicate/index.md +9 -0
  51. package/ai-docs/src/50_http-client/10_basics.ts +102 -0
  52. package/ai-docs/src/50_http-client/index.md +3 -0
  53. package/ai-docs/src/51_http-server/10_basics.ts +116 -0
  54. package/ai-docs/src/51_http-server/fixtures/api/Api.ts +14 -0
  55. package/ai-docs/src/51_http-server/fixtures/api/Authorization.ts +36 -0
  56. package/ai-docs/src/51_http-server/fixtures/api/System.ts +10 -0
  57. package/ai-docs/src/51_http-server/fixtures/api/Users.ts +91 -0
  58. package/ai-docs/src/51_http-server/fixtures/domain/User.ts +12 -0
  59. package/ai-docs/src/51_http-server/fixtures/domain/UserErrors.ts +22 -0
  60. package/ai-docs/src/51_http-server/fixtures/server/Authorization.ts +36 -0
  61. package/ai-docs/src/51_http-server/fixtures/server/Users/http.ts +71 -0
  62. package/ai-docs/src/51_http-server/fixtures/server/Users.ts +62 -0
  63. package/ai-docs/src/51_http-server/index.md +3 -0
  64. package/ai-docs/src/60_child-process/10_working-with-child-processes.ts +117 -0
  65. package/ai-docs/src/60_child-process/index.md +3 -0
  66. package/ai-docs/src/70_cli/10_basics.ts +136 -0
  67. package/ai-docs/src/70_cli/index.md +5 -0
  68. package/ai-docs/src/71_ai/10_language-model.ts +156 -0
  69. package/ai-docs/src/71_ai/20_tools.ts +226 -0
  70. package/ai-docs/src/71_ai/30_chat.ts +158 -0
  71. package/ai-docs/src/71_ai/fixtures/domain/LaunchPlan.ts +9 -0
  72. package/ai-docs/src/71_ai/index.md +5 -0
  73. package/ai-docs/src/80_cluster/10_entities.ts +97 -0
  74. package/ai-docs/src/80_cluster/index.md +4 -0
  75. package/ai-docs/src/index.md +10 -0
  76. package/ai-docs/tsconfig.json +24 -0
  77. package/dist/NodeSdk.js +1 -1
  78. package/dist/NodeSdk.js.map +1 -1
  79. package/dist/OtelLogger.d.ts.map +1 -1
  80. package/dist/OtelLogger.js +5 -4
  81. package/dist/OtelLogger.js.map +1 -1
  82. package/dist/OtelMetrics.d.ts +32 -21
  83. package/dist/OtelMetrics.d.ts.map +1 -1
  84. package/dist/OtelMetrics.js +31 -20
  85. package/dist/OtelMetrics.js.map +1 -1
  86. package/dist/OtelTracer.d.ts.map +1 -1
  87. package/dist/OtelTracer.js +28 -19
  88. package/dist/OtelTracer.js.map +1 -1
  89. package/dist/Resource.d.ts +1 -1
  90. package/dist/Resource.d.ts.map +1 -1
  91. package/dist/Resource.js +7 -6
  92. package/dist/Resource.js.map +1 -1
  93. package/dist/WebSdk.d.ts.map +1 -1
  94. package/dist/WebSdk.js +1 -1
  95. package/dist/WebSdk.js.map +1 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/internal/attributes.js +2 -1
  98. package/dist/internal/attributes.js.map +1 -1
  99. package/dist/internal/metrics.js +5 -1
  100. package/dist/internal/metrics.js.map +1 -1
  101. package/dist/internal/utilities.js.map +1 -1
  102. package/package.json +15 -13
  103. package/src/NodeSdk.ts +1 -1
  104. package/src/OtelLogger.ts +6 -4
  105. package/src/OtelMetrics.ts +33 -22
  106. package/src/OtelTracer.ts +32 -20
  107. package/src/Resource.ts +7 -6
  108. package/src/WebSdk.ts +3 -2
  109. package/src/internal/attributes.ts +2 -1
  110. package/src/internal/metrics.ts +6 -1
package/src/OtelTracer.ts CHANGED
@@ -130,24 +130,20 @@ export const makeExternalSpan = (options: {
130
130
  readonly traceFlags?: number | undefined
131
131
  readonly traceState?: string | Otel.TraceState | undefined
132
132
  }): Tracer.ExternalSpan => {
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
- }
133
+ let annotations = Context.empty()
134
+ if (options.traceFlags !== undefined) {
135
+ annotations = Context.add(annotations, OtelTraceFlags, options.traceFlags)
136
+ }
138
137
 
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)
138
+ if (typeof options.traceState === "string") {
139
+ try {
140
+ annotations = Context.add(annotations, OtelTraceState, Otel.createTraceState(options.traceState))
141
+ } catch {
142
+ //
147
143
  }
148
-
149
- return next
150
- })
144
+ } else if (options.traceState) {
145
+ annotations = Context.add(annotations, OtelTraceState, options.traceState)
146
+ }
151
147
 
152
148
  return {
153
149
  _tag: "ExternalSpan",
@@ -314,7 +310,7 @@ const makeOtelSpan = (span: Tracer.Span, clock: Clock.Clock): Otel.Span => {
314
310
  return self
315
311
  },
316
312
  setStatus(status) {
317
- exit = Otel.SpanStatusCode.ERROR
313
+ exit = status.code === Otel.SpanStatusCode.ERROR
318
314
  ? Exit.die(status.message ?? "Unknown error")
319
315
  : Exit.void
320
316
  return self
@@ -535,18 +531,23 @@ export class OtelSpan implements Tracer.Span {
535
531
  const isSampled = (traceFlags: Otel.TraceFlags): boolean =>
536
532
  (traceFlags & Otel.TraceFlags.SAMPLED) === Otel.TraceFlags.SAMPLED
537
533
 
534
+ class OtelParentSpanContext extends Context.Service<
535
+ OtelParentSpanContext,
536
+ Otel.SpanContext
537
+ >()("@effect/opentelemetry/Tracer/OtelParentSpanContext") {}
538
+
538
539
  const getOtelParent = (
539
540
  tracer: Otel.TraceAPI,
540
541
  context: Otel.Context,
541
542
  annotations: Context.Context<never>
542
543
  ): Option.Option<Tracer.AnySpan> => {
543
- const otelParent = tracer.getSpan(context)?.spanContext()
544
+ const otelParent = tracer.getSpanContext(context)
544
545
  if (!otelParent) return Option.none()
545
546
  return Option.some(Tracer.externalSpan({
546
547
  spanId: otelParent.spanId,
547
548
  traceId: otelParent.traceId,
548
- sampled: (otelParent.traceFlags & 1) === 1,
549
- annotations
549
+ sampled: isSampled(otelParent.traceFlags),
550
+ annotations: Context.add(annotations, OtelParentSpanContext, otelParent)
550
551
  }))
551
552
  }
552
553
 
@@ -554,6 +555,17 @@ const makeSpanContext = (
554
555
  span: Tracer.AnySpan,
555
556
  annotations?: Context.Context<never>
556
557
  ): Otel.SpanContext => {
558
+ const otelParent = Context.getOrUndefined(span.annotations, OtelParentSpanContext)
559
+ if (otelParent !== undefined) {
560
+ if (annotations === undefined) return otelParent
561
+ const traceFlags = extractTraceService(span, annotations, OtelTraceFlags)
562
+ const traceState = extractTraceService(span, annotations, OtelTraceState)
563
+ return {
564
+ ...otelParent,
565
+ traceFlags: traceFlags ?? otelParent.traceFlags,
566
+ traceState: traceState ?? otelParent.traceState!
567
+ }
568
+ }
557
569
  const traceFlags = makeTraceFlags(span, annotations)
558
570
  const traceState = makeTraceState(span, annotations)!
559
571
  return ({
package/src/Resource.ts CHANGED
@@ -18,6 +18,7 @@ import * as Config from "effect/Config"
18
18
  import * as Context from "effect/Context"
19
19
  import * as Effect from "effect/Effect"
20
20
  import * as Layer from "effect/Layer"
21
+ import * as Rec from "effect/Record"
21
22
 
22
23
  /**
23
24
  * Service tag for OpenTelemetry metadata attached to emitted telemetry.
@@ -74,7 +75,7 @@ export const layer = (config: {
74
75
  * @see {@link layer} for creating a `Resource` layer from explicit metadata
75
76
  * @see {@link layerFromEnv} for merging attributes with OpenTelemetry environment variables
76
77
  *
77
- * @category configuration
78
+ * @category converting
78
79
  * @since 4.0.0
79
80
  */
80
81
  export const configToAttributes = (options: {
@@ -120,7 +121,7 @@ export const layerFromEnv = (
120
121
  if (parts.length !== 2) {
121
122
  return acc
122
123
  }
123
- acc[parts[0].trim()] = parts[1].trim()
124
+ Rec.assignProperty(acc, parts[0].trim(), parts[1].trim())
124
125
  return acc
125
126
  })
126
127
  })
@@ -128,10 +129,10 @@ export const layerFromEnv = (
128
129
  if (serviceName._tag === "Some") {
129
130
  attributes[OtelSemConv.ATTR_SERVICE_NAME] = serviceName.value
130
131
  }
131
- if (additionalAttributes) {
132
- Object.assign(attributes, additionalAttributes)
133
- }
134
- return Resources.resourceFromAttributes(attributes)
132
+ return Resources.resourceFromAttributes({
133
+ ...attributes,
134
+ ...additionalAttributes
135
+ })
135
136
  }).pipe(Effect.orDie)
136
137
  )
137
138
 
package/src/WebSdk.ts CHANGED
@@ -69,8 +69,9 @@ export const layerTracerProvider = (
69
69
  return provider
70
70
  }),
71
71
  (provider) =>
72
- Effect.ignore(
73
- Effect.promise(() => provider.forceFlush().then(() => provider.shutdown()))
72
+ Effect.promise(() => provider.forceFlush()).pipe(
73
+ Effect.ensuring(Effect.promise(() => provider.shutdown())),
74
+ Effect.ignore
74
75
  )
75
76
  )
76
77
  })
@@ -1,5 +1,6 @@
1
1
  import type * as Otel from "@opentelemetry/api"
2
2
  import * as Inspectable from "effect/Inspectable"
3
+ import * as Rec from "effect/Record"
3
4
 
4
5
  const bigint1e9 = BigInt(1_000_000_000)
5
6
 
@@ -12,7 +13,7 @@ export const nanosToHrTime = (timestamp: bigint): Otel.HrTime => {
12
13
  export const recordToAttributes = (record: Record<string, unknown>): Otel.Attributes => {
13
14
  const attributes: Otel.Attributes = {}
14
15
  for (const [key, value] of Object.entries(record)) {
15
- attributes[key] = unknownToAttributeValue(value)
16
+ Rec.assignProperty(attributes, key, unknownToAttributeValue(value))
16
17
  }
17
18
  return attributes
18
19
  }
@@ -13,6 +13,7 @@ import type { InstrumentDescriptor } from "@opentelemetry/sdk-metrics/build/src/
13
13
  import * as Arr from "effect/Array"
14
14
  import type * as Context from "effect/Context"
15
15
  import * as Metric from "effect/Metric"
16
+ import * as Rec from "effect/Record"
16
17
  import type * as Metrics from "../OtelMetrics.ts"
17
18
 
18
19
  const sdkName = "@effect/opentelemetry/Metrics"
@@ -64,6 +65,10 @@ export class MetricProducerImpl implements MetricProducer {
64
65
  this.previousSummaryState = new Map()
65
66
  }
66
67
 
68
+ fork(): MetricProducerImpl {
69
+ return new MetricProducerImpl(this.resource, this.context, this.temporality)
70
+ }
71
+
67
72
  startTimeFor(name: string, hrTime: HrTime) {
68
73
  if (this.startTimes.has(name)) {
69
74
  return this.startTimes.get(name)!
@@ -94,7 +99,7 @@ export class MetricProducerImpl implements MetricProducer {
94
99
  const state = snapshot[i]
95
100
  const attributes = state.attributes
96
101
  ? Arr.reduce(Object.entries(state.attributes), {} as Record<string, string>, (acc, [key, value]) => {
97
- acc[key] = String(value)
102
+ Rec.assignProperty(acc, key, String(value))
98
103
  return acc
99
104
  })
100
105
  : {}