Winston: El registro en el archivo falla al llamar a process.exit (0)

Creado en 25 mar. 2013  ·  87Comentarios  ·  Fuente: winstonjs/winston

Cuando ha configurado winston para iniciar sesión en un archivo y llama a process.exit (0) en su código, winston nunca termina creando el archivo de registro y agregando los mensajes de registro al archivo.

En un mundo perfecto, winston manejaría felizmente este caso de borde y escribiría en el archivo, pero también estaría bien con poder llamar a flush en una instancia de registrador para forzar manualmente un flush en el archivo.

Puede haber alguna forma de 'vaciar' manualmente en este momento, pero no está documentado ni he tenido suerte con el cierre / finalización / destrucción manual de una instancia de registrador o sus flujos internos hasta ahora de una manera que realmente da como resultado los registros. siendo escrito en un archivo ..

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)(),
    new (winston.transports.File)({ filename: 'winston.log' })
  ]
});

logger.info('info logged');
logger.error('error logged');

process.exit(0);
// the two logs get written out to console, but not to the winston.log file/
bug important winston-file

Comentario más útil

@danielweck No, está roto: # 1629 # 1504!

6 años, eso es correcto, 6 años para un error marcado como _importante_. Es casi impresionante.

Todos 87 comentarios

En el nodo, los métodos de la consola. * Escriben de forma asíncrona, el transporte de archivos es asíncrono. Está cerrando el proceso antes de que el nodo haya escrito datos.

El lunes 25 de marzo de 2013 a las 19:45, Yuri Zapuchlak escribió:

Cuando ha configurado winston para iniciar sesión en un archivo y llama a process.exit (0) en su código, winston nunca termina creando el archivo de registro y agregando los mensajes de registro al archivo.
En un mundo perfecto, winston manejaría felizmente este caso de borde y escribiría en el archivo, pero también estaría bien con poder llamar a flush en una instancia de registrador para forzar manualmente un flush en el archivo.
Puede haber alguna forma de 'vaciar' manualmente en este momento, pero no está documentado ni he tenido suerte con el cierre / finalización / destrucción manual de una instancia de registrador o sus flujos internos hasta ahora de una manera que realmente da como resultado los registros. siendo escrito en un archivo ..
var winston = require ('winston'); var logger = new (winston.Logger) ({transportes: [nuevo (winston.transports.Console) (), nuevo (winston.transports.File) ({nombre de archivo: 'winston.log'})]}); logger.info ('información registrada'); logger.error ('error registrado'); process.exit (0); // los dos registros se escriben en la consola, pero no en el archivo winston.log /

-
Responda a este correo electrónico directamente o véalo en GitHub (https://github.com/flatiron/winston/issues/228).

Mmm. En ese caso, si uno debe matar un proceso de nodo pero necesita registrar información justo antes de matarlo, es poner el process.exit () dentro de un setTimeout () con una duración de tiempo suficientemente grande, lo único que se puede hacer para asegurar que winston realmente escribe mensajes en el archivo de registro?

Solo para mayor claridad, console.log y los amigos son sincrónicos .

@yzapuchlak En realidad, no he probado, pero eso es lo que también hago.

@yzapuchlak setTimeout _probablemente_ funcionará sin problemas, pero creo que sería prudente usar el parámetro de devolución de llamada opcional en su lugar.

setTimeout de 2000 o 5000 funciona en mi script de prueba simple, pero no cuando trato de usarlo en mi código real. Entonces, no sé qué tan confiable será esa posible solución. Profundizaré en ese problema más tarde si no tengo suerte en el frente de devolución de llamada opcional.

@dtex Acabo de intentar usar la devolución de llamada opcional (como se ve en el siguiente código de ejemplo), pero todavía no resulta en que los registros se escriban en el archivo. El archivo realmente se crea en este caso, pero no se escriben registros en él.

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)(),
    new (winston.transports.File)({ filename: 'winston.log' })
  ]
});

logger.info('winston - info logged');
logger.error('winston - error logged');

logger.info('winston - exiting now', { seriously: true }, function(err, level, msg, meta) {
  console.log('console - CALLING PROCESS EXIT');
  process.exit(0);
});

logger.warn('winston - I probably should only appear in console, not the log file?');

@yzaouchiak Curioso, ¿esa es la versión 0.6.2?

Ahora que tiene el mismo problema, debe finalizar el proceso y hacer una nota en el archivo de registro. Sería bueno tener la opción de devolución de llamada, que podríamos usar para salir del proceso solo después de que se haya escrito el mensaje. ¿O tal vez ya existe?

Tengo el mismo problema, con Winston 0.7.2.
Probé la solución alternativa setTimeout y callback sin ningún éxito.

Este es el mismo problema que el # 288 y también el problema del nodo log4js (https://github.com/nomiddlename/log4js-node/issues/148). Creo que el problema es que el bucle de eventos no se ejecuta una vez que la devolución de llamada process.exit ha finalizado, por lo que las llamadas asíncronas pendientes (como escrituras de archivos) no tienen la oportunidad de ejecutarse. Sería muy feliz si alguien pudiera demostrar que estoy equivocado y encontrar una solución.

Estoy dispuesto a dedicar tiempo a solucionar este problema si podemos encontrar una solución. El problema clave parece ser que WritableStreams no garantiza el vaciado en process.exit () o una excepción no controlada. ¿Se han investigado soluciones alternativas? Parece que podríamos almacenar en caché los registros en la memoria hasta que WritableStream se agote. Luego, si ocurre una excepción de process.exit o no detectada, podemos escribir sincrónicamente cualquier registro que no haya sido drenado. Esto podría producir registros duplicados, pero al menos evitaría la pérdida de registros. ¿Alguna idea?

Relacionado con el # 288.

¿Alguna actualización aquí? Todavía me falla con ~ 0.9.0

