Winston: O registro no arquivo falha ao chamar process.exit (0)

Criado em 25 mar. 2013  ·  87Comentários  ·  Fonte: winstonjs/winston

Quando você configura o winston para registrar em um arquivo e chama process.exit (0) em seu código, o winston nunca acaba criando o arquivo de log e anexando as mensagens de log ao arquivo.

Em um mundo perfeito, o winston ficaria feliz em lidar com esse caso extremo e escrever no arquivo, mas eu também ficaria bem em poder chamar o flush em uma instância do logger para forçar manualmente um flush para o arquivo.

Pode haver alguma maneira de 'descarregar' manualmente no momento, mas não está documentado nem tive sorte em fechar / encerrar / destruir manualmente uma instância do logger ou seus fluxos internos de uma forma que realmente resulte nos logs sendo gravado em um arquivo ..

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

Comentários muito úteis

@danielweck Não, está quebrado: # 1629 # 1504!

6 anos, isso mesmo, 6 anos para um bug marcado como _importante_. É impressionante.

Todos 87 comentários

No nó, os métodos console. * Estão gravando de forma assíncrona, o transporte de arquivo é assíncrono. Você está fechando o processo antes mesmo que o nó tenha escrito os dados.

Na segunda-feira, 25 de março de 2013 às 19:45, Yuri Zapuchlak escreveu:

Quando você configura o winston para registrar em um arquivo e chama process.exit (0) em seu código, o winston nunca acaba criando o arquivo de log e anexando as mensagens de log ao arquivo.
Em um mundo perfeito, o winston ficaria feliz em lidar com esse caso extremo e escrever no arquivo, mas eu também ficaria bem em poder chamar o flush em uma instância do logger para forçar manualmente um flush para o arquivo.
Pode haver alguma maneira de 'descarregar' manualmente no momento, mas não está documentado nem tive sorte em fechar / encerrar / destruir manualmente uma instância do logger ou seus fluxos internos de uma forma que realmente resulte nos logs sendo gravado em um arquivo ..
var winston = require ('winston'); var logger = new (winston.Logger) ({transportes: [novo (winston.transports.Console) (), novo (winston.transports.File) ({nome do arquivo: 'winston.log'})]}); logger.info ('informações registradas'); logger.error ('erro registrado'); processo.exit (0); // os dois logs são gravados no console, mas não no arquivo winston.log /

-
Responda a este e-mail diretamente ou visualize-o no GitHub (https://github.com/flatiron/winston/issues/228).

Hmm. Nesse caso, se alguém deve matar um processo de nó, mas precisa registrar informações antes de matá-lo, é colocar o process.exit () dentro de um setTimeout () com uma duração de tempo suficientemente grande, a única coisa que se pode fazer para garantir que o winston realmente grava mensagens no arquivo de log?

Apenas para maior clareza, console.log e amigos são síncronos .

@yzapuchlak Eu não testei, mas é o que eu também faço.

@yzapuchlak setTimeout _probably_ funcionará sem problemas, mas acho que seria sábio usar o parâmetro de retorno de chamada opcional.

setTimeout de 2000 ou 5000 funciona em meu script de teste simples, mas não quando tento usá-lo em meu código real. Portanto, não sei quão confiável será essa solução potencial. Examinarei esse problema mais tarde se não tiver sorte no callback opcional

@dtex Acabei de tentar usar o retorno de chamada opcional (como visto no código de exemplo a seguir), mas ainda não está resultando nos logs sendo gravados no arquivo. O arquivo realmente é criado neste caso, mas nenhum log é gravado nele.

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, essa é a versão 0.6.2?

Tendo o mesmo problema agora, é necessário encerrar o processo e fazer uma anotação no arquivo de log. Seria bom ter a opção de retorno de chamada, que poderíamos usar para sair do processo somente após a mensagem ser escrita. Ou talvez já exista?

Estou tendo o mesmo problema com o Winston 0.7.2.
Testei setTimeout e a solução alternativa de retorno de chamada sem sucesso.

Este é o mesmo problema do nº 288 e também o problema do nó log4js (https://github.com/nomiddlename/log4js-node/issues/148). Acho que o problema é que o loop de eventos não é executado depois que o retorno de chamada process.exit termina - portanto, todas as chamadas assíncronas pendentes (como gravações de arquivo) não têm chance de ser executadas. Ficaria muito feliz se alguém pudesse provar que estou errado e encontrar uma solução.

Estou disposto a dedicar tempo para consertar isso, se pudermos encontrar uma solução. O problema principal parece ser que WritableStreams não garante liberação em process.exit () ou exceção não tratada. Alguma solução alternativa foi investigada? Parece que podemos armazenar os logs na memória até que o WritableStream seja drenado. Então, se ocorrer uma exceção process.exit ou não capturada, podemos gravar de forma síncrona todos os logs que não foram drenados. Isso pode produzir logs duplicados, mas pelo menos evitará a perda de log. Alguma ideia?

Relacionado a # 288.

Alguma atualização aqui? Ainda falhando para mim com ~ 0.9.0

Sim, ainda estou usando o hack setTimeout () mencionado por @yzapuchlak anteriormente :(

Eu realmente não vejo isso como um bug do winston de qualquer maneira. Quando você process.exit em seu código, você tomou a decisão de matar completamente tudo que ainda está em execução no processamento. Se ainda houver solicitações HTTP em execução, você não presume que elas também serão respondidas, então por que presumir que as mensagens de log vão parar em seu log? É assim que o nó funciona, as coisas são assíncronas por uma razão. Se você usou a abordagem de retorno de chamada ou setTimeout, não há nada impedindo seu aplicativo de registrar outra linha antes que setTimeout seja concluído ou o retorno de chamada seja chamado.

A única maneira de contornar isso é ter o registro síncrono, mas então você anula todo o propósito de ter um sistema assíncrono como uma instrução de registro simples quando estiver lidando com solicitações.

Portanto, o que estou sugerindo é encerrar esse problema com uma correção habitual. Se você não quiser perder nenhuma mensagem de log, certifique-se de limpar e encerrar corretamente seu aplicativo antes de chamar process.exit.

editar Além disso, todos os seus hacks setTimeout são falhos e não corrigem o problema, pois você não tem ideia de quanto tempo levará para que todos os dados sejam gravados no sistema operacional e a rapidez com que seus discos ou ssds estão processando-os. A única solução decente aqui é ouvir o evento drain do stream e sair do processo. Mas se seu aplicativo está continuamente registrando, isso pode não ser chamado por um longo período; p tornando isso apenas mais um hack, porque você não desligou corretamente seu aplicativo antes de sair.

A questão é que atualmente não há como esperar (retorno de chamada / promessa / qualquer coisa) para que os logs sejam liberados. Forçar também o registro de sincronização tornaria possível adicionar registros em process.on('exit')

Se você deseja ter um log assíncrono durante o tempo de vida de seu aplicativo e um log de sincronização durante process.exit, você deve criar uma nova instância winston com uma implementação de arquivo customizada que sincroniza gravações. E se você quiser saber quando as coisas são liberadas, você deve ouvir o evento de drenagem de um riacho.

Vou tentar isso, obrigado!

Pelo que vale a pena, você pode contornar o uso de setTimeout mas você precisa pegar o _stream subjacente:

// 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);
  }
});

Conforme mencionado acima, o uso da função de retorno de chamada sozinha _não é suficiente_ para que seja liberado corretamente para o arquivo. Isso parece um bug para mim.

Observe que estou realmente ouvindo o evento finish : https://nodejs.org/api/stream.html#stream_event_finish em vez de usar o evento flush ou closed do winston porque isso também é insuficiente para fazê-lo registrar corretamente: /

Tente este. Funciona muito bem no meu caso. Em vez de chamar process.exit diretamente, deixamos o logger chamar process.exit depois que o log foi liberado.

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);
};

em seu código:

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

Testado em NodeJS v4.1.2 e winston 1.1.0

Estou usando algo semelhante 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);
    });
}

em seu código:

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

Idealmente, seria bom se eu pudesse apenas chamar o método close no loggerInstance , mas uma vez que isso emite o evento closed assim que terminar de chamar close método nos transportes subjacentes, em vez de depois de eles realmente fecharem, isso não funcionará. Parece que é um bug o logger poder ser fechado sem que os transportes subjacentes sejam totalmente fechados.

Usando @Kegsay, as etapas e os logs são gravados em arquivo.

Também usando os passos de @Kegsay com sucesso ... envolvidos em minha própria função.

Ainda tenho esse problema na versão 2.2.0 .

Ainda não foi implementado? Mais de 3 anos. Não quero usar a saída de processo.

