Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Structured logging for Next.js
Arcjet profile imageDavid Mytton
David Mytton forArcjet

Posted on • Originally published atblog.arcjet.com on

Structured logging for Next.js

Next.js is a powerful framework for building modern web applications, but it doesn't ship with a robust logging solution out of the box. The first place you’ll start is probablyconsole.log. It works consistently across client and server and can easily print most JavaScript objects (docs). You can also use other console functionality such astimers.

However, If you've ever found yourself digging through console logs in production, struggling to pinpoint errors, or wishing you had more insight into how users interact with your app, you know the pain.

AtArcjet, we already havestructured logging for our Go backend. Piped into Datadog, it’s easy to search for a specific user or trace ID because each log line has various attributes attached, including the user ID. We wanted to do the same with our web app, so we spent some time switching Next.js to structured JSON logging.

In this post, we'll walk you through implementing structured logging in Next.js.

Structured logging for Next.js
Screenshot of Next.js logs generated by Pino and displayed in the Orbstack container log viewer.

Automatically patched globals with next-logger

When searching for a structured logging solution for Next.js, you might stumble uponnext-logger. This library conveniently patches the logging mechanisms used by Next.js, allowing you to continue usingconsole.log without any code changes. It automatically formats your logs as JSON and adds useful metadata like hostname and timestamp.

Implementation is easy: start your Next.js server withNODE_OPTIONS='-r next-logger' next start and you’re done!

A simple modification to your package.json:

"scripts":{"start":"NODE_OPTIONS='-r next-logger' next start",// ...your other scripts},
Enter fullscreen modeExit fullscreen mode

This works well if you are running your own Next.js server in a Docker container or self-hosted somewhere. However, if you’re deploying on a service likeVercel or Netlify then this won’t work. You can’t control theNODE_OPTIONS on those platforms.

This led us to explore more customizable options.

Custom Next.js logs with pino

The next library I found waspino, which is a fast logger for JS. It supports log levels, different output formats, and has a nicepretty-print plugin for local logging with colorized output.

Pino is a high-performance logging library for Node.js that offers the flexibility and customization we needed at Arcjet. It supports log levels, different output formats, and has a handypretty-print plugin for development environments. It even allows you toredact fields by JSON path.

While Pino doesn't have out-of-the-box support for Next.js, it's easy to integrate witha few tweaks. Here's how:

Installation

npminstallpino pino-pretty
Enter fullscreen modeExit fullscreen mode

Next.js configuration

In yournext.config.js file, add pino and its pretty-print plugin to theserverComponentsExternalPackages array:

experimental:{serverComponentsExternalPackages:["pino","pino-pretty"],},
Enter fullscreen modeExit fullscreen mode

Create a logger utility

To streamline logging across your codebase, create a utility file (e.g.,lib/logger.ts) that configures Pino with the desired output format and log level:

importpino,{Logger}from"pino";exportconstlogger:Logger=process.env["NODE_ENV"]==="production"?// JSON in productionpino({level:"WARN"}):// Pretty print in developmentpino({transport:{target:"pino-pretty",options:{colorize:true,},},level:"debug",});
Enter fullscreen modeExit fullscreen mode

Then in each file where you want to log, importlogger and create a child logger. This allows you to set attributes which appear on every log line, which we use to identify the module:

import{logger}from"@/lib/logger";constlog=logger.child({module:"totoro"});
Enter fullscreen modeExit fullscreen mode

Logging

Then we can use the logger:

log.debug("called");
Enter fullscreen modeExit fullscreen mode

And if we want to include additional attributes then they come first:

log.debug({"magic":"hats"},"a log line");
Enter fullscreen modeExit fullscreen mode

Pinohas a lot more options, but this will get you started.

Conclusion

Pino is known for its high performance which is important for production environments where you want minimal overhead for your logging. It also gives you fine-grained control so you can output JSON in production to make it easy to search on fields, but pretty-print in development.

This has been working well for us in production so we now have consistent JSON logging for both frontend (Next.js) andbackend (Go). Let us know if you’ve found other improvements we should consider!

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Security as code

Try Arcjet Today! It's free, and only takes minutes to implement robust security measures in your web applications. What are you waiting for?

More fromArcjet

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp