Unhandled exceptions logged as undefined in winstonJs

Viewed 29

If I enable stack: true, then logged unhandled exceptions and rejections are undefined in the log files. Nothing is even printed via console. If I remove stack: true, then output is logged in files and printed via console BUT definitely loose the stack trace and message of the Error object.

The following is my config:

import { ENVIRONMENT } from '../config/constants'
import { createLogger, format, transports, addColors } from 'winston'
import path from 'path'

const { combine, timestamp, printf, errors, colorize } = format

// Log directory path
const logDirectory      = path.join(__dirname, '../../logs')

// Log Formats
const httpRequestFormat = printf(i => {
  const { timestamp, message } = i
  const parsedMessage = JSON.parse(message)
  const {
    ip,
    method,
    url,
    httpVersion,
    headers
  } = parsedMessage

  // TODO Check if we are logging correct IP of user
  return `[${timestamp}]:  ${method}  ${url}  HTTP/${httpVersion}  ${headers.referrer ?? '-'}  ${headers['user-agent']}  ${ip}`
})

const errorFormat = printf(i => {
  const { timestamp, message, statusCode, stack } = i

  return `[${timestamp}]:  ${statusCode ?? ''}  ${message}  ${stack ?? ''}`
})

const consoleFormat = printf(i => {
  const { timestamp, level, message, statusCode, stack } = i

  if (/http/.test(level)) {
    const parsedMessage = JSON.parse(message)
    return `${level} [${timestamp}]:  ${parsedMessage.method}  ${parsedMessage.url}`
  } else if (/error/.test(level)) {
    return `${level} [${timestamp}]:  ${statusCode ?? '---'}  ${message}  ${stack ?? '---'}`
  } else {
    return `${level} [${timestamp}]:  ${message}`
  }
})

// Filters
const httpFilter = format((info, opts) => {
  return info.level === 'http' ? info : false
})

const errorFilter = format((info, opts) => {
  return info.level === 'error' ? info : false
})

// Transports
const consoleTransport = new transports.Console({
  format: combine(
    colorize(),
    timestamp({
      format: 'YYYY-MM-DD HH:mm:ss'
    }),
    consoleFormat
  )
})

const httpRequestTransport = new transports.File({
  level: 'http',
  filename: `${logDirectory}/httpRequests.log`,
  format: combine(
    httpFilter(),
    timestamp({
      format: 'YYYY-MM-DD HH:mm:ss'
    }),
    httpRequestFormat
  )
})

const errorTransport = new transports.File({
  level: 'error',
  filename: `${logDirectory}/errors.log`,
  format: combine(
    errorFilter(),
    timestamp({
      format: 'YYYY-MM-DD HH:mm:ss'
    }),
    errorFormat
  )
})

const exceptionTransport = new transports.File({
  filename: `${logDirectory}/exceptions.log`
})

const rejectionTransport = new transports.File({
  filename: `${logDirectory}/rejections.log`
})

const logger = createLogger({
  level: ENVIRONMENT === 'PROD' ? 'info' : 'debug',
  format: combine(
    errors({ stack: true })
  ),
  transports: [
    httpRequestTransport,
    errorTransport,
    consoleTransport
  ],
  exceptionHandlers: [exceptionTransport],
  rejectionHandlers: [rejectionTransport],
  handleExceptions: true,
  handleRejections: true
})

addColors({
  debug: 'yellow',
  info: 'blue'
})

export default logger
0 Answers
Related