winstonjs / winston

A logger for just about everything.
http://github.com/winstonjs/winston
MIT License
22.39k stars 1.8k forks source link

[Bug]: HTTP transporter not logging warnings or errors #2426

Open eloisetaylor5693 opened 4 months ago

eloisetaylor5693 commented 4 months ago

🔎 Search Terms

HTTP error, http datadog, http warning

The problem

Info logs are successfully being sent to datadog, but error and warning logs are not.

Unhandled exceptions are being logged somehow though, just not errors I specifically log.

I see no errors in the console to explain why they are not being sent

[Update] the last logs before exiting disappear. Usually it's errors and warnings that don't get logged, perhaps because they are bigger log messages than other logs due to error stacktraces etc

What version of Winston presents the issue?

v3.10.0

What version of Node are you using?

v18.16.1

If this worked in a previous version of Winston, which was it?

No response

Minimum Working Example

import process from 'node:process'
import path from 'node:path'
import { hostname } from 'node:os'
import { config, createLogger, format, transports } from 'winston'

import type { HttpTransportOptions } from 'winston/lib/winston/transports'

const { combine, timestamp } = format

const nodeEnv = process.env.NODE_ENV ? process.env.NODE_ENV : 'development'
const filename = path.join('../log', `${nodeEnv}-log.log`)

const httpTransportOptions: HttpTransportOptions = {
  host: 'http-intake.logs.datadoghq.com',
  path: `/api/v2/logs?dd-api-key=${process.env.DATADOG_API_TOKEN}`,
  port: 443,
  ssl: true,
  handleExceptions: true,
  format: combine(timestamp(), format.json()),
  batch: false,
}

export const Logger = createLogger({
  level: 'debug',
  levels: config.npm.levels,
  defaultMeta: {
    ddsource: 'nodejs',
    service: 'my-service',
    node_env: `${process.env.NODE_ENV}`,
    version: process.env.DD_VERSION,
    hostname: hostname(),
  },
  transports: [
    new transports.Http(httpTransportOptions),
    new transports.Console({
      handleExceptions: true,
      format: format.combine(format.colorize(), format.simple()),
    }),
    new transports.File({
      filename,
      handleExceptions: false,
      format: combine(timestamp(), format.json()),
    }),
  ],
})

Additional information

No response

westberliner commented 4 months ago

Hi, I have more or less the same problem. Somehow my custom format won't apply if I use new transports.Http(httpTransportOptions, {format: myCustomFormat}). If I output it via transport.console it outputs valid JSON. But Datadog receives just an unformatted version of it. Maybe this info helps a bit.

Locking deeper into the API request I got this:

request! {
  service: 'my-service',
  context: 'foo',
  level: 'error',
  message: 'This is a server log',
  timestamp: '2024-03-15T06:55:18.096Z',
  [Symbol(level)]: 'error',
  [Symbol(splat)]: [ { context: 'foo' } ],
  [Symbol(message)]: 'my-service - - [2024-03-15T06:55:18.096Z] - [error]: This is a server log'
}
eloisetaylor5693 commented 4 months ago

I found it was the way I was exiting the app

I was using process.exit(1)

After googling around a stack overflow post suggested something similar to this

import process from 'node:process'
import { Logger } from '../logger/logger'

function sleep(milliseconds: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, milliseconds)
  })
}

/** Allows processes to finish before exiting.
 * Before this, winston HTTP transport logs weren't being sent to datadog when a process.exit() command was called
 */
export async function exitGracefully(
  exitCode: number,
  milliseconds: number = 1500
) {
  Logger?.debug('Exiting', { exit_code: exitCode })

  await sleep(milliseconds)

  process.exit(exitCode)
}