Eu entendo que isso não é um problema, mas definitivamente deve haver uma função para terminar todas as gravações em arquivos e fechar qualquer coisa aberta para que o processo possa sair sozinho sem chamá-lo explicitamente. É tão difícil usar essas coisas em sistemas de produção.

Ecoando que isso realmente precisa de uma solução do lado de winston. Se isso é fornecer um transporte de arquivo síncrono ou fornecer um gancho de desligamento para fechar o Winston 'com segurança', eu realmente não me importo, qualquer um seria uma solução satisfatória para mim. Mas não ter nada torna impossível escrever logs e, em seguida, encerrar e ter a certeza de que eles serão realmente escritos.

O que acontece com os transportes síncronos é que a execução do seu código será bloqueada até que o IO seja concluído, o que limita o desempenho. Não há como converter uma gravação assíncrona em uma gravação de bloqueio, o que significa que depois de gravar async nos logs, você tem que esperar até que o NodeJS resolva isso e, nesse meio tempo, outro código JS pode ser executado.

Por outro lado, as promessas podem ser canceladas de forma síncrona, os tempos limites podem ser limpos de forma síncrona, as conexões de arquivo e banco de dados podem ser fechadas de forma síncrona, então uma solução melhor (com mais desempenho) pode ser manter o controle das coisas que precisam ser canceladas / limpas / fechou e fechou-os no manipulador de exceções que chama winston.log_and_exit() , ou o retorno de chamada opcional para winston.log_and_exit() .

Claro que seria bom se o Winston mantivesse o controle de todas as coisas que você precisaria fechar no caso de um erro, mas esse gerenciador de tarefas provavelmente seria uma coisa útil por si só, e provavelmente merece uma estrutura separada (consulte Lei de Curley).

Não vejo como o desempenho tem impacto aqui. O processo está prestes a ser encerrado, o winston só precisa fazer a contabilidade nas linhas de log finais, durante o qual ele pode bloquear o IMO.

Considerando a antiguidade desse problema e o fato de que há uma solução alternativa para ele, não estou exatamente esperando que alguém resolva isso no winston tão cedo.

Parece que você e eu estamos conversando (escrevendo) com objetivos diferentes. Parece que você está interessado em gravar mensagens finais de forma síncrona no arquivo, enquanto minha preocupação era garantir que os logs que foram gravados de forma assíncrona pouco antes do erro fossem gravados no arquivo.

Gravar as mensagens no arquivo que ocorreu pouco antes do erro de forma síncrona exigiria que todas as mensagens fossem gravadas de forma síncrona e esse é o problema de desempenho.

Outros têm se preocupado em impedir a execução de outro código JS após um erro, mas antes que os últimos logs sejam gravados no arquivo.

Uma opção que pode satisfazer as necessidades de todos é escrever um transporte personalizado que grava de forma assíncrona e mantém um buffer de mensagens ainda não confirmadas como gravadas (liberadas) no arquivo, que podem ser gravadas no arquivo de forma síncrona em caso de erro (sob o risco de duplicar mensagens , no caso de o NodeJS já ter concluído a gravação no arquivo, mas o evento liberado ainda não foi processado ...).

É realmente difícil fornecer um gancho de desligamento para chamar que esperaria até que tudo fosse liberado antes de retornar e / ou chamar um retorno de chamada? Isso resolveria praticamente todos os casos de uso.

Mas deixe-me contar também sobre meu caso de uso, o motivo pelo qual não me importo com logs síncronos. Testes. Não me importo se meus testes demoram um ou dois segundos a mais para serem executados. Eu me importo se os logs são não determinísticos porque eles podem ou não ser gravados, dependendo exatamente da rapidez com que o nó decide desligar. Isso é ruim . Eu concordo plenamente que assíncrono deve ser o padrão. Não concordo que deva ser a única opção, especialmente à luz de questões como essa dentro do próprio nó.

@mscharley é assim que log4js faz - há uma função log4js.shutdown que você pode fornecer um retorno de chamada. Ele vai esperar para ter certeza de que todos os anexadores (winston os chama de transportes, eu acho) terminaram de escrever antes de chamar o retorno de chamada. Parece funcionar bem para meus usuários. Ele requer suporte dos anexadores, pois eles precisam ser gravados para que possam responder às chamadas de desligamento.

