Skip to content

Commit 41e5623

Browse files
feat(opentelemetry): expose OtlpExporter as public API
Exposes the internal OTLP exporter as OtlpExporter.make() to allow building custom multi-endpoint tracers or composing multiple exporters.
1 parent cfdd411 commit 41e5623

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

.changeset/export-otlp-exporter.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
"@effect/opentelemetry": minor
3+
---
4+
5+
feat(OtlpExporter): expose internal OTLP exporter as public API
6+
7+
The internal OTLP exporter is now available as `OtlpExporter.make()`. This allows building custom multi-endpoint tracers or composing multiple exporters without copying internal code.
8+
9+
Example:
10+
```typescript
11+
import { OtlpExporter } from "@effect/opentelemetry"
12+
13+
const exporter = yield* OtlpExporter.make({
14+
url: "https://api.honeycomb.io/v1/traces",
15+
headers: { "x-honeycomb-team": "api-key" },
16+
label: "honeycomb",
17+
exportInterval: "5 seconds",
18+
maxBatchSize: 100,
19+
body: (spans) => ({ resourceSpans: [{ scopeSpans: [{ spans }] }] }),
20+
shutdownTimeout: "3 seconds"
21+
})
22+
23+
exporter.push(spanData)
24+
```
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* OTLP Exporter
3+
*
4+
* A generic OTLP exporter that can be used to build custom tracers, metrics exporters,
5+
* or loggers that send data to OTLP-compatible backends.
6+
*
7+
* This exporter handles:
8+
* - Batching of data with configurable batch size
9+
* - Automatic retry with backoff on transient errors
10+
* - Rate limiting with 429 Retry-After header support
11+
* - Graceful shutdown with timeout
12+
* - Automatic disabling for 60 seconds on persistent failures
13+
*
14+
* @since 1.0.0
15+
* @example
16+
* ```typescript
17+
* import { OtlpExporter } from "@effect/opentelemetry"
18+
* import { BunHttpClient } from "@effect/platform-bun"
19+
* import { Effect, Layer } from "effect"
20+
*
21+
* const program = Effect.gen(function*() {
22+
* const exporter = yield* OtlpExporter.make({
23+
* url: "https://api.honeycomb.io/v1/traces",
24+
* headers: { "x-honeycomb-team": "your-api-key" },
25+
* label: "honeycomb",
26+
* exportInterval: "5 seconds",
27+
* maxBatchSize: 100,
28+
* body: (spans) => ({ resourceSpans: [{ scopeSpans: [{ spans }] }] }),
29+
* shutdownTimeout: "3 seconds"
30+
* })
31+
*
32+
* // Push data to be exported
33+
* exporter.push({ traceId: "...", spanId: "...", name: "my-span" })
34+
* })
35+
*
36+
* program.pipe(
37+
* Effect.scoped,
38+
* Effect.provide(BunHttpClient.layer),
39+
* Effect.runPromise
40+
* )
41+
* ```
42+
*/
43+
import type * as Headers from "@effect/platform/Headers"
44+
import type * as HttpClient from "@effect/platform/HttpClient"
45+
import type * as Duration from "effect/Duration"
46+
import type * as Effect from "effect/Effect"
47+
import type * as Scope from "effect/Scope"
48+
import * as internal from "./internal/otlpExporter.js"
49+
50+
/**
51+
* @since 1.0.0
52+
* @category Models
53+
*/
54+
export interface Exporter {
55+
/**
56+
* Push data to be exported. The data will be batched and sent according
57+
* to the configured export interval and batch size.
58+
*/
59+
readonly push: (data: unknown) => void
60+
}
61+
62+
/**
63+
* @since 1.0.0
64+
* @category Models
65+
*/
66+
export interface MakeOptions {
67+
/**
68+
* The OTLP endpoint URL to send data to.
69+
*/
70+
readonly url: string
71+
/**
72+
* Optional HTTP headers to include in requests (e.g., authentication).
73+
*/
74+
readonly headers?: Headers.Input | undefined
75+
/**
76+
* A label for this exporter, used in log messages and User-Agent header.
77+
*/
78+
readonly label: string
79+
/**
80+
* How often to flush the buffer and send data.
81+
* @default "5 seconds"
82+
*/
83+
readonly exportInterval: Duration.DurationInput
84+
/**
85+
* Maximum number of items to batch before triggering an immediate export.
86+
* Set to "disabled" to only export on interval.
87+
* @default 1000
88+
*/
89+
readonly maxBatchSize: number | "disabled"
90+
/**
91+
* Function to transform buffered items into the request body.
92+
* This allows customizing the OTLP payload format.
93+
*/
94+
readonly body: (data: Array<unknown>) => unknown
95+
/**
96+
* Maximum time to wait for pending exports during shutdown.
97+
* @default "3 seconds"
98+
*/
99+
readonly shutdownTimeout: Duration.DurationInput
100+
}
101+
102+
/**
103+
* Create an OTLP exporter that batches and sends data to an OTLP-compatible endpoint.
104+
*
105+
* The exporter automatically handles:
106+
* - Batching based on interval and max batch size
107+
* - Retry with exponential backoff on transient errors
108+
* - 429 rate limiting with Retry-After header support
109+
* - Graceful shutdown ensuring pending data is flushed
110+
* - Auto-disable for 60 seconds on persistent failures (logged via Effect.logDebug)
111+
*
112+
* @since 1.0.0
113+
* @category Constructors
114+
*/
115+
export const make: (
116+
options: MakeOptions
117+
) => Effect.Effect<Exporter, never, HttpClient.HttpClient | Scope.Scope> = internal.make as any

packages/opentelemetry/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export * as NodeSdk from "./NodeSdk.js"
1818
*/
1919
export * as Otlp from "./Otlp.js"
2020

21+
/**
22+
* @since 1.0.0
23+
*/
24+
export * as OtlpExporter from "./OtlpExporter.js"
25+
2126
/**
2227
* @since 1.0.0
2328
*/

0 commit comments

Comments
 (0)