Structured logging for Cloudflare Workers with automatic request context and Hono middleware
bun add @workkit/logger// No structure, no levels, no request context
console.log("processing request", request.url)
console.log("user found", JSON.stringify(user))
console.error("something failed", error.message)import { createLogger } from "@workkit/logger"
const log = createLogger({ service: "api", level: "debug" })
log.info("processing request", { url: request.url })
log.info("user found", { userId: user.id })
log.error("something failed", { error })
// {"level":"info","msg":"processing request","ts":1234567890,"service":"api","url":"/users"}import { Hono } from "hono"
import { logger, getLogger } from "@workkit/logger"
const app = new Hono()
// Auto-logs request start/complete with timing and requestId
app.use(logger({ exclude: ["/health"], fields: { service: "api" } }))
app.get("/users", (c) => {
const log = getLogger(c)
log.info("fetching users", { count: 50 })
return c.json(users)
})const log = createLogger({ service: "worker" })
const batchLog = log.child({ batchId: "abc-123" })
batchLog.info("processing item", { itemId: 1 })
// {"level":"info","msg":"processing item","ts":...,"service":"worker","batchId":"abc-123","itemId":1}app.use(
logger({
redact: ["authorization", "cookie", "x-api-key"],
}),
)
// Fields matching redacted keys are replaced with "[REDACTED]"
// Or use a custom redactor function
app.use(
logger({
redact: (key, value) =>
key.toLowerCase().includes("secret") ? "[REDACTED]" : value,
}),
)import { getRequestContext } from "@workkit/logger"
// Inside a request handled by the logger middleware:
const ctx = getRequestContext()
if (ctx) {
console.log(ctx.requestId) // "a1b2c3d4e5f67890"
console.log(ctx.method) // "GET"
console.log(ctx.path) // "/users"
}createLogger(options?)-- Create a structured loggeroptions.level-- Minimum log level ("debug","info","warn","error"). Default:"info"options.fields-- Base fields attached to every log entry- Returns
Loggerwith.debug(),.info(),.warn(),.error(),.child()
-
logger(options?)-- Hono middleware for structured request loggingoptions.level-- Minimum log level. Default:"info"options.exclude-- Routes to skip (exact match or prefix)options.requestId-- Header name to use as requestId (default: auto-generate)options.fields-- Base fields on every entryoptions.timing-- Auto-log request duration. Default:trueoptions.redact-- Field names or custom function for redacting sensitive data
-
getLogger(c)-- Get a logger from Hono context (includes requestId, method, path)
getRequestContext()-- Get the current request context from AsyncLocalStorage
LogLevel--"debug" | "info" | "warn" | "error"LogFields--Record<string, unknown>LogEntry--{ level, msg, ts, ...fields }Logger-- Logger interface with level methods and.child()RequestContext--{ requestId, method, path, startTime, fields }
MIT