A propósito, não estou tentando promover o log4js ou dizer que ele é melhor do que o winston - só estou apontando que essa abordagem pode funcionar. Pode não ser a melhor abordagem.

Isso é o que winston.log_and_exit() faz. Observe que log4js.shutdown() depende de writable.end(complete) no caso de anexos baseados em fluxos graváveis, ( appenders.filter(a => a.shutdown).forEach(a => a.shutdown(complete)); ) que ainda é um desligamento assíncrono.

Acho que com relação ao comentário de @mscharley , a vantagem é que existe um fileSync appender, que não requer o uso de shutdown() para ter os logs completos gravados no arquivo quando o Node processo termina ...

Sim, ter um transporte fileSync seria útil em algumas situações, mesmo que fosse uma diminuição do desempenho líquido.

@jdthorpe Eu acho que sua ideia de ter uma biblioteca que lida com o fechamento de coisas de forma limpa antes de desligar é boa, mas ainda não transfere a responsabilidade do winston para fornecer um método de esperar que ele libere tudo para o disco (ou seja, fornecer um mecanismo para se fechar), que poderia então ser combinado com essa biblioteca para agregar os métodos de fechamento para várias bibliotecas.

Este tíquete pode pelo menos alterar os documentos para que não pareça ser compatível no momento? Só passei 30 minutos depurando esse problema que parece ser compatível quando você procura por seriously no repo, ele só é compatível com README . Isso parece ser um recurso sem suporte ou um bug e as soluções alternativas não são muito palatáveis.

Quando isso vai ser corrigido? Isso já existe há 3 anos e é muito importante.

Vamos, pelo menos, colocar um retorno de chamada no logger que realmente funciona.

Eu diria que talvez tenha escrito uma função shutdown() genérica para todos como um novo recurso, e esse recurso é muito crítico.

Sim, esta é uma questão muito, muito importante para mim

1 para isto

Francamente, acho que adicionar shutdown(callback) parece apropriado, mas com a ressalva de que os transportes precisam apoiá-lo ativamente. Os transportes individuais são os "Especialistas em Informação" sobre o mecanismo de produção subjacente; eles têm mais informações sobre como deve ser encerrado de forma limpa.

Tudo o que o winston core faz - e mais definitivamente tudo o que fazemos na terra do usuário - requer que detalhes de implementação dos transportes vazem.

Portanto, winston não deve precisar fazer o trabalho ... mas realmente precisa fornecer uma maneira para que o trabalho seja feito. Então, todos nós podemos trabalhar com os autores de Transporte para fazer o trabalho pesado.

Algum código psuedo para ilustrar o ponto abaixo.

