Pino Logs installation
Contents
Send your existing Pino logs to PostHog with the OpenTelemetry Pino instrumentation. You don't need to change your logger calls. Requires Pino v7 to v10.
- 1
Install OpenTelemetry packages
RequiredTerminal - 2
Get your project token
RequiredYou'll need your PostHog project token to authenticate log requests. This is the same key you use for capturing events and exceptions with the PostHog SDK.
Important: Use your project token which starts with
phc_. Do not use a personal API key (which starts withphx_).You can find your project token in Project Settings.
- 3
Create an instrumentation file
RequiredCreate an
instrumentation.jsfile. It starts the OpenTelemetry SDK and tells it to send every Pino log to PostHog.instrumentation.jsIf your app already handles
SIGTERM(for example, to drain open requests), don't add a second handler. Exportsdkand callawait sdk.shutdown()at the end of your existing shutdown code instead. - 4
Load the instrumentation before your app
RequiredThe instrumentation must load before your app imports
pino. Otherwise it can't patch Pino and no logs are sent. Use the--requireflag when you start your app:TerminalIf you can't change the start command (for example, on a hosting platform), set
NODE_OPTIONSinstead:TerminalIf your app uses ES modules
--requiredoesn't patchimportstatements. Install the OpenTelemetry instrumentation package:TerminalName the file
instrumentation.mjs, change therequirecalls toimportstatements, and register the OpenTelemetry loader hook before you start the SDK:instrumentation.mjsThen start your app with
--import:Terminal - 5
Use your Pino logger
RequiredKeep using Pino as before. Your logs still go to their usual destination, and a copy goes to PostHog:
JavaScriptPostHog receives each Pino record like this:
Pino PostHog Logs Message ( msg)Log body Level ( info,warn,error, etc.)Severity Object fields and child logger bindings Log attributes Errorobjectsexception.type,exception.message, andexception.stacktraceattributesTo link logs to a person and their session replay, add the
posthogDistinctIdandsessionIdfields. A child logger adds them to every log in a request:JavaScript - 6
Next steps
CheckpointWhat you can do with your logsAction Description Why you need logs What logs show you that nothing else does Search logs Use the search interface to find specific log entries Filter by level Filter by INFO,WARN,ERROR, etc.Link session replay Connect logs to users and session replays by passing posthogDistinctIdandsessionIdLink logs to a person Surface every log emitted on behalf of a user on their PostHog person profile Logging best practices Learn what to log, how to structure logs, and patterns that make logs useful in production
Troubleshooting
Logs not appearing in PostHog
- Make sure the instrumentation file loads before
pino. If your app uses ES modules, you need the--importflag and the loader hook. - Check your Pino version. Log sending requires Pino v7 to v10.
- The SDK sends logs in batches, so a short-lived script that ends on its own loses the last batch. Add
module.exports = sdk;toinstrumentation.jsand callawait require('./instrumentation').shutdown()before the script ends.
For general Logs troubleshooting (authentication, connection issues, format problems), see the Logs troubleshooting guide.











