ti-enxame.com

Nó: faça o login em um arquivo em vez do console

Posso configurar console.log para que os logs sejam gravados em um arquivo em vez de serem impressos no console?

140
Randomblue

Update 2013 - Isso foi escrito em torno do Node v0.2 e v0.4; Existem utilitários muito melhores agora em torno do log. Eu recomendo altamente Winston

Update Late 2013 - Nós ainda usamos winston, mas agora com uma biblioteca de logger para envolver a funcionalidade em torno do log de objetos personalizados e formatação. Aqui está uma amostra do nosso logger.js https://Gist.github.com/rtgibbons/7354879


Deve ser tão simples quanto isso. 

var access = fs.createWriteStream(dir + '/node.access.log', { flags: 'a' })
      , error = fs.createWriteStream(dir + '/node.error.log', { flags: 'a' });

// redirect stdout / stderr
proc.stdout.pipe(access);
proc.stderr.pipe(error);
61
Ryan Gibbons

Você também pode sobrecarregar a função default console.log:

var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write(util.format(d) + '\n');
  log_stdout.write(util.format(d) + '\n');
};

O exemplo acima será registrado em debug.log e stdout.

Edit:Veja a versão multiparâmetro de Clément também nesta página.

156
ceeroover

Se você está procurando algo em produção winston é provavelmente a melhor escolha.

Se você quer apenas fazer coisas de desenvolvimento rapidamente, envie diretamente para um arquivo (acho que isso funciona apenas para sistemas * nix):

Nohup node simple-server.js > output.log &
47
alessioalex

Eu costumo usar muitos argumentos para console.log () e console.error () , então minha solução seria:

var fs = require('fs');
var util = require('util');
var logFile = fs.createWriteStream('log.txt', { flags: 'a' });
  // Or 'w' to truncate the file every time the process starts.
var logStdout = process.stdout;

