Nœud: connectez-vous dans un fichier au lieu de la console


174

Puis-je configurer console.logpour que les journaux soient écrits sur un fichier au lieu d'être imprimés dans la console?


1
pourrait, mais pour les applications de production à longue durée d'exécution, il serait difficile de trouver des journaux pour un jour spécifique, non? @racar

Réponses:


72

Mise à jour 2013 - Ceci a été écrit autour de Node v0.2 et v0.4; Il existe maintenant de bien meilleurs utilitaires pour la journalisation. Je recommande vivement Winston

Mise à jour fin 2013 - Nous utilisons toujours winston, mais maintenant avec une bibliothèque de journalisation pour envelopper la fonctionnalité autour de la journalisation des objets personnalisés et du formatage. Voici un échantillon de notre logger.js https://gist.github.com/rtgibbons/7354879


Cela devrait être aussi simple que cela.

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

1
NVM, ça veut dire processus je pense ... Comment ça marche? console.log(whatever);va toujours à la console, pas au fichier.
— trusktr du

12
En raison d'un changement récent, vous ne pouvez plus appeler stderr.pipe () - cela prend maintenant:process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) })
— damianb

15
Personnellement, j'éviterais bien Winston. Nous l'utilisons depuis plus d'un an maintenant et avons finalement décidé de le supprimer complètement car il causait de nombreux problèmes dans notre environnement de production. Le projet semble aujourd'hui extrêmement mal entretenu. Il y a une liste de problèmes aussi longtemps que votre bras. De nombreux problèmes ont fait l'objet de demandes d'extraction soumises par d'autres utilisateurs, mais les responsables du projet ne prennent même pas le temps de les fusionner. Pour les alternatives, node-bunyan et caterpillar pourraient valoir la peine d'être examinées.
— UpTheCreek

Ça craint que les responsables ne soient pas réactifs. Je pensais qu'il était maintenu par les gens de Nodejitsu. Nous l'avons utilisé sur plusieurs sites enregistrant plus d'un million de pages vues par jour et n'avons eu aucun problème de journalisation. Cela a peut-être à voir avec ce qui est enregistré et sa quantité.
— Ryan Gibbons

1
Il semble qu'en avril 2015, Winston soit à jour et reçoive beaucoup d'activité.
— Mike Grace

181

Vous pouvez également simplement surcharger la fonction console.log par défaut:

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

L'exemple ci-dessus se connectera à debug.log et stdout.

Edit: Voir la version multiparamètre de Clément également sur cette page.


9
je ne prendrais pas la peine d'écraser console.log. Créez simplement votre propre fonction qui se connecte à un fichier spécifique.
— Alexander Mills

De plus, cela ne fonctionne pas pour plusieurs paramètres. Par exemple, console.log (p1, p2, p3)
— user603749

10
Très bonne réponse! De plus, si vous souhaitez capturer plusieurs arguments console.log, saisissez simplement l'objet 'Arguments' à la place de 'd' - developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
— Charlie

@AlexMills Bonjour, peut-être pourriez-vous donner un exemple sur la façon dont cela serait fait exactement?
— Jonathan

6
mais je dois l'avoir dans chaque fichier js, est-il possible de le rendre global?
— stackdave

60

Si vous cherchez quelque chose en production, winston est probablement le meilleur choix.

Si vous voulez juste faire des choses de développement rapidement, sortez directement dans un fichier (je pense que cela ne fonctionne que pour les systèmes * nix):

nohup node simple-server.js > output.log &

7
Utiliser >pour rediriger STDOUT fonctionne également sur Windows. nohuppas.
— Brad

1
cela fonctionne heureusement sans nohupsur * nix, ce est à dire node simple-server.js > output.log. Ensuite, si vous souhaitez suivre le journal tel qu'il est écrittail -f output.log
— méchant pâteux

Cela n'a pas fonctionné 2 quand j'ai eu des arguments passés au processus
— eran otzap

Quel est l'inconvénient de faire cela en production?
— marcelino

1
btw en fonction de votre OS, ce "faire-quelque chose-à ce sujet" pourrait simplement être une rotation des journaux, ce qui est une bonne solution imo - abdussamad.com/archives/541-Log-rotation-in-CentOS-Linux.html
— ferr

59

J'utilise souvent de nombreux arguments pour console.log () et console.error () , donc ma solution serait:

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;

32

Winston est un module npm très populaire utilisé pour la journalisation.

Voici un guide pratique.
Installez winston dans votre projet en tant que:

npm install winston --save

Voici une configuration prête à l'emploi prête à l'emploi que j'utilise fréquemment dans mes projets comme logger.js sous 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
};

Et puis importez simplement là où c'est nécessaire comme ceci:

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

Ensuite, vous pouvez enregistrer le succès comme:

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

et erreurs comme:

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

Il enregistre également tous les journaux de succès et les journaux d'erreurs dans un fichier sous le répertoire des journaux par date, comme vous pouvez le voir ici.
enregistrement de direcotry


Les journaux sont visibles dans la console. et aucun fichier n'est créé immédiatement !! Est-ce que je manque quelque chose?
— Nigilan

1
Pourriez-vous éventuellement partager vos configs? Ou l'avez-vous utilisé comme je l'ai suggéré? Vérifiez les importations ( winston& winston-daily-rotate-file) une fois si les configurations sont correctes. Ils doivent être créés dans un dossier nommé logsdans le répertoire racine du projet. Pardonnez-moi pour la réponse retardée.
— keshavDulal

@Nigilan comment avez-vous résolu ce problème? Je suis confronté au même problème.
— user2180794

@ user2180794 Jetez un œil à mon commentaire au-dessus du commentaire de Nigilan. Faites-nous savoir si vous ne pouvez toujours pas le faire.
— keshavDulal

1
N'oubliez pas de les ajouter en plus de logger-util const winston = require('winston'); const winstonRotator = require('winston-daily-rotate-file'); et const errorLog = require('../util/logger').errorlog; const successlog = require('../util/logger').successlog; partout où vous voulez enregistrer quelque chose.
— keshavDulal

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

Pour l'utiliser, faites quelque chose comme:

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

est-il possible de simplement enregistrer les erreurs?
— stackdave

Au lieu de boucler sur les Console.prototypeclés, il suffit de définir explicitement this.erroruniquement.
— riche remer

Cela casse console.log?
— G_V

Ça ne casse pas console.log. Il modifie son comportement, bien que vous puissiez restaurer l'ancien comportement en appelant console.file().
— riche souvenir du


6

Une autre solution non encore mentionnée consiste à accrocher les Writableflux dans process.stdoutet process.stderr. De cette façon, vous n'avez pas besoin de remplacer toutes les fonctions de la console qui sortent vers stdout et stderr. Cette implémentation redirige à la fois stdout et stderr vers un fichier journal:

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

Il devrait s'imprimer dans la console

a
b
c
d
e
f

et dans le fichier journal:

c
d

Pour plus d'informations, consultez l' essentiel .


Bonne réponse.
— nikk wong

6

Pour les cas simples, nous pourrions rediriger les flux de sortie standard (STDOUT) et d'erreur standard (STDERR) directement vers un fichier par '>' et '2> & 1'

Exemple:

// test.js
(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");
})();

nœud test.js> test.log 2> & 1

Conformément à la norme POSIX, les flux «entrée», «sortie» et «erreur» sont identifiés par les descripteurs de fichier entiers positifs (0, 1, 2). c'est-à-dire que stdin vaut 0, stdout vaut 1 et stderr vaut 2.

'2> & 1' redirigera de 2 (stderr) vers 1 (stdout)

'>' redirigera de 1 (stdout) vers le fichier (test.log)


5

Écraser console.log est la voie à suivre. Mais pour qu'il fonctionne dans les modules requis, vous devez également l'exporter.

module.exports = console;

Pour vous éviter d'écrire des fichiers journaux, de les faire pivoter et d'autres choses, vous pouvez envisager d'utiliser un simple module de journalisation comme 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;

Oui. Désolé. My bad
— Simon Rigét

vous pouvez remplacer les propriétés de la console sur l' globalobjet. pourquoi faire module.exports?
— r3wt

3

MÉTHODE STDOUT ET STDERR

Cette approche peut vous aider (j'utilise quelque chose de similaire dans mes projets) et fonctionne pour toutes les méthodes, y compris console.log, console.warn, console.error, console.info

Cette méthode écrit les octets écrits dans stdout et stderr dans un fichier. C'est mieux que de changer les méthodes console.log, console.warn, console.error, console.info, car la sortie sera exactement la même que celle de cette méthode


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)

je vais utiliser ceci dans mon module npm et vous attribuer ce code. c'est cool?
— r3wt

2

Directement à partir de la documentation de l'API de nodejs sur la 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

Vous pouvez désormais utiliser Caterpillar, un système de journalisation basé sur les flux, vous permettant de vous y connecter, puis de diriger la sortie vers différents transformations et emplacements.

La sortie vers un fichier est aussi simple que:

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

Exemple complet sur le site Web de Caterpillar



0

J'ai pris l'idée d'échanger le flux de sortie vers un flux mon.

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

Améliorer sur Andres Riofrio, pour gérer n'importe quel nombre d'arguments

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

Pour ma part, j'ai simplement pris l'exemple de winston et ajouté la log(...)méthode (car winston le nomme 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;

Ensuite, utilisez simplement dans votre code:

const console = require('Console')

Maintenant, vous pouvez simplement utiliser les fonctions normales de journal dans votre fichier et il créera un fichier ET le consignera sur votre console (pendant le débogage / développement). À cause de if (process.env.NODE_ENV !== 'production') {(au cas où vous le voudriez également en production) ...


Winston n'ajoute-t-il pas un tas de déchets comme "message" et le niveau de journalisation?
— G_V

@G_V Que voulez-vous dire? winston est très flexible, vous pouvez le configurer ... cherchez-vous ... github.com/winstonjs/winston#formats ?
— TechupBusiness
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.