26 — Structured logging
Use Effect.logDebug, logInfo, logWarning, and logError instead of direct console calls. Attach searchable fields with Effect.annotateLogs; scope annotations around a workflow when every nested message needs the same request or entity identity.
Logger implementations are runtime services supplied at the application edge. Feature code emits semantic events and does not choose formatting or transports.
The full test suite
The index.test.ts for this lesson, verbatim from steps/26-logger/.
import { describe, it } from "vite-plus/test"import { Effect } from "effect"
describe("structured logging", () => { it("attaches fields at the call site", async () => { await Effect.runPromise( Effect.logInfo("user loaded").pipe(Effect.annotateLogs({ userId: "u1", source: "cache" })), ) })
it("scopes annotations across a workflow", async () => { const workflow = Effect.gen(function*() { yield* Effect.logDebug("start") yield* Effect.logInfo("complete") }).pipe(Effect.annotateLogs("requestId", "r1")) await Effect.runPromise(workflow) })})