Nút: đăng nhập vào một tệp thay vì bảng điều khiển


174

Tôi có thể định cấu hình console.logđể nhật ký được ghi trên một tệp thay vì được in trong bảng điều khiển không?


1
có thể, nhưng đối với các ứng dụng sản xuất thời gian chạy dài, thật khó để tìm thấy nhật ký chỉ trong một ngày cụ thể, phải không? @racar

Câu trả lời:


72

Cập nhật 2013 - Điều này đã được viết xung quanh Node v0.2 và v0.4; Có nhiều sử dụng tốt hơn bây giờ xung quanh đăng nhập. Tôi đánh giá cao Winston

Cập nhật Cuối năm 2013 - Chúng tôi vẫn sử dụng winston, nhưng giờ đây với thư viện logger để bọc chức năng xung quanh việc ghi nhật ký các đối tượng tùy chỉnh và định dạng. Dưới đây là mẫu logger.js https://gist.github.com/rtg Ribbon / 7354879 của chúng tôi


Nên đơn giản như thế này.

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, nó có nghĩa là quá trình tôi nghĩ ... Làm thế nào nó hoạt động? console.log(whatever);vẫn đi đến bàn điều khiển, không tập tin.
trusktr

12
Do một sự thay đổi gần đây, bạn không thể gọi stderr.pipe () nữa - phải mất ngay bây giờ:process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) })
damianb

15
Cá nhân tôi sẽ tránh xa Winston. Chúng tôi đã sử dụng nó hơn một năm nay và cuối cùng đã quyết định loại bỏ nó hoàn toàn vì nó gây ra nhiều vấn đề trong môi trường sản xuất của chúng tôi. Dự án dường như bây giờ được bảo trì cực kỳ kém. Có một danh sách các vấn đề miễn là cánh tay của bạn. Nhiều vấn đề đã có yêu cầu kéo được gửi bởi người dùng khác, nhưng những người duy trì dự án thậm chí không dành thời gian để hợp nhất những yêu cầu này. Đối với các lựa chọn thay thế nút-bunyan và sâu bướm có thể đáng xem xét.
UpTheCux

Nó hút rằng các nhà bảo trì không được đáp ứng. Tôi nghĩ rằng nó được duy trì bởi những người Nodejitsu. Chúng tôi đã sử dụng nó trên một số trang web thu hút hơn một triệu lượt xem trang mỗi ngày và không có vấn đề gì với việc đăng nhập. Có lẽ nó phải làm với những gì đang được ghi lại và số lượng của nó.
Ryan Gibbons

1
Có vẻ như kể từ tháng 4 năm 2015 Winston đã cập nhật và nhận được rất nhiều hoạt động.
Mike Grace

178

Bạn cũng có thể quá tải chức năng console.log mặc định:

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

Ví dụ trên sẽ đăng nhập vào debug.log và stdout.

Chỉnh sửa: Xem phiên bản đa thông số của Clément trên trang này.


9
Tôi sẽ không bận tâm đến việc ghi đè console.log. Chỉ cần tạo chức năng của riêng bạn mà đăng nhập vào một tập tin cụ thể.
Alexander Mills

Ngoài ra, điều này không làm việc cho nhiều tham số. Ví dụ: console.log (p1, p2, p3)
user603749

10
Câu trả lời chính xác! Ngoài ra, nếu bạn muốn nắm bắt nhiều đối số console.log, chỉ cần lấy đối tượng 'Đối số' thay cho 'd' - developer.mozilla.org/en/docs/Web/JavaScript/Reference/
trộm

@AlexMills Xin chào, có lẽ bạn có thể cung cấp một ví dụ về cách chính xác điều đó sẽ được thực hiện?
Jonathan

6
Nhưng tôi cần phải có điều này trong mỗi tập tin js, có thể làm cho nó toàn cầu?
stackdave

60

Nếu bạn đang tìm kiếm một cái gì đó trong sản xuất winston có lẽ là sự lựa chọn tốt nhất.

Nếu bạn chỉ muốn thực hiện công cụ dev nhanh chóng, hãy xuất trực tiếp ra một tệp (tôi nghĩ rằng điều này chỉ hoạt động cho các hệ thống * nix):

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

7
Sử dụng >để chuyển hướng STDOUT cũng hoạt động trên Windows. nohupkhông.
Brad

1
cái này hoạt động rất vui vẻ mà không cần nohupbật * nix node simple-server.js > output.log. Sau đó, nếu bạn muốn theo dõi nhật ký như văn bản của nótail -f output.log
pasty khó chịu

Điều này đã không hoạt động 2 khi tôi có các đối số được chuyển qua quá trình
eran otzap 04/12/2016

Nhược điểm của việc này trong sản xuất là gì?
marcelino

1
btw tùy thuộc vào hệ điều hành của bạn, rằng "do- Something
ferr

58

Tôi thường sử dụng nhiều đối số cho console.log ()console.error () , vì vậy giải pháp của tôi sẽ là:

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 là một mô-đun npm rất phổ biến được sử dụng để đăng nhập.

Đây là một cách làm.
Cài đặt winston trong dự án của bạn như:

npm install winston --save

Đây là một cấu hình sẵn sàng để sử dụng ngoài hộp mà tôi thường xuyên sử dụng trong các dự án của mình dưới dạng logger.js dưới các tiện ích.

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

Và sau đó chỉ cần nhập bất cứ nơi nào cần thiết như thế này:

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

Sau đó, bạn có thể đăng nhập thành công như:

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

và lỗi như:

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

Nó cũng ghi nhật ký tất cả các nhật ký thành công và nhật ký lỗi trong một tệp trong thư mục nhật ký theo ngày như bạn có thể thấy ở đây.
đăng nhập direcotry


Các bản ghi có thể nhìn thấy trong giao diện điều khiển. và không có tập tin nào được tạo ra ngay lập tức !! Tui bỏ lỡ điều gì vậy ?
Nigilan

1
Bạn có thể chia sẻ cấu hình của bạn? Hay bạn đã sử dụng nó như tôi đề nghị? Kiểm tra nhập ( winston& winston-daily-rotate-file) một lần nếu cấu hình ổn. Chúng nên được tạo bên trong một thư mục có tên logstrong thư mục gốc của dự án. Xin lỗi vì đã trả lời chậm trễ.
keshavDulal

@Nigilan bạn đã sửa cái này như thế nào? Tôi đang phải đối mặt với vấn đề tương tự.
dùng2180794

@ user2180794 Hãy xem nhận xét của tôi ở trên bình luận của Nigilan. Hãy cho chúng tôi biết nếu bạn vẫn không thể hoàn thành nó.
keshavDulal

1
Đừng quên thêm chúng vào đầu logger const winston = require('winston'); const winstonRotator = require('winston-daily-rotate-file');const errorLog = require('../util/logger').errorlog; const successlog = require('../util/logger').successlog; bất cứ nơi nào bạn muốn đăng nhập một cái gì đó.
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;

Để sử dụng nó, hãy làm một cái gì đó như:

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

chỉ có thể để cứu các erros?
stackdave

Thay vì lặp qua Console.prototypecác phím, chỉ cần đặt rõ ràng this.error.
người làm giàu giàu có

Điều này phá vỡ console.log?
G_V

Nó không phá vỡ console.log. Nó thay đổi hành vi của nó, mặc dù bạn có thể khôi phục hành vi cũ bằng cách gọi console.file().
người làm giàu giàu có


6

Một giải pháp khác chưa được đề cập là bằng cách nối các Writableluồng trong process.stdoutprocess.stderr. Bằng cách này, bạn không cần ghi đè tất cả các chức năng của bàn điều khiển xuất ra thiết bị xuất chuẩn và thiết bị xuất chuẩn. Việc triển khai này chuyển hướng cả thiết bị xuất chuẩn và thiết bị xuất chuẩn thành tệp nhật ký:

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

Nó sẽ in trong giao diện điều khiển

a
b
c
d
e
f

và trong tệp nhật ký:

c
d

Để biết thêm thông tin, kiểm tra ý chính này .


Câu trả lời chính xác.
nikk wong

6

Đối với các trường hợp đơn giản, chúng tôi có thể chuyển hướng các luồng Tiêu chuẩn (STDOUT) và Lỗi tiêu chuẩn (STDERR) trực tiếp sang tệp theo '>''2> & 1'

Thí dụ:

// 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út test.js> test.log 2> & 1

Theo tiêu chuẩn POSIX, các luồng 'đầu vào', 'đầu ra' và 'lỗi' được xác định bởi các mô tả tệp số nguyên dương (0, 1, 2). tức là, stdin là 0, stdout là 1 và stderr là 2.

'2> & 1' sẽ chuyển hướng từ 2 (stderr) sang 1 (stdout)

'>' sẽ chuyển hướng từ 1 (stdout) sang tệp (test.log)


5

Ghi đè console.log là cách để đi. Nhưng để nó hoạt động trong các mô-đun cần thiết, bạn cũng cần xuất nó.

module.exports = console;

Để tự cứu mình khỏi những rắc rối khi viết các tệp nhật ký, xoay và các thứ, bạn có thể cân nhắc sử dụng một mô-đun logger đơn giản như 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;

Vâng. Lấy làm tiếc. Xấu của tôi
Simon Rigét

bạn có thể ghi đè các thuộc tính giao diện điều khiển trên globalđối tượng. tại sao module.exports?
r3wt

3

PHƯƠNG PHÁP STDOUT VÀ STDERR

Cách tiếp cận này có thể giúp bạn (tôi sử dụng một cái gì đó tương tự trong các dự án của tôi) và hoạt động cho tất cả các phương thức bao gồm console.log, console.warn, console.error, console.info

Phương thức này ghi các byte được ghi trong thiết bị xuất chuẩn và thiết bị xuất chuẩn vào tệp. Tốt hơn là thay đổi các phương thức console.log, console.warn, console.error, console.info, bởi vì đầu ra sẽ chính xác giống như đầu ra của phương thức này


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)

Tôi sẽ sử dụng điều này trong mô-đun npm của tôi và gán mã này cho bạn. cái đó có ngầu không?
r3wt

2

Trực tiếp từ tài liệu API của nodejs trên Bảng điều khiển

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

Bây giờ bạn có thể sử dụng con sâu bướm , một hệ thống ghi nhật ký dựa trên luồng, cho phép bạn đăng nhập vào nó, sau đó chuyển đầu ra sang các biến đổi và vị trí khác nhau.

Xuất ra một tập tin dễ dàng như:

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

Ví dụ đầy đủ trên trang web của Sâu bướm



0

Tôi đã có ý tưởng hoán đổi luồng đầu ra thành luồng của mình.

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

Cải thiện về Andres Riofrio, để xử lý bất kỳ số lượng đối số

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

Bản thân tôi chỉ đơn giản lấy ví dụ từ winston và thêm log(...)phương thức (vì winston đặt tên cho nó 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;

Sau đó, chỉ cần sử dụng trong mã của bạn:

const console = require('Console')

Bây giờ bạn có thể chỉ cần sử dụng các chức năng nhật ký bình thường trong tệp của mình và nó sẽ tạo một tệp VÀ ghi nhật ký vào bảng điều khiển của bạn (trong khi gỡ lỗi / phát triển). Bởi vì if (process.env.NODE_ENV !== 'production') {(trong trường hợp bạn muốn nó cũng được sản xuất) ...


Winston không thêm một đống rác như "tin nhắn" và cấp độ nhật ký?
G_V

@G_V Ý bạn là gì? winston rất linh hoạt, bạn có thể định cấu hình nó ... bạn đang tìm kiếm ... github.com/winstonjs/winston#formats ?
TechupBusiness
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.