Sí, todavía estoy usando el truco setTimeout () mencionado anteriormente por @yzapuchlak :(

De todos modos, no veo esto como un error de Winston. Cuando process.exit en su código , ha tomado la decisión de eliminar por completo todo lo que aún se está procesando. Si todavía hay solicitudes HTTP en ejecución, no asume que estas también serán respondidas, entonces, ¿por qué asumir que los mensajes de registro terminan en su registro? Así es como funciona el nodo, las cosas son asíncronas por una razón. Si usó el enfoque de devolución de llamada o setTimeout, no hay nada que impida que su aplicación registre otra línea justo antes de que termine su setTimeout o se llame a la devolución de llamada.

La única forma de evitar esto es tener un registro síncrono, pero luego anula todo el propósito de tener un sistema asíncrono como una simple declaración de registro cuando maneja solicitudes.

Entonces, lo que estoy sugiriendo es cerrar este problema con una solución. Si no desea perder ningún mensaje de registro, asegúrese de limpiar y cerrar correctamente su aplicación antes de llamar a process.exit.

edit Además, todos sus hacks de setTimeout son defectuosos y no solucionan el problema, ya que no tiene idea de cuánto tiempo llevará escribir todos los datos en el sistema operativo y qué tan rápido los procesan sus discos o ssds. La única solución decente aquí es escuchar el evento drain la transmisión y salir del proceso. Pero si su aplicación está registrando continuamente, es posible que ni siquiera se llame durante un período prolongado; p haciendo que esto sea solo otro truco porque no cerró correctamente su aplicación antes de salir.

El caso es que actualmente no hay forma de esperar (devolución de llamada / promesa / lo que sea) para que se vacíen los registros. También forzar el registro de sincronización haría posible agregar registros en process.on('exit')

Si desea tener un registro asíncrono durante el tiempo de vida de su aplicación y sincronizar el registro durante process.exit, debe crear una nueva instancia de Winston con una implementación de archivo personalizada que sincronice las escrituras. Y si desea saber cuándo se eliminan las cosas, debe escuchar el evento de drenaje de una transmisión.

¡Lo intentaré, gracias!

Por lo que vale, puede evitar el uso de setTimeout pero necesita tomar el _stream subyacente:

// log then exit(1)
logger.error("The thing to log", function(err) {
  var numFlushes = 0;
  var numFlushed = 0;
  Object.keys(logger.transports).forEach(function(k) {
    if (logger.transports[k]._stream) {
      numFlushes += 1;
      logger.transports[k]._stream.once("finish", function() {
        numFlushed += 1;
        if (numFlushes === numFlushed) {
          process.exit(1);
        }
      });
      logger.transports[k]._stream.end();
    }
  });
  if (numFlushes === 0) {
    process.exit(1);
  }
});

Como se mencionó anteriormente, el uso de la función de devolución de llamada por sí sola _no es suficiente_ para que se descargue correctamente en el archivo. Esto me parece un error.

Tenga en cuenta que en realidad estoy escuchando el evento finish : https://nodejs.org/api/stream.html#stream_event_finish en lugar de usar el evento flush o closed winston porque eso también es insuficiente para que se registre correctamente: /

Prueba este. Funciona bastante bien en mi caso. En lugar de llamar a process.exit directamente, dejamos que el registrador llame a process.exit después de que se haya vaciado el registro.

logger.js:

var winston = require('winston');

winston.loggers.add('my-logger', {
    console: {
        level: 'debug',
        colorize: true,
        timestamp: true,
        handleExceptions: true
    },
    file: {
        level: 'info',
        colorize: false,
        timestamp: true,
        filename: 'file.log',
        handleExceptions: true
    }
});

var logger = winston.loggers.get('my-logger');


/* ******* *
 * EXPORTS
 * ******* */

exports.exitAfterFlush = function(code) {
    logger.transports.file.on('flush', function() {
        process.exit(code);
    });
};

exports.info = function() {
    logger.info.apply(this, arguments);
};

exports.warn = function() {
    logger.info.apply(this, arguments);
};

exports.error = function() {
    logger.info.apply(this, arguments);
};

en tu código:

var logger = require('./logger.js');
logger.exitAfterFlush(0);
logger.info('Done!');

Probado en NodeJS v4.1.2 y winston 1.1.0

Estoy usando algo similar a @ da-mkay.

function closeAllLoggersAndDisconnect() {
    "use strict";

    let openCount = 0;

    Object.keys(loggerInstance.transports).forEach((key) => {

        let transportInstance = loggerInstance.transports[key];

        if (typeof transportInstance.close === "function") {
            transportInstance.close();
            openCount++;
        }

        transportInstance.on("closed", () => {
            openCount--;
        });

        setInterval(() => {
            if (openCount === 0) {
                if (process.connected) {
                    process.disconnect();
                }
            }
        }, 100);
    });
}

en tu código:

winston.error("Error Occured", err, () => {
    closeAllLoggersAndDisconnect();
});

Idealmente, sería bueno si pudiera simplemente llamar al método close en el loggerInstance , pero dado que eso emite el evento closed tan pronto como termine de llamar al close método en los transportes subyacentes, en lugar de después de que realmente se cierren, eso no funcionará. Parece que es un error que el registrador se pueda cerrar sin que los transportes subyacentes estén completamente cerrados.

Usando @Kegsay, los pasos y registros se escriben en el archivo.

También usando los pasos de @Kegsay con éxito ... envuelto en mi propia función.

Todavía tengo este problema en la versión 2.2.0 .

¿Esto todavía no se ha implementado? Más de 3 años. No quiero usar la salida del proceso.

Entiendo que esto no es un problema, pero definitivamente debería haber una función para finalizar todas las escrituras en archivos y cerrar cualquier elemento abierto para que el proceso pueda salir por sí solo sin llamarlo explícitamente. Es tan difícil usar tales cosas en los sistemas de producción.

Haciéndose eco de que esto realmente necesita una solución por parte de Winston. Ya sea que se trate de proporcionar un transporte de archivos síncrono o proporcionar un enlace de apagado para cerrar Winston de forma `` segura '', realmente no me importa, tampoco sería una solución satisfactoria para mí. Pero no tener nada simplemente hace que sea imposible escribir registros y luego salir y estar seguro de que realmente se escribirán.

Lo que pasa con los transportes síncronos es que la ejecución de su código se bloqueará hasta que se complete el IO, lo que limita el rendimiento. No hay forma de convertir una escritura asíncrona en una escritura de bloqueo, lo que significa que una vez que realiza una escritura asíncrona en los registros, debe esperar hasta que NodeJS lo haga y, mientras tanto, se puede ejecutar otro código JS.

Por otro lado, las promesas se pueden cancelar sincrónicamente, los tiempos de espera se pueden borrar sincrónicamente, las conexiones de archivos y bases de datos se pueden cerrar sincrónicamente, por lo que una mejor solución (más eficaz) podría ser realizar un seguimiento de las cosas que deben cancelarse / borrarse / cerró y ciérrelos en el controlador de excepciones que llama a winston.log_and_exit() , o la devolución de llamada opcional a winston.log_and_exit() .

Seguro que sería bueno que Winston mantuviera un registro de todas las cosas que necesitaría cerrar en caso de un error, pero tal administrador de tareas probablemente sería algo útil por derecho propio y probablemente merezca un marco separado (ver Ley de Curley).

No veo cómo el rendimiento tenga algún impacto aquí. El proceso está a punto de terminar, Winston solo necesita llevar la contabilidad de las líneas de registro finales durante las cuales puede bloquear felizmente la OMI.

Dada la antigüedad de este problema y el hecho de que existe una solución alternativa, no estoy esperando a nadie que aborde esto en Winston en el corto plazo.

Parece que tú y yo estamos hablando (escribiendo) a través de propósitos. Parece que está interesado en escribir mensajes finales de forma sincrónica en el archivo, mientras que mi preocupación era garantizar que los registros que se escribieron de forma asincrónica justo antes del error se escribieran en el archivo.

Escribir los mensajes en el archivo que ocurrieron justo antes del error de forma sincrónica requeriría que todos los mensajes se escribieran de forma sincrónica, y ese es el problema de rendimiento.

Otros han estado preocupados por detener la ejecución de otro código JS después de un error, pero antes de que se hayan escrito los últimos registros en el archivo.

Una opción que podría satisfacer las necesidades de todos es escribir un transporte personalizado que escriba de forma asincrónica y mantenga un búfer de mensajes aún no confirmados como escritos (vaciados) en el archivo, que podría escribirse en el archivo sincrónicamente en caso de error (con el riesgo de duplicar mensajes , en el caso de que NodeJS ya haya terminado de escribir en el archivo, pero el evento descargado aún no se ha procesado ...).

¿Es realmente difícil proporcionar un gancho de apagado para llamar que esperaría hasta que todo se descargó antes de regresar y / o llamar a una devolución de llamada? Esto resolvería prácticamente todos los casos de uso.

Pero déjame también contarte sobre mi caso de uso, la razón por la que no me importan los registros sincrónicos. Pruebas. No me importa si mis pruebas tardan uno o dos segundos más en ejecutarse. Me importa si los registros no son deterministas porque pueden o no escribirse dependiendo de la rapidez con la que el nodo decida cerrarse. Eso es malo . Estoy totalmente de acuerdo en que el sistema asincrónico debería ser el predeterminado. No estoy de acuerdo en que debería ser la única opción, especialmente a la luz de problemas como este dentro del propio nodo.

@mscharley así es como lo hace log4js: hay una función log4js.shutdown que puede proporcionar una devolución de llamada. Esperará para asegurarse de que todos los agregadores (creo que winston los llama transportes) hayan terminado de escribir antes de llamar a la devolución de llamada. Parece funcionar bien para mis usuarios. Requiere el apoyo de los agregadores, ya que deben escribirse para que puedan responder a las llamadas de apagado.

No estoy tratando de promover log4js o decir que es mejor que winston, por cierto, solo señalo que este enfoque puede funcionar. Puede que no sea el mejor enfoque.

Se trata de lo que hace winston.log_and_exit() . Tenga en cuenta que log4js.shutdown() depende de writable.end(complete) en el caso de anexos basados ​​en flujos de escritura, ( appenders.filter(a => a.shutdown).forEach(a => a.shutdown(complete)); ) que sigue siendo un cierre asincrónico.

Creo que con respecto al comentario de fileSync , que no requiere el uso de shutdown() para tener los registros completos escritos en el archivo cuando el nodo el proceso se cierra ...

Sí, tener un transporte fileSync sería útil en algunas situaciones, incluso si sería una disminución neta del rendimiento.

@jdthorpe Creo que su idea de tener una biblioteca que maneje el cierre de las cosas limpiamente antes de cerrar es buena, pero aún así no le quita la responsabilidad a winston de proporcionar un método para esperar a que descargue todo en el disco (es decir, proporcionar un mecanismo para cerrarse) que luego podría combinarse con dicha biblioteca para agregar los métodos de cierre para varias bibliotecas.

¿Puede este ticket al menos cambiar los documentos para que no parezca que es compatible actualmente? Acabo de pasar 30 minutos depurando este problema que pretende ser compatible cuando busca seriously en el repositorio , solo se admite en el README . Esto parece ser una característica no admitida o un error y las soluciones no son realmente demasiado aceptables.

¿Cuándo se va a arreglar esto? Esto existe desde hace 3 años y es bastante importante.

Al menos, pongamos una devolución de llamada en el registrador que realmente funciona.

Yo diría que tal vez escribí una función genérica shutdown() para todos como una nueva característica, y esta característica es bastante crítica.

Sí, este es un tema muy, muy importante en mi opinión.

+1 para esto

Francamente, creo que agregar shutdown(callback) parece apropiado, pero con la advertencia de que los transportes deben respaldarlo activamente. Los transportes individuales son los "expertos en información" sobre su mecanismo de salida subyacente; ellos tienen la mayor información sobre cómo debería apagarse limpiamente.

Cualquier cosa que haga el núcleo winston , y definitivamente cualquier cosa que hagamos en la tierra del usuario, requiere que los detalles de implementación de los transportes se filtren.

Por lo tanto, winston no debería necesitar hacer el trabajo ... pero realmente necesita proporcionar una forma para que se realice el trabajo. Entonces todos podemos trabajar con los autores de Transport para hacer el trabajo pesado.

Algún código pseudo para ilustrar el punto siguiente.

`` js
shutdown (devolución de llamada) {
var transportCount = transportes.longitud
var terminado = 0;
// para cada transporte
if (transporte.shutdown) {
transport.shutdown (function () {
// aumenta el recuento terminado.
// si todo ha terminado, llama a la devolución de llamada original.
});
} demás {
// El transporte (todavía) no lo admite.
// incremento del contador terminado
}
}

Me encantaría ver esto arreglado en v3.x.

Aquí está mi solución (asume un entorno que admite async / await )


Para un solo transporte:

const logTransport = new winston.transports.File({filename: '/log/app.log'})

global.log = winston.createLogger({transports: [logTransport]})

// helper to exit with a given return code, but only after the logger is finished
// this will return a Promise that will never resolve, thus halting execution
log.exit = (exit = 5) => {
  return new Promise(() => {
    logTransport.on('finished', () => process.exit(exit))
  })
}



Para transportes múltiples (no probados):

`` js
const logTransports = [new winston.transports.File ({nombre de archivo: '/log/app.log'})]

global.log = winston.createLogger ({transportes: [logTransport]})

// ayuda para salir con un código de retorno dado, pero solo después de que el registrador haya finalizado
// esto devolverá una Promesa que nunca se resolverá, deteniendo así la ejecución
log.exit = (salida = 5) => {
devolver nueva promesa (() => {
Promise.all (
logTransports.map (transporte => nueva Promesa (resolver => transporte.on ('terminado', resolver)))
) .entonces (() => process.exit (salir))
})
}

</details>
<br>
Then, call with `await` like:

```js
try {
  something()
} catch(e) {   
  //do something with the error
  await log.exit(5) // <--- nothing will happen past this line as the promise will never resolve!
  // <--- process will have exited before it reaches here
  trySomethingElse() // <--- this will never be called, and control wont return to the calling code
}

No es un récord rayado , pero

Solo para casos de uso muy, muy específicos. No pude usar winston-log-and-exit en, digamos, AWS Lambda donde el proceso no se cierra, pero se congela entre ejecuciones, por lo que los registros aún se pierden. También asume que sé qué mensajes son mis últimos, lo que puede no ser siempre el caso en una ruta de ejecución exitosa.

@mscharley, ¿la solución await funcionaría para su caso de uso? Quizás en lugar de log.exit() una mejor api sería await log.finish() que esperaría hasta que todos los transportes hayan terminado de escribir y luego te dejaría hacer lo que sea (llama process.exit , llama a lamda done devolución

Básicamente, eso es exactamente lo que hemos estado presionando en este número, excepto dentro de Winston. ¿Por qué sería esto un complemento? Parece algo que debería surgir con más frecuencia. No siento que lo que estamos haciendo sea nada especial, pero hemos chocado contra este muro en cada proyecto, por lo que finalmente nos alejamos de Winston. Perder registros, especialmente al final del proceso, donde es más probable que ocurran errores, parece al menos peligroso.

log4js-node ha implementado un método de apagado que vacía todos los transportes y recibe una devolución de llamada como process.exit() . ¿Se podría agregar algo como esto a winston?

log4js-node es entonces

¿alguna actualización? El problema es muy real.

Para cualquier sistema de registro, el cálculo es:

  • Si absolutamente debe tener sus registros y está dispuesto a pagar el costo de tiempos de respuesta más lentos, use un registrador síncrono
  • Si está llamando a process.exit() usted mismo, espere hasta que se borren los mensajes almacenados en búfer. Para winston, el paquete winston-log-and-exit hace esto por usted.
  • Si algún otro código está llamando a process.exit() y su plataforma tiene un gancho de salida, use ese gancho y espere hasta que se borren los mensajes almacenados en búfer. winston-log-and-exit también puede ayudar con eso.
  • Si está utilizando una plataforma como AWS Lambda que no tiene un gancho de salida, entonces está intercambiando los beneficios de la plataforma por el riesgo de perder datos.

Por cierto, @ begin-again, este método log_and_exit() es esencialmente el mismo que el método shutdown() log-4js con la garantía adicional de que se registrará el mensaje de registro proporcionado.

@jdthorpe Pero winston-log-and-exit no funcionará fácilmente en winston 3

@VRuzhentsov Oh, bueno, eso es un problema. Realmente deberían hacer algo al respecto.

@jdthorpe Lo arregló con

const transport = new Transport();
const logger = createLogger({
  transports: [
    transport 
  ]
})

logger.finish = (exitCode) => {
  transport.on('finish', () => process.exit(exitCode));
  transport.close();
};

const shutDown = (exitCode) => {
  logger.info('Shutting down');
  logger.finish(exitCode);
};

shutDown(1);

Lo siguiente funciona para mí:

logger.info('winston - info logged');
logger.error('winston - error logged');
process.nextTick(() => {
    process.exit(0)
})

@ redhat-raptor. Eso funcionará la mayor parte del tiempo, pero no se garantiza que funcione todo el tiempo. Simplemente sucede que sus búferes se borraron en el momento en que se llamó a nextTick (), pero dependiendo de las conexiones en las que confían sus registradores, esto podría resultar fácilmente en la pérdida de mensajes ...

Este código funcionó para mí:

            logger.error(`No value specified for ${value} variable! Node will exit now...`);
            logger._flush(() => {
                process.exit(1);
            })

¿No es esto compatible de forma nativa en v3?

https://github.com/winstonjs/winston/blob/master/README.md#awaiting -logs-to-be-writing-in-winston

@danielweck No, está roto: # 1629 # 1504!

6 años, eso es correcto, 6 años para un error marcado como _importante_. Es casi impresionante.

Yo uso una promesa waitForWinston() :

const winston = require('winston');

const fileTransport = new winston.transports.File({ name: 'file', filename: FILE_PATH });
const consoleTransport = new winston.transports.Console({ name: 'console', stderrLevels: ['error'] });
const transports = [
    fileTransport,
    consoleTransport
];
winston.configure({
    level: 'verbose',
    transports,
    format: winston.format.cli()
});
winston.log('info', 'TEST MSG');
try {
    await waitForWinston();
} catch (err) {
    console.log(err);
}
process.exit(0);
const waitForWinston = async () => {
    return new Promise(async (resolve, _reject) => {
        for (const transport of transports) {
            try {
                await closeWinstonTransportAndWaitForFinish(transport);
            } catch (err) {
                console.log(err);
            }
        }
        resolve();
    });
};
const closeWinstonTransportAndWaitForFinish = async (transport) => {
    if (!transport.close) {
        // e.g. transport.name === 'console'
        return Promise.resolve();
    }
    // e.g. transport.name === 'file'

    return new Promise(async (resolve, _reject) => {
        transport._doneFinish = false;
        function done() {
            if (transport._doneFinish) {
                return; // avoid resolving twice, for example timeout after successful 'finish' event
            }
            transport._doneFinish = true;
            resolve();
        }
        setTimeout(() => { // TODO: use a cancellable setInterval instead
            done();
        }, 5000); // just in case the 'finish' event never occurs
        const finished = () => {
            done();
        };

/* Update: `stream.end()` does not flush pending writes, so this solution is inadequate.  For some reason, in recent tests `transport.close();` + `transport.once('finish', ...);` works just fine ... not sure why this works now though! (it used to fail!) */

/*
        if (transport._stream) {
            transport._stream.once('finish', finished);
            transport._stream.end();
        }
*/
            transport.once('finish', finished);
            transport.close();
    });  
};

Actualización: stream.end() no elimina las escrituras pendientes, por lo que esta solución es inadecuada. Por alguna razón, en pruebas recientes transport.close(); + transport.once('finish', ...); funciona bien ... ¡aunque no estoy seguro de por qué funciona ahora! (¡solía fallar!)

En mi solución de trabajo anterior, la clave es usar:
transport._stream.once('finish', finished); transport._stream.end();
en vez de:
transport.once('finish', finished); transport.close();
(la estrategia de tiempo de espera adicional es específica para mi caso de uso, y probablemente sea opcional / redundante en el caso general)

Manera más fácil:

logger.error(`No value specified for ${missing_vars.join(',')} variable! Node will exit now...`, () => {
            process.exit(1);
        });

@danielweck ¿Alguna vez

@matttowerssonos , IIRC, todos estos problemas están relacionados con Winston @ 2. Dada la longitud de este hilo y el hecho de que no estás preguntando sobre el comentario original de los carteles, ¿por qué no empiezas un nuevo hilo con tu problema?

Por cierto, no veo ningún problema con los registros perdidos en Winston @ 3 , por lo que es posible que desee incluir su configuración en su nuevo problema.

@cjbarth Esto no funciona:

  process.on(type as any, (err: ErrorExtended) => {
    const processLogger: Logger = loggers.get('processLogger');

    processLogger.error(errorFormatter(err, type));

    processLogger.on('finish', function () {
      processLogger.end();
      console.log('never reaches here');
      process.exit(1);
    });
  });

processExit('uncaughtException');
// log and exit for unhandledRejection events.
processExit('unhandledRejection');

@stephanoparaskeva Si no me equivoco, el evento finish nunca se activará en processLogger porque nunca llamas a processLogger.end() . Si llama a eso, entonces, cuando Winston termine de registrar, el evento finish debería dispararse.

También usaría process.disconnect() lugar de process.exit() , lo que permite que la cola se vacíe. Saldrá automáticamente cuando se agote la cola.

@stephanoparaskeva Si no me equivoco, el evento finish nunca se activará en processLogger porque nunca llamas a processLogger.end() . Si llama a eso, entonces, cuando Winston termine de registrar, el evento finish debería dispararse.

También usaría process.disconnect() lugar de process.exit() , lo que permite que la cola se vacíe. Saldrá automáticamente cuando se agote la cola.

Entendido, ¿algo como esto?

process.on(type as any, (err: ErrorExtended) => {
  const processLogger: Logger = loggers.get('processLogger');

  processLogger.error(errorFormatter(err, type));
  processLogger.end()

  processLogger.on('finish', function () {
    process.disconnect();
  });
});

// log and exit for uncaughtException events.
processExit('uncaughtException');
// log and exit for unhandledRejection events.
processExit('unhandledRejection');

@stephanoparaskeva Eso se ve mejor.

Por lo general, vincularía el controlador de eventos antes de llamar a processLogger.end() , pero no debería importar porque el evento finish debería activarse solo después de que el bucle de eventos gire, momento en el que el controlador estará vinculado. Creo que escribir el código donde el controlador de eventos está vinculado primero lo hace más claro.

@cjbarth
Oh, ¿cómo se vincula el controlador de eventos a algo?
Sera eso:

processLogger.on('finish', () => {
    this.process.disconnect();
  });

@stephanoparaskeva Sí. Esa es la sintaxis correcta para vincular la función.

{
  this.process.disconnect();
}

Al evento finish emitido por el objeto processLogger .

Si no llama a process.exit pero en su lugar realiza un apagado adecuado, cerrando todas las conexiones y esperando a que se agote el bucle de eventos, entonces no hay ningún problema.

Vea esto: https://stackoverflow.com/a/37592669 para comprender mejor a qué se refiere @deedf . Seguir este consejo también me alivió este problema.

El hecho de que el evento final aún no se emita después de años es vergonzoso en este momento. Va a ser un fastidio tener que cambiar de registrador y reescribir todos mis transportes personalizados para ellos.

No entiendo cómo esto aún no ha sido resuelto por Winston. Tengo el problema de que solo el primer registrador de mi código se registra en Logstash (utilizando también winston-elasticsearch). Si utilizo logger.end (), todo se registra, pero el programa se cierra demasiado pronto. Intenté usar todas las soluciones anteriores, y ninguna funcionó realmente.
Estoy realmente indefenso

No entiendo cómo esto aún no ha sido resuelto por Winston. Tengo el problema de que solo el primer registrador de mi código se registra en Logstash (utilizando también winston-elasticsearch). Si utilizo logger.end (), todo se registra, pero el programa se cierra demasiado pronto. Intenté usar todas las soluciones anteriores, y ninguna funcionó realmente.
Estoy realmente indefenso

¿Intentaste esto ?

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

Entonces, ¿nuestra solución a este problema es no llamar a process.exit ()?

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

Entonces, ¿nuestra solución a este problema es no llamar a process.exit ()?

Sí, siempre es una mala idea en nodejs, consulte https://stackoverflow.com/a/37592669

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

Entonces, ¿nuestra solución a este problema es no llamar a process.exit ()?

Sí, siempre es una mala idea en nodejs, consulte https://stackoverflow.com/a/37592669

Bueno, la razón por la que personalmente estoy usando process.exit es porque estoy escuchando uncaughtException y unhandledRejection para iniciar sesión en todos mis transportes, luego salgo de la aplicación. ¿Existe una mejor manera de solucionar este problema?

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

¿Dónde viste que dije que usé exit ()?

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

¿Dónde viste que dije que usé exit ()?

Perdón por asumir que su capacidad de lectura y comprensión es suficiente para comprender de qué se trata este error. Revisa el título nuevamente.

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

¿Dónde viste que dije que usé exit ()?

Perdón por asumir que su capacidad de lectura y comprensión es suficiente para comprender de qué se trata este error. Revisa el título nuevamente.

Debe estar muy ocupado si llega a un problema que ha estado abierto durante 8 años y no ofrece la ayuda adecuada.

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

Entonces, ¿nuestra solución a este problema es no llamar a process.exit ()?

Sí, siempre es una mala idea en nodejs, consulte https://stackoverflow.com/a/37592669

Bueno, la razón por la que personalmente estoy usando process.exit es porque estoy escuchando uncaughtException y unhandledRejection para iniciar sesión en todos mis transportes, luego salgo de la aplicación. ¿Existe una mejor manera de solucionar este problema?

No he usado Winston en un tiempo, pero ¿no los registrará de todos modos? si no, ¿no funcionará volver a generar el error después de registrarlo?

No entiendo cómo la gente no entiende que este "problema" no ha sido "resuelto" porque no lo hay. Simplemente escriba el código adecuado sin llamar a exit () y estará bien.

¿Dónde viste que dije que usé exit ()?

Perdón por asumir que su capacidad de lectura y comprensión es suficiente para comprender de qué se trata este error. Revisa el título nuevamente.

Debe estar muy ocupado si llega a un problema que ha estado abierto durante 8 años y no ofrece la ayuda adecuada.

Al menos puedo resolver mis propios problemas sin quejarme como un mocoso con derecho.

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

Temas relacionados

Buzut picture Buzut  ·  3Comentarios

KingRial picture KingRial  ·  3Comentarios

Infinitay picture Infinitay  ·  3Comentarios

sinai-doron picture sinai-doron  ·  3Comentarios

anks333 picture anks333  ·  3Comentarios