@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.
- package/LICENSE +1 -1
- package/dist/{dts/Logger.d.ts → Logger.d.ts} +19 -13
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +76 -0
- package/dist/Logger.js.map +1 -0
- package/dist/Metrics.d.ts +76 -0
- package/dist/Metrics.d.ts.map +1 -0
- package/dist/Metrics.js +59 -0
- package/dist/Metrics.js.map +1 -0
- package/dist/{dts/NodeSdk.d.ts → NodeSdk.d.ts} +12 -9
- package/dist/NodeSdk.d.ts.map +1 -0
- package/dist/{esm/NodeSdk.js → NodeSdk.js} +23 -14
- package/dist/NodeSdk.js.map +1 -0
- package/dist/{dts/Resource.d.ts → Resource.d.ts} +10 -13
- package/dist/Resource.d.ts.map +1 -0
- package/dist/{esm/Resource.js → Resource.js} +12 -13
- package/dist/Resource.js.map +1 -0
- package/dist/Tracer.d.ts +129 -0
- package/dist/Tracer.d.ts.map +1 -0
- package/dist/Tracer.js +391 -0
- package/dist/Tracer.js.map +1 -0
- package/dist/{dts/WebSdk.d.ts → WebSdk.d.ts} +12 -9
- package/dist/WebSdk.d.ts.map +1 -0
- package/dist/WebSdk.js +41 -0
- package/dist/WebSdk.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/attributes.d.ts +2 -0
- package/dist/internal/attributes.d.ts.map +1 -0
- package/dist/internal/attributes.js +19 -0
- package/dist/internal/attributes.js.map +1 -0
- package/dist/{dts/internal → internal}/metrics.d.ts.map +1 -1
- package/dist/internal/metrics.js +406 -0
- package/dist/internal/metrics.js.map +1 -0
- package/dist/internal/utilities.d.ts +2 -0
- package/dist/internal/utilities.d.ts.map +1 -0
- package/dist/internal/utilities.js +3 -0
- package/dist/internal/utilities.js.map +1 -0
- package/package.json +86 -119
- package/src/Logger.ts +52 -55
- package/src/Metrics.ts +92 -18
- package/src/NodeSdk.ts +67 -64
- package/src/Resource.ts +16 -24
- package/src/Tracer.ts +469 -78
- package/src/WebSdk.ts +59 -51
- package/src/index.ts +7 -36
- package/src/internal/attributes.ts +21 -0
- package/src/internal/metrics.ts +381 -250
- package/src/internal/utilities.ts +5 -0
- package/Logger/package.json +0 -6
- package/Metrics/package.json +0 -6
- package/NodeSdk/package.json +0 -6
- package/Otlp/package.json +0 -6
- package/OtlpLogger/package.json +0 -6
- package/OtlpMetrics/package.json +0 -6
- package/OtlpResource/package.json +0 -6
- package/OtlpSerialization/package.json +0 -6
- package/OtlpTracer/package.json +0 -6
- package/Resource/package.json +0 -6
- package/Tracer/package.json +0 -6
- package/WebSdk/package.json +0 -6
- package/dist/cjs/Logger.js +0 -85
- package/dist/cjs/Logger.js.map +0 -1
- package/dist/cjs/Metrics.js +0 -24
- package/dist/cjs/Metrics.js.map +0 -1
- package/dist/cjs/NodeSdk.js +0 -53
- package/dist/cjs/NodeSdk.js.map +0 -1
- package/dist/cjs/Otlp.js +0 -64
- package/dist/cjs/Otlp.js.map +0 -1
- package/dist/cjs/OtlpLogger.js +0 -163
- package/dist/cjs/OtlpLogger.js.map +0 -1
- package/dist/cjs/OtlpMetrics.js +0 -357
- package/dist/cjs/OtlpMetrics.js.map +0 -1
- package/dist/cjs/OtlpResource.js +0 -136
- package/dist/cjs/OtlpResource.js.map +0 -1
- package/dist/cjs/OtlpSerialization.js +0 -55
- package/dist/cjs/OtlpSerialization.js.map +0 -1
- package/dist/cjs/OtlpTracer.js +0 -231
- package/dist/cjs/OtlpTracer.js.map +0 -1
- package/dist/cjs/Resource.js +0 -75
- package/dist/cjs/Resource.js.map +0 -1
- package/dist/cjs/Tracer.js +0 -87
- package/dist/cjs/Tracer.js.map +0 -1
- package/dist/cjs/WebSdk.js +0 -42
- package/dist/cjs/WebSdk.js.map +0 -1
- package/dist/cjs/index.js +0 -32
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/internal/metrics.js +0 -288
- package/dist/cjs/internal/metrics.js.map +0 -1
- package/dist/cjs/internal/otlpExporter.js +0 -83
- package/dist/cjs/internal/otlpExporter.js.map +0 -1
- package/dist/cjs/internal/otlpProtobuf.js +0 -430
- package/dist/cjs/internal/otlpProtobuf.js.map +0 -1
- package/dist/cjs/internal/protobuf.js +0 -183
- package/dist/cjs/internal/protobuf.js.map +0 -1
- package/dist/cjs/internal/tracer.js +0 -306
- package/dist/cjs/internal/tracer.js.map +0 -1
- package/dist/cjs/internal/utils.js +0 -34
- package/dist/cjs/internal/utils.js.map +0 -1
- package/dist/dts/Logger.d.ts.map +0 -1
- package/dist/dts/Metrics.d.ts +0 -29
- package/dist/dts/Metrics.d.ts.map +0 -1
- package/dist/dts/NodeSdk.d.ts.map +0 -1
- package/dist/dts/Otlp.d.ts +0 -80
- package/dist/dts/Otlp.d.ts.map +0 -1
- package/dist/dts/OtlpLogger.d.ts +0 -47
- package/dist/dts/OtlpLogger.d.ts.map +0 -1
- package/dist/dts/OtlpMetrics.d.ts +0 -41
- package/dist/dts/OtlpMetrics.d.ts.map +0 -1
- package/dist/dts/OtlpResource.d.ts +0 -104
- package/dist/dts/OtlpResource.d.ts.map +0 -1
- package/dist/dts/OtlpSerialization.d.ts +0 -53
- package/dist/dts/OtlpSerialization.d.ts.map +0 -1
- package/dist/dts/OtlpTracer.d.ts +0 -50
- package/dist/dts/OtlpTracer.d.ts.map +0 -1
- package/dist/dts/Resource.d.ts.map +0 -1
- package/dist/dts/Tracer.d.ts +0 -143
- package/dist/dts/Tracer.d.ts.map +0 -1
- package/dist/dts/WebSdk.d.ts.map +0 -1
- package/dist/dts/index.d.ts +0 -54
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/dts/internal/otlpExporter.d.ts +0 -2
- package/dist/dts/internal/otlpExporter.d.ts.map +0 -1
- package/dist/dts/internal/otlpProtobuf.d.ts +0 -501
- package/dist/dts/internal/otlpProtobuf.d.ts.map +0 -1
- package/dist/dts/internal/protobuf.d.ts +0 -100
- package/dist/dts/internal/protobuf.d.ts.map +0 -1
- package/dist/dts/internal/tracer.d.ts +0 -2
- package/dist/dts/internal/tracer.d.ts.map +0 -1
- package/dist/dts/internal/utils.d.ts +0 -2
- package/dist/dts/internal/utils.d.ts.map +0 -1
- package/dist/esm/Logger.js +0 -75
- package/dist/esm/Logger.js.map +0 -1
- package/dist/esm/Metrics.js +0 -17
- package/dist/esm/Metrics.js.map +0 -1
- package/dist/esm/NodeSdk.js.map +0 -1
- package/dist/esm/Otlp.js +0 -56
- package/dist/esm/Otlp.js.map +0 -1
- package/dist/esm/OtlpLogger.js +0 -155
- package/dist/esm/OtlpLogger.js.map +0 -1
- package/dist/esm/OtlpMetrics.js +0 -349
- package/dist/esm/OtlpMetrics.js.map +0 -1
- package/dist/esm/OtlpResource.js +0 -124
- package/dist/esm/OtlpResource.js.map +0 -1
- package/dist/esm/OtlpSerialization.js +0 -46
- package/dist/esm/OtlpSerialization.js.map +0 -1
- package/dist/esm/OtlpTracer.js +0 -223
- package/dist/esm/OtlpTracer.js.map +0 -1
- package/dist/esm/Resource.js.map +0 -1
- package/dist/esm/Tracer.js +0 -80
- package/dist/esm/Tracer.js.map +0 -1
- package/dist/esm/WebSdk.js +0 -33
- package/dist/esm/WebSdk.js.map +0 -1
- package/dist/esm/index.js +0 -54
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/internal/metrics.js +0 -278
- package/dist/esm/internal/metrics.js.map +0 -1
- package/dist/esm/internal/otlpExporter.js +0 -76
- package/dist/esm/internal/otlpExporter.js.map +0 -1
- package/dist/esm/internal/otlpProtobuf.js +0 -396
- package/dist/esm/internal/otlpProtobuf.js.map +0 -1
- package/dist/esm/internal/protobuf.js +0 -155
- package/dist/esm/internal/protobuf.js.map +0 -1
- package/dist/esm/internal/tracer.js +0 -297
- package/dist/esm/internal/tracer.js.map +0 -1
- package/dist/esm/internal/utils.js +0 -23
- package/dist/esm/internal/utils.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/index/package.json +0 -6
- package/src/Otlp.ts +0 -118
- package/src/OtlpLogger.ts +0 -263
- package/src/OtlpMetrics.ts +0 -575
- package/src/OtlpResource.ts +0 -232
- package/src/OtlpSerialization.ts +0 -64
- package/src/OtlpTracer.ts +0 -352
- package/src/internal/otlpExporter.ts +0 -126
- package/src/internal/otlpProtobuf.ts +0 -729
- package/src/internal/protobuf.ts +0 -219
- package/src/internal/tracer.ts +0 -448
- package/src/internal/utils.ts +0 -31
- /package/dist/{dts/internal → internal}/metrics.d.ts +0 -0
package/src/internal/protobuf.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Low-level protobuf wire format encoding utilities.
|
|
3
|
-
*
|
|
4
|
-
* Protobuf wire types:
|
|
5
|
-
* - 0: Varint (int32, int64, uint32, uint64, sint32, sint64, bool, enum)
|
|
6
|
-
* - 1: 64-bit (fixed64, sfixed64, double)
|
|
7
|
-
* - 2: Length-delimited (string, bytes, embedded messages, packed repeated fields)
|
|
8
|
-
* - 5: 32-bit (fixed32, sfixed32, float)
|
|
9
|
-
*
|
|
10
|
-
* @internal
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const enum WireType {
|
|
14
|
-
Varint = 0,
|
|
15
|
-
Fixed64 = 1,
|
|
16
|
-
LengthDelimited = 2,
|
|
17
|
-
Fixed32 = 5
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Encodes a field tag (field number + wire type)
|
|
22
|
-
*/
|
|
23
|
-
const encodeTag = (fieldNumber: number, wireType: WireType): number => (fieldNumber << 3) | wireType
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Encodes a varint (variable-length integer)
|
|
27
|
-
*/
|
|
28
|
-
export const encodeVarint = (value: number | bigint): Uint8Array => {
|
|
29
|
-
const bytes: Array<number> = []
|
|
30
|
-
let n = typeof value === "bigint" ? value : BigInt(value)
|
|
31
|
-
while (n > 0x7fn) {
|
|
32
|
-
bytes.push(Number(n & 0x7fn) | 0x80)
|
|
33
|
-
n >>= 7n
|
|
34
|
-
}
|
|
35
|
-
bytes.push(Number(n))
|
|
36
|
-
return new Uint8Array(bytes)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Encodes a signed varint using ZigZag encoding
|
|
41
|
-
*/
|
|
42
|
-
export const encodeSint = (value: number | bigint): Uint8Array => {
|
|
43
|
-
const n = typeof value === "bigint" ? value : BigInt(value)
|
|
44
|
-
const zigzag = (n << 1n) ^ (n >> 63n)
|
|
45
|
-
return encodeVarint(zigzag)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Encodes a 64-bit fixed value (little-endian)
|
|
50
|
-
*/
|
|
51
|
-
export const encodeFixed64 = (value: bigint): Uint8Array => {
|
|
52
|
-
const bytes = new Uint8Array(8)
|
|
53
|
-
const view = new DataView(bytes.buffer)
|
|
54
|
-
view.setBigUint64(0, value, true)
|
|
55
|
-
return bytes
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Encodes a 32-bit fixed value (little-endian)
|
|
60
|
-
*/
|
|
61
|
-
export const encodeFixed32 = (value: number): Uint8Array => {
|
|
62
|
-
const bytes = new Uint8Array(4)
|
|
63
|
-
const view = new DataView(bytes.buffer)
|
|
64
|
-
view.setUint32(0, value, true)
|
|
65
|
-
return bytes
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Encodes a double (64-bit float, little-endian)
|
|
70
|
-
*/
|
|
71
|
-
export const encodeDouble = (value: number): Uint8Array => {
|
|
72
|
-
const bytes = new Uint8Array(8)
|
|
73
|
-
const view = new DataView(bytes.buffer)
|
|
74
|
-
view.setFloat64(0, value, true)
|
|
75
|
-
return bytes
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Encodes a string to UTF-8 bytes
|
|
80
|
-
*/
|
|
81
|
-
export const encodeString = (value: string): Uint8Array => new TextEncoder().encode(value)
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Encodes bytes as a hex string to Uint8Array
|
|
85
|
-
*/
|
|
86
|
-
export const encodeHexBytes = (hex: string): Uint8Array => {
|
|
87
|
-
const bytes = new Uint8Array(hex.length / 2)
|
|
88
|
-
for (let i = 0; i < hex.length; i += 2) {
|
|
89
|
-
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16)
|
|
90
|
-
}
|
|
91
|
-
return bytes
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Concatenates multiple Uint8Arrays
|
|
96
|
-
*/
|
|
97
|
-
export const concat = (...arrays: Array<Uint8Array>): Uint8Array => {
|
|
98
|
-
const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0)
|
|
99
|
-
const result = new Uint8Array(totalLength)
|
|
100
|
-
let offset = 0
|
|
101
|
-
for (const arr of arrays) {
|
|
102
|
-
result.set(arr, offset)
|
|
103
|
-
offset += arr.length
|
|
104
|
-
}
|
|
105
|
-
return result
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Field encoders
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Encodes a varint field
|
|
112
|
-
*/
|
|
113
|
-
export const varintField = (fieldNumber: number, value: number | bigint): Uint8Array =>
|
|
114
|
-
concat(
|
|
115
|
-
encodeVarint(encodeTag(fieldNumber, WireType.Varint)),
|
|
116
|
-
encodeVarint(value)
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Encodes a sint field (ZigZag encoded)
|
|
121
|
-
*/
|
|
122
|
-
export const sintField = (fieldNumber: number, value: number | bigint): Uint8Array =>
|
|
123
|
-
concat(
|
|
124
|
-
encodeVarint(encodeTag(fieldNumber, WireType.Varint)),
|
|
125
|
-
encodeSint(value)
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Encodes a bool field
|
|
130
|
-
*/
|
|
131
|
-
export const boolField = (fieldNumber: number, value: boolean): Uint8Array => varintField(fieldNumber, value ? 1 : 0)
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Encodes a fixed64 field
|
|
135
|
-
*/
|
|
136
|
-
export const fixed64Field = (fieldNumber: number, value: bigint): Uint8Array =>
|
|
137
|
-
concat(
|
|
138
|
-
encodeVarint(encodeTag(fieldNumber, WireType.Fixed64)),
|
|
139
|
-
encodeFixed64(value)
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Encodes a fixed32 field
|
|
144
|
-
*/
|
|
145
|
-
export const fixed32Field = (fieldNumber: number, value: number): Uint8Array =>
|
|
146
|
-
concat(
|
|
147
|
-
encodeVarint(encodeTag(fieldNumber, WireType.Fixed32)),
|
|
148
|
-
encodeFixed32(value)
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Encodes a double field
|
|
153
|
-
*/
|
|
154
|
-
export const doubleField = (fieldNumber: number, value: number): Uint8Array =>
|
|
155
|
-
concat(
|
|
156
|
-
encodeVarint(encodeTag(fieldNumber, WireType.Fixed64)),
|
|
157
|
-
encodeDouble(value)
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Encodes a length-delimited field (bytes, string, embedded message)
|
|
162
|
-
*/
|
|
163
|
-
export const lengthDelimitedField = (fieldNumber: number, value: Uint8Array): Uint8Array =>
|
|
164
|
-
concat(
|
|
165
|
-
encodeVarint(encodeTag(fieldNumber, WireType.LengthDelimited)),
|
|
166
|
-
encodeVarint(value.length),
|
|
167
|
-
value
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Encodes a string field
|
|
172
|
-
*/
|
|
173
|
-
export const stringField = (fieldNumber: number, value: string): Uint8Array =>
|
|
174
|
-
lengthDelimitedField(fieldNumber, encodeString(value))
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Encodes a bytes field from hex string
|
|
178
|
-
*/
|
|
179
|
-
export const bytesFieldFromHex = (fieldNumber: number, hex: string): Uint8Array =>
|
|
180
|
-
lengthDelimitedField(fieldNumber, encodeHexBytes(hex))
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Encodes an embedded message field
|
|
184
|
-
*/
|
|
185
|
-
export const messageField = (fieldNumber: number, message: Uint8Array): Uint8Array =>
|
|
186
|
-
lengthDelimitedField(fieldNumber, message)
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Encodes repeated fields
|
|
190
|
-
*/
|
|
191
|
-
export const repeatedField = <T>(
|
|
192
|
-
fieldNumber: number,
|
|
193
|
-
values: ReadonlyArray<T>,
|
|
194
|
-
encode: (value: T) => Uint8Array
|
|
195
|
-
): Uint8Array => concat(...values.map((v) => messageField(fieldNumber, encode(v))))
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Encodes repeated varint fields (not packed)
|
|
199
|
-
*/
|
|
200
|
-
export const repeatedVarintField = (
|
|
201
|
-
fieldNumber: number,
|
|
202
|
-
values: ReadonlyArray<number | bigint>
|
|
203
|
-
): Uint8Array => concat(...values.map((v) => varintField(fieldNumber, v)))
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Helper to conditionally encode an optional field
|
|
207
|
-
*/
|
|
208
|
-
export const optionalField = <T>(
|
|
209
|
-
value: T | undefined,
|
|
210
|
-
encode: (v: T) => Uint8Array
|
|
211
|
-
): Uint8Array => value !== undefined ? encode(value) : new Uint8Array(0)
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Helper to conditionally encode a string field if non-empty
|
|
215
|
-
*/
|
|
216
|
-
export const optionalStringField = (
|
|
217
|
-
fieldNumber: number,
|
|
218
|
-
value: string | undefined
|
|
219
|
-
): Uint8Array => value !== undefined && value !== "" ? stringField(fieldNumber, value) : new Uint8Array(0)
|
package/src/internal/tracer.ts
DELETED
|
@@ -1,448 +0,0 @@
|
|
|
1
|
-
import * as OtelApi from "@opentelemetry/api"
|
|
2
|
-
import * as OtelSemConv from "@opentelemetry/semantic-conventions"
|
|
3
|
-
import * as Cause from "effect/Cause"
|
|
4
|
-
import type * as Clock from "effect/Clock"
|
|
5
|
-
import * as Context from "effect/Context"
|
|
6
|
-
import * as Effect from "effect/Effect"
|
|
7
|
-
import * as Exit from "effect/Exit"
|
|
8
|
-
import { constTrue, dual } from "effect/Function"
|
|
9
|
-
import * as Layer from "effect/Layer"
|
|
10
|
-
import * as Option from "effect/Option"
|
|
11
|
-
import * as EffectTracer from "effect/Tracer"
|
|
12
|
-
import { Resource } from "../Resource.js"
|
|
13
|
-
import type { OtelTraceFlags, OtelTracer, OtelTracerProvider, OtelTraceState } from "../Tracer.js"
|
|
14
|
-
import { nanosToHrTime, recordToAttributes, unknownToAttributeValue } from "./utils.js"
|
|
15
|
-
|
|
16
|
-
const OtelSpanTypeId = Symbol.for("@effect/opentelemetry/Tracer/OtelSpan")
|
|
17
|
-
|
|
18
|
-
const kindMap = {
|
|
19
|
-
"internal": OtelApi.SpanKind.INTERNAL,
|
|
20
|
-
"client": OtelApi.SpanKind.CLIENT,
|
|
21
|
-
"server": OtelApi.SpanKind.SERVER,
|
|
22
|
-
"producer": OtelApi.SpanKind.PRODUCER,
|
|
23
|
-
"consumer": OtelApi.SpanKind.CONSUMER
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const getOtelParent = (tracer: OtelApi.TraceAPI, otelContext: OtelApi.Context, context: Context.Context<never>) => {
|
|
27
|
-
const active = tracer.getSpan(otelContext)
|
|
28
|
-
const otelParent = active ? active.spanContext() : undefined
|
|
29
|
-
return otelParent
|
|
30
|
-
? Option.some(
|
|
31
|
-
EffectTracer.externalSpan({
|
|
32
|
-
spanId: otelParent.spanId,
|
|
33
|
-
traceId: otelParent.traceId,
|
|
34
|
-
sampled: (otelParent.traceFlags & 1) === 1,
|
|
35
|
-
context
|
|
36
|
-
})
|
|
37
|
-
)
|
|
38
|
-
: Option.none()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** @internal */
|
|
42
|
-
export class OtelSpan implements EffectTracer.Span {
|
|
43
|
-
readonly [OtelSpanTypeId]: typeof OtelSpanTypeId
|
|
44
|
-
readonly _tag = "Span"
|
|
45
|
-
|
|
46
|
-
readonly span: OtelApi.Span
|
|
47
|
-
readonly spanId: string
|
|
48
|
-
readonly traceId: string
|
|
49
|
-
readonly attributes = new Map<string, unknown>()
|
|
50
|
-
readonly sampled: boolean
|
|
51
|
-
readonly parent: Option.Option<EffectTracer.AnySpan>
|
|
52
|
-
status: EffectTracer.SpanStatus
|
|
53
|
-
|
|
54
|
-
constructor(
|
|
55
|
-
contextApi: OtelApi.ContextAPI,
|
|
56
|
-
traceApi: OtelApi.TraceAPI,
|
|
57
|
-
tracer: OtelApi.Tracer,
|
|
58
|
-
readonly name: string,
|
|
59
|
-
effectParent: Option.Option<EffectTracer.AnySpan>,
|
|
60
|
-
readonly context: Context.Context<never>,
|
|
61
|
-
readonly links: Array<EffectTracer.SpanLink>,
|
|
62
|
-
startTime: bigint,
|
|
63
|
-
readonly kind: EffectTracer.SpanKind,
|
|
64
|
-
options?: EffectTracer.SpanOptions
|
|
65
|
-
) {
|
|
66
|
-
this[OtelSpanTypeId] = OtelSpanTypeId
|
|
67
|
-
const active = contextApi.active()
|
|
68
|
-
this.parent = effectParent._tag === "Some"
|
|
69
|
-
? effectParent
|
|
70
|
-
: (options?.root !== true)
|
|
71
|
-
? getOtelParent(traceApi, active, context)
|
|
72
|
-
: Option.none()
|
|
73
|
-
this.span = tracer.startSpan(
|
|
74
|
-
name,
|
|
75
|
-
{
|
|
76
|
-
startTime: nanosToHrTime(startTime),
|
|
77
|
-
links: links.length > 0
|
|
78
|
-
? links.map((link) => ({
|
|
79
|
-
context: makeSpanContext(link.span),
|
|
80
|
-
attributes: recordToAttributes(link.attributes)
|
|
81
|
-
}))
|
|
82
|
-
: undefined as any,
|
|
83
|
-
kind: kindMap[this.kind]
|
|
84
|
-
},
|
|
85
|
-
this.parent._tag === "Some"
|
|
86
|
-
? populateContext(active, this.parent.value, context)
|
|
87
|
-
: OtelApi.trace.deleteSpan(active)
|
|
88
|
-
)
|
|
89
|
-
const spanContext = this.span.spanContext()
|
|
90
|
-
this.spanId = spanContext.spanId
|
|
91
|
-
this.traceId = spanContext.traceId
|
|
92
|
-
this.status = {
|
|
93
|
-
_tag: "Started",
|
|
94
|
-
startTime
|
|
95
|
-
}
|
|
96
|
-
this.sampled = (spanContext.traceFlags & OtelApi.TraceFlags.SAMPLED) === OtelApi.TraceFlags.SAMPLED
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
attribute(key: string, value: unknown) {
|
|
100
|
-
this.span.setAttribute(key, unknownToAttributeValue(value))
|
|
101
|
-
this.attributes.set(key, value)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
addLinks(links: ReadonlyArray<EffectTracer.SpanLink>): void {
|
|
105
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
106
|
-
this.links.push(...links)
|
|
107
|
-
this.span.addLinks(links.map((link) => ({
|
|
108
|
-
context: makeSpanContext(link.span),
|
|
109
|
-
attributes: recordToAttributes(link.attributes)
|
|
110
|
-
})))
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
end(endTime: bigint, exit: Exit.Exit<unknown, unknown>) {
|
|
114
|
-
const hrTime = nanosToHrTime(endTime)
|
|
115
|
-
this.status = {
|
|
116
|
-
_tag: "Ended",
|
|
117
|
-
endTime,
|
|
118
|
-
exit,
|
|
119
|
-
startTime: this.status.startTime
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (exit._tag === "Success") {
|
|
123
|
-
this.span.setStatus({ code: OtelApi.SpanStatusCode.OK })
|
|
124
|
-
} else {
|
|
125
|
-
if (Cause.isInterruptedOnly(exit.cause)) {
|
|
126
|
-
this.span.setStatus({
|
|
127
|
-
code: OtelApi.SpanStatusCode.OK,
|
|
128
|
-
message: Cause.pretty(exit.cause)
|
|
129
|
-
})
|
|
130
|
-
this.span.setAttribute("span.label", "⚠︎ Interrupted")
|
|
131
|
-
this.span.setAttribute("status.interrupted", true)
|
|
132
|
-
} else {
|
|
133
|
-
const firstError = Cause.prettyErrors(exit.cause)[0]
|
|
134
|
-
if (firstError) {
|
|
135
|
-
firstError.stack = Cause.pretty(exit.cause, { renderErrorCause: true })
|
|
136
|
-
this.span.recordException(firstError, hrTime)
|
|
137
|
-
this.span.setStatus({
|
|
138
|
-
code: OtelApi.SpanStatusCode.ERROR,
|
|
139
|
-
message: firstError.message
|
|
140
|
-
})
|
|
141
|
-
} else {
|
|
142
|
-
// empty cause means no error
|
|
143
|
-
this.span.setStatus({ code: OtelApi.SpanStatusCode.OK })
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
this.span.end(hrTime)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
event(name: string, startTime: bigint, attributes?: Record<string, unknown>) {
|
|
151
|
-
this.span.addEvent(
|
|
152
|
-
name,
|
|
153
|
-
attributes ? recordToAttributes(attributes) : undefined,
|
|
154
|
-
nanosToHrTime(startTime)
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/** @internal */
|
|
160
|
-
export const TracerProvider = Context.GenericTag<OtelTracerProvider, OtelApi.TracerProvider>(
|
|
161
|
-
"@effect/opentelemetry/Tracer/OtelTracerProvider"
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
/** @internal */
|
|
165
|
-
export const Tracer = Context.GenericTag<OtelTracer, OtelApi.Tracer>("@effect/opentelemetry/Tracer/OtelTracer")
|
|
166
|
-
|
|
167
|
-
/** @internal */
|
|
168
|
-
export const make = Effect.map(Tracer, (tracer) =>
|
|
169
|
-
EffectTracer.make({
|
|
170
|
-
span(name, parent, context, links, startTime, kind, options) {
|
|
171
|
-
return new OtelSpan(
|
|
172
|
-
OtelApi.context,
|
|
173
|
-
OtelApi.trace,
|
|
174
|
-
tracer,
|
|
175
|
-
name,
|
|
176
|
-
parent,
|
|
177
|
-
context,
|
|
178
|
-
links.slice(),
|
|
179
|
-
startTime,
|
|
180
|
-
kind,
|
|
181
|
-
options
|
|
182
|
-
)
|
|
183
|
-
},
|
|
184
|
-
context(execution, fiber) {
|
|
185
|
-
const currentSpan = fiber.currentSpan
|
|
186
|
-
|
|
187
|
-
if (currentSpan === undefined) {
|
|
188
|
-
return execution()
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return OtelApi.context.with(
|
|
192
|
-
populateContext(OtelApi.context.active(), currentSpan),
|
|
193
|
-
execution
|
|
194
|
-
)
|
|
195
|
-
}
|
|
196
|
-
}))
|
|
197
|
-
|
|
198
|
-
/** @internal */
|
|
199
|
-
export const traceFlagsTag = Context.GenericTag<OtelTraceFlags, OtelApi.TraceFlags>(
|
|
200
|
-
"@effect/opentelemetry/Tracer/OtelTraceFlags"
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
/** @internal */
|
|
204
|
-
export const traceStateTag = Context.GenericTag<OtelTraceState, OtelApi.TraceState>(
|
|
205
|
-
"@effect/opentelemetry/Tracer/OtelTraceState"
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
/** @internal */
|
|
209
|
-
export const makeExternalSpan = (options: {
|
|
210
|
-
readonly traceId: string
|
|
211
|
-
readonly spanId: string
|
|
212
|
-
readonly traceFlags?: number | undefined
|
|
213
|
-
readonly traceState?: string | OtelApi.TraceState | undefined
|
|
214
|
-
}): EffectTracer.ExternalSpan => {
|
|
215
|
-
let context = Context.empty()
|
|
216
|
-
|
|
217
|
-
if (options.traceFlags !== undefined) {
|
|
218
|
-
context = Context.add(context, traceFlagsTag, options.traceFlags)
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
if (typeof options.traceState === "string") {
|
|
222
|
-
context = Option.match(createTraceState(options.traceState), {
|
|
223
|
-
onNone: () => context,
|
|
224
|
-
onSome: (traceState) => Context.add(context, traceStateTag, traceState)
|
|
225
|
-
})
|
|
226
|
-
} else if (options.traceState) {
|
|
227
|
-
context = Context.add(context, traceStateTag, options.traceState)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
_tag: "ExternalSpan",
|
|
232
|
-
traceId: options.traceId,
|
|
233
|
-
spanId: options.spanId,
|
|
234
|
-
sampled: options.traceFlags !== undefined
|
|
235
|
-
? (options.traceFlags & OtelApi.TraceFlags.SAMPLED) === OtelApi.TraceFlags.SAMPLED
|
|
236
|
-
: true,
|
|
237
|
-
context
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const makeOtelSpan = (span: EffectTracer.Span, clock: Clock.Clock): OtelApi.Span => {
|
|
242
|
-
const spanContext: OtelApi.SpanContext = {
|
|
243
|
-
traceId: span.traceId,
|
|
244
|
-
spanId: span.spanId,
|
|
245
|
-
traceFlags: span.sampled ? OtelApi.TraceFlags.SAMPLED : OtelApi.TraceFlags.NONE,
|
|
246
|
-
isRemote: false
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
let exit = Exit.void
|
|
250
|
-
|
|
251
|
-
const self: OtelApi.Span = {
|
|
252
|
-
spanContext: () => spanContext,
|
|
253
|
-
setAttribute(key, value) {
|
|
254
|
-
span.attribute(key, value)
|
|
255
|
-
return self
|
|
256
|
-
},
|
|
257
|
-
setAttributes(attributes) {
|
|
258
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
259
|
-
span.attribute(key, value)
|
|
260
|
-
}
|
|
261
|
-
return self
|
|
262
|
-
},
|
|
263
|
-
addEvent(name) {
|
|
264
|
-
let attributes: OtelApi.Attributes | undefined = undefined
|
|
265
|
-
let startTime: OtelApi.TimeInput | undefined = undefined
|
|
266
|
-
if (arguments.length === 3) {
|
|
267
|
-
attributes = arguments[1]
|
|
268
|
-
startTime = arguments[2]
|
|
269
|
-
} else if (arguments.length === 2) {
|
|
270
|
-
const arg1 = arguments[1]
|
|
271
|
-
if (isTimeInput(arg1)) {
|
|
272
|
-
startTime = arg1
|
|
273
|
-
} else {
|
|
274
|
-
attributes = arg1
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
span.event(name, convertOtelTimeInput(startTime, clock), attributes)
|
|
278
|
-
return self
|
|
279
|
-
},
|
|
280
|
-
addLink(link) {
|
|
281
|
-
span.addLinks([{
|
|
282
|
-
_tag: "SpanLink",
|
|
283
|
-
span: makeExternalSpan(link.context),
|
|
284
|
-
attributes: link.attributes ?? {}
|
|
285
|
-
}])
|
|
286
|
-
return self
|
|
287
|
-
},
|
|
288
|
-
addLinks(links) {
|
|
289
|
-
span.addLinks(links.map((link) => ({
|
|
290
|
-
_tag: "SpanLink",
|
|
291
|
-
span: makeExternalSpan(link.context),
|
|
292
|
-
attributes: link.attributes ?? {}
|
|
293
|
-
})))
|
|
294
|
-
return self
|
|
295
|
-
},
|
|
296
|
-
setStatus(status) {
|
|
297
|
-
exit = OtelApi.SpanStatusCode.ERROR
|
|
298
|
-
? Exit.die(status.message ?? "Unknown error")
|
|
299
|
-
: Exit.void
|
|
300
|
-
return self
|
|
301
|
-
},
|
|
302
|
-
updateName: () => self,
|
|
303
|
-
end(endTime) {
|
|
304
|
-
const time = convertOtelTimeInput(endTime, clock)
|
|
305
|
-
span.end(time, exit)
|
|
306
|
-
return self
|
|
307
|
-
},
|
|
308
|
-
isRecording: constTrue,
|
|
309
|
-
recordException(exception, timeInput) {
|
|
310
|
-
const time = convertOtelTimeInput(timeInput, clock)
|
|
311
|
-
const cause = Cause.fail(exception)
|
|
312
|
-
const error = Cause.prettyErrors(cause)[0]
|
|
313
|
-
span.event(error.message, time, {
|
|
314
|
-
"exception.type": error.name,
|
|
315
|
-
"exception.message": error.message,
|
|
316
|
-
"exception.stacktrace": error.stack ?? ""
|
|
317
|
-
})
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
return self
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const bigint1e6 = BigInt(1_000_000)
|
|
324
|
-
const bigint1e9 = BigInt(1_000_000_000)
|
|
325
|
-
|
|
326
|
-
/** Distinguishes TimeInput (number | Date | [number, number]) from Attributes (plain object) */
|
|
327
|
-
const isTimeInput = (u: unknown): u is OtelApi.TimeInput =>
|
|
328
|
-
typeof u === "number" ||
|
|
329
|
-
u instanceof Date ||
|
|
330
|
-
(Array.isArray(u) && u.length === 2 && typeof u[0] === "number" && typeof u[1] === "number")
|
|
331
|
-
|
|
332
|
-
const convertOtelTimeInput = (input: OtelApi.TimeInput | undefined, clock: Clock.Clock): bigint => {
|
|
333
|
-
if (input === undefined) {
|
|
334
|
-
return clock.unsafeCurrentTimeNanos()
|
|
335
|
-
} else if (typeof input === "number") {
|
|
336
|
-
return BigInt(Math.round(input * 1_000_000))
|
|
337
|
-
} else if (input instanceof Date) {
|
|
338
|
-
return BigInt(input.getTime()) * bigint1e6
|
|
339
|
-
}
|
|
340
|
-
const [seconds, nanos] = input
|
|
341
|
-
return BigInt(seconds) * bigint1e9 + BigInt(nanos)
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/** @internal */
|
|
345
|
-
export const currentOtelSpan: Effect.Effect<OtelApi.Span, Cause.NoSuchElementException> = Effect.clockWith((clock) =>
|
|
346
|
-
Effect.map(Effect.currentSpan, (span): OtelApi.Span => {
|
|
347
|
-
if (OtelSpanTypeId in span) {
|
|
348
|
-
return (span as OtelSpan).span
|
|
349
|
-
}
|
|
350
|
-
return makeOtelSpan(span, clock)
|
|
351
|
-
})
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
/** @internal */
|
|
355
|
-
export const layerGlobalProvider = Layer.sync(
|
|
356
|
-
TracerProvider,
|
|
357
|
-
() => OtelApi.trace.getTracerProvider()
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
/** @internal */
|
|
361
|
-
export const layerTracer = Layer.effect(
|
|
362
|
-
Tracer,
|
|
363
|
-
Effect.flatMap(
|
|
364
|
-
Effect.zip(Resource, TracerProvider),
|
|
365
|
-
([resource, provider]) =>
|
|
366
|
-
Effect.sync(() =>
|
|
367
|
-
provider.getTracer(
|
|
368
|
-
resource.attributes[OtelSemConv.ATTR_SERVICE_NAME] as string,
|
|
369
|
-
resource.attributes[OtelSemConv.ATTR_SERVICE_VERSION] as string
|
|
370
|
-
)
|
|
371
|
-
)
|
|
372
|
-
)
|
|
373
|
-
)
|
|
374
|
-
|
|
375
|
-
/** @internal */
|
|
376
|
-
export const layerGlobalTracer = layerTracer.pipe(
|
|
377
|
-
Layer.provide(layerGlobalProvider)
|
|
378
|
-
)
|
|
379
|
-
|
|
380
|
-
/** @internal */
|
|
381
|
-
export const layerGlobal = Layer.unwrapEffect(Effect.map(make, Layer.setTracer)).pipe(
|
|
382
|
-
Layer.provideMerge(layerGlobalTracer)
|
|
383
|
-
)
|
|
384
|
-
|
|
385
|
-
/** @internal */
|
|
386
|
-
export const layerWithoutOtelTracer = Layer.unwrapEffect(Effect.map(make, Layer.setTracer))
|
|
387
|
-
|
|
388
|
-
/** @internal */
|
|
389
|
-
export const layer = layerWithoutOtelTracer.pipe(
|
|
390
|
-
Layer.provideMerge(layerTracer)
|
|
391
|
-
)
|
|
392
|
-
|
|
393
|
-
// -------------------------------------------------------------------------------------
|
|
394
|
-
// utils
|
|
395
|
-
// -------------------------------------------------------------------------------------
|
|
396
|
-
|
|
397
|
-
const createTraceState = Option.liftThrowable(OtelApi.createTraceState)
|
|
398
|
-
|
|
399
|
-
const populateContext = (
|
|
400
|
-
otelContext: OtelApi.Context,
|
|
401
|
-
span: EffectTracer.AnySpan,
|
|
402
|
-
context?: Context.Context<never>
|
|
403
|
-
): OtelApi.Context =>
|
|
404
|
-
span instanceof OtelSpan ?
|
|
405
|
-
OtelApi.trace.setSpan(otelContext, span.span) :
|
|
406
|
-
OtelApi.trace.setSpanContext(otelContext, makeSpanContext(span, context))
|
|
407
|
-
|
|
408
|
-
const makeSpanContext = (span: EffectTracer.AnySpan, context?: Context.Context<never>): OtelApi.SpanContext => ({
|
|
409
|
-
spanId: span.spanId,
|
|
410
|
-
traceId: span.traceId,
|
|
411
|
-
isRemote: span._tag === "ExternalSpan",
|
|
412
|
-
traceFlags: Option.getOrElse(
|
|
413
|
-
context ?
|
|
414
|
-
extractTraceTag(span, context, traceFlagsTag) :
|
|
415
|
-
Context.getOption(span.context, traceFlagsTag),
|
|
416
|
-
() => OtelApi.TraceFlags.SAMPLED
|
|
417
|
-
),
|
|
418
|
-
traceState: Option.getOrUndefined(
|
|
419
|
-
context ?
|
|
420
|
-
extractTraceTag(span, context, traceStateTag) :
|
|
421
|
-
Context.getOption(span.context, traceStateTag)
|
|
422
|
-
) as OtelApi.TraceState
|
|
423
|
-
})
|
|
424
|
-
|
|
425
|
-
const extractTraceTag = <I, S>(
|
|
426
|
-
parent: EffectTracer.AnySpan,
|
|
427
|
-
context: Context.Context<never>,
|
|
428
|
-
tag: Context.Tag<I, S>
|
|
429
|
-
) =>
|
|
430
|
-
Option.orElse(
|
|
431
|
-
Context.getOption(context, tag),
|
|
432
|
-
() => Context.getOption(parent.context, tag)
|
|
433
|
-
)
|
|
434
|
-
|
|
435
|
-
/** @internal */
|
|
436
|
-
export const withSpanContext = dual<
|
|
437
|
-
(
|
|
438
|
-
spanContext: OtelApi.SpanContext
|
|
439
|
-
) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, EffectTracer.ParentSpan>>,
|
|
440
|
-
<A, E, R>(
|
|
441
|
-
effect: Effect.Effect<A, E, R>,
|
|
442
|
-
spanContext: OtelApi.SpanContext
|
|
443
|
-
) => Effect.Effect<A, E, Exclude<R, EffectTracer.ParentSpan>>
|
|
444
|
-
>(2, <A, E, R>(
|
|
445
|
-
effect: Effect.Effect<A, E, R>,
|
|
446
|
-
spanContext: OtelApi.SpanContext
|
|
447
|
-
): Effect.Effect<A, E, Exclude<R, EffectTracer.ParentSpan>> =>
|
|
448
|
-
Effect.withParentSpan(effect, makeExternalSpan(spanContext)))
|
package/src/internal/utils.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type * as OtelApi from "@opentelemetry/api"
|
|
2
|
-
import type { NonEmptyReadonlyArray } from "effect/Array"
|
|
3
|
-
import * as Inspectable from "effect/Inspectable"
|
|
4
|
-
|
|
5
|
-
const bigint1e9 = 1_000_000_000n
|
|
6
|
-
|
|
7
|
-
/** @internal */
|
|
8
|
-
export const nanosToHrTime = (timestamp: bigint): OtelApi.HrTime => {
|
|
9
|
-
return [Number(timestamp / bigint1e9), Number(timestamp % bigint1e9)]
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** @internal */
|
|
13
|
-
export const recordToAttributes = (value: Record<string, unknown>): OtelApi.Attributes =>
|
|
14
|
-
Object.entries(value).reduce((acc, [key, value]) => {
|
|
15
|
-
acc[key] = unknownToAttributeValue(value)
|
|
16
|
-
return acc
|
|
17
|
-
}, {} as OtelApi.Attributes)
|
|
18
|
-
|
|
19
|
-
/** @internal */
|
|
20
|
-
export const unknownToAttributeValue = (value: unknown): OtelApi.AttributeValue => {
|
|
21
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
22
|
-
return value
|
|
23
|
-
} else if (typeof value === "bigint") {
|
|
24
|
-
return value.toString()
|
|
25
|
-
}
|
|
26
|
-
return Inspectable.toStringUnknown(value)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** @internal */
|
|
30
|
-
export const isNonEmpty = <A>(a: A | ReadonlyArray<A> | undefined): a is A | NonEmptyReadonlyArray<A> =>
|
|
31
|
-
a !== undefined && !(Array.isArray(a) && a.length === 0)
|
|
File without changes
|