← Back to blog

Logging in the Age of AI: Structured Observability with evlog

Traditional logging falls short for AI agents. evlog redefines the logging paradigm with wide events and structured errors. This TypeScript-based, zero-dependency library supporting 13+ frameworks is shaping the future of observability.

Logging in the Age of AI: Structured Observability with evlog

Logging in the Age of AI: Structured Observability with evlog

Imagine an AI agent. It works through the night, makes thousands of API calls, queries databases, and produces a report by morning. But what happens when something goes wrong? As developers, we face thousands of console.log lines. Each carries a piece of information, but none shows the whole picture. Why did the agent fail? At which stage did the error occur? What is the solution? Answering these questions requires hours of log digging. This is exactly where evlog comes in.

evlog is one of the most ambitious logging libraries in the modern TypeScript ecosystem. With zero dependencies, approximately 6 KB gzip size, and about 3 microseconds latency per request, it leaves traditional loggers behind. But the real difference is not in its speed, it is in its paradigm. Centered around wide events and structured errors, evlog transforms logging from a mere debugging tool into an AI-native observability platform. In this article, we deeply examine evlog's background, technical architecture, relationship with AI observability, and how it differs from the existing ecosystem.

Data observability and structured logging dashboardStructured logging transforms the chaos of traditional logs into organized, queryable data.

Origins: Hugo Richard and the Logging Sucks Movement

The story of evlog begins with Hugo Richard's personal experiences as a software engineer on the Nuxt team at Vercel. Richard, who stands out as both an engineer and designer, noticed the inadequacy of existing tools that meet the logging needs of modern web applications. Piles of console.log, pino's fragmented ecosystem, winston's aging structure... Each offers some solution, but none provides a TypeScript-first, framework-agnostic, and AI-ready whole.

One of Richard's inspirations is Nominal founder Boris Tane's Logging Sucks manifesto. Tane presents a revolutionary argument in the observability world: Traditional logs and metrics are insufficient to solve the complexity of modern distributed systems. Instead, a single context-rich event should be emitted for each request (or operation). This event, what Tane calls an arbitrarily-wide event, combines all relevant data about that request within a single JSON structure. Later, this structure can be decomposed to derive metrics and traces, but the reverse is not possible.

evlog implements exactly this philosophy. It combines Tane's theoretical framework with Richard's modern TypeScript practice, optimizing for both developer experience and machine readability.

Why Traditional Logging Falls Short

For years, a prevailing assumption about logging has been: more logs mean better observability. But the reality is the exact opposite. Every console.log carries a piece of information, but also adds a piece of noise. Consider a three-step payment system:

// Traditional approach
console.log('User authenticated:', user.id)
console.log('Cart items:', cart.items)
console.log('Payment processing...')
console.log('Payment failed:', error.message)
console.log('Status code:', 402)

These five lines are five separate log entries. When searching in Kibana or a similar tool, correlating these lines requires mechanisms like correlation IDs. But when the number of requests reaches thousands, this correlation becomes expensive and error-prone. Moreover, each line lacks the full context of the request. When payment fails, we have to examine these lines one by one to understand why.

evlog's solution is to merge these five lines into a single wide event:

import { useLogger, createError } from 'evlog'

const log = useLogger(event)
log.set({ user: { id: user.id, plan: user.plan } })
log.set({ cart: { items: 3, total: 9999 } })

if (!charge.success) {
  throw createError({
    status: 402,
    why: 'Card declined by issuer (insufficient funds)',
    fix: 'Try a different payment method or contact your bank',
    link: 'https://docs.example.com/payments/declined'
  })
}

When this code runs, a single INFO event is produced in the success case. It contains user information, cart details, request ID, duration, and all other context together. In the error case, a single ERROR event comes with the error message, why it failed (why), how to fix it (fix), and the relevant documentation link (link). This is a critical advantage not just for developers, but also for AI agents.

Let's recall Karpathy's autoresearch project. AI agents work through the night conducting their own research. So what happens when these agents encounter an error? They will try to read and understand traditional logs. But when logs are unstructured, the agent's debugging capability is severely limited. evlog's why and fix fields provide agents with directly actionable context at exactly this point.

