Winston: El método de registro de errores no registra la instancia de error correctamente

Creado en 9 oct. 2018  ·  29Comentarios  ·  Fuente: winstonjs/winston

Cuéntanos sobre tu entorno:

  • _ winston versión?_ 3.1.0

    • [ ] winston@2

    • [x] winston@3

  • _ node -v salidas:_ v8.11.3

  • _¿Sistema Operativo?_ Linux

  • _¿Idioma?_ todo

¿Cuál es el problema?

logger.error llamado con la instancia Error no usa los campos message y stack , sino que registra la prueba error .

Ejemplo de código:

const winston = require('winston');

const alignedWithColorsAndTime = winston.format.combine(
  // winston.format.colorize({ all: true }),
  // winston.format.timestamp(),
  // winston.format.align(),
  winston.format.printf((info) => {
    const { level, message, ...args } = info;

    if (level.indexOf('error') !== -1) {
      console.log(typeof message, JSON.stringify(message));
    }

    return `[${level}]: ${message} ${Object.keys(args).length ? JSON.stringify(args, null, 2) : ''}`;
  })
);

const transports = [new winston.transports.Console({
  level: 'debug',
  format: alignedWithColorsAndTime
})];

const logger = winston.createLogger({
  level: 'debug',
  transports
});

try {
  logger.info('aaaaa');
  logger.debug('bbbb');
  logger.error('eeee');

  throw new Error('Scary error');
} catch (error) {
  logger.error(error);
}

¿Qué esperas que suceda en su lugar?

Al menos se registró un mensaje de error real. Idealmente, con pila.

Comentario más útil

Entonces, resulta que estaba equivocado sobre el formateador de errores. Todavía no está en Winston, pero está en [email protected] , y debe usarlo en combinación con los formateadores metadata y json .

Entonces, sí, muchas advertencias para que funcione. Sería mejor si pudieras usarlo solo, pero es mejor que nada.

const winston = require('winston');
const { format } = require('logform');

const logger = winston.createLogger({
  format: format.combine(
    format.errors({ stack: true }),
    format.metadata(),
    format.json(),
  ),
  transports: [ new winston.transports.Console() ],
});

logger.error(new Error(FakeError));

Todos 29 comentarios

No depende del formateador printf , simple da el mismo resultado. Evento sin formateador devuelve mensaje vacío.

Problema probablemente relacionado # 1422

Tuve el mismo problema, tuve que implementar logger.error yo mismo:

  logger.error = err => {
      if (err instanceof Error) {
        logger.log({ level: 'error', message: `${err.stack || err}` });
      } else {
        logger.log({ level: 'error', message: err });
      }
    };

@gtsec en realidad hice casi lo mismo, solo usé el nuevo nombre de método .exception .

Esto podría deberse a wintson-transport , consulte https://github.com/winstonjs/winston-transport/issues/31 para conocer el problema y https://github.com/winstonjs/winston-transport/pull/ 34 para el PR.

En un repositorio de muestra donde estoy probando la migración winston-graylog2 para usar winston@3x , terminé implementando la conversión de error como un formateador personalizado.

const errorFormatter = format((info, opts) => {
  let formatted = {};

  if (info instanceof Error) {
    // An error object is not 100% like a normal object, so
    // we have to jump through hoops to get needed info out
    // of error objects for logging.
    formatted = Object.assign(formatted, info);
    formatted.message = info.stack;
  } else {
    formatted = info;
  }

  return formatted;
});

Sin embargo , para una experiencia consistente, sería beneficioso si este manejo se hiciera dentro del método de error del registrador, en lugar de depender de formateadores personalizados (inconsistentes de un proyecto a otro) o volver a implementar/sobrescribir los métodos de la biblioteca (súper inseguro y pirateado). ).

En realidad, acabo de darme cuenta de que el objeto de formato winston predeterminado tiene un controlador de errores, por lo que solo necesita adjuntarlo como formateador.

https://github.com/winstonjs/logform#errors

¿Ejemplo?

Entonces, resulta que estaba equivocado sobre el formateador de errores. Todavía no está en Winston, pero está en [email protected] , y debe usarlo en combinación con los formateadores metadata y json .

Entonces, sí, muchas advertencias para que funcione. Sería mejor si pudieras usarlo solo, pero es mejor que nada.

const winston = require('winston');
const { format } = require('logform');

const logger = winston.createLogger({
  format: format.combine(
    format.errors({ stack: true }),
    format.metadata(),
    format.json(),
  ),
  transports: [ new winston.transports.Console() ],
});

logger.error(new Error(FakeError));

Solución ingeniosa @ jeremy-j-ackso

Sugiriendo que esto se cierre debido a # 1576.

Puede utilizar los formateadores.

const winston = require('winston');
const { format } = winston;

const logger = winston.createLogger({
  format: format.combine(
    format.errors({ stack: true }),
    format.metadata(),
    format.json(),
  ),
  transports: [ new winston.transports.Console() ],
});

logger.error(new Error('FakeError'));

¡Sí, los errores finalmente deberían poder registrarse de una manera agradable para las personas que desean activar esa funcionalidad!

Si bien este enfoque funciona principalmente, no parece proporcionar una manera fácil de registrar errores en un formato de texto como simple(). Parece un caso de uso muy común, y sería maravilloso si hubiera una forma estándar, libre de problemas y obstinada de hacerlo.

Aprecio el deseo de un formato único para todos, hazlo todo por mí, hazlo mágico, no me hagas pensar. Es una trampa en la que es fácil caer, y es por eso que winston@2 y las líneas de lanzamiento anteriores tuvieron un rendimiento tan terrible en comparación con otras bibliotecas de registro. Simplemente trató de hacer demasiado por defecto para satisfacer las demandas de funciones de un gran conjunto de usuarios con diferentes opiniones y gustos.

Como proyecto, winston@3 encarna una nueva opinión: impulsar el formato complejo en formatos de un solo propósito desacoplados y hacer que la combinación sea fácil para los usuarios.

Admito que todavía queda trabajo por hacer en la documentación, junto con explicaciones de alto nivel y depuración de formatos.

Todo lo dicho, el formato de errores sugerido refleja la opinión del proyecto: ¿Se puede implementar esto como un formato personalizado?

@DABH ¿por qué cerraste este problema? El uso del formateador sugerido por @jeremy-j-ackso no funciona sin el formateador format.json() . Ni siquiera es una solución.

const winston = require('winston');
const { format } = winston;

const logger = winston.createLogger({
  format: format.combine(
    format.errors({ stack: true }),
    format.metadata()
  ),
  transports: [ new winston.transports.Console() ],
});


function a() {
  throw new Error('Error from "a"');
  console.log('a()');
}

function b() {
  a();

  console.log('a() called from b()');
}

function c() {
  b();

  console.log('b() called from c()');
}

function f() {
  try {
    c();

    console.log('c() called from d()');
  } catch(error) {
    logger.error(error);
  }
}

f();
$ node 1.js
Error from "a"

Probado en [email protected] .

Sí, estoy de acuerdo con @nosuchip : no parece haber una buena solución si desea usar el formato simple() . De hecho, necesitamos a ambos para trabajar en un proyecto que tengo. Terminé creando un formateador personalizado que funciona pero es un poco complicado. Este código me da una pila en json cuando uso ese formato y una pila en texto sin procesar cuando uso un formato simple:

const displayStack = winston.format((info) => {
  info.message = info.stack ? info.stack : info.message
  return info
})

const consoleDebugFormat = winston.format.combine(
  displayStack(),
  winston.format.simple()
)

const jsonFormat = winston.format.combine(
  winston.format.errors({ stack: true }),
  winston.format.json()
)

const activeFormat = process.env.LOG_FORMAT === 'simple' ? consoleDebugFormat : jsonFormat

const loggerConsole = new winston.transports.Console()
const logger = winston.createLogger({
  transports: [loggerConsole],
  format: activeFormat,
  exitOnError: false
})

Entonces, ¿todavía no hay una solución para este problema?

@cogscape lamentablemente no. Acabo de probar el último Winston y ninguna solución encontrada en Internet dio un mensaje de error de salida y la pila. Excepto el método personalizado, por supuesto.

Para TypeScript, estoy usando el siguiente fragmento para evitar escribir advertencias:

... 
// standard transports and format initialization

export interface BetterLogger extends winston.Logger {
    exception: (error: Error, prefix?: string) => BetterLogger;
}

const logger: BetterLogger = winston.createLogger({
    level: config.logLevel,
    transports,
}) as BetterLogger;

// Monkey patching Winston because it incorrectly logs `Error` instances even in 2020
// Related issue: https://github.com/winstonjs/winston/issues/1498
logger.exception = function (error, prefix?) {
    const message = error.message || error.toString();
    const stack = error.stack;
    prefix = prefix ? `${prefix} ` : '';

    return this.error(`${prefix}${message}, stack ${stack}`) as BetterLogger;
};

export default logger;

Funciona con cualquier otro formateador.

Razón: el intento de implementar el formateador actual siempre termina con falla ya que info pasó al formateador nunca instanceof Error .

No puedo registrar ningún error significativo:

import winston from 'winston';
const consoleTransport = new winston.transports.Console({
    format: winston.format.combine(
        winston.format.errors({ stack: true }),
        winston.format.metadata(),
        winston.format.json(),
    )
});
export const logger = winston.createLogger({
    transports: [
        consoleTransport,
    ]
});

Solo registra este bit triste:
{"level":"error","metadata":{}}

simplemente usar simple es casi mejor ya que produce el doble de información:
error: undefined

Lo que necesito:

TypeError: Cannot read property 'check' of undefined
    at Object.updateSession (U:\Users\muj\endpoint\src\services\cookieService.ts:88:23)

¿Hay alguna forma de obtener a través de Winston la información que el nodo imprime automáticamente cuando detecta un error no controlado?

¿Alguna actualización?

Me di cuenta de que el motivo es que Object.assign({}, info) no copia la propiedad de la pila en:

https://github.com/shrinktofit/editor-3d/blob/5afb36943c4f4fd9a145d82cd4bd44cd6b188242/app/node_modules/winston-transport/index.js#L91

así que básicamente, si quiero el seguimiento de la pila, tengo que

  1. use el formateador de errores con los formateadores json y meta y obtenga un registro del formateador json
  2. o implementar mi propio formateador personalizado para obtener una salida de registro de texto simple
    estoy en lo cierto o me estoy perdiendo algo??

Es 2021 y todavía no funcionó para las instancias de error. Dejé de usar esto.

Esto es un up, ya que creo que esto se debe tener en cuenta.
Actualicé winston de 2 a 3, pero ahora estoy bajando a 2 debido a esto.
@DABH vuelve a abrir este problema
gracias por tu trabajo

Este es un problema muy crítico para nuestra aplicación, usamos winston y cuando ocurren errores, no hay forma de ver la pila sin modificar el .error

Este es un problema muy crítico para nuestra aplicación, usamos winston y cuando ocurren errores, no hay forma de ver la pila sin modificar el .error

Tengo el mismo problema

¡Hola chicos!
Hice una solución para eso en formato errors .
https://github.com/winstonjs/logform/pull/118

¿Fue útil esta página
0 / 5 - 0 calificaciones