console.log = function () {
  logFile.write(util.format.apply(null, arguments) + '\n');
  logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = console.log;
47
Clément Désiles

Winston é um módulo npm muito popular usado para registro. 

Aqui está um how-to.
Instale o winston em seu projeto como:

npm install winston --save

Aqui está uma configuração pronta para usar pronto para uso que eu uso com frequência em meus projetos como logger.js em utils.

 /**
 * Configurations of logger.
 */
const winston = require('winston');
const winstonRotator = require('winston-daily-rotate-file');

const consoleConfig = [
  new winston.transports.Console({
    'colorize': true
  })
];

const createLogger = new winston.Logger({
  'transports': consoleConfig
});

const successLogger = createLogger;
successLogger.add(winstonRotator, {
  'name': 'access-file',
  'level': 'info',
  'filename': './logs/access.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

const errorLogger = createLogger;
errorLogger.add(winstonRotator, {
  'name': 'error-file',
  'level': 'error',
  'filename': './logs/error.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

module.exports = {
  'successlog': successLogger,
  'errorlog': errorLogger
};

E então simplesmente importe onde for necessário como isto:

const errorLog = require('../util/logger').errorlog;
const successlog = require('../util/logger').successlog;

Então você pode registrar o sucesso como:

successlog.info(`Success Message and variables: ${variable}`);

e erros como:

errorlog.error(`Error Message : ${error}`);

Ele também registra todos os logs de erro e logs de erros em um arquivo no diretório de registros, como você pode ver aqui.
log direcotry

24
keshavDulal
const fs = require("fs");
const {keys} = Object;
const {Console} = console;

/**
 * Redirect console to a file.  Call without path or with false-y
 * value to restore original behavior.
 * @param {string} [path]
 */
function file(path) {
    const con = path ? new Console(fs.createWriteStream(path)) : null;

    keys(Console.prototype).forEach(key => {
        if (path) {
            this[key] = (...args) => con[key](...args);
        } else {
            delete this[key];
        }
    });
};

// patch global console object and export
module.exports = console.file = file;

Para usá-lo, faça algo como:

require("./console-file");
console.file("/path/to.log");
console.log("write to file!");
console.error("also write to file!");
console.file();    // go back to writing to stdout
11
rich remer

Se isso é para um aplicativo, provavelmente é melhor usar um módulo de registro. Isso lhe dará mais flexibilidade. Algumas sugestões.

10
Marco

Outra solução ainda não mencionada é ligando os fluxos Writable em process.stdout e process.stderr. Desta forma você não precisa sobrescrever todas as funções do console que saem para stdout e stderr. Essa implementação redireciona stdout e stderr para um arquivo de log:

var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})

function hook_stream(stream, callback) {
    var old_write = stream.write

    stream.write = (function(write) {
        return function(string, encoding, fd) {
            write.apply(stream, arguments)  // comments this line if you don't want output in the console
            callback(string, encoding, fd)
        }
    })(stream.write)

    return function() {
        stream.write = old_write
    }
}

console.log('a')
console.error('b')

var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

console.log('c')
console.error('d')

unhook_stdout()
unhook_stderr()

console.log('e')
console.error('f')

Deve imprimir no console

a
b
c
d
e
f

e no arquivo de log:

c
d

Para mais informações, verifique isto Gist .

3
reliasn

Sobrescrever console.log é o caminho a percorrer. Mas para funcionar nos módulos necessários, você também precisa exportá-lo.

module.exports = console;

Para evitar o problema de escrever arquivos de log, rotacionar e outras coisas, você pode considerar usar um módulo de logger simples como o winston:

// Include the logger module
var winston = require('winston');
// Set up log file. (you can also define size, rotation etc.)
winston.add(winston.transports.File, { filename: 'somefile.log' });
// Overwrite some of the build-in console functions
console.error=winston.error;
console.log=winston.info;
console.info=winston.info;
console.debug=winston.debug;
console.warn=winston.warn;
module.exports = console;
3
Simon Rigét

Diretamente da documentação da API do nodejs em Console

const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// custom simple logger
const logger = new Console(output, errorOutput);
// use it like console
const count = 5;
logger.log('count: %d', count);
// in stdout.log: count 5
1
Mr. 14

MÉTODO STDOUT E STDERR

Esta abordagem pode ajudá-lo (eu uso algo semelhante em meus projetos) e funciona para todos os métodos, incluindo console.log, console.warn, console.error, console.info

Esse método grava os bytes gravados em stdout e stderr em arquivo. É melhor do que mudar os métodos console.log, console.warn, console.error, console.info, porque a saída será exatamente a mesma que esta saída de métodos


var fs= require("fs")
var os= require("os")
var HOME= os.homedir()
var stdout_r = fs.createWriteStream(HOME + '/node.stdout.log', { flags: 'a' })
var stderr_r = fs.createWriteStream(HOME + '/node.stderr.log', { flags: 'a' })

var attachToLog= function(std, std_new){

    var originalwrite= std.write
    std.write= function(data,enc){
        try{
            var d= data
            if(!Buffer.isBuffer(d))
                d= Buffer.from(data, (typeof enc === 'string') ? enc : "utf8")
            std_new.write.apply(std_new, d)
        }catch(e){}
        return originalwrite.apply(std, arguments)
    }


}
attachToLog(process.stdout, stdout_r)
attachToLog(process.stderr, stderr_r)

// recommended catch error on stdout_r and stderr_r
// stdout_r.on("error", yourfunction)
// stderr_r.on("error", yourfunction)
1

Agora você pode usar Caterpillar , que é um sistema de registro baseado em fluxos, permitindo que você efetue o registro e, em seguida, canalize a saída para diferentes transformações e locais.

A saída para um arquivo é tão fácil quanto:

var logger = new (require('./').Logger)();
logger.pipe(require('fs').createWriteStream('./debug.log'));
logger.log('your log message');

Exemplo completo no Site da Caterpillar

1
balupton

Eu assumi a idéia de trocar o fluxo de saída para um fluxo meu.

const LogLater                = require ('./loglater.js');
var logfile=new LogLater( 'log'+( new Date().toISOString().replace(/[^a-zA-Z0-9]/g,'-') )+'.txt' );


var PassThrough = require('stream').PassThrough;

var myout= new PassThrough();
var wasout=console._stdout;
myout.on('data',(data)=>{logfile.dateline("\r\n"+data);wasout.write(data);});
console._stdout=myout;

var myerr= new PassThrough();
var waserr=console._stderr;
myerr.on('data',(data)=>{logfile.dateline("\r\n"+data);waserr.write(data);});
console._stderr=myerr;

loglater.js:

const fs = require('fs');

function LogLater(filename, noduplicates, interval) {
    this.filename = filename || "loglater.txt";
    this.arr = [];
    this.timeout = false;
    this.interval = interval || 1000;
    this.noduplicates = noduplicates || true;
    this.onsavetimeout_bind = this.onsavetimeout.bind(this);
    this.lasttext = "";
    process.on('exit',()=>{ if(this.timeout)clearTimeout(this.timeout);this.timeout=false; this.save(); })
}

LogLater.prototype = {
    _log: function _log(text) {
        this.arr.Push(text);
        if (!this.timeout) this.timeout = setTimeout(this.onsavetimeout_bind, this.interval);
    },
    text: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text);
    },
    line: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text + '\r\n');
    },
    dateline: function dateline(text) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(((new Date()).toISOString()) + '\t' + text + '\r\n');
    },
    onsavetimeout: function onsavetimeout() {
        this.timeout = false;
        this.save();
    },
    save: function save() { fs.appendFile(this.filename, this.arr.splice(0, this.arr.length).join(''), function(err) { if (err) console.log(err.stack) }); }
}

