This repo has two libraries, @navikt/pino-logger for logging in a node/bun/deno server environment, and @navikt/next-logger for isomorphic logging in a Next.js application.
- Docs for @navikt/pino-logger - A pino logger for node/bun/deno
- Docs for @navikt/next-logger - An isomorphic logger for Next.js applications
Go to migrations from v1 to v2/3
Go to migrations from v3 to v4
An simple logger that lets you log in your server runtime. Logs in a JSON format that logs.adeo.no understands. And all logs are grouped under your application (+application:yourapp
) with correct log level.
yarn add @navikt/pino-logger pino
npm i @navikt/pino-logger pino
if you want to use the team logs, you also need to
install pino-socket
:
yarn add pino-socket
npm i pino-socket
if you want to use the deprecated secure logger (don't, use team logs), you also need to install pino-roll
:
yarn add pino-roll
npm i pino-roll
Anywhere in your application where you want to log, you should import import { logger } from '@navikt/pino-logger';
,
this is a pino instance, use it to log, for example:
logger.warn("Uh oh")
.
Alternatively, if you need secure logging, use ìmport { teamLogger } from '@navikt/pino-logger/team-logs';
.
See Team Logs for more information on secure logging.
If you want pino-pretty for local development (and you probably do, simply install it and pipe it:
yarn add -D pino-pretty
npm i --save-dev pino-pretty
Simply pipe the output of your development server into pino pretty with correct message key:
"scripts": {
"dev": "<your server> | pino-pretty --messageKey=message",
}
An isomorphic logger that lets you log from both the frontend and the backend. Both will log in a JSON format
that logs.adeo.no understands. And all logs are grouped under your application (+application:yourapp
) with correct log level.
Now with SecureLogs support!
yarn add @navikt/next-logger pino
npm i @navikt/next-logger pino
if you want to use the secure logger, you also need to install pino-roll
:
yarn add pino-roll
npm i pino-roll
You need an API route that will receive all the log statements from the frontend.
For app dir:
Create a new API route /app/api/logger/route.ts
, it should look like this:
export { POST } from '@navikt/next-logger/app-dir'
For pages dir:
Create a new API route /pages/api/logger.ts
, it should look like this:
export { loggingRoute as default } from '@navikt/next-logger/pages'
Anywhere in your application where you want to log, you should import import { logger } from '@navikt/next-logger';
,
this is a pino instance, use it to log, for example:
logger.warn("Uh oh")
.
Alternatively, if you need secure logging, use ìmport { teamLogger } from '@navikt/next-logger/team-logs';
.
See Team Logs for more information on secure logging.
If you want pino-pretty for local development (and you probably do, simply install it and pipe it:
yarn add -D pino-pretty
npm i --save-dev pino-pretty
Simply pipe the output of your development server into pino pretty:
"scripts": {
"dev": "next dev | pino-pretty --messageKey=message",
}
Step 4 (Optional): Integrating with next-logger
The pino configuration from this library can be shared with next-logger.
Simply create a next-logger.config.js
in the root of your project, and re-export the logging config as following:
const { backendLogger } = require('@navikt/next-logger')
module.exports = {
logger: backendLogger,
}
You want this configuration to execute as early as possible, but on the actual client. Typically in your app-dir app,
you will have for example a <Providers>
-client that is "use client"
-enabled.
On the root of any "use client"
-enabled file that wraps your root layout.tsx, you can configure the library, for
example:
"use client"
configureLogger({
basePath: '/my/base/path',
})
export function MyProviders(): ReactElement {
...
}
If your application is using a base path, or you want to have your logger on a different API-route, you can configure the logger.
In your _app.tsx
, on root in the file, you can use configureLogger
as such:
configureLogger({
basePath: '/my/base/path',
apiPath: '/api/other-logger',
})
Or if you only want to change the base path:
configureLogger({
basePath: '/my/base/path',
})
If you want to log sensitive information, this will ship the logs to nais' "Team Logs" instead of the default logs. This is useful for logging sensitive information that you don't want to be publicly available.
See the team log docs for details on how to enable it for your app.
This library uses the pino-socket
library to send logs to the team logs over TCP to the nais' team log ingester.
Using team logger as an isomorphic logger requires an additonal API-route in your next app, the configuration is similar to the primary logger route.
For app dir:
Create a new API route /app/api/team-logger/route.ts
, it should look like this:
export { POST } from '@navikt/next-logger/team-log/app-dir'
For pages dir:
Create a new API route /pages/api/team-logger.ts
, it should look like this:
export { pinoLoggingRoute as default } from '@navikt/next-logger/team-log/pages'
If you need to add some extra metadata to team log statements server side, you can add an metadata-middleware to extract info from the request:
App dir
import { withMetadata } from '@navikt/next-logger/team-log/app-dir'
import { UAParser } from 'ua-parser-js'
export const POST = withMetadata((request) => {
const userAgent = request.headers.get('user-agent')
if (!userAgent) return { platform: 'unknown' }
const ua = UAParser(userAgent)
return {
platform: ua.device.type ?? 'unknown',
}
})
Pages
import { withMetadata } from '@navikt/next-logger/team-log/pages'
import { UAParser } from 'ua-parser-js'
export default withMetadata((req) => {
const userAgent = request.headers.get('user-agent')
if (!userAgent) return { platform: 'unknown' }
const ua = UAParser(userAgent)
return {
platform: ua.device.type ?? 'unknown',
}
})
Remember not to parse the body using .json()
or .text
!
This feature is available only for team-log and secure-log.
If you want to log sensitive information, you can use the secureLogger
function. This will instead of logging to
stdout log to a file on /secure-logs.
This requires some setup, see nais docs for how
to enable secure logging in your app.
The log file is setup with pino-roll for rolling the logs based on file size.
For more details on how to configure the required API-routes for secure logging, see the team log section above, but replace the imports with the secure logger imports.
Remember secure logs are being deprecated in favor of team logs, so you should not use this feature in new applications.
The only breaking change is that the paths for the API routes have been updated.
v2→v3 has no breaking changes, but changed how the library was built.
app/api/logger/route.ts
:
- export { POSTLoggingRouteHandler as POST } from '@navikt/next-logger'
+ export { POST } from '@navikt/next-logger/app-dir'
pages/api/logger/route.ts
:
- export { pinoLoggingRoute as default } from '@navikt/next-logger'
+ export { loggingRoute as default } from '@navikt/next-logger/pages'
If you want to use the new secureLogger feature, refer to the Securelogs docs above.
The only change is that the default message key is message
instead of msg
. This doesn't affect you
if you only view logs in Elastic, but if you have used some manual filters in Grafana ({{ .msg }}
), you will need to
change it to {{ .message }}
.
If you use pino-pretty
you will also need to change the --messageKey
option to message
instead of msg
.
"scripts": {
"dev": "<dev> | pino-pretty --messageKey=message"
}