Pino HTTP Log Transport

0.4.2 · active · verified Wed Apr 22

pino-http-send is a basic handler for Pino logs that facilitates sending batches of structured log data to a desired HTTP or HTTPS endpoint. Currently at version 0.4.2, it is pre-v1, meaning minor version changes may introduce breaking changes. The library supports configurable HTTP methods (POST, PUT, PATCH, GET), two body types (JSON array wrapped in a 'logs' object or newline-delimited JSON), and includes basic authentication and retry mechanisms for failed sends. It can be used either as a command-line interface tool, piping `pino` output directly, or programmatically via its `createWriteStream` API, which acts as a Pino destination. Its key differentiators include its simplicity in setting up a direct HTTP log sink, batching capabilities to optimize network requests, and built-in retry logic, making it a robust, low-overhead option for forwarding Pino logs.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates programmatic usage of `pino-http-send` by creating a dummy HTTP server to receive logs and configuring Pino to send logs to it via `createWriteStream`.

import { createWriteStream } from 'pino-http-send';
import pino from 'pino';
import http from 'http';

// 1. Setup a dummy HTTP server to receive logs (your actual log ingestion endpoint)
const server = http.createServer((req, res) => {
  if (req.url === '/logs' && req.method === 'POST') {
    let body = '';
    req.on('data', (chunk) => { body += chunk.toString(); });
    req.on('end', () => {
      try {
        console.log(`\n--- Received Batch (${req.headers['content-type']}) ---\n`);
        if (req.headers['content-type']?.includes('application/json')) {
          console.log(JSON.parse(body).logs); // 'json' bodyType wraps logs in { logs: [...] }
        } else {
          console.log(body); // 'ndjson' is raw new-line delimited JSON
        }
        console.log(`--- End Batch ---\n`);
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ status: 'ok', receivedLogsCount: body.split('\n').filter(Boolean).length }));
      } catch (e) {
        console.error('Error parsing received logs:', e);
        res.writeHead(400).end('Bad Request');
      }
    });
  } else {
    res.writeHead(404).end('Not Found');
  }
});

server.listen(3000, () => {
  console.log('Dummy log server listening on http://localhost:3000');
  console.log('Sending logs via pino-http-send...');

  // 2. Configure pino-http-send as a Pino destination
  const pinoSendStream = createWriteStream({
    url: 'http://localhost:3000/logs',
    method: 'POST',
    bodyType: 'json', // or 'ndjson'
    batchSize: 2,      // Send every 2 logs
    timeout: 1000,     // or flush after 1 second if batch not full
    log: true,         // Enable internal logging for pino-http-send itself
    headers: { 'X-Custom-Header': 'pino-test' }
  });

  // 3. Create a Pino logger instance using the pino-http-send stream
  const logger = pino(pinoSendStream);

  let count = 0;
  const interval = setInterval(() => {
    logger.info({ id: ++count, service: 'my-app', event: 'data_processed', timestamp: new Date().toISOString() });
    if (count >= 5) {
      clearInterval(interval);
      logger.flush(); // Ensure any buffered logs are sent
      setTimeout(() => {
        server.close(() => console.log('Dummy server closed. Exiting.'));
      }, 2000); // Give time for the last batch to be sent
    }
  }, 500);
});

view raw JSON →