@effect/opentelemetry 0.61.0 → 4.0.0-beta.1

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 (183) hide show
  1. package/LICENSE +1 -1
  2. package/dist/{dts/Logger.d.ts → Logger.d.ts} +19 -13
  3. package/dist/Logger.d.ts.map +1 -0
  4. package/dist/Logger.js +76 -0
  5. package/dist/Logger.js.map +1 -0
  6. package/dist/Metrics.d.ts +76 -0
  7. package/dist/Metrics.d.ts.map +1 -0
  8. package/dist/Metrics.js +59 -0
  9. package/dist/Metrics.js.map +1 -0
  10. package/dist/{dts/NodeSdk.d.ts → NodeSdk.d.ts} +12 -9
  11. package/dist/NodeSdk.d.ts.map +1 -0
  12. package/dist/{esm/NodeSdk.js → NodeSdk.js} +23 -14
  13. package/dist/NodeSdk.js.map +1 -0
  14. package/dist/{dts/Resource.d.ts → Resource.d.ts} +10 -13
  15. package/dist/Resource.d.ts.map +1 -0
  16. package/dist/{esm/Resource.js → Resource.js} +12 -13
  17. package/dist/Resource.js.map +1 -0
  18. package/dist/Tracer.d.ts +129 -0
  19. package/dist/Tracer.d.ts.map +1 -0
  20. package/dist/Tracer.js +391 -0
  21. package/dist/Tracer.js.map +1 -0
  22. package/dist/{dts/WebSdk.d.ts → WebSdk.d.ts} +12 -9
  23. package/dist/WebSdk.d.ts.map +1 -0
  24. package/dist/WebSdk.js +41 -0
  25. package/dist/WebSdk.js.map +1 -0
  26. package/dist/index.d.ts +28 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +29 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/internal/attributes.d.ts +2 -0
  31. package/dist/internal/attributes.d.ts.map +1 -0
  32. package/dist/internal/attributes.js +19 -0
  33. package/dist/internal/attributes.js.map +1 -0
  34. package/dist/{dts/internal → internal}/metrics.d.ts.map +1 -1
  35. package/dist/internal/metrics.js +406 -0
  36. package/dist/internal/metrics.js.map +1 -0
  37. package/dist/internal/utilities.d.ts +2 -0
  38. package/dist/internal/utilities.d.ts.map +1 -0
  39. package/dist/internal/utilities.js +3 -0
  40. package/dist/internal/utilities.js.map +1 -0
  41. package/package.json +86 -119
  42. package/src/Logger.ts +52 -55
  43. package/src/Metrics.ts +92 -18
  44. package/src/NodeSdk.ts +67 -64
  45. package/src/Resource.ts +16 -24
  46. package/src/Tracer.ts +469 -78
  47. package/src/WebSdk.ts +59 -51
  48. package/src/index.ts +7 -36
  49. package/src/internal/attributes.ts +21 -0
  50. package/src/internal/metrics.ts +381 -250
  51. package/src/internal/utilities.ts +5 -0
  52. package/Logger/package.json +0 -6
  53. package/Metrics/package.json +0 -6
  54. package/NodeSdk/package.json +0 -6
  55. package/Otlp/package.json +0 -6
  56. package/OtlpLogger/package.json +0 -6
  57. package/OtlpMetrics/package.json +0 -6
  58. package/OtlpResource/package.json +0 -6
  59. package/OtlpSerialization/package.json +0 -6
  60. package/OtlpTracer/package.json +0 -6
  61. package/Resource/package.json +0 -6
  62. package/Tracer/package.json +0 -6
  63. package/WebSdk/package.json +0 -6
  64. package/dist/cjs/Logger.js +0 -85
  65. package/dist/cjs/Logger.js.map +0 -1
  66. package/dist/cjs/Metrics.js +0 -24
  67. package/dist/cjs/Metrics.js.map +0 -1
  68. package/dist/cjs/NodeSdk.js +0 -53
  69. package/dist/cjs/NodeSdk.js.map +0 -1
  70. package/dist/cjs/Otlp.js +0 -64
  71. package/dist/cjs/Otlp.js.map +0 -1
  72. package/dist/cjs/OtlpLogger.js +0 -163
  73. package/dist/cjs/OtlpLogger.js.map +0 -1
  74. package/dist/cjs/OtlpMetrics.js +0 -357
  75. package/dist/cjs/OtlpMetrics.js.map +0 -1
  76. package/dist/cjs/OtlpResource.js +0 -136
  77. package/dist/cjs/OtlpResource.js.map +0 -1
  78. package/dist/cjs/OtlpSerialization.js +0 -55
  79. package/dist/cjs/OtlpSerialization.js.map +0 -1
  80. package/dist/cjs/OtlpTracer.js +0 -231
  81. package/dist/cjs/OtlpTracer.js.map +0 -1
  82. package/dist/cjs/Resource.js +0 -75
  83. package/dist/cjs/Resource.js.map +0 -1
  84. package/dist/cjs/Tracer.js +0 -87
  85. package/dist/cjs/Tracer.js.map +0 -1
  86. package/dist/cjs/WebSdk.js +0 -42
  87. package/dist/cjs/WebSdk.js.map +0 -1
  88. package/dist/cjs/index.js +0 -32
  89. package/dist/cjs/index.js.map +0 -1
  90. package/dist/cjs/internal/metrics.js +0 -288
  91. package/dist/cjs/internal/metrics.js.map +0 -1
  92. package/dist/cjs/internal/otlpExporter.js +0 -83
  93. package/dist/cjs/internal/otlpExporter.js.map +0 -1
  94. package/dist/cjs/internal/otlpProtobuf.js +0 -430
  95. package/dist/cjs/internal/otlpProtobuf.js.map +0 -1
  96. package/dist/cjs/internal/protobuf.js +0 -183
  97. package/dist/cjs/internal/protobuf.js.map +0 -1
  98. package/dist/cjs/internal/tracer.js +0 -306
  99. package/dist/cjs/internal/tracer.js.map +0 -1
  100. package/dist/cjs/internal/utils.js +0 -34
  101. package/dist/cjs/internal/utils.js.map +0 -1
  102. package/dist/dts/Logger.d.ts.map +0 -1
  103. package/dist/dts/Metrics.d.ts +0 -29
  104. package/dist/dts/Metrics.d.ts.map +0 -1
  105. package/dist/dts/NodeSdk.d.ts.map +0 -1
  106. package/dist/dts/Otlp.d.ts +0 -80
  107. package/dist/dts/Otlp.d.ts.map +0 -1
  108. package/dist/dts/OtlpLogger.d.ts +0 -47
  109. package/dist/dts/OtlpLogger.d.ts.map +0 -1
  110. package/dist/dts/OtlpMetrics.d.ts +0 -41
  111. package/dist/dts/OtlpMetrics.d.ts.map +0 -1
  112. package/dist/dts/OtlpResource.d.ts +0 -104
  113. package/dist/dts/OtlpResource.d.ts.map +0 -1
  114. package/dist/dts/OtlpSerialization.d.ts +0 -53
  115. package/dist/dts/OtlpSerialization.d.ts.map +0 -1
  116. package/dist/dts/OtlpTracer.d.ts +0 -50
  117. package/dist/dts/OtlpTracer.d.ts.map +0 -1
  118. package/dist/dts/Resource.d.ts.map +0 -1
  119. package/dist/dts/Tracer.d.ts +0 -143
  120. package/dist/dts/Tracer.d.ts.map +0 -1
  121. package/dist/dts/WebSdk.d.ts.map +0 -1
  122. package/dist/dts/index.d.ts +0 -54
  123. package/dist/dts/index.d.ts.map +0 -1
  124. package/dist/dts/internal/otlpExporter.d.ts +0 -2
  125. package/dist/dts/internal/otlpExporter.d.ts.map +0 -1
  126. package/dist/dts/internal/otlpProtobuf.d.ts +0 -501
  127. package/dist/dts/internal/otlpProtobuf.d.ts.map +0 -1
  128. package/dist/dts/internal/protobuf.d.ts +0 -100
  129. package/dist/dts/internal/protobuf.d.ts.map +0 -1
  130. package/dist/dts/internal/tracer.d.ts +0 -2
  131. package/dist/dts/internal/tracer.d.ts.map +0 -1
  132. package/dist/dts/internal/utils.d.ts +0 -2
  133. package/dist/dts/internal/utils.d.ts.map +0 -1
  134. package/dist/esm/Logger.js +0 -75
  135. package/dist/esm/Logger.js.map +0 -1
  136. package/dist/esm/Metrics.js +0 -17
  137. package/dist/esm/Metrics.js.map +0 -1
  138. package/dist/esm/NodeSdk.js.map +0 -1
  139. package/dist/esm/Otlp.js +0 -56
  140. package/dist/esm/Otlp.js.map +0 -1
  141. package/dist/esm/OtlpLogger.js +0 -155
  142. package/dist/esm/OtlpLogger.js.map +0 -1
  143. package/dist/esm/OtlpMetrics.js +0 -349
  144. package/dist/esm/OtlpMetrics.js.map +0 -1
  145. package/dist/esm/OtlpResource.js +0 -124
  146. package/dist/esm/OtlpResource.js.map +0 -1
  147. package/dist/esm/OtlpSerialization.js +0 -46
  148. package/dist/esm/OtlpSerialization.js.map +0 -1
  149. package/dist/esm/OtlpTracer.js +0 -223
  150. package/dist/esm/OtlpTracer.js.map +0 -1
  151. package/dist/esm/Resource.js.map +0 -1
  152. package/dist/esm/Tracer.js +0 -80
  153. package/dist/esm/Tracer.js.map +0 -1
  154. package/dist/esm/WebSdk.js +0 -33
  155. package/dist/esm/WebSdk.js.map +0 -1
  156. package/dist/esm/index.js +0 -54
  157. package/dist/esm/index.js.map +0 -1
  158. package/dist/esm/internal/metrics.js +0 -278
  159. package/dist/esm/internal/metrics.js.map +0 -1
  160. package/dist/esm/internal/otlpExporter.js +0 -76
  161. package/dist/esm/internal/otlpExporter.js.map +0 -1
  162. package/dist/esm/internal/otlpProtobuf.js +0 -396
  163. package/dist/esm/internal/otlpProtobuf.js.map +0 -1
  164. package/dist/esm/internal/protobuf.js +0 -155
  165. package/dist/esm/internal/protobuf.js.map +0 -1
  166. package/dist/esm/internal/tracer.js +0 -297
  167. package/dist/esm/internal/tracer.js.map +0 -1
  168. package/dist/esm/internal/utils.js +0 -23
  169. package/dist/esm/internal/utils.js.map +0 -1
  170. package/dist/esm/package.json +0 -4
  171. package/index/package.json +0 -6
  172. package/src/Otlp.ts +0 -118
  173. package/src/OtlpLogger.ts +0 -263
  174. package/src/OtlpMetrics.ts +0 -575
  175. package/src/OtlpResource.ts +0 -232
  176. package/src/OtlpSerialization.ts +0 -64
  177. package/src/OtlpTracer.ts +0 -352
  178. package/src/internal/otlpExporter.ts +0 -126
  179. package/src/internal/otlpProtobuf.ts +0 -729
  180. package/src/internal/protobuf.ts +0 -219
  181. package/src/internal/tracer.ts +0 -448
  182. package/src/internal/utils.ts +0 -31
  183. /package/dist/{dts/internal → internal}/metrics.d.ts +0 -0
