@mertdogar/otel-cf-workers 1.0.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 ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2023, Erwin van der Koogh
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,308 @@
1
+ # otel-cf-workers
2
+
3
+ An OpenTelemetry compatible library for instrumenting and exporting traces from Cloudflare Workers.
4
+
5
+ ## Getting started
6
+
7
+ ```bash
8
+ npm install @mertdogar/otel-cf-workers @opentelemetry/api
9
+ ```
10
+
11
+ > [!IMPORTANT]
12
+ > To be able to use the Open Telemetry library you have to add the NodeJS compatibility flag in your `wrangler.toml` file.
13
+
14
+ ```json
15
+ compatibility_flags = [ "nodejs_compat" ]
16
+ ```
17
+
18
+ > [!IMPORTANT]
19
+ > As of version 1.0.0-rc.52, we are no longer providing a CommonJS build. It is already hard enough trying to write a library that deals with all of Cloudflare's functionality over every single combination of compatibility flags and dates. Combining that with two different build is just too much. If you really need CommonJS support, please create a ticket (if there isn't already) and describe your use-case.
20
+
21
+ For a simple setup example with configuration examples, have a look at the [Quickstart Example](https://github.com/evanderkoogh/otel-cf-workers/tree/main/examples/worker)
22
+
23
+ ### Code example
24
+
25
+ ```typescript
26
+ import { trace } from '@opentelemetry/api'
27
+ import { instrument, ResolveConfigFn } from '@mertdogar/otel-cf-workers'
28
+
29
+ export interface Env {
30
+ HONEYCOMB_API_KEY: string
31
+ OTEL_TEST: KVNamespace
32
+ }
33
+
34
+ const handler = {
35
+ async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
36
+ await fetch('https://cloudflare.com')
37
+
38
+ const greeting = "G'day World"
39
+ trace.getActiveSpan()?.setAttribute('greeting', greeting)
40
+ ctx.waitUntil(fetch('https://workers.dev'))
41
+ return new Response(`${greeting}!`)
42
+ },
43
+ }
44
+
45
+ const config: ResolveConfigFn = (env: Env, _trigger) => {
46
+ return {
47
+ exporter: {
48
+ url: 'https://api.honeycomb.io/v1/traces',
49
+ headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
50
+ },
51
+ service: { name: 'greetings' },
52
+ }
53
+ }
54
+
55
+ export default instrument(handler, config)
56
+ ```
57
+
58
+ ## Auto-instrumentation
59
+
60
+ ### Workers
61
+
62
+ Wrapping your exporter handler with the `instrument` function is all you need to do to automatically have not just the functions of you handler auto-instrumented, but also the global `fetch` and `caches` and all of the supported bindings in your environment such as KV.
63
+
64
+ See the quick start code sample for an example of how it works.
65
+
66
+ ### Durable Objects
67
+
68
+ Instrumenting Durable Objects work very similar to the regular Worker auto-instrumentation. Instead of wrapping the handler in an `instrument` call, you wrap the Durable Object class with the `instrumentDO` function.
69
+
70
+ ```typescript
71
+ import { instrumentDO, PartialTraceConfig } from '@mertdogar/otel-cf-workers'
72
+
73
+ const config: ResolveConfigFn = (env: Env, _trigger) => {
74
+ return {
75
+ exporter: {
76
+ url: 'https://api.honeycomb.io/v1/traces',
77
+ headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
78
+ },
79
+ service: { name: 'greetings-do' },
80
+ }
81
+ }
82
+
83
+ class OtelDO implements DurableObject {
84
+ async fetch(request: Request): Promise<Response> {
85
+ return new Response('Hello World!')
86
+ }
87
+ }
88
+
89
+ const TestOtelDO = instrumentDO(OtelDO, doConfig)
90
+
91
+ export { TestOtelDO }
92
+ ```
93
+
94
+ ## Creating custom spans
95
+
96
+ While auto-instrumenting should take care of a lot of the information that you would want to add, there will always be application specific information you want to send along.
97
+
98
+ You can get the current active span by doing:
99
+
100
+ ```typescript
101
+ import {trace} from '@opentelemetry/api'
102
+
103
+ const handler = {
104
+ async fetch(request: Request) {
105
+ const span = trace.getActiveSpan()
106
+ if(span) span.setAttributes('name', 'value')
107
+ ....
108
+ }
109
+ }
110
+ ```
111
+
112
+ Or if you want to create a new span:
113
+
114
+ ```typescript
115
+ import { trace } from '@opentelemetry/api'
116
+
117
+ const handler = {
118
+ async fetch(request: Request) {
119
+ const tracer = trace.getTracer('my_own_tracer_name')
120
+ return tracer.startActiveSpan('name', (span) => {
121
+ const response = await doSomethingAwesome
122
+ span.end()
123
+ return response
124
+ })
125
+ },
126
+ }
127
+ ```
128
+
129
+ ## Configuration
130
+
131
+ For configuration you can either pass in a [TraceConfig](https://github.com/evanderkoogh/otel-cf-workers/blob/0da125a4e16ff13e49f8e486340eb6080e631eb9/src/types.ts#L24C18-L24C29) or a function that takes the Environment and the trigger for this particular trace and returns a `TraceConfig`.
132
+
133
+ Because the configuration function is run separately for every new invocation, it is possible to tailor your configuration for every type of request. So it is for example possible to have a much lower sampling ratio for your healthchecks than actual API requests.
134
+
135
+ ### Exporter
136
+
137
+ In the `exporter`, you need to configure where to send spans to. It can take either an instance of a class that implements the standard Open Telemetry `SpanExporter`interface, or an object with the properties `url` and optionally `headers` to configure an exporter for the Open Telemetry format.
138
+
139
+ Examples:
140
+
141
+ ```typescript
142
+ const exporter = new ConsoleSpanExporter()
143
+ ```
144
+
145
+ ```typescript
146
+ const exporter = {
147
+ url: 'https://api.honeycomb.io/v1/traces',
148
+ headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
149
+ }
150
+ ```
151
+
152
+ ### Fetch
153
+
154
+ `includeTraceContext` is used to specify if outgoing requests should include the TraceContext so that the other service can participate in a distributed trace.
155
+ The default is `true` for all outgoing requests, but you can turn it off for all requests with `false`, or specify a method that takes the outgoing `Request` method and return a boolean on whether to include the tracing context.
156
+
157
+ Example:
158
+
159
+ ```typescript
160
+ const fetchConf = (request: Request): boolean => {
161
+ return new URL(request.url).hostname === 'example.com'
162
+ }
163
+ ```
164
+
165
+ ### Handlers
166
+
167
+ The `handlers` field of the configuration overrides the way in which event handlers, such as `fetch` or `queue`, are instrumented.
168
+
169
+ #### Fetch Handler
170
+
171
+ `acceptTraceContext` is used to specify if incoming requests handled by `fetch` should accept a TraceContext and participate in a distributed trace.
172
+ The default is `true` for all incoming requests, but you can turn it off for all requests with `false` or specify a method that takes the incoming `Request` and returns a boolean indicating whether to accept the tracing context.
173
+
174
+ Example:
175
+
176
+ ```typescript
177
+ const fetchConf = (request: Request): boolean => {
178
+ return new URL(request.url).hostname === 'example.com'
179
+ }
180
+ ```
181
+
182
+ ### PostProcessor
183
+
184
+ The PostProcessor function is called just before exporting the spans and allows you to make any changes to the spans before sending this. For example to remove entire spans, or to remove or redact security or privacy sensitive data.
185
+
186
+ Example:
187
+
188
+ ```typescript
189
+ const postProcessor = (spans: ReadableSpan[]): ReadableSpan[] => {
190
+ spans[0].attributes['http.url'] = 'REDACTED'
191
+ return spans
192
+ }
193
+ ```
194
+
195
+ ### Sampling
196
+
197
+ One of the challenges of tracing is that for sites and applications with a lot of traffic it becomes prohibitively expensive to store every trace. So the question becomes how to store the ones with the most interesting information and drop the ones that are the least interesting. That is where sampling comes in.
198
+
199
+ #### Head Sampling vs Tail Sampling
200
+
201
+ There are two (complimentary) sampling strategies: Head Sampling and Tail Sampling and in a lot of cases you will want to use a combination to get the most information into the least amount of sampled events.
202
+
203
+ To understand the difference in head vs tail sampling in our context, we have to understand distributed tracing. A distributed trace is one that spans multiple systems or services. At every point another service is called, we inject a header with the information about the trace, such as the traceId, the parentSpanId and a hint if this trace is sampled.
204
+
205
+ Head Sampling, as the name implies, is done at the beginning of a span/trace. In our case it is mostly used to signal to downstream systems whether or not to sample a particular trace, because we can always drop the current services portion of a trace during Tail Sampling.
206
+
207
+ Head Sampling can be configured with any standard Open Telemetry `Sampler` or an object with a `ratio` property and optional `acceptRemote` property. The default is the AlwaysOnSampler, which samples every single request.
208
+
209
+ Examples:
210
+
211
+ ```typescript
212
+ const headSampler = new AlwaysOnSampler()
213
+ ```
214
+
215
+ ```typescript
216
+ const headSampler = {
217
+ acceptRemote: false //Whether to accept incoming trace contexts
218
+ ratio: 0.5 //number between 0 and 1 that represents the ratio of requests to sample. 0 is none and 1 is all requests.
219
+ }
220
+ ```
221
+
222
+ Tail Sampling on the other hand is done at the end. Because we record every single span, even if it isn't head sampled, it is possible to still sample the local part of a trace in say the event of an error.
223
+
224
+ Example:
225
+
226
+ ```typescript
227
+ const tailSampler = (traceInfo: LocalTrace): boolean => {
228
+ const localRootSpan = traceInfo.localRootSpan as unknown as ReadableSpan
229
+ return (localRootSpan.spanContext().traceFlags & TraceFlags.SAMPLED) === TraceFlags.SAMPLED
230
+ }
231
+ ```
232
+
233
+ The default is a tailSampler that samples traces that have been head sampled or if the local root span is marked as an error.
234
+
235
+ #### Service
236
+
237
+ Service identifies the service and version to help with querying.
238
+
239
+ Example:
240
+
241
+ ```typescript
242
+ const service = {
243
+ name: 'some_name' //required. The name of your service
244
+ version: '1.0.4' //optional: An opaque version string. Can be a semver or git hash for example
245
+ namespace: 'namespace' //optional: Useful to group multiple services together in one namespace.
246
+ }
247
+ ```
248
+
249
+ ### Propagation
250
+
251
+ Register a custom propagator with:
252
+
253
+ ```ts
254
+ const config: ResolveConfigFn = (env: Env, _trigger) => {
255
+ return {
256
+ propagator: new MyCoolPropagator(),
257
+ }
258
+ }
259
+ ```
260
+
261
+ ## Distributed Tracing
262
+
263
+ One of the advantages of using Open Telemetry is that it makes it easier to do distributed tracing through multiple different services. This library will automatically inject the W3C Trace Context headers when making calls to Durable Objects or outbound fetch calls.
264
+
265
+ ## Limitations
266
+
267
+ - The worker runtime does not expose accurate timing information to protect against side-channel attacks such as Spectre and will only update the clock on IO, so any CPU heavy processing will look like it takes 0 milliseconds.
268
+ - Not everything is auto-instrumented yet. See the lists below for what is and isn't.
269
+
270
+ Triggers:
271
+
272
+ - [x] Email (`handler.email`)
273
+ - [x] HTTP (`handler.fetch`)
274
+ - [x] Queue (`handler.queue`)
275
+ - [x] Cron (`handler.scheduled`)
276
+ - [ ] Tail (`handler.tail`)
277
+ - [x] Durable Objects fetch
278
+ - [x] Durable Objects alarm
279
+ - [ ] Durable Objects hibernated WebSocket
280
+ - [x] waitUntil (`ctx.waitUntil`)
281
+
282
+ Globals/built-ins:
283
+
284
+ - [x] Fetch
285
+ - [x] Caches
286
+ - [x] Durable Object Storage
287
+
288
+ Cloudflare modules
289
+
290
+ - [ ] `cloudflare:email`
291
+ - [ ] `cloudflare:sockets`
292
+
293
+ Bindings:
294
+
295
+ - [x] KV
296
+ - [x] Queue
297
+ - [x] Durable Objects
298
+ - [ ] R2
299
+ - [x] D1
300
+ - [x] Service Bindings
301
+ - [x] Analytics Engine
302
+ - [ ] Browser Rendering
303
+ - [ ] Workers AI
304
+ - [ ] Email Sending
305
+ - [ ] mTLS
306
+ - [ ] Vectorize
307
+ - [ ] Hyperdrive
308
+ - [ ] Workers for Platforms Dispatch
@@ -0,0 +1,235 @@
1
+ import { SpanExporter, ReadableSpan, Sampler, SpanProcessor, TimedEvent } from '@opentelemetry/sdk-trace-base';
2
+ import { TextMapPropagator, SpanOptions, Context, Attributes, Span, SpanContext, SpanKind, SpanStatus, HrTime, Link, TimeInput, AttributeValue, Exception } from '@opentelemetry/api';
3
+ import { ExportResult, InstrumentationScope } from '@opentelemetry/core';
4
+ import { OTLPExporterError } from '@opentelemetry/otlp-exporter-base';
5
+ import { DurableObject as DurableObject$1 } from 'cloudflare:workers';
6
+ import { Resource } from '@opentelemetry/resources';
7
+
8
+ interface OTLPExporterConfig {
9
+ url: string;
10
+ headers?: Record<string, string>;
11
+ }
12
+ declare class OTLPExporter implements SpanExporter {
13
+ private headers;
14
+ private url;
15
+ constructor(config: OTLPExporterConfig);
16
+ export(items: any[], resultCallback: (result: ExportResult) => void): void;
17
+ private _export;
18
+ send(items: any[], onSuccess: () => void, onError: (error: OTLPExporterError) => void): void;
19
+ shutdown(): Promise<void>;
20
+ }
21
+
22
+ type IncludeTraceContextFn = (request: Request) => boolean;
23
+ interface FetcherConfig {
24
+ includeTraceContext?: boolean | IncludeTraceContextFn;
25
+ }
26
+ type AcceptTraceContextFn = (request: Request) => boolean;
27
+ interface FetchHandlerConfig {
28
+ /**
29
+ * Whether to enable context propagation for incoming requests to `fetch`.
30
+ * This enables or disables distributed tracing from W3C Trace Context headers.
31
+ * @default true
32
+ */
33
+ acceptTraceContext?: boolean | AcceptTraceContextFn;
34
+ }
35
+
36
+ type OrPromise<T extends any> = T | Promise<T>;
37
+ type ResolveConfigFn<Env = any> = (env: Env, trigger: Trigger) => TraceConfig;
38
+ type ConfigurationOption = TraceConfig | ResolveConfigFn;
39
+ type PostProcessorFn = (spans: ReadableSpan[]) => ReadableSpan[];
40
+ type ExporterConfig = OTLPExporterConfig | SpanExporter;
41
+ interface InitialSpanInfo {
42
+ name: string;
43
+ options: SpanOptions;
44
+ context?: Context;
45
+ }
46
+ interface HandlerInstrumentation<T extends Trigger, R extends any> {
47
+ getInitialSpanInfo: (trigger: T) => InitialSpanInfo;
48
+ getAttributesFromResult?: (result: Awaited<R>) => Attributes;
49
+ instrumentTrigger?: (trigger: T) => T;
50
+ executionSucces?: (span: Span, trigger: T, result: Awaited<R>) => void;
51
+ executionFailed?: (span: Span, trigger: T, error?: any) => void;
52
+ }
53
+ type TraceFlushableSpanProcessor = SpanProcessor & {
54
+ forceFlush: (traceId?: string) => Promise<void>;
55
+ };
56
+ interface HandlerConfig {
57
+ fetch?: FetchHandlerConfig;
58
+ }
59
+ interface ServiceConfig {
60
+ name: string;
61
+ namespace?: string;
62
+ version?: string;
63
+ }
64
+ interface ParentRatioSamplingConfig {
65
+ acceptRemote?: boolean;
66
+ ratio: number;
67
+ }
68
+ type HeadSamplerConf = Sampler | ParentRatioSamplingConfig;
69
+ interface SamplingConfig<HS extends HeadSamplerConf = HeadSamplerConf> {
70
+ headSampler?: HS;
71
+ tailSampler?: TailSampleFn;
72
+ }
73
+ interface InstrumentationOptions {
74
+ instrumentGlobalFetch?: boolean;
75
+ instrumentGlobalCache?: boolean;
76
+ }
77
+ interface TraceConfigBase {
78
+ service: ServiceConfig;
79
+ handlers?: HandlerConfig;
80
+ fetch?: FetcherConfig;
81
+ postProcessor?: PostProcessorFn;
82
+ sampling?: SamplingConfig;
83
+ propagator?: TextMapPropagator;
84
+ instrumentation?: InstrumentationOptions;
85
+ }
86
+ interface TraceConfigExporter extends TraceConfigBase {
87
+ exporter: ExporterConfig;
88
+ }
89
+ interface TraceConfigSpanProcessors extends TraceConfigBase {
90
+ spanProcessors: SpanProcessor | SpanProcessor[];
91
+ }
92
+ type TraceConfig = TraceConfigExporter | TraceConfigSpanProcessors;
93
+ declare function isSpanProcessorConfig(config: TraceConfig): config is TraceConfigSpanProcessors;
94
+ interface ResolvedTraceConfig extends TraceConfigBase {
95
+ handlers: Required<HandlerConfig>;
96
+ fetch: Required<FetcherConfig>;
97
+ postProcessor: PostProcessorFn;
98
+ sampling: Required<SamplingConfig<Sampler>>;
99
+ spanProcessors: SpanProcessor[];
100
+ propagator: TextMapPropagator;
101
+ instrumentation: InstrumentationOptions;
102
+ }
103
+ interface DOConstructorTrigger {
104
+ id: string;
105
+ name?: string;
106
+ }
107
+ type Trigger = Request | MessageBatch | ScheduledController | DOConstructorTrigger | 'do-alarm' | ForwardableEmailMessage;
108
+
109
+ interface LocalTrace {
110
+ readonly traceId: string;
111
+ readonly localRootSpan: ReadableSpan;
112
+ readonly spans: ReadableSpan[];
113
+ }
114
+ type TailSampleFn = (traceInfo: LocalTrace) => boolean;
115
+ declare function multiTailSampler(samplers: TailSampleFn[]): TailSampleFn;
116
+ declare const isHeadSampled: TailSampleFn;
117
+ declare const isRootErrorSpan: TailSampleFn;
118
+ declare function createSampler(conf: ParentRatioSamplingConfig): Sampler;
119
+
120
+ type DO = DurableObject | DurableObject$1;
121
+ type DOClass = {
122
+ new (state: DurableObjectState, env: any): DO;
123
+ };
124
+
125
+ declare class PromiseTracker {
126
+ _outstandingPromises: Promise<unknown>[];
127
+ get outstandingPromiseCount(): number;
128
+ track(promise: Promise<unknown>): void;
129
+ wait(): Promise<void>;
130
+ }
131
+
132
+ type Env = Record<string, any>;
133
+ declare function isRequest(trigger: Trigger): trigger is Request;
134
+ declare function isMessageBatch(trigger: Trigger): trigger is MessageBatch;
135
+ declare function isAlarm(trigger: Trigger): trigger is 'do-alarm';
136
+ declare function exportSpans(traceId: string, tracker?: PromiseTracker): Promise<void>;
137
+ declare function instrument<E extends Env, Q, C>(handler: ExportedHandler<E, Q, C>, config: ConfigurationOption): ExportedHandler<E, Q, C>;
138
+ declare function instrumentDO(doClass: DOClass, config: ConfigurationOption): DOClass;
139
+ declare const __unwrappedFetch: typeof fetch;
140
+
141
+ type OnSpanEnd = (span: Span) => void;
142
+ interface SpanInit {
143
+ attributes: unknown;
144
+ name: string;
145
+ onEnd: OnSpanEnd;
146
+ resource: Resource;
147
+ spanContext: SpanContext;
148
+ parentSpanContext?: SpanContext;
149
+ links?: Link[];
150
+ parentSpanId?: string;
151
+ spanKind?: SpanKind;
152
+ startTime?: TimeInput;
153
+ }
154
+ declare class SpanImpl implements Span, ReadableSpan {
155
+ name: string;
156
+ private readonly _spanContext;
157
+ private readonly onEnd;
158
+ readonly parentSpanId?: string;
159
+ readonly parentSpanContext?: SpanContext | undefined;
160
+ readonly kind: SpanKind;
161
+ readonly attributes: Attributes;
162
+ status: SpanStatus;
163
+ endTime: HrTime;
164
+ private _duration;
165
+ readonly startTime: HrTime;
166
+ readonly events: TimedEvent[];
167
+ readonly links: Link[];
168
+ readonly resource: Resource;
169
+ instrumentationScope: InstrumentationScope;
170
+ private _ended;
171
+ private _droppedAttributesCount;
172
+ private _droppedEventsCount;
173
+ private _droppedLinksCount;
174
+ constructor(init: SpanInit);
175
+ addLink(link: Link): this;
176
+ addLinks(links: Link[]): this;
177
+ spanContext(): SpanContext;
178
+ setAttribute(key: string, value?: AttributeValue): this;
179
+ setAttributes(attributes: Attributes): this;
180
+ addEvent(name: string, attributesOrStartTime?: Attributes | TimeInput, startTime?: TimeInput): this;
181
+ setStatus(status: SpanStatus): this;
182
+ updateName(name: string): this;
183
+ end(endTime?: TimeInput): void;
184
+ isRecording(): boolean;
185
+ recordException(exception: Exception, time?: TimeInput): void;
186
+ get duration(): HrTime;
187
+ get ended(): boolean;
188
+ get droppedAttributesCount(): number;
189
+ get droppedEventsCount(): number;
190
+ get droppedLinksCount(): number;
191
+ }
192
+
193
+ declare class MultiSpanExporter implements SpanExporter {
194
+ private exporters;
195
+ constructor(exporters: Array<SpanExporter>);
196
+ export(items: any[], resultCallback: (result: ExportResult) => void): void;
197
+ shutdown(): Promise<void>;
198
+ }
199
+ declare class MultiSpanExporterAsync implements SpanExporter {
200
+ private exporters;
201
+ constructor(exporters: Array<SpanExporter>);
202
+ export(items: any[], resultCallback: (result: ExportResult) => void): void;
203
+ shutdown(): Promise<void>;
204
+ }
205
+
206
+ declare class TraceState {
207
+ private unexportedSpans;
208
+ private inprogressSpans;
209
+ private exporter;
210
+ private exportPromises;
211
+ private localRootSpan?;
212
+ private traceDecision?;
213
+ constructor(exporter: SpanExporter);
214
+ addSpan(span: Span): void;
215
+ endSpan(span: ReadableSpan): void;
216
+ sample(): void;
217
+ flush(): Promise<void>;
218
+ private isSpanInProgress;
219
+ private exportSpans;
220
+ }
221
+ type traceId = string;
222
+ declare class BatchTraceSpanProcessor implements TraceFlushableSpanProcessor {
223
+ private exporter;
224
+ private traces;
225
+ constructor(exporter: SpanExporter);
226
+ getTraceState(traceId: string): TraceState;
227
+ onStart(span: Span, _parentContext: Context): void;
228
+ onEnd(span: ReadableSpan): void;
229
+ forceFlush(traceId?: traceId): Promise<void>;
230
+ shutdown(): Promise<void>;
231
+ }
232
+
233
+ declare function withNextSpan(attrs: Attributes): void;
234
+
235
+ export { BatchTraceSpanProcessor, type ConfigurationOption, type DOConstructorTrigger, type ExporterConfig, type HandlerConfig, type HandlerInstrumentation, type InitialSpanInfo, type InstrumentationOptions, type LocalTrace, MultiSpanExporter, MultiSpanExporterAsync, OTLPExporter, type OTLPExporterConfig, type OrPromise, type ParentRatioSamplingConfig, type PostProcessorFn, type ResolveConfigFn, type ResolvedTraceConfig, type SamplingConfig, type ServiceConfig, SpanImpl, type TailSampleFn, type TraceConfig, type TraceFlushableSpanProcessor, type Trigger, __unwrappedFetch, createSampler, exportSpans, instrument, instrumentDO, isAlarm, isHeadSampled, isMessageBatch, isRequest, isRootErrorSpan, isSpanProcessorConfig, multiTailSampler, withNextSpan };