Choosing a TypeScript Logger
A TypeScript logging library should make the next bug easier to understand. If you spend more time piecing together requests than fixing them, evlog brings the context you collect into one event: who made the request, what it did, and how it ended.
This guide helps you decide where evlog fits in your project. For a working example, follow Structured Logging in Node.js.
Choose around the questions you ask your logs
A script may only need to report progress. Use evlog’s simple logging API for individual structured messages.
When a checkout crosses authentication, inventory, and payment code, the useful answer is usually the whole operation. Wide events let each step add context to the same event. You can then filter failed checkouts by customer, payment provider, or order amount without first joining separate messages.
If your current logger already gives you the answers you need, you can keep it. evlog becomes useful when you want context accumulation, request lifecycle handling, and structured errors together. The feature comparison above covers the differences with other loggers, including the features you may want to retain.
Let TypeScript keep your context consistent
As more people add logging, a field named orderId in one place can become orderID in another. evlog lets you opt into a shared context type, so your editor and compiler catch those mismatches while you work.
For example, this checkout logger accepts a known set of outcomes and a numeric payment amount:
import { createLogger, initLogger } from 'evlog'
initLogger({ env: { service: 'checkout' }, pretty: false })
type CheckoutContext = {
orderId: string
payment: { chargeId: string, amount: number }
outcome: 'paid' | 'declined'
}
const log = createLogger<CheckoutContext>()
log.set({ orderId: 'order-123' })
log.set({ payment: { chargeId: 'ch_123', amount: 2999 } })
log.emit({ outcome: 'paid' })
Type checking catches an amount passed as a string or an outcome outside that union in set() and emit(). Fields can be added progressively; the type does not require every field before emission or validate incoming data. Typed Fields covers the typing patterns and framework setup.
Bring your existing setup with you
Start with one route or background job. Keep your existing logger elsewhere. Use the resulting events to investigate a real issue before adopting evlog more widely.
The migration examples in Simple Logging map familiar calls from console.log, Pino, Consola, and Winston to evlog. The APIs differ, so use those examples when updating calls. If you combine several records into one event, update the queries that read them too.
You can keep your observability backend when it has a supported drain adapter. The logger collects context in your application; the adapter sends it to the service where you search and store your events.
Try it in your project
Use the Quick Start above to learn the APIs, then choose your framework integration. For scripts and background jobs, Standalone TypeScript covers initialization and delivery. For bundle sizes and benchmark conditions, see Performance.