/**
 * Sentry stream for Bunyan. Modified from https://github.com/transcovo/bunyan-sentry-stream
 * for compatibility with new API
 */ import * as Sentry from '@sentry/node' ; import type { Stream } from 'bunyan' ; import { mapValues , pick } from 'lodash' ; interface SentryError extends Error { code ? : string ; signal ? : string ; } type BunyanRecord = { msg : string ; level : number ; err ? : Error ; code ? : string ; signal ? : number ; } ; param { Object } record return { String } function getSentryLevel ( record ) { const { level } = record ; if ( level >= 60 ) return Sentry . Severity . Critical ; if ( level >= 50 ) return Sentry . Severity . Error ; if ( level === 40 ) return Sentry . Severity . Warning ; return Sentry . Severity . Info ; } param { object } data return { Error } function deserializeError ( data ) { if ( data instanceof Error ) return data ; const error = new Error ( data . message ) ; error . name = data . name ; error . stack = data . stack ; if ( data . code ) error . code = data . code ; if ( data . signal ) error . signal = data . signal ; return error ; } type StreamConfig = { /** Array of properties to turn into tags */ tags ? : string [ ] ; /** Array of properties to turn into extra data */ extra ? : string [ ] ; } ; export default function getSentryStream ( config = { } ) { const tagProps = config . tags ?? [ ] ; const extraProps = config . extra ?? [ ] ; const stream = { write ( record ) { Sentry . withScope ( ( scope ) => { scope . setLevel ( getSentryLevel ( record ) ) ; scope . setTags ( mapValues ( pick ( record , tagProps ) , ( v ) => String ( v ) ) ) ; scope . setExtras ( mapValues ( pick ( record , extraProps ) , ( v ) => v ?? null ) ) ; if ( record . err ) { scope . setExtra ( 'msg' , record . msg ) ; Sentry . captureException ( deserializeError ( record . err ) ) ; } else { Sentry . captureMessage ( record . msg ) ; } } ) ; return true ; } , } ; return stream ; }