@@ -1,232 +0,0 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import * as Arr from "effect/Array"
5
- import * as Config from "effect/Config"
6
- import * as Effect from "effect/Effect"
7
- import * as Inspectable from "effect/Inspectable"
8
-
9
- const ATTR_SERVICE_NAME = "service.name"
10
- const ATTR_SERVICE_VERSION = "service.version"
11
-
12
- /**
13
- * @since 1.0.0
14
- * @category Models
15
- */
16
- export interface Resource {
17
- /** Resource attributes */
18
- attributes: Array<KeyValue>
19
- /** Resource droppedAttributesCount */
20
- droppedAttributesCount: number
21
- }
22
-
23
- /**
24
- * @since 1.0.0
25
- * @category Constructors
26
- */
27
- export const make = (options: {
28
- readonly serviceName: string
29
- readonly serviceVersion?: string | undefined
30
- readonly attributes?: Record<string, unknown> | undefined
31
- }): Resource => {
32
- const resourceAttributes = options.attributes
33
- ? entriesToAttributes(Object.entries(options.attributes))
34
- : []
35
- resourceAttributes.push({
36
- key: ATTR_SERVICE_NAME,
37
- value: {
38
- stringValue: options.serviceName
39
- }
40
- })
41
- if (options.serviceVersion) {
42
- resourceAttributes.push({
43
- key: ATTR_SERVICE_VERSION,
44
- value: {
45
- stringValue: options.serviceVersion
46
- }
47
- })
48
- }
49
-
50
- return {
51
- attributes: resourceAttributes,
52
- droppedAttributesCount: 0
53
- }
54
- }
55
-
56
- /**
57
- * @since 1.0.0
58
- * @category Constructors
59
- */
60
- export const fromConfig: (
61
- options?: {
62
- readonly serviceName?: string | undefined
63
- readonly serviceVersion?: string | undefined
64
- readonly attributes?: Record<string, unknown> | undefined
65
- } | undefined
66
- ) => Effect.Effect<Resource> = Effect.fnUntraced(function*(options?: {
67
- readonly serviceName?: string | undefined
68
- readonly serviceVersion?: string | undefined
69
- readonly attributes?: Record<string, unknown> | undefined
70
- }) {
71
- const attributes = yield* Config.string("OTEL_RESOURCE_ATTRIBUTES").pipe(
72
- Config.map((s) => {
73
- const attrs = s.split(",")
74
- return Arr.reduce(attrs, {} as Record<string, string>, (acc, attr) => {
75
- const parts = attr.split("=")
76
- if (parts.length !== 2) {
77
- return acc
78
- }
79
- acc[parts[0].trim()] = parts[1].trim()
80
- return acc
81
- })
82
- }),
83
- Config.withDefault({}),
84
- Effect.map((envAttrs) => ({
85
- ...envAttrs,
86
- ...options?.attributes
87
- }))
88
- )
89
- const serviceName = options?.serviceName ?? attributes[ATTR_SERVICE_NAME] as string ??
90
- (yield* Config.string("OTEL_SERVICE_NAME"))
91
- const serviceVersion = options?.serviceVersion ?? attributes[ATTR_SERVICE_VERSION] as string ??
92
- (yield* Config.string("OTEL_SERVICE_VERSION").pipe(Config.withDefault(undefined)))
93
- return make({
94
- serviceName,
95
- serviceVersion,
96
- attributes
97
- })
98
- }, Effect.orDie)
99
-
100
- /**
101
- * @since 1.0.0
102
- * @category Attributes
103
- */
104
- export const unsafeServiceName = (resource: Resource): string => {
105
- const serviceNameAttribute = resource.attributes.find(
106
- (attr) => attr.key === ATTR_SERVICE_NAME
107
- )
108
- if (!serviceNameAttribute || !serviceNameAttribute.value.stringValue) {
109
- throw new Error("Resource does not contain a service name")
110
- }
111
- return serviceNameAttribute.value.stringValue
112
- }
113
-
114
- /**
115
- * @since 1.0.0
116
- * @category Attributes
117
- */
118
- export const entriesToAttributes = (entries: Iterable<[string, unknown]>): Array<KeyValue> => {
119
- const attributes: Array<KeyValue> = []
120
- for (const [key, value] of entries) {
121
- attributes.push({
122
- key,
123
- value: unknownToAttributeValue(value)
124
- })
125
- }
126
- return attributes
127
- }
128
-
129
- /**
130
- * @since 1.0.0
131
- * @category Attributes
132
- */
133
- export const unknownToAttributeValue = (value: unknown): AnyValue => {
134
- if (Array.isArray(value)) {
135
- return {
136
- arrayValue: {
137
- values: value.map(unknownToAttributeValue)
138
- }
139
- }
140
- }
141
- switch (typeof value) {
142
- case "string":
143
- return {
144
- stringValue: value
145
- }
146
- case "bigint":
147
- return {
148
- intValue: Number(value)
149
- }
150
- case "number":
151
- return Number.isInteger(value)
152
- ? {
153
- intValue: value
154
- }
155
- : {
156
- doubleValue: value
157
- }
158
- case "boolean":
159
- return {
160
- boolValue: value
161
- }
162
- default:
163
- return {
164
- stringValue: Inspectable.toStringUnknown(value)
165
- }
166
- }
167
- }
168
-
169
- /**
170
- * @since 1.0.0
171
- * @category Models
172
- */
173
- export interface KeyValue {
174
- /** KeyValue key */
175
- key: string
176
- /** KeyValue value */
177
- value: AnyValue
178
- }
179
-
180
- /**
181
- * @since 1.0.0
182
- * @category Models
183
- */
184
- export interface AnyValue {
185
- /** AnyValue stringValue */
186
- stringValue?: string | null
187
- /** AnyValue boolValue */
188
- boolValue?: boolean | null
189
- /** AnyValue intValue */
190
- intValue?: number | null
191
- /** AnyValue doubleValue */
192
- doubleValue?: number | null
193
- /** AnyValue arrayValue */
194
- arrayValue?: ArrayValue
195
- /** AnyValue kvlistValue */
196
- kvlistValue?: KeyValueList
197
- /** AnyValue bytesValue */
198
- bytesValue?: Uint8Array
199
- }
200
-
201
- /**
202
- * @since 1.0.0
203
- * @category Models
204
- */
205
- export interface ArrayValue {
206
- /** ArrayValue values */
207
- values: Array<AnyValue>
208
- }
209
-
210
- /**
211
- * @since 1.0.0
212
- * @category Models
213
- */
214
- export interface KeyValueList {
215
- /** KeyValueList values */
216
- values: Array<KeyValue>
217
- }
218
-
219
- /**
220
- * @since 1.0.0
221
- * @category Models
222
- */
223
- export interface LongBits {
224
- low: number
225
- high: number
226
- }
227
-
228
- /**
229
- * @since 1.0.0
230
- * @category Models
231
- */
232
- export type Fixed64 = LongBits | string | number
@@ -1,64 +0,0 @@
1
- /**
2
- * OtlpSerialization service for tree-shakable protobuf support.
3
- *
4
- * This module provides the `OtlpSerialization` service that abstracts the
5
- * encoding of OTLP telemetry data to HttpBody.
6
- *
7
- * @since 1.0.0
8
- */
9
- import * as HttpBody from "@effect/platform/HttpBody"
10
- import * as Context from "effect/Context"
11
- import * as Layer from "effect/Layer"
12
- import * as OtlpProtobuf from "./internal/otlpProtobuf.js"
13
-
14
- /**
15
- * @since 1.0.0
16
- * @category Tags
17
- */
18
- export class OtlpSerialization extends Context.Tag("@effect/opentelemetry/OtlpSerialization")<
19
- OtlpSerialization,
20
- {
21
- /**
22
- * Encodes trace data for transmission.
23
- */
24
- readonly traces: (data: unknown) => HttpBody.HttpBody
25
- /**
26
- * Encodes metrics data for transmission.
27
- */
28
- readonly metrics: (data: unknown) => HttpBody.HttpBody
29
- /**
30
- * Encodes logs data for transmission.
31
- */
32
- readonly logs: (data: unknown) => HttpBody.HttpBody
33
- }
34
- >() {}
35
-
36
- /**
37
- * JSON serializer layer for OTLP telemetry data.
38
- *
39
- * It encodes telemetry data as JSON with `application/json` content type.
40
- *
41
- * @since 1.0.0
42
- * @category Layers
43
- */
44
- export const layerJson: Layer.Layer<OtlpSerialization> = Layer.succeed(OtlpSerialization, {
45
- traces: (data) => HttpBody.unsafeJson(data),
46
- metrics: (data) => HttpBody.unsafeJson(data),
47
- logs: (data) => HttpBody.unsafeJson(data)
48
- })
49
-
50
- /**
51
- * Protobuf serializer layer for OTLP telemetry data.
52
- *
53
- * This serializer encodes telemetry data using Protocol Buffers binary
54
- * format with `application/x-protobuf` content type. It provides more
55
- * efficient wire format compared to JSON.
56
- *
57
- * @since 1.0.0
58
- * @category Layers
59
- */
60
- export const layerProtobuf: Layer.Layer<OtlpSerialization> = Layer.succeed(OtlpSerialization, {
61
- traces: (data) => HttpBody.uint8Array(OtlpProtobuf.encodeTracesData(data as any), "application/x-protobuf"),
62
- metrics: (data) => HttpBody.uint8Array(OtlpProtobuf.encodeMetricsData(data as any), "application/x-protobuf"),
63
- logs: (data) => HttpBody.uint8Array(OtlpProtobuf.encodeLogsData(data as any), "application/x-protobuf")
64
- })
package/src/OtlpTracer.ts DELETED
@@ -1,352 +0,0 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import type * as Headers from "@effect/platform/Headers"
5
- import type * as HttpClient from "@effect/platform/HttpClient"
6
- import * as Cause from "effect/Cause"
7
- import type * as Context from "effect/Context"
8
- import * as Duration from "effect/Duration"
9
- import * as Effect from "effect/Effect"
10
- import type * as Exit from "effect/Exit"
11
- import * as Layer from "effect/Layer"
12
- import * as Option from "effect/Option"
13
- import type * as Scope from "effect/Scope"
14
- import * as Tracer from "effect/Tracer"
15
- import type { ExtractTag } from "effect/Types"
16
- import * as Exporter from "./internal/otlpExporter.js"
17
- import type { KeyValue, Resource } from "./OtlpResource.js"
18
- import { entriesToAttributes } from "./OtlpResource.js"
19
- import * as OtlpResource from "./OtlpResource.js"
20
- import { OtlpSerialization } from "./OtlpSerialization.js"
21
-
22
- const ATTR_EXCEPTION_TYPE = "exception.type"
23
- const ATTR_EXCEPTION_MESSAGE = "exception.message"
24
- const ATTR_EXCEPTION_STACKTRACE = "exception.stacktrace"
25
-
26
- /**
27
- * @since 1.0.0
28
- * @category Constructors
29
- */
30
- export const make: (
31
- options: {
32
- readonly url: string
33
- readonly resource?: {
34
- readonly serviceName?: string | undefined
35
- readonly serviceVersion?: string | undefined
36
- readonly attributes?: Record<string, unknown>
37
- } | undefined
38
- readonly headers?: Headers.Input | undefined
39
- readonly exportInterval?: Duration.DurationInput | undefined
40
- readonly maxBatchSize?: number | undefined
41
- readonly context?: (<X>(f: () => X, span: Tracer.AnySpan) => X) | undefined
42
- readonly shutdownTimeout?: Duration.DurationInput | undefined
43
- }
44
- ) => Effect.Effect<
45
- Tracer.Tracer,
46
- never,
47
- HttpClient.HttpClient | OtlpSerialization | Scope.Scope
48
- > = Effect.fnUntraced(function*(options) {
49
- const otelResource = yield* OtlpResource.fromConfig(options.resource)
50
- const scope: Scope = {
51
- name: OtlpResource.unsafeServiceName(otelResource)
52
- }
53
- const serialization = yield* OtlpSerialization
54
-
55
- const exporter = yield* Exporter.make({
56
- label: "OtlpTracer",
57
- url: options.url,
58
- headers: options.headers,
59
- exportInterval: options.exportInterval ?? Duration.seconds(5),
60
- maxBatchSize: options.maxBatchSize ?? 1000,
61
- body(spans) {
62
- const data: TraceData = {
63
- resourceSpans: [{
64
- resource: otelResource,
65
- scopeSpans: [{
66
- scope,
67
- spans
68
- }]
69
- }]
70
- }
71
- return serialization.traces(data)
72
- },
73
- shutdownTimeout: options.shutdownTimeout ?? Duration.seconds(3)
74
- })
75
-
76
- const exportFn = (span: SpanImpl) => {
77
- exporter.push(makeOtlpSpan(span))
78
- }
79
-
80
- return Tracer.make({
81
- span(name, parent, context, links, startTime, kind) {
82
- return makeSpan({
83
- name,
84
- parent,
85
- context,
86
- status: {
87
- _tag: "Started",
88
- startTime
89
- },
90
- attributes: new Map(),
91
- links,
92
- sampled: true,
93
- kind,
94
- export: exportFn
95
- })
96
- },
97
- context: options.context ?
98
- function(f, fiber) {
99
- if (fiber.currentSpan === undefined) {
100
- return f()
101
- }
102
- return options.context!(f, fiber.currentSpan)
103
- } :
104
- defaultContext
105
- })
106
- })
107
-
108
- /**
109
- * @since 1.0.0
110
- * @category Layers
111
- */
112
- export const layer = (options: {
113
- readonly url: string
114
- readonly resource?: {
115
- readonly serviceName?: string | undefined
116
- readonly serviceVersion?: string | undefined
117
- readonly attributes?: Record<string, unknown>
118
- } | undefined
119
- readonly headers?: Headers.Input | undefined
120
- readonly exportInterval?: Duration.DurationInput | undefined
121
- readonly maxBatchSize?: number | undefined
122
- readonly context?: (<X>(f: () => X, span: Tracer.AnySpan) => X) | undefined
123
- readonly shutdownTimeout?: Duration.DurationInput | undefined
124
- }): Layer.Layer<never, never, HttpClient.HttpClient | OtlpSerialization> =>
125
- Layer.unwrapScoped(Effect.map(make(options), Layer.setTracer))
126
-
127
- // internal
128
-
129
- function defaultContext<X>(f: () => X, _: any): X {
130
- return f()
131
- }
132
-
133
- interface SpanImpl extends Tracer.Span {
134
- readonly export: (span: SpanImpl) => void
135
- readonly attributes: Map<string, unknown>
136
- readonly links: Array<Tracer.SpanLink>
137
- readonly events: Array<[name: string, startTime: bigint, attributes: Record<string, unknown> | undefined]>
138
- status: Tracer.SpanStatus
139
- }
140
-
141
- const SpanProto = {
142
- _tag: "Span",
143
- end(this: SpanImpl, endTime: bigint, exit: Exit.Exit<unknown, unknown>) {
144
- this.status = {
145
- _tag: "Ended",
146
- startTime: this.status.startTime,
147
- endTime,
148
- exit
149
- }
150
- this.export(this)
151
- },
152
- attribute(this: SpanImpl, key: string, value: unknown) {
153
- this.attributes.set(key, value)
154
- },
155
- event(this: SpanImpl, name: string, startTime: bigint, attributes?: Record<string, unknown>) {
156
- this.events.push([name, startTime, attributes])
157
- },
158
- addLinks(this: SpanImpl, links: ReadonlyArray<Tracer.SpanLink>) {
159
- // eslint-disable-next-line no-restricted-syntax
160
- this.links.push(...links)
161
- }
162
- }
163
-
164
- const makeSpan = (options: {
165
- readonly name: string
166
- readonly parent: Option.Option<Tracer.AnySpan>
167
- readonly context: Context.Context<never>
168
- readonly status: Tracer.SpanStatus
169
- readonly attributes: ReadonlyMap<string, unknown>
170
- readonly links: ReadonlyArray<Tracer.SpanLink>
171
- readonly sampled: boolean
172
- readonly kind: Tracer.SpanKind
173
- readonly export: (span: SpanImpl) => void
174
- }): SpanImpl => {
175
- const self = Object.assign(Object.create(SpanProto), options)
176
- if (Option.isSome(self.parent)) {
177
- self.traceId = self.parent.value.traceId
178
- } else {
179
- self.traceId = generateId(32)
180
- }
181
- self.spanId = generateId(16)
182
- self.events = []
183
- return self
184
- }
185
-
186
- const generateId = (len: number): string => {
187
- const chars = "0123456789abcdef"
188
- let result = ""
189
- for (let i = 0; i < len; i++) {
190
- result += chars[Math.floor(Math.random() * chars.length)]
191
- }
192
- return result
193
- }
194
-
195
- const makeOtlpSpan = (self: SpanImpl): OtlpSpan => {
196
- const status = self.status as ExtractTag<Tracer.SpanStatus, "Ended">
197
- const attributes = entriesToAttributes(self.attributes.entries())
198
- const events = self.events.map(([name, startTime, attributes]) => ({
199
- name,
200
- timeUnixNano: String(startTime),
201
- attributes: attributes
202
- ? entriesToAttributes(Object.entries(attributes))
203
- : [],
204
- droppedAttributesCount: 0
205
- }))
206
- let otelStatus: Status
207
-
208
- if (status.exit._tag === "Success") {
209
- otelStatus = constOtelStatusSuccess
210
- } else if (Cause.isInterruptedOnly(status.exit.cause)) {
211
- otelStatus = {
212
- code: StatusCode.Ok,
213
- message: Cause.pretty(status.exit.cause)
214
- }
215
- } else {
216
- const errors = Cause.prettyErrors(status.exit.cause)
217
- const firstError = errors[0]
218
- otelStatus = {
219
- code: StatusCode.Error
220
- }
221
- attributes.push({
222
- key: "span.label",
223
- value: { stringValue: "⚠︎ Interrupted" }
224
- }, {
225
- key: "status.interrupted",
226
- value: { boolValue: true }
227
- })
228
- if (firstError) {
229
- otelStatus.message = firstError.message
230
- events.push({
231
- name: "exception",
232
- timeUnixNano: String(status.endTime),
233
- droppedAttributesCount: 0,
234
- attributes: [
235
- {
236
- "key": ATTR_EXCEPTION_TYPE,
237
- "value": {
238
- "stringValue": firstError.name
239
- }
240
- },
241
- {
242
- "key": ATTR_EXCEPTION_MESSAGE,
243
- "value": {
244
- "stringValue": firstError.message
245
- }
246
- },
247
- {
248
- "key": ATTR_EXCEPTION_STACKTRACE,
249
- "value": {
250
- "stringValue": Cause.pretty(status.exit.cause, { renderErrorCause: true })
251
- }
252
- }
253
- ]
254
- })
255
- }
256
- }
257
-
258
- return {
259
- traceId: self.traceId,
260
- spanId: self.spanId,
261
- parentSpanId: Option.isSome(self.parent) ? self.parent.value.spanId : undefined,
262
- name: self.name,
263
- kind: SpanKind[self.kind],
264
- startTimeUnixNano: String(status.startTime),
265
- endTimeUnixNano: String(status.endTime),
266
- attributes,
267
- droppedAttributesCount: 0,
268
- events,
269
- droppedEventsCount: 0,
270
- status: otelStatus,
271
- links: self.links.map((link) => ({
272
- traceId: link.span.traceId,
273
- spanId: link.span.spanId,
274
- attributes: entriesToAttributes(Object.entries(link.attributes)),
275
- droppedAttributesCount: 0
276
- })),
277
- droppedLinksCount: 0
278
- }
279
- }
280
-
281
- interface TraceData {
282
- readonly resourceSpans: Array<ResourceSpan>
283
- }
284
-
285
- interface ResourceSpan {
286
- readonly resource: Resource
287
- readonly scopeSpans: Array<ScopeSpan>
288
- }
289
-
290
- interface ScopeSpan {
291
- readonly scope: Scope
292
- readonly spans: Array<OtlpSpan>
293
- }
294
-
295
- interface Scope {
296
- readonly name: string
297
- }
298
-
299
- interface OtlpSpan {
300
- readonly traceId: string
301
- readonly spanId: string
302
- readonly parentSpanId: string | undefined
303
- readonly name: string
304
- readonly kind: number
305
- readonly startTimeUnixNano: string
306
- readonly endTimeUnixNano: string
307
- readonly attributes: Array<KeyValue>
308
- readonly droppedAttributesCount: number
309
- readonly events: Array<Event>
310
- readonly droppedEventsCount: number
311
- readonly status: Status
312
- readonly links: Array<Link>
313
- readonly droppedLinksCount: number
314
- }
315
-
316
- interface Event {
317
- readonly attributes: Array<KeyValue>
318
- readonly name: string
319
- readonly timeUnixNano: string
320
- readonly droppedAttributesCount: number
321
- }
322
-
323
- interface Link {
324
- readonly attributes: Array<KeyValue>
325
- readonly spanId: string
326
- readonly traceId: string
327
- readonly droppedAttributesCount: number
328
- }
329
-
330
- interface Status {
331
- readonly code: StatusCode
332
- message?: string
333
- }
334
-
335
- const enum StatusCode {
336
- Unset = 0,
337
- Ok = 1,
338
- Error = 2
339
- }
340
-
341
- enum SpanKind {
342
- unspecified = 0,
343
- internal = 1,
344
- server = 2,
345
- client = 3,
346
- producer = 4,
347
- consumer = 5
348
- }
349
-
350
- const constOtelStatusSuccess: Status = {
351
- code: StatusCode.Ok
352
- }