Wide Events: The Whole Story in a Single Event

The wide event concept is an increasingly popular approach in the observability space. Modern observability platforms like Honeycomb also adopt this approach, where a single context-rich event is recorded for each operation or request. This event contains all relevant data as key-value pairs. Later, this data can be queried to derive metrics, distributions, and correlations.

evlog offers this concept in three different modes:

  1. Simple Logging (log.*): One event per single call. Replaces console.log or pino. Works at roughly the same speed but provides structured data.
  2. Wide Events (createLogger / createRequestLogger): Accumulates context and publishes as a single event when you want. Ideal for background jobs, queue systems, or manual HTTP handlers.
  3. Framework Middleware (useLogger): Automatically managed wide events through framework integrations. Supports more than 13 frameworks including Nuxt, Next.js, Express, and Hono. The logger is created as soon as the request starts and automatically emitted when the response is returned.

That these three modes run under the same drain pipeline, same redaction (sensitive data masking), and same type system is one of evlog's strongest aspects. You can use different modes in different layers of your project, but they all reach the same destination.

Modern technology circuits and AI observabilityWide events merge the complex layers of modern distributed systems into a single structured event.

13 Frameworks, One API: The evlog Ecosystem

The success of a logging library is proportional to the ecosystem it supports. evlog surpasses pino and winston in this regard. It offers official integrations for more than 13 frameworks:

  • Meta-frameworks: Nuxt (as a module), Next.js (factory), SvelteKit (hooks), React Router (middleware), TanStack Start
  • API servers: Express (middleware), Fastify (register), Hono (middleware), Elysia (plugin), NestJS (module)
  • Edge and serverless: Cloudflare Workers, AWS Lambda, Nitro v2/v3
  • Standalone and browser: Plain TypeScript scripts, CLI tools, client-side logging

This broad framework support shows that evlog is not just a logger but also a platform vision. In a Nuxt project, you can start working with zero config by adding modules: ['evlog/nuxt']. In Next.js, you get the same experience with the createEvlog() factory.

Especially when we consider the rise of modern developer tools like Zed 1.0, the importance of editor-agnostic, framework-agnostic tools increases. evlog answers exactly this need. Working in Nuxt? Express? It doesn't matter, you use the same API.

AI Observability: Illuminating the Black Box of LLMs

Logging for Large Language Models (LLMs) involves challenges different from traditional software logging. What happens in an LLM call? How many tokens were consumed? Which tools were called? How long did streaming take? Tracking this information manually is difficult and error-prone.

evlog solves this problem with the createAILogger API, which works integrated with the Vercel AI SDK. With a single line of wrapping, you make your LLM calls observable:

const ai = createAILogger(log, {
  cost: { 'claude-sonnet-4.6': { input: 3, output: 15 } }
})

const result = await streamText({
  model: ai.wrap('anthropic/claude-sonnet-4.6'),
  messages
})

Thanks to this integration, token usage, cost calculation, tool call chains, and streaming metrics of your LLM calls are collected within the same wide event. For AI agents, this provides the necessary data to analyze and optimize their own performance.

Let's think of architectures like Kimi K2.6's 300 parallel agents. Each agent works independently and produces its own logs. When we keep these logs unstructured, cross-agent correlation and debugging become almost impossible. evlog's log.fork() API allows creating child loggers for sub-operations and correlating them with the main request via _parentRequestId. This is critical for error tracking and performance analysis in parallel agent systems.

Taking it one step further, evlog's structured error format allows AI agents to read not only the errors but also the solution suggestions. When a payment fails, the agent receives not just a Card declined message, but also why: Card declined by issuer (insufficient funds) and fix: Try a different payment method. This can enable the agent to automatically offer a solution to the user or suggest an alternative payment method.

Code screen and artificial intelligence observabilityAI observability transforms the black box structure of LLM calls into structured events.

Production Ready: Drain Pipeline, Sampling, and Audit

When choosing a logging library, how it behaves in production is as important as performance. evlog processes logs without ever blocking the response through its drain pipeline architecture. It comes with capabilities like batching, exponential backoff with jitter for retry, and fan-out to multiple destinations.

Supported drain targets include Axiom, OTLP (OpenTelemetry), Sentry, PostHog, Better Stack, file system, and custom drains. Client-to-server logging is also supported. On the browser side, it is possible to not lose events even when the page closes, thanks to sendBeacon.

To manage log volume, evlog offers two-tier sampling. Head sampling allows you to set ratios by level (for example, keep 10% of INFO, 50% of WARN, and all of ERROR). Tail sampling unconditionally keeps events that match certain criteria (400 errors, requests longer than 1 second, critical paths). This allows you to reduce noise without missing critical signals.

There is also a special layer for audit logs (who did what). The audit system, which offers tamper-evident protection with HMAC signatures or hash chains, has a fixed schema with action, actor, target, outcome. Safe retry with idempotency keys is also supported. This is a lifesaver for projects with regulatory requirements such as financial transactions, GDPR deletion requests, or permission changes.

Comparison: evlog vs the Ecosystem

The choice of a logging library varies depending on the project. The evlog team has made this comparison honestly:

Against pino: evlog offers built-in structured errors, redaction, and wide events while operating in the same speed class. In pino, you need to assemble pino-pretty, pino-http, and custom transports for these. In wide event lifecycles, evlog is 7.7x faster than pino (1.58M ops/s vs 206K ops/s). pino may have a slight advantage in standalone log.info('hello') calls, but wide event usage is common in real applications.

Against winston: evlog is a more modern, faster, and richer option for new TypeScript projects. winston remains in the past with its aging structure and insufficient TypeScript support.

Against consola: consola is a powerful pretty-print tool for CLI environments. But when you go to production, there is no drain pipeline, sampling, or wide event support. evlog offers both beautiful output in development and structured JSON in production.

But evlog does not claim to be superior in everything. Among the acknowledged gaps are runtime level mutation (like logger.level = 'debug' in pino), custom levels, and async I/O worker thread support. These trade-offs are deliberate choices to keep the library simple and focused.

Future: The Foundations of AI-Native Observability

evlog's roadmap goes beyond being just a logging library. Features like AI SDK integration, agent capabilities (Cursor, Claude, ChatGPT plugins), and Better Auth integration are signs that the library is transforming into an observability platform.

Let's think about the performance revolution FlashQLA started on edge devices and Mojo 1.0 Beta increasing Python performance by 68,000x. Such leaps enable AI applications to become smaller, faster, and more distributed. But this distribution also makes observability even more challenging. This is exactly where tools like evlog, which are based on wide events and AI-ready, gain critical importance.

In a world where artificial intelligence agents work autonomously, thousands of microservices begin to communicate, and data flows from edge to cloud, traditional logging approaches collapse. evlog is one of the rare open source projects that foresees this collapse and offers a solution.

Conclusion: Log Digging Is a Thing of the Past

evlog's slogan, Digging through logs is not observability. It's hope., defines the bitter truth of the modern software development world. Traditional logging is nothing more than hoping. We hope to find the right log, we hope to establish correlation, we hope to fix the error.

evlog transforms this hope into data and structure. With wide events, it presents the full story of each request in a single event. With structured errors, it not only reports errors but also shows the solution path. With AI SDK integration, it illuminates the black box of LLM calls. With support for 13 frameworks, it offers ecosystem independence.

If you are starting a new TypeScript project or considering modernizing your existing logging infrastructure, evlog is an option that should be seriously evaluated. The quick start guide in the official documentation allows you to set up a working example in minutes. The GitHub repository is open under the MIT license. Contributing, reporting bugs, or simply examining the code is completely free.

In the age of artificial intelligence, observability is not just an option but a necessity. evlog is one of the ways to fulfill this necessity in the lightest, fastest, and most structured way. It is time to stop digging through logs and start widening events.

Efe Hüseyin Özkan

Software Engineer & AI Developer

Working on AI systems, full-stack development, and scalable product architecture. Follow the blog for more technical articles.