Forward Pino logs to LogFlow using a destination stream. Keep your existing Pino setup and get structured search, alerts, and anomaly detection on top.
Pino is the fastest Node.js logger — used by Fastify, NestJS, and high-throughput services. The LogFlow Pino integration works as a destination stream, so Pino continues writing JSON at full speed and LogFlow picks it up automatically.
pino v6, v7, v8, or v9)npm install @getlogflow/js
import pino from 'pino'
import { createLogFlowStream } from '@getlogflow/js/transports/pino'
const logger = pino(
{ level: 'info' },
createLogFlowStream({
apiKey: process.env.LOGFLOW_API_KEY!,
service: 'api', // rename to your service
environment: process.env.NODE_ENV,
release: process.env.APP_VERSION, // optional
})
)
export default logger
Add your API key to .env:
LOGFLOW_API_KEY=lf_your_api_key_here
Pino encourages putting data in the first object and the message second:
logger.info({ userId: 'u_123', plan: 'starter' }, 'User signed up')
logger.warn({ ip: req.ip, limit: 100 }, 'Rate limit approaching')
logger.error({ err, orderId: 'ord_456' }, 'Payment failed')
All fields are preserved in LogFlow as searchable attributes.
In development you likely want Pino to print to stdout while also sending to LogFlow:
import pino from 'pino'
import pinoPretty from 'pino-pretty'
import { createLogFlowStream } from '@getlogflow/js/transports/pino'
const isDev = process.env.NODE_ENV !== 'production'
const logger = isDev
// Development: pretty print to console only
? pino({ level: 'debug' }, pinoPretty())
// Production: send to LogFlow
: pino(
{ level: 'info' },
createLogFlowStream({ apiKey: process.env.LOGFLOW_API_KEY!, service: 'api' })
)
Or use pino-multi-stream to send to both simultaneously:
import pino from 'pino'
import { multistream } from 'pino-multi-stream'
import { createLogFlowStream } from '@getlogflow/js/transports/pino'
const logger = pino(
{ level: 'info' },
multistream([
{ stream: process.stdout },
{ stream: createLogFlowStream({ apiKey: process.env.LOGFLOW_API_KEY!, service: 'api' }) },
])
)
Fastify has built-in Pino support. Pass the LogFlow stream as Fastify's logger:
import Fastify from 'fastify'
import { createLogFlowStream } from '@getlogflow/js/transports/pino'
const app = Fastify({
logger: {
level: 'info',
stream: createLogFlowStream({
apiKey: process.env.LOGFLOW_API_KEY!,
service: 'api',
environment: process.env.NODE_ENV,
}),
},
})
// Fastify's built-in request logging now goes to LogFlow
app.get('/users/:id', async (request, reply) => {
request.log.info({ userId: request.params.id }, 'Fetching user')
// ...
})
Fastify automatically logs every request with method, url, status, and response time.
Add a traceId to all logs from a single request using Pino's child logger:
app.addHook('onRequest', async (request) => {
request.traceId = request.headers['x-trace-id'] || crypto.randomUUID()
request.log = request.log.child({ traceId: request.traceId })
})
In LogFlow, click View trace to see the entire request flow grouped by traceId.
Restart your app and make a request. Open LogFlow → Live Tail — logs appear within a few seconds.
Does this affect Pino's performance? The stream writes are synchronous from Pino's side. The actual HTTP requests to LogFlow happen asynchronously in the background, so there's no blocking.
What if LogFlow is down? Logs are queued in memory and retried automatically. If the queue fills up (default 1000 logs), the oldest are dropped.
Pino levels vs LogFlow levels
Pino numeric levels map to LogFlow as follows: 10 (trace) → trace, 20 → debug, 30 → info, 40 → warn, 50 → error, 60 → fatal.
Free plan available. No credit card required. Up and running in 2 minutes.
Get started freeLogging in Python with LogFlow
Add production-ready structured logging to any Python application and ship logs to LogFlow.
Structured Logging in Flask
Add production-ready structured logging to any Flask app in under 10 minutes.
Structured Logging in Laravel
Add production-ready structured logging to Laravel and ship logs to LogFlow.