Winston: Winston log ke semua file. (atau: Batasi transportasi hanya 1 level)

Dibuat pada 27 Apr 2015  ·  23Komentar  ·  Sumber: winstonjs/winston

Ini adalah konfigurasi winston saya:

var winston = require('winston');
var fs = require('fs');
var _ = require('lodash');

winston.emitErrs = true;

var logDir = 'logs';
if (!fs.existsSync(logDir)) {
    fs.mkdirSync(logDir);
}

//add custom logging levels
var levels = _.clone(winston.config.syslog.levels);
var colors = _.clone(winston.config.syslog.colors);

levels.request = _.max(levels) + 1;
colors.request = 'blue';

var logger = new winston.Logger({
    levels: levels,
    colors: colors,
    exceptionHandlers: [
        new winston.transports.File({filename: 'logs/exceptions.log'})
    ],
    transports: [
        new winston.transports.File({
            name: 'info-file',
            level: 'info',
            filename: 'logs/all-logs.log',
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.File({
            name: 'error-file',
            level: 'error',
            filename: 'logs/error-logs.log',
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.File({
            name: 'request-file',
            level: 'request',
            filename: 'logs/requests.log',
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        })
    ],
    exitOnError: false
});

module.exports = logger;

Saya mencoba masuk, kesalahan, permintaan http, dan pengecualian ke file mereka sendiri.
Namun, saya melihat, misalnya, di log permintaan error-logs.log (http).

Adakah yang bisa menjelaskan kepada saya apa yang saya lakukan salah?

feature request investigate

Komentar yang paling membantu

Saya menggunakan winston 3.x, setelah percobaan dan kesalahan saya menemukan bahwa kami dapat memfilter log berdasarkan level untuk mencatatnya ke file terpisah. Berikut adalah kode yang saya gunakan:

const customFormat = winston.format.printf(i => {
    return `${i.level.toUpperCase()}: ${i.timestamp} ${i.message}`;
});

// Log unhandled exceptions to separate file
var exceptionHandlers = [
    new (winston.transports.DailyRotateFile)({
        name: 'Error Logs',
        filename: 'server/logs/errlogs/exceptions-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d'
    })
]

const infoAndWarnFilter = winston.format((info, opts) => { 
    return info.level === 'info' || info.level === 'warn' ? info : false
})

const errorFilter = winston.format((info, opts) => { 
    return info.level === 'error' ? info : false 
})

// Separate warn/error 
var transports = [
    new (winston.transports.DailyRotateFile)({
        name: 'Error Logs',
        filename: 'server/logs/errlogs/application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d',
        level: 'warn',
        json: true,
        colorize: false,
        format: winston.format.combine(
            errorFilter(),
            winston.format.timestamp(),
            customFormat
        )
    }),
    new (winston.transports.DailyRotateFile)({
        name: 'INFO logs',
        filename: 'server/logs/infologs/application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d',
        json: true,
        colorize: false,
        level: 'info',
        format: winston.format.combine(
            infoAndWarnFilter(),
            winston.format.timestamp(),
            customFormat
        )
    }),
    new (winston.transports.Console)({      
        level: config.debugMode ? 'debug' : 'warn', // log warn level to console only
        handleExceptions: true,
        json: false,
        colorize: true,
        format: winston.format.combine(
            winston.format.colorize(),
            winston.format.simple()
        )
    })
]

var logger = winston.createLogger({
    transports: transports,
    exceptionHandlers: exceptionHandlers,
    level: config.debugMode ? 'debug' : 'info',
    exitOnError: false,
    // Default format
    format: winston.format.combine(
        winston.format.timestamp(),
        customFormat
    )
})

Semua 23 komentar

Beginilah cara saya mencatat permintaan

// Log all requests
app.use(function(req, res, next) {
    var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
    logger.log('request', req.method, req.url, ip);
    next();
});

Tetapi lihat output di ketiga file:
nama file: 'logs/all-logs.log',
nama file: 'logs/error-logs.log',
nama file: 'logs/requests.log'

Yang saya inginkan adalah level kustom "permintaan" hanya akan menampilkan file khusus sendiri.

@t0lkman Saya percaya bahwa Anda perlu memanggil setLevel explicilty pada instance Logger , tetapi ini mungkin merupakan bug dalam menyetel level kustom. Kami akan menyelidiki.

Idealnya, yang ingin saya capai adalah, memiliki file log yang berbeda untuk hal yang berbeda.. misalnya semua permintaan http pergi ke satu tempat, semua kesalahan mongo ke tempat lain, dll...

Saat ini ada beberapa sistem logging hierarki ... di mana tergantung pada urutan hal-hal yang dicatat ..

Saya sebenarnya mengalami masalah yang sangat mirip, menggunakan level bawaan.

Konfigurasi Winston saya:

logger = new winston.Logger({
        emitErrs: true,
        transports: [
            new winston.transports.Console({
                level:'debug',
                name: 'console',
                handleExceptions: true,
                prettyPrint: true,
                silent:false,
                timestamp: true,
                colorize: true,
                json: false
            }),
            new winston.transports.DailyRotateFile({
                level:'info',
                name: 'info',
                filename: accessLogsPath,
                handleExceptions: true,
                prettyPrint: true,
                silent:false,
                timestamp: true,
                json: true,
                colorize: true,
                maxsize: 20000,
                tailable: true
            }),
            new winston.transports.DailyRotateFile({
                level:'error',
                name: 'error',
                filename: errorLogsPath,
                handleExceptions: true,
                prettyPrint: true,
                silent: false,
                timestamp: true,
                json: true,
                colorize: false,
                maxsize: 20000,
                tailable: true
            })
        ],
        exitOnError: false 
    });

Kemudian ketika saya menjalankan moduleName.logger.error(err); itu menghasilkan ketiganya (saya berharap itu dari debug, tetapi bukan info). Saya mengubah level:'error', menjadi level:'debug', dan hanya mencatat kesalahan untuk debug hanya sebagai solusi.

@NukaPunk Bukankah ini perilaku yang diharapkan dari seorang logger?

Biasanya instance logger akan masuk ke semua transport yang cocok dengan level minimum pesan. Contoh: debug -> info -> peringatan -> kesalahan. Transport yang menangani info tidak akan mencatat pesan debug tetapi akan mencatat info, peringatan, dan kesalahan.

Ini biasanya diselesaikan dengan membuat beberapa instance logger, masing-masing menangani kasus tertentu.

Terima kasih atas jawabannya @masom.

Saya kira itu kontra intuitif untuk membuat kesalahan Anda masuk ke log info Anda kepada saya, tetapi sekarang setelah saya lebih memahami cara kerja level, saya akan menerima saran Anda dan membuat contoh yang berbeda.

Terima kasih lagi.

@NukaPunk ya itu benar-benar kontra-intuitif pada awalnya. Hal yang sama terjadi dengan pencatat bahasa lain dan beberapa di antaranya memungkinkan Anda menentukan tingkat log eksklusif untuk transportasi tertentu.

@masom jadi bukan bug, tapi fitur ;-)

File readme tidak benar-benar menjelaskan konsep logging level yang lebih rendah, jadi saya menganggap level itu eksklusif. Saya akan merekomendasikan menambahkan beberapa informasi tentang itu ke readme untuk menghindari kebingungan, jika memungkinkan.

Terima kasih sekali lagi, kerja bagus di transportasi logging!

Apakah ada contoh, bagaimana saya melakukan beberapa instance logger? Yang saya butuhkan hanyalah memiliki file log yang benar-benar terpisah.
Saya tidak ingin kesalahan muncul di info dll

@t0lkman Dugaan saya akan seperti ini:

module.exports = {
    errorLog: new winston.Logger({
        levels: levels,
        colors: colors,
        exceptionHandlers: [
            new winston.transports.File({filename: 'logs/exceptions.log'})
        ],
        transports: [

            new winston.transports.File({
                name: 'error-file',
                level: 'error',
                filename: 'logs/error-logs.log',
                json: true,
                maxsize: 5242880, //5MB
                maxFiles: 5,
                colorize: false
            })
        ],
        exitOnError: false
    }),
    requestLog: new winston.Logger({
            levels: levels,
            colors: colors,
            exceptionHandlers: [
                new winston.transports.File({filename: 'logs/exceptions.log'})
            ],
            transports: [
                new winston.transports.File({
                    name: 'request-file',
                    level: 'request',
                    filename: 'logs/requests.log',
                    json: true,
                    maxsize: 5242880, //5MB
                    maxFiles: 5,
                    colorize: false
                })
            ],
            exitOnError: false
        }
    ),

    infoLog: new winston.Logger({
        levels: levels,
        colors: colors,
        exceptionHandlers: [
            new winston.transports.File({filename: 'logs/exceptions.log'})
        ],
        transports: [
            new winston.transports.File({
                name: 'info-file',
                level: 'info',
                filename: 'logs/all-logs.log',
                json: true,
                maxsize: 5242880, //5MB
                maxFiles: 5,
                colorize: false
            })
        ],
        exitOnError: false
    })
};

Dan kemudian Anda bisa menggunakannya seperti ini:

var logger = require(/path/to/file);

logger.errorLog('This is an error!');
logger.infoLog('This is info!');
logger.request('request', req.method, req.url, ip);

Atau Anda dapat menggunakan Morgan untuk permintaan logging dengan cukup mudah:

infoLogger.stream = {
    write: function(message, encoding){
        logger.info(message);
    }
};
app.use(require("morgan")("combined", { "stream":  infoLogger.stream }));

Saya harap itu membantu!

Mencoba, tidak berhasil :(

new winston.Logger( mengembalikan objek, tetapi mengharapkan fungsi

@t0lkman Anda benar. Saya mencobanya dan tidak berhasil (itulah yang saya dapatkan dengan menulisnya di browser saya). Coba ini sebagai gantinya:

var errorLog = require('./models/winston').errorLog;
errorLog.error('test');

ada update untuk yang satu ini?

@davidfeldi Mungkin ini bisa membantu, saya pernah mengalami masalah ini sebelumnya dan berhasil membuat pembungkus saya sendiri. Ini memisahkan log kesalahan untuk setiap level. https://github.com/odegraciajr/winston-logger

Masalah ini sekarang telah ada selama dua tahun. Saya sendiri berpikir itu agak disayangkan bahwa saya tidak dapat membuat file log error-only bersama dengan info-log dengan satu contoh.
Tetapi jika ini adalah perilaku yang diinginkan/diharapkan, Anda harus menutup masalah ini di masa lalu tidak akan memperbaiki masalah dan memberi tahu orang-orang di readme, cara memisahkan file log, dengan menggunakan dua contoh, satu untuk log kesalahan dan satu untuk infonya.

Hai teman-teman, inilah solusi saya untuk masalah tersebut (juga di Gist :

const winston = require('winston');
const path = require('path');

const getLogger = (module, type) => {
    const modulePath = module.filename.split('/').slice(-2).join('/');
    const logger = new winston.Logger({
        transports: [
            new (winston.transports.Console)({
                colorize: true,
                level: (process.env.NODE_ENV === 'development') ? 'debug' : 'error',
                label: modulePath
            })
        ]
    });

    switch (type) {
        case 'error':
            logger.add(winston.transports.File, {
                name: 'error-file',
                filename: path.join(__dirname, '../../logs/error_default.log'),
                level: 'error'
            });
            return logger;
        case 'info':
            logger.add(winston.transports.File, {
                name: 'info-file',
                filename: path.join(__dirname, '../../logs/info_default.log'),
                level: 'info'
            });
            return logger;
        default:
            return logger;
    }
};

module.exports = module => ({
    error(err) {
        getLogger(module, 'error').error(err);
    },
    info(err) {
        getLogger(module, 'info').info(err);
    },
    debug(err) {
        getLogger(module, 'default').debug(err);
    }
});

Penggunaan:

const logger = require('path/to/logger')(module);
logger.info('Logging with winston');

Berhasil! hanya jika level log minimum harus sama di semua transportasi yang ditentukan,
misalnya
baru(winston.Logger)({
transportasi: [
baru(winston.transports.Console)({ level : ' error ' }),
baru(winston.transports.File)({
nama: 'file kesalahan',
tingkat : ' kesalahan ',
nama file: 'nama file.log',
json: benar,
ukuran maksimal: 5242880, //5MB
file maks: 5,
mewarnai: palsu
})
],
exitOnError: salah
});

Secara pribadi, saya pikir setiap transportasi harus masuk sesuai dengan level yang ditentukan

Pembaruan apa pun tentang ini, rc3 terbaru tidak berfungsi

Anda dapat mencapai ini dengan format khusus yang memeriksa level yang diinginkan:

    `new transports.File({
            filename: logFileInfo,
            level: 'info',
            json: false,
            format: combine(
                timestamp(),
                printf(i => i.level === 'info' ? `${i.level.toUpperCase()}: ${i.timestamp} ${i.message}` : '')
            )
        })`

+1

@ madal3x Itu masih akan mencatat baris kosong ke file setiap kali levelnya tidak cocok. Saya sudah mencoba mengembalikan nol atau bahkan tidak mengembalikan apa pun dan masih mencatat nol/tidak terdefinisi. Kecuali ada sesuatu yang berubah dalam rilis 3.x yang saya tidak sadari.

Sayang sekali sepertinya tidak ada cara untuk membatalkan baris tertentu agar tidak dicatat atau contoh format khusus Anda mungkin merupakan solusi yang layak. Sepertinya itu akan menjadi perbaikan sederhana untuk tidak mencatat nilai yang tidak ditentukan sama sekali, jadi mengembalikan tidak terdefinisi dari fungsi format/formatter tidak akan mencatat baris kosong. Perhatikan bahwa ini tidak akan memengaruhi kemampuan untuk mencatat variabel yang tidak ditentukan selama total pesan yang dicatat lebih dari sekadar nilai undefined tunggal.

Solusi yang lebih kuat mungkin dengan menambahkan beberapa jenis fungsi intersep ke transport yang memungkinkan pengembalian true untuk mencatat pesan atau false untuk mengabaikannya.

Saya menggunakan winston 3.x, setelah percobaan dan kesalahan saya menemukan bahwa kami dapat memfilter log berdasarkan level untuk mencatatnya ke file terpisah. Berikut adalah kode yang saya gunakan:

const customFormat = winston.format.printf(i => {
    return `${i.level.toUpperCase()}: ${i.timestamp} ${i.message}`;
});

// Log unhandled exceptions to separate file
var exceptionHandlers = [
    new (winston.transports.DailyRotateFile)({
        name: 'Error Logs',
        filename: 'server/logs/errlogs/exceptions-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d'
    })
]

const infoAndWarnFilter = winston.format((info, opts) => { 
    return info.level === 'info' || info.level === 'warn' ? info : false
})

const errorFilter = winston.format((info, opts) => { 
    return info.level === 'error' ? info : false 
})

// Separate warn/error 
var transports = [
    new (winston.transports.DailyRotateFile)({
        name: 'Error Logs',
        filename: 'server/logs/errlogs/application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d',
        level: 'warn',
        json: true,
        colorize: false,
        format: winston.format.combine(
            errorFilter(),
            winston.format.timestamp(),
            customFormat
        )
    }),
    new (winston.transports.DailyRotateFile)({
        name: 'INFO logs',
        filename: 'server/logs/infologs/application-%DATE%.log',
        datePattern: 'YYYY-MM-DD',
        zippedArchive: true,
        maxSize: '128m',
        maxFiles: '14d',
        json: true,
        colorize: false,
        level: 'info',
        format: winston.format.combine(
            infoAndWarnFilter(),
            winston.format.timestamp(),
            customFormat
        )
    }),
    new (winston.transports.Console)({      
        level: config.debugMode ? 'debug' : 'warn', // log warn level to console only
        handleExceptions: true,
        json: false,
        colorize: true,
        format: winston.format.combine(
            winston.format.colorize(),
            winston.format.simple()
        )
    })
]

var logger = winston.createLogger({
    transports: transports,
    exceptionHandlers: exceptionHandlers,
    level: config.debugMode ? 'debug' : 'info',
    exitOnError: false,
    // Default format
    format: winston.format.combine(
        winston.format.timestamp(),
        customFormat
    )
})

@ngthienlinh Anda benar, itu berhasil, dan ini bahkan dirinci di bagian Filtering info Objects dari dokumentasi untuk versi 3.x. Tidak yakin bagaimana saya melewatkan itu sebelumnya. Ini bekerja cukup baik dan pada dasarnya mengubah fitur format menjadi arsitektur middleware yang kuat.

Saya pikir masalah ini dapat ditutup sekarang karena telah ditunjukkan dengan jelas bahwa tidak ada lagi pekerjaan yang dilakukan pada basis kode winston 2.x.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat