import { Array, Config, Duration, Effect, Number, pipe, Runtime, String, } from "effect"; export const withSpanProcessorLive = Effect.fn(function* ( effect: Effect.Effect, ) { const enabled = yield* Config.boolean("LOG_SPAN").pipe( Config.withDefault(false), ); if (!enabled) { return yield* effect; } const NodeSdk = yield* Effect.promise( () => import("@effect/opentelemetry/NodeSdk"), ); const { SpanStatusCode } = yield* Effect.promise( () => import("@opentelemetry/api"), ); const runtime = yield* Effect.runtime(); const layer = NodeSdk.layer(() => ({ resource: { serviceName: "nodecg" }, spanProcessor: { forceFlush: () => Promise.resolve(), onStart: (span) => { Runtime.runSync(runtime, Effect.logTrace(`▶️ ${span.name}`)); }, onEnd: (span) => { const formattedDuration = pipe( span.duration, Duration.toMillis, Number.round(0), Duration.millis, Duration.format, String.split(" "), Array.take(2), Array.join(" "), ); const status = span.status.code === SpanStatusCode.ERROR ? "❌" : "✅"; let log = `${status} ${span.name} (${formattedDuration})`; if (span.status.code === SpanStatusCode.ERROR) { log += ` ${span.status.message}`; } Runtime.runSync(runtime, Effect.logTrace(log)); }, shutdown: () => Promise.resolve(), }, })); return yield* Effect.provide(effect, layer); });