`` `js
desligamento (retorno de chamada) {
var transportCount = transports.length
var terminado = 0;
// para cada transporte
if (transport.shutdown) {
transport.shutdown (function () {
// aumenta a contagem finalizada.
// se tudo terminar, chame o callback original.
});
} senão {
// O transporte (ainda) não o suporta.
// incremento do contador final
}
}

Adoraria ver isso corrigido na v3.x.

Aqui está minha solução (assume um ambiente que suporta async / await )


Para um único 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 vários transportes (não testado):

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

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

// helper para sair com um determinado código de retorno, mas somente depois que o logger for concluído
// isso retornará uma promessa que nunca será resolvida, interrompendo a execução
log.exit = (exit = 5) => {
retornar nova promessa (() => {
Promise.all (
logTransports.map (transport => new Promise (resolve => transport.on ('terminado', resolve)))
) .então (() => process.exit (sair))
})
}

</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
}

Não deve ser um recorde quebrado, mas winston-log-and-exit também resolve esse problema

Apenas para casos de uso muito específicos. Eu não poderia usar winston-log-and-exit, digamos, AWS Lambda, onde o processo não sai, mas ele congela entre as execuções, então os logs ainda se perdem. Também presume que eu sei quais mensagens são minhas mensagens finais, o que nem sempre é o caso em um caminho de execução bem-sucedido.

@mscharley a solução await funcionaria para o seu caso de uso? Talvez em vez de log.exit() uma api melhor seria await log.finish() que esperaria até que todos os transportes terminassem de escrever e então deixaria você fazer o que quer que fosse (chame process.exit , chame a lamda done callback, etc)

Isso é basicamente exatamente o que estamos defendendo nesta edição, exceto dentro do Winston. Por que isso seria um plugin? Parece algo que deveria surgir com mais frequência. Não sinto que o que estamos fazendo seja algo especial, mas atingimos essa barreira em todos os projetos - e é por isso que acabamos nos afastando de Winston. Perder logs, especialmente no final do processo - onde os erros são mais prováveis ​​de ocorrer - parece no mínimo perigoso.

log4js-node implementou um método de desligamento com descarrega todos os transportes e recebe um retorno de chamada, como process.exit() . Algo assim poderia ser adicionado ao winston?

nó log4js é então

alguma atualização? O problema é muito real.

Para qualquer sistema de registro, o cálculo é:

  • Se você absolutamente precisa ter seus registros e está disposto a pagar o custo de tempos de resposta mais lentos, use um registrador síncrono
  • Se você estiver chamando process.exit() você mesmo, espere até que as mensagens em buffer sejam apagadas. Para winston, o pacote winston-log-and-exit faz isso para você.
  • Se algum outro código estiver chamando process.exit() e sua plataforma tiver um gancho de saída, use esse gancho e espere até que as mensagens armazenadas em buffer sejam apagadas. winston-log-and-exit também pode ajudar nisso.
  • Se você estiver usando uma plataforma como o AWS Lambda, que não tem um gancho de saída, você está trocando os benefícios da plataforma pelo risco de perda de dados.

Incidentalmente, @ begin-again este método log_and_exit() é essencialmente igual ao método shutdown() log-4js com a garantia adicional de que a mensagem de log fornecida será registrada.

@jdthorpe Mas winston-log-and-exit não funcionará facilmente no winston 3

@VRuzhentsov Oh, bem, isso é um problema. Eles realmente deveriam fazer algo a respeito.

@jdthorpe corrigido com

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);

O seguinte funciona para mim:

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

@ redhat-raptor. Que irá trabalhar a maior parte do tempo, mas não é garantido que funcione o tempo todo. Acontece que seus buffers foram limpos no momento em que nextTick () foi chamado, mas dependendo das conexões das quais seus registradores dependem, isso pode facilmente resultar em mensagens perdidas ...

Este código funcionou para mim:

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

Isso não tem suporte nativo na v3?

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

@danielweck Não, está quebrado: # 1629 # 1504!

6 anos, isso mesmo, 6 anos para um bug marcado como _importante_. É impressionante.

Eu uso uma promessa de 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();
    });  
};

Atualização: stream.end() não libera gravações pendentes, portanto, esta solução é inadequada. Por alguma razão, em testes recentes, transport.close(); + transport.once('finish', ...); funciona muito bem ... mas não tenho certeza porque funciona agora! (costumava falhar!)

Na minha solução de trabalho acima, a chave é usar:
transport._stream.once('finish', finished); transport._stream.end();
em vez de:
transport.once('finish', finished); transport.close();
(a estratégia de tempo limite adicionada é específica para meu caso de uso e provavelmente é opcional / redundante no caso geral)

Maneira mais fácil:

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

@danielweck Você já conseguiu encontrar uma solução para isso? Recentemente, atualizamos para o Winston 3.x, mas talvez seja necessário voltar para a 2.x ou encontrar um registrador diferente sem uma solução aqui.

@matttowerssonos , Winston @ 2. Dada a extensão deste tópico e o fato de que você não está perguntando sobre o comentário original do postador, por que não começar um novo tópico com o seu problema?

BTW, não estou vendo nenhum problema com logs perdidos no Winston @ 3 , então você pode querer incluir sua configuração em seu novo problema.

@cjbarth Isso não 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 Se não me engano, o evento finish nunca será disparado em processLogger porque você nunca chama processLogger.end() . Se você chamar isso, então, quando o Winston terminar o registro, o evento finish deve ser acionado.

Eu também usaria process.disconnect() vez de process.exit() , o que permite que a fila escoe. Ele sairá automaticamente quando a fila acabar.

@stephanoparaskeva Se não me engano, o evento finish nunca será disparado em processLogger porque você nunca chama processLogger.end() . Se você chamar isso, então, quando o Winston terminar o registro, o evento finish deve ser acionado.

Eu também usaria process.disconnect() vez de process.exit() , o que permite que a fila escoe. Ele sairá automaticamente quando a fila acabar.

Te peguei, então algo assim?

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 Isso parece melhor.

Normalmente, eu vincularia o manipulador de eventos antes de chamar processLogger.end() , mas isso não deve importar porque o evento finish deve disparar apenas depois que o loop de eventos for girado, momento em que o manipulador estará vinculado. Só acho que escrever o código onde o manipulador de eventos está vinculado primeiro torna isso mais claro.

@cjbarth
Oh, como você vincula o manipulador de eventos a algo?
Isso seria:

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

@stephanoparaskeva Sim. Essa é a sintaxe correta para vincular a função

{
  this.process.disconnect();
}

Ao evento finish emitido pelo objeto processLogger .

Se você não chamar process.exit, mas fizer um desligamento adequado, fechando todas as conexões e esperando que o loop de eventos seja drenado, não haverá problema algum.

Consulte: https://stackoverflow.com/a/37592669 para entender melhor a que @deedf se refere. Seguindo esse conselho, aliviou esse problema para mim também.

O fato de que o evento final ainda não emite depois de anos é simplesmente embaraçoso neste ponto. Vai ser um saco ter que trocar de loggers e reescrever todos os meus transportes personalizados para eles.

Não entendo como isso ainda não foi resolvido por winston. Eu tenho um problema que apenas o primeiro criador de logs em meu código é conectado ao Logstash (usando também winston-elasticsearch). Se eu usar logger.end (), tudo será registrado, mas o programa será encerrado muito cedo. tentei usar todas as soluções acima e nenhuma funcionou.
Estou realmente indefeso

Não entendo como isso ainda não foi resolvido por winston. Eu tenho um problema que apenas o primeiro criador de logs em meu código é conectado ao Logstash (usando também winston-elasticsearch). Se eu usar logger.end (), tudo será registrado, mas o programa será encerrado muito cedo. tentei usar todas as soluções acima e nenhuma funcionou.
Estou realmente indefeso

Você tentou isso ?

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Portanto, nossa solução para esse problema é não chamar process.exit ()?

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Portanto, nossa solução para esse problema é não chamar process.exit ()?

Sim, é sempre uma má ideia em nodejs, consulte https://stackoverflow.com/a/37592669

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Portanto, nossa solução para esse problema é não chamar process.exit ()?

Sim, é sempre uma má ideia em nodejs, consulte https://stackoverflow.com/a/37592669

Bem, o motivo pelo qual pessoalmente estou usando process.exit é porque estou ouvindo uncaughtException e unhandledRejection para registrar todos os meus transportes e, em seguida, encerre o aplicativo. Existe uma maneira melhor de resolver esse problema?

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Onde você viu que eu disse que usei exit ()?

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Onde você viu que eu disse que usei exit ()?

Desculpe por presumir que sua habilidade de leitura e compreensão é suficiente para entender do que se trata esse bug. Verifique o título novamente.

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Onde você viu que eu disse que usei exit ()?

Desculpe por presumir que sua habilidade de leitura e compreensão é suficiente para entender do que se trata esse bug. Verifique o título novamente.

Você deve estar muito ocupado se chegar a um problema que está aberto há 8 anos e não oferecer nenhuma ajuda adequada.

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Portanto, nossa solução para esse problema é não chamar process.exit ()?

Sim, é sempre uma má ideia em nodejs, consulte https://stackoverflow.com/a/37592669

Bem, o motivo pelo qual pessoalmente estou usando process.exit é porque estou ouvindo uncaughtException e unhandledRejection para registrar todos os meus transportes e, em seguida, encerre o aplicativo. Existe uma maneira melhor de resolver esse problema?

Eu não uso o winston há algum tempo, mas ele não irá logar assim mesmo? caso contrário, relançar o erro após registrá-lo não funcionará?

Não entendo como as pessoas não entendem que esse "problema" não foi "resolvido" porque não há nenhum. Basta escrever o código adequado não chamando exit () e você ficará bem.

Onde você viu que eu disse que usei exit ()?

Desculpe por presumir que sua habilidade de leitura e compreensão é suficiente para entender do que se trata esse bug. Verifique o título novamente.

Você deve estar muito ocupado se chegar a um problema que está aberto há 8 anos e não oferecer nenhuma ajuda adequada.

Pelo menos posso resolver meus próprios problemas sem me lamentar como um pirralho nobre.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

xungwoo picture xungwoo  ·  3Comentários

anks333 picture anks333  ·  3Comentários

greenhat616 picture greenhat616  ·  3Comentários

pocesar picture pocesar  ·  3Comentários

ghost picture ghost  ·  4Comentários