module.exports = LogLater;
0
Shimon Doodkin

Para casos simples, podemos redirecionar os fluxos de saída Standard Out (STDOUT) e Standard Error (STDERR) diretamente para o arquivo por> e 2> & 1

Exemplo:

(function() {
    // Below outputs are sent to Standard Out (STDOUT) stream
    console.log("Hello Log");
    console.info("Hello Info");
    // Below outputs are sent to Standard Error (STDERR) stream
    console.error("Hello Error");
    console.warn("Hello Warning");
})();

node test.js> test.log 2> & 1

De acordo com o padrão POSIX, 'input', 'output' e 'error' streams são identificados pelo inteiro positivofile descriptors(0, 1, 2). isto é, stdin é 0, stdout é 1 e stderr é 2.  

'2> & 1' irá redirecionar 2 (stderr) para 1 (stdout)

'>' irá redirecionar 1 (stdout) para o arquivo

0
SridharKritha

Eu, por mim mesmo, simplesmente peguei o exemplo do winston e adicionei o método log(...) (porque o winston o nomeia info(..):

Console.js:

"use strict"

// Include the logger module
const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        //
        // - Write to all logs with level `info` and below to `combined.log`
        // - Write all logs error (and below) to `error.log`.
        //
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
    logger.add(new winston.transports.Console({
        format: winston.format.simple()
    }));
}

// Add log command
logger.log=logger.info;

module.exports = logger;

Então, simplesmente use em seu código:

const console = require('Console')

Agora você pode simplesmente usar as funções de log normais em seu arquivo e criar um arquivo E registrá-lo em seu console (durante a depuração/desenvolvimento). Por causa de if (process.env.NODE_ENV !== 'production') { (no caso de você querer também em produção) ...

0
TechupBusiness

Eu apenas construo um pacote para fazer isso, espero que você goste;) https://www.npmjs.com/package/writelog

0
Phung Thang

Você também pode dar uma olhada neste módulo npm: https://www.npmjs.com/package/noogger

noogger

simples e direto ...

0
Xsmael

Melhorar em Andres Riofrio, para lidar com qualquer número de argumentos

var fs = require('fs');
var util = require('util');

var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(...args) {
    var output = args.join(' ');
    log_file.write(util.format(output) + '\r\n');
    log_stdout.write(util.format(output) + '\r\n');
};
0
Liran BarNiv