Documentation Index
Fetch the complete documentation index at: https://mintlify.com/effect-TS/effect-smol/llms.txt
Use this file to discover all available pages before exploring further.
OpenTelemetry integration for Effect that provides distributed tracing, metrics, and logging capabilities for your Effect applications.
Installation
pnpm add @effect/opentelemetry
You’ll also need to install OpenTelemetry peer dependencies:
pnpm add @opentelemetry/api @opentelemetry/sdk-trace-node @opentelemetry/sdk-metrics
Setup
Node.js Application
Set up OpenTelemetry for a Node.js application:
import { NodeSdk } from "@effect/opentelemetry"
import { Effect, Layer } from "effect"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { Resource } from "@opentelemetry/resources"
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"
const resource = Resource.default().merge(
new Resource({
[ATTR_SERVICE_NAME]: "my-effect-app"
})
)
const OpenTelemetryLive = NodeSdk.layer({
resource,
spanProcessor: new BatchSpanProcessor(
new OTLPTraceExporter({
url: "http://localhost:4318/v1/traces"
})
)
})
Web Application
Set up OpenTelemetry for a browser application:
import { WebSdk } from "@effect/opentelemetry"
import { Effect, Layer } from "effect"
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { Resource } from "@opentelemetry/resources"
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"
const resource = Resource.default().merge(
new Resource({
[ATTR_SERVICE_NAME]: "my-web-app"
})
)
const OpenTelemetryLive = WebSdk.layer({
resource,
spanProcessor: new BatchSpanProcessor(
new OTLPTraceExporter({
url: "http://localhost:4318/v1/traces"
})
)
})
Tracing
Effect automatically creates spans for your operations:
import { Tracer } from "@effect/opentelemetry"
import { Effect } from "effect"
const fetchUser = (id: string) =>
Effect.gen(function*() {
// This will be automatically traced
const response = yield* Effect.promise(() =>
fetch(`https://api.example.com/users/${id}`)
)
return yield* Effect.promise(() => response.json())
}).pipe(
Effect.withSpan("fetchUser", { attributes: { userId: id } })
)
const program = Effect.gen(function*() {
const user = yield* fetchUser("123")
console.log(user)
}).pipe(
Effect.provide(OpenTelemetryLive)
)
Effect.runPromise(program)
Custom Spans
Create custom spans to track specific operations:
import { Tracer } from "@effect/opentelemetry"
import { Effect } from "effect"
const processData = (data: string) =>
Effect.gen(function*() {
// Create a custom span
yield* Effect.annotateCurrentSpan({ dataSize: data.length })
// Your processing logic
const result = yield* Effect.sync(() => data.toUpperCase())
yield* Effect.annotateCurrentSpan({ result: "success" })
return result
}).pipe(
Effect.withSpan("processData")
)
Metrics
Collect and export metrics:
import { Metrics, NodeSdk } from "@effect/opentelemetry"
import { Effect, Layer } from "effect"
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics"
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http"
const OpenTelemetryLive = NodeSdk.layer({
resource,
meterProvider: new MeterProvider({
resource,
readers: [
new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: "http://localhost:4318/v1/metrics"
}),
exportIntervalMillis: 1000
})
]
})
})
const requestCounter = Metrics.counter("http_requests_total", {
description: "Total number of HTTP requests"
})
const program = Effect.gen(function*() {
yield* requestCounter.add(1, { method: "GET", path: "/users" })
}).pipe(
Effect.provide(OpenTelemetryLive)
)
Logging
Integrate Effect logging with OpenTelemetry:
import { Logger, NodeSdk } from "@effect/opentelemetry"
import { Effect, Layer } from "effect"
import { LoggerProvider, BatchLogRecordProcessor } from "@opentelemetry/sdk-logs"
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http"
const OpenTelemetryLive = NodeSdk.layer({
resource,
loggerProvider: new LoggerProvider({
resource
})
}).pipe(
Layer.provideMerge(Logger.layer)
)
const program = Effect.gen(function*() {
yield* Effect.log("Processing request")
yield* Effect.logInfo("Request completed successfully")
}).pipe(
Effect.provide(OpenTelemetryLive)
)
Resource Configuration
Configure resource attributes for better observability:
import { Resource } from "@effect/opentelemetry"
import { Resource as OtelResource } from "@opentelemetry/resources"
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
ATTR_DEPLOYMENT_ENVIRONMENT
} from "@opentelemetry/semantic-conventions"
const resource = OtelResource.default().merge(
new OtelResource({
[ATTR_SERVICE_NAME]: "my-service",
[ATTR_SERVICE_VERSION]: "1.0.0",
[ATTR_DEPLOYMENT_ENVIRONMENT]: "production",
"service.namespace": "my-company"
})
)
const resourceLayer = Resource.layer(resource)
Exporter Options
OTLP Exporter
Export to any OTLP-compatible backend (Jaeger, Grafana Tempo, etc.):
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node"
const exporter = new OTLPTraceExporter({
url: "http://localhost:4318/v1/traces",
headers: {
Authorization: `Bearer ${process.env.OTLP_TOKEN}`
}
})
const spanProcessor = new BatchSpanProcessor(exporter)
Console Exporter
Useful for local development:
import { ConsoleSpanExporter, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node"
const spanProcessor = new SimpleSpanProcessor(new ConsoleSpanExporter())
Prometheus Exporter
Expose metrics in Prometheus format:
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus"
const prometheusExporter = new PrometheusExporter(
{
port: 9464,
endpoint: "/metrics"
},
() => {
console.log("Prometheus scrape endpoint: http://localhost:9464/metrics")
}
)
API Modules
- NodeSdk: OpenTelemetry SDK for Node.js applications
- WebSdk: OpenTelemetry SDK for browser applications
- Tracer: Distributed tracing functionality
- Metrics: Metrics collection and export
- Logger: Logging integration
- Resource: Resource attribute configuration
Best Practices
- Service Naming: Use consistent service names across your application
- Span Attributes: Add meaningful attributes to spans for better observability
- Sampling: Configure sampling rates for high-traffic applications
- Error Tracking: Ensure errors are properly recorded in spans
- Metric Naming: Follow OpenTelemetry semantic conventions for metric names