sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

Feature Request: Support For Automatically Generating Breadcrumbs With Pino

Open souredoutlook opened this issue 4 years ago • 1 comments

Customer asking - wrote in with the following snippet for @sentry/node:

import { Router } from 'express'
import pino from 'pino'

const logger = pino({level: 'info'});

const object = {
  id: '123',
  name: 'My Object'
}

export const objectRouter = new Router({ mergeParams: true})

objectRouter.get('/', (req, res) => {
  const { id } = req.params

  console.log(`Fetching object:${id}`) // <-- this shows up as breadcrumb
  logger.info(`Fetching object:${id}`) // <-- this doesn't

Breadcrumbs from logging currently only support the 'console' module.

souredoutlook avatar Nov 29 '21 19:11 souredoutlook

We probably need to build an integration for pino similar to https://github.com/getsentry/sentry-javascript/blob/master/packages/node/src/integrations/console.ts to make this work.

AbhiPrasad avatar Nov 29 '21 19:11 AbhiPrasad

I'm trying to do some work on this. I've looked at the console.ts file and seen how sentry is integrating to the console object. One thing that I don't fully understand is the import * as util from 'util'; line. What import is this getting?

Lilja avatar Jan 17 '23 14:01 Lilja

@Lilja that is importing the util node standard library: https://nodejs.org/api/util.html

AbhiPrasad avatar Jan 17 '23 15:01 AbhiPrasad

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

github-actions[bot] avatar Feb 08 '23 00:02 github-actions[bot]

Until an official integration exists, here's a simple bridge between pino and the console log methods:

import pino from 'pino'
import { Writable } from 'node:stream'

// By default, pino uses the `process.stdout` stream, which is not instrumented
// by Sentry. Sentry does instrument the methods on the `console` object, so we
// set up these streams to use the `console` object instead of `process.stdout`.
// This way, pino logs will be sent to Sentry.

function createConsoleStream(level: 'info' | 'warn' | 'error') {
  return new Writable({
    write(chunk: Buffer, _encoding, callback) {
      // Both pino and the console methods add a trailing newline, so we slice
      // off one character to avoid double newlines in the logs.
      const msg = chunk.toString().slice(0, -1)
      console[level](msg)
      callback()
    },
  })
}

const consoleInfoStream = createConsoleStream('info')

const consoleWarnStream = createConsoleStream('warn')

const consoleErrorStream = createConsoleStream('error')

export const logger = pino(
  {
    level: 'info',
  },
  pino.multistream(
    [
      { stream: consoleInfoStream },
      { level: 'warn', stream: consoleWarnStream },
      { level: 'error', stream: consoleErrorStream },
      { level: 'fatal', stream: consoleErrorStream },
    ],
    { dedupe: true }
  )
)
  • fatal and error -> console.error
  • warn -> console.warn
  • info -> console.info

Other log levels (if the level option allows) will also go to console.info. If you want to set a different stream for those, the streams array can be expanded. Though be aware that pino.multistream requires that the logger's level option be set to the lowest level used in the streams array.

mickdekkers avatar Mar 14 '24 08:03 mickdekkers