温斯顿记录对象
Winston logging object
我使用 Winston 进行后端日志记录 我无法在不使用 JSON.stringify
的情况下记录对象,这很烦人
logger.debug(`Register ${JSON.stringify(req.body)}`)
const logger: Logger = createLogger({
// change level if in dev environment versus production
level: env === 'production' ? 'info' : 'debug',
format: format.combine(
format.label({label: path.basename(process.mainModule.filename)}),
format.timestamp({format: 'YYYY-MM-DD HH:mm:ss'}),
format.prettyPrint()
),
transports: [
new transports.Console({
format: format.combine(format.colorize(), logFormat),
}),
new transports.File({
filename,
format: format.combine(format.json()),
}),
],
exitOnError: false,
})
你能告诉我用温斯顿记录对象的方法吗?我使用的是版本 3.2.1
您试图将 JSON 对象直接插入到字符串中,因此它将打印 [Object Object]
而没有 JSON.stringify
.
这无法通过配置 Winston 来解决,因为这个问题是在生成字符串时发生的(在 logger.debug
函数实际读取它之前),所以 console.log
调用会打印相同的内容。
logger.*
函数的第一个参数是消息(字符串),然后你可以传递一个元数据对象(JSON)。
要在您的 logFormat
函数中使用元数据,请按如下方式更新您的 Logger 实例化:
const winston = require('winston')
const { format, transports } = winston
const path = require('path')
const logFormat = format.printf(info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`)
const logger = winston.createLogger({
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
format: format.combine(
format.label({ label: path.basename(process.mainModule.filename) }),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
// Format the metadata object
format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] })
),
transports: [
new transports.Console({
format: format.combine(
format.colorize(),
logFormat
)
}),
new transports.File({
filename: 'logs/combined.log',
format: format.combine(
// Render in one line in your log file.
// If you use prettyPrint() here it will be really
// difficult to exploit your logs files afterwards.
format.json()
)
})
],
exitOnError: false
})
用法:
const req = {
body: {
name: 'Daniel Duuch',
email: 'daniel.duuch@greatmail.com',
password: 'myGreatPassword'
}
}
logger.debug(`Register ${req.body.name} with email ${req.body.email}`, { ...req.body, action: 'register' })
控制台输出:
2019-05-11 17:05:45 debug [index.js]: Register Daniel Duuch with email daniel.duuch@greatmail.com
日志文件输出(手工美化,见传输文件格式注释):
{
message: 'Register Daniel Duuch with email daniel.duuch@greatmail.com',
level: 'debug',
timestamp: '2019-05-11 17:05:45',
label: 'index.js',
metadata: {
name: 'Daniel Duuch',
email: 'daniel.duuch@greatmail.com',
password: 'myGreatPassword',
action: 'register'
}
}
希望这能解决您的问题。
您可以在记录器配置中使用 format.splat()
:
const logger = createLogger({
format: combine(
...
format.splat(), // <--
...
),
...
});
...并使用字符串插值记录对象:
let myObj = { /* ... */ };
logger.info('This message will include a complete object: %O', myObj);
我不得不结合@SherloxFR 和@Anton 提供的解决方案。
const Winston = require('winston');
const { format } = Winston;
const options = {
file: {
....
format: format.combine(
format.splat(),
format.json()
),
...
},
console: {
...
format: format.combine(
format.splat(),
format.json()
),
...
}
};
你可以看到我在上面的代码中添加了 format.splat()
和 format.json()
到选项配置中。
const logger = new Winston.createLogger({
transports: [
new Winston.transports.File(options.file),
new Winston.transports.Console(options.console)
],
exitOnError: false // do not exit on handled exceptions
});
这就是我使用选项配置对象的方式。您实际上可以在传输数组中编写格式代码,但我不喜欢那样。无论如何这是你的选择。
这样的配置后,我在代码中的使用方式是这样的
let myObj = {
name: "Whosebug",
};
logger.info('Content: %o', myObj);
喜欢也可以这样传播
logger.info('Content: %o', {...myObj});
就是这样。 Winston 应该使用此设置记录您的对象。
或者您只需使用
printf
函数结合JSON.stringify
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
winston.format.printf(context => {
const msgstr = JSON.stringify(context.message, null, '\t')
return `[${context.level}]${msgstr}`
}),
),
})
我的解决方案是使用这种格式化程序:
const { format } = winston
const consoleFormat = format.combine(
format.prettyPrint(),
format.splat(),
format.printf((info) => {
if (typeof info.message === 'object') {
info.message = JSON.stringify(info.message, null, 3)
}
return info.message
})
)
现在所有这些选项都按预期工作了:
logger.info('plain text')
logger.info('plain text with object %o', { a:1, b: 2} )
logger.info({ a:1, b: 2 })
如果您希望将对象记录到控制台和文件中,您可以执行以下操作:
1.Initialize 2 种格式。一个用于文件,另一个用于控制台。注意 JSON.stringify
中使用的方法 consoleFormat
const winston = require("winston");
const { format, transports, createLogger } = winston;
const path = require("path");
const consoleloggerLevel = process.env.WINSTON_LOGGER_LEVEL || "info";
const consoleFormat = format.combine(
format.colorize(),
format.timestamp(),
format.align(),
format.printf((info) => {
return `${info.timestamp} - ${info.level}: [${info.label}]: ${
info.message
} ${JSON.stringify(info.metadata)}`;
})
);
const fileFormat = format.combine(
format.timestamp(),
format.label({ label: path.basename(process.mainModule.filename) }),
format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }),
format.json()
);
2.Now,创建记录器。
const logger = createLogger({
level: "info",
defaultMeta: { service: "some-random-service" },
format: fileFormat,
transports: [
new transports.File({
filename: path.join(__dirname, "../logs/error.log"),
level: "error",
}),
new transports.File({
filename: path.join(__dirname, "../logs/activity.log"),
maxsize: 5242880, //5MB
maxFiles: 5 // just in case
}),
],
});
3.Enable 仅在非产品环境中进行控制台日志记录:
if (process.env.NODE_ENV !== "production") {
logger.add(
new transports.Console({
level: consoleloggerLevel,
format: consoleFormat,
})
);
}
4.Export 它作为默认记录器
module.exports = logger;
在 logger.info("Server started listening", { port: 9000 } );
这将打印,
在控制台上:
2021-06-22T07:47:25.988Z - info: [index.js]: Server started listening {"service":"some-random-service", "port": 9000}
文件中:
{"message":"Server started listening","level":"info","timestamp":"2021-06-22T07:47:25.988Z","label":"index.js","metadata":{"service":"some-random-service", "port": 9000}}
我使用 Winston 进行后端日志记录 我无法在不使用 JSON.stringify
的情况下记录对象,这很烦人
logger.debug(`Register ${JSON.stringify(req.body)}`)
const logger: Logger = createLogger({
// change level if in dev environment versus production
level: env === 'production' ? 'info' : 'debug',
format: format.combine(
format.label({label: path.basename(process.mainModule.filename)}),
format.timestamp({format: 'YYYY-MM-DD HH:mm:ss'}),
format.prettyPrint()
),
transports: [
new transports.Console({
format: format.combine(format.colorize(), logFormat),
}),
new transports.File({
filename,
format: format.combine(format.json()),
}),
],
exitOnError: false,
})
你能告诉我用温斯顿记录对象的方法吗?我使用的是版本 3.2.1
您试图将 JSON 对象直接插入到字符串中,因此它将打印 [Object Object]
而没有 JSON.stringify
.
这无法通过配置 Winston 来解决,因为这个问题是在生成字符串时发生的(在 logger.debug
函数实际读取它之前),所以 console.log
调用会打印相同的内容。
logger.*
函数的第一个参数是消息(字符串),然后你可以传递一个元数据对象(JSON)。
要在您的 logFormat
函数中使用元数据,请按如下方式更新您的 Logger 实例化:
const winston = require('winston')
const { format, transports } = winston
const path = require('path')
const logFormat = format.printf(info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`)
const logger = winston.createLogger({
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
format: format.combine(
format.label({ label: path.basename(process.mainModule.filename) }),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
// Format the metadata object
format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] })
),
transports: [
new transports.Console({
format: format.combine(
format.colorize(),
logFormat
)
}),
new transports.File({
filename: 'logs/combined.log',
format: format.combine(
// Render in one line in your log file.
// If you use prettyPrint() here it will be really
// difficult to exploit your logs files afterwards.
format.json()
)
})
],
exitOnError: false
})
用法:
const req = {
body: {
name: 'Daniel Duuch',
email: 'daniel.duuch@greatmail.com',
password: 'myGreatPassword'
}
}
logger.debug(`Register ${req.body.name} with email ${req.body.email}`, { ...req.body, action: 'register' })
控制台输出:
2019-05-11 17:05:45 debug [index.js]: Register Daniel Duuch with email daniel.duuch@greatmail.com
日志文件输出(手工美化,见传输文件格式注释):
{
message: 'Register Daniel Duuch with email daniel.duuch@greatmail.com',
level: 'debug',
timestamp: '2019-05-11 17:05:45',
label: 'index.js',
metadata: {
name: 'Daniel Duuch',
email: 'daniel.duuch@greatmail.com',
password: 'myGreatPassword',
action: 'register'
}
}
希望这能解决您的问题。
您可以在记录器配置中使用 format.splat()
:
const logger = createLogger({
format: combine(
...
format.splat(), // <--
...
),
...
});
...并使用字符串插值记录对象:
let myObj = { /* ... */ };
logger.info('This message will include a complete object: %O', myObj);
我不得不结合@SherloxFR 和@Anton 提供的解决方案。
const Winston = require('winston');
const { format } = Winston;
const options = {
file: {
....
format: format.combine(
format.splat(),
format.json()
),
...
},
console: {
...
format: format.combine(
format.splat(),
format.json()
),
...
}
};
你可以看到我在上面的代码中添加了 format.splat()
和 format.json()
到选项配置中。
const logger = new Winston.createLogger({
transports: [
new Winston.transports.File(options.file),
new Winston.transports.Console(options.console)
],
exitOnError: false // do not exit on handled exceptions
});
这就是我使用选项配置对象的方式。您实际上可以在传输数组中编写格式代码,但我不喜欢那样。无论如何这是你的选择。
这样的配置后,我在代码中的使用方式是这样的
let myObj = {
name: "Whosebug",
};
logger.info('Content: %o', myObj);
喜欢也可以这样传播
logger.info('Content: %o', {...myObj});
就是这样。 Winston 应该使用此设置记录您的对象。
或者您只需使用
printf
函数结合JSON.stringify
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple(),
winston.format.printf(context => {
const msgstr = JSON.stringify(context.message, null, '\t')
return `[${context.level}]${msgstr}`
}),
),
})
我的解决方案是使用这种格式化程序:
const { format } = winston
const consoleFormat = format.combine(
format.prettyPrint(),
format.splat(),
format.printf((info) => {
if (typeof info.message === 'object') {
info.message = JSON.stringify(info.message, null, 3)
}
return info.message
})
)
现在所有这些选项都按预期工作了:
logger.info('plain text')
logger.info('plain text with object %o', { a:1, b: 2} )
logger.info({ a:1, b: 2 })
如果您希望将对象记录到控制台和文件中,您可以执行以下操作:
1.Initialize 2 种格式。一个用于文件,另一个用于控制台。注意 JSON.stringify
中使用的方法 consoleFormat
const winston = require("winston");
const { format, transports, createLogger } = winston;
const path = require("path");
const consoleloggerLevel = process.env.WINSTON_LOGGER_LEVEL || "info";
const consoleFormat = format.combine(
format.colorize(),
format.timestamp(),
format.align(),
format.printf((info) => {
return `${info.timestamp} - ${info.level}: [${info.label}]: ${
info.message
} ${JSON.stringify(info.metadata)}`;
})
);
const fileFormat = format.combine(
format.timestamp(),
format.label({ label: path.basename(process.mainModule.filename) }),
format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }),
format.json()
);
2.Now,创建记录器。
const logger = createLogger({
level: "info",
defaultMeta: { service: "some-random-service" },
format: fileFormat,
transports: [
new transports.File({
filename: path.join(__dirname, "../logs/error.log"),
level: "error",
}),
new transports.File({
filename: path.join(__dirname, "../logs/activity.log"),
maxsize: 5242880, //5MB
maxFiles: 5 // just in case
}),
],
});
3.Enable 仅在非产品环境中进行控制台日志记录:
if (process.env.NODE_ENV !== "production") {
logger.add(
new transports.Console({
level: consoleloggerLevel,
format: consoleFormat,
})
);
}
4.Export 它作为默认记录器
module.exports = logger;
在 logger.info("Server started listening", { port: 9000 } );
这将打印,
在控制台上:
2021-06-22T07:47:25.988Z - info: [index.js]: Server started listening {"service":"some-random-service", "port": 9000}
文件中:
{"message":"Server started listening","level":"info","timestamp":"2021-06-22T07:47:25.988Z","label":"index.js","metadata":{"service":"some-random-service", "port": 9000}}