Seeking Feedback on Effect-Next.js Example Repo with OpenTelemetry Tracing Integration
Hi everybody,
I’ve published an effect-nextjs example repo (https://github.com/mcrovero/effect-nextjs-example) where I use the following code to create a tracer that sets the current request span as the parent:
I’ve noticed it’s gained some traction, and I want to make sure this is a correct solution to show the correct path. How would you improve it/fix it?
I’ve published an effect-nextjs example repo (https://github.com/mcrovero/effect-nextjs-example) where I use the following code to create a tracer that sets the current request span as the parent:
import { Resource, Tracer as OtelTracer } from "@effect/opentelemetry"
import { context as otelContext, trace } from "@opentelemetry/api"
import { Effect, Layer, Option, pipe, Schema, Tracer } from "effect"
export const makeTracer: Effect.Effect<Tracer.Tracer, never, never> = Effect.gen(function* () {
const currentTracer = yield* Effect.tracer
return Tracer.make({
span(name, parent, context, links, startTime, kind) {
const active = trace.getSpan(otelContext.active())
const otelParent = active ? active.spanContext() : undefined
// If there's an active OTel span (The Next.js one), use it as the external parent for Effect spans
const externalParent = otelParent
? Option.some(
Tracer.externalSpan({
spanId: otelParent.spanId,
traceId: otelParent.traceId,
sampled: (otelParent.traceFlags & 1) === 1,
context
})
)
: Option.none()
const effectiveParent = parent._tag === "Some" ? parent : externalParent
const span = currentTracer.span(name, effectiveParent, context, links, startTime, kind)
return span
},
context: currentTracer.context
})
})
export const layerTracer: Layer.Layer<never, never, never> = pipe(
makeTracer,
Effect.map(Layer.setTracer),
Layer.unwrapEffect
)
const tracerWithOtel = layerTracer.pipe(
Layer.provide(
OtelTracer.layerGlobal.pipe(
Layer.provide(Resource.layer({ serviceName: "next-app" }))
)
)
);import { Resource, Tracer as OtelTracer } from "@effect/opentelemetry"
import { context as otelContext, trace } from "@opentelemetry/api"
import { Effect, Layer, Option, pipe, Schema, Tracer } from "effect"
export const makeTracer: Effect.Effect<Tracer.Tracer, never, never> = Effect.gen(function* () {
const currentTracer = yield* Effect.tracer
return Tracer.make({
span(name, parent, context, links, startTime, kind) {
const active = trace.getSpan(otelContext.active())
const otelParent = active ? active.spanContext() : undefined
// If there's an active OTel span (The Next.js one), use it as the external parent for Effect spans
const externalParent = otelParent
? Option.some(
Tracer.externalSpan({
spanId: otelParent.spanId,
traceId: otelParent.traceId,
sampled: (otelParent.traceFlags & 1) === 1,
context
})
)
: Option.none()
const effectiveParent = parent._tag === "Some" ? parent : externalParent
const span = currentTracer.span(name, effectiveParent, context, links, startTime, kind)
return span
},
context: currentTracer.context
})
})
export const layerTracer: Layer.Layer<never, never, never> = pipe(
makeTracer,
Effect.map(Layer.setTracer),
Layer.unwrapEffect
)
const tracerWithOtel = layerTracer.pipe(
Layer.provide(
OtelTracer.layerGlobal.pipe(
Layer.provide(Resource.layer({ serviceName: "next-app" }))
)
)
);I’ve noticed it’s gained some traction, and I want to make sure this is a correct solution to show the correct path. How would you improve it/fix it?
