Logging
Send structured logs with metadata, context, and automatic batching.
Log methods
Four methods, matching standard severity levels:
logger.debug("Cache miss for user lookup", { userId: "u_123" })
logger.info("Order placed", { orderId: "ord_456", total: 99.99 })
logger.warn("Rate limit approaching", { current: 95, limit: 100 })
logger.error("Payment failed", { provider: "stripe", code: "card_declined" })Each method takes (message: string, metadata?: object). The metadata can contain any serializable data -- strings, numbers, booleans, arrays, nested objects.
Metadata examples
// Primitives
logger.info("Server started", { port: 3000, host: "0.0.0.0" })
// Nested objects
logger.info("User signed up", {
user: { id: "u_123", plan: "pro" },
source: "google-oauth",
})
// Arrays
logger.warn("Slow queries detected", {
queries: ["SELECT * FROM users", "SELECT * FROM orders"],
avgMs: 1200,
})
// Errors as metadata (auto-extracted)
try {
await fetchData()
} catch (err) {
logger.error("Fetch failed", err) // stack trace included automatically
}Log level filtering
Only logs at or above the configured level are sent to DeepTracer. The order is:
debug < info < warn < errorIn production, the default level is "info" -- debug logs are filtered out. In development, the default is "debug" -- everything is sent.
const logger = init({ level: "warn" }) // only warn + error are sent
logger.debug("skipped") // not sent
logger.info("skipped") // not sent
logger.warn("sent") // sent
logger.error("sent") // sentFiltered logs still record breadcrumbs. So if an error happens later, the breadcrumb trail includes those debug/info entries for full context.
Context loggers
Tag all logs from a specific module or feature area:
const authLogger = logger.withContext("auth")
authLogger.info("Login attempt", { email: "user@example.com" })
// → log entry includes context: "auth"
const dbLogger = logger.withContext("database")
dbLogger.warn("Connection pool exhausted")
// → log entry includes context: "database"Context loggers share the same transport and batcher as the parent. They get an independent copy of user/tags/contexts state, so setting a user on one doesn't affect the other.
Request loggers
Extract trace context from incoming HTTP headers:
const reqLogger = logger.forRequest(request)
reqLogger.info("Processing checkout")
// → log entry includes trace_id, span_id from headersThe forRequest() method reads traceparent, x-trace-id, x-span-id, x-request-id, and x-vercel-id headers. Useful for correlating logs across services.
Local console output
Set debug: true to also print logs to your terminal during development:
const logger = init({ debug: true })
logger.info("Server started", { port: 3000 })
// → sent to DeepTracer AND printed to consoleThis uses the original console.log internally, so it works even when captureConsole is enabled (no infinite loop).