@contrast/logger
使用量
集中,结构化的采伐 对比剂服务,建于皮诺.
@contrast/agentify 将日志写入核心, 因此组件使用
core.logger数字 :
core.logger.info({ foo, bar }, 'message with %s, %d', 'string', 123);
在代理机外,将其安装到自己的核心对象上:
const { default: install } = require('@contrast/logger');
const logger = install(core); // also sets core.logger
见 皮诺 记录日志的 API .
结构化日志
皮诺日志为JSON,因此特别擅长记录JavaScript对象.
鉴于:
logger.info('hello world');
logger.error('this is at error level');
logger.info('the answer is %d', 42);
logger.info({ obj: 42 }, 'hello world');
logger.info({ obj: 42, b: 2 }, 'hello world');
logger.info({ nested: { obj: 42 } }, 'nested');
日志输出外观如下:
{"level":30,"time":1649266923912,"pid":12345,"hostname":"foo","msg":"hello world"}
{"level":50,"time":1649266923913,"pid":12345,"hostname":"foo","msg":"this is at error level"}
{"level":30,"time":1649266923913,"pid":12345,"hostname":"foo","msg":"the answer is 42"}
{"level":30,"time":1649266923913,"pid":12345,"hostname":"foo","obj":42,"msg":"hello world"}
{"level":30,"time":1649266923913,"pid":12345,"hostname":"foo","obj":42,"b":2,"msg":"hello world"}
{"level":30,"time":1649266923913,"pid":12345,"hostname":"foo","nested":{"obj":42},"msg":"nested"}
你用得着 pino-pretty 改为格式
开发过程中的日志.
之前的台词,当传递到pino- pretty,将
格式改为:
node example.js | npx pino-pretty
[1649266998216] INFO (12345 on foo): hello world
[1649266998216] ERROR (12345 on foo): this is at error level
[1649266998216] INFO (12345 on foo): the answer is 42
[1649266998216] INFO (12345 on foo): hello world
obj: 42
[1649266998216] INFO (12345 on foo): hello world
obj: 42
b: 2
[1649266998216] INFO (12345 on foo): nested
nested: {
"obj": 42
}
过滤
JSON记录除了在漂亮印刷时更容易阅读外
我们用公用设施过滤 jq。 。 。 .
例如,我们只能过滤错误消息:
node example.js | jq "select(.level == 50)"
输出( 单击以扩展)
{
"level": 50,
"time": 1649268122322,
"pid": 12345,
"hostname": "foo",
"msg": "this is at error level"
}
或者,我们可以只查看登录条目 obj 属性 :
node example.js | jq "select(.obj)"
输出( 单击以扩展)
{
"level": 30,
"time": 1649268235040,
"pid": 12345,
"hostname": "foo",
"obj": 42,
"msg": "hello world"
}
{
"level": 30,
"time": 1649268235040,
"pid": 12345,
"hostname": "foo",
"obj": 42,
"b": 2,
"msg": "hello world"
}
见 jq是因为 教程 财务报告和审定财务报表
手动 以实例说明
强大的JSON处理可以是!
最佳做法
错误
皮诺在通过时会特别处理错误 err 或者说 当通过时
作为第一个论点.
见: https://github.com/pinojs/pino/blob/master/docs/api.md#serializers-object 页面存档备份,存于互联网档案馆
例如,在处理错误时,我们应该使用以下模式:
try {
// ...something that throws
} catch (err) {
logger.warn(err);
// if we want to customize the message:
logger.warn(err, 'something bad happened');
// or if we need to provide additional data:
logger.warn({ err, data }, 'something broke when handling %s', filename);
}
输出( 单击以扩展)
[1649264653814] WARN (12345 on foo): yikes!
err: {
"type": "Error",
"message": "yikes!",
"stack":
Error: yikes!
at Object.<anonymous> (/path/to/file.js:5:13)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
at internal/main/run_main_module.js:17:47
}
[1649264653814] WARN (12345 on foo): something bad happened
err: {
"type": "Error",
"message": "yikes!",
"stack":
Error: yikes!
at Object.<anonymous> (/path/to/file.js:5:13)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
at internal/main/run_main_module.js:17:47
}
[1649264653814] WARN (12345 on foo): something broke when handling foo.js
data: {
"foo": "bar"
}
err: {
"type": "Error",
"message": "yikes!",
"stack":
Error: yikes!
at Object.<anonymous> (/path/to/file.js:5:13)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:75:12)
at internal/main/run_main_module.js:17:47
}
对象
与其将信息纳入日志信息本身,不如 在第一个参数中包括数据.
例如,如果我们想要记录对象的内容:
const route = { method: 'GET', path: '/users/:id', handler: 'getUser' };
logger.info({ route }, 'route registered');
// instead of
logger.info('route registered: %o', route);
输出( 点击可扩展)
[1649265443612] INFO (12345 on foo): route registered
route: {
"method": "GET",
"path": "/users/:id",
"handler": "getUser"
}
[1649265443613] INFO (12345 on foo): route registered: {"method":"GET","path":"/users/:id","handler":"getUser"}
名称间隔
当在另一个模块中使用日志时, 您可以使用
页:1 child 方法.
例如,在 @contrast/rewriter 模块,我们可以命名日志
内容如下:
const logger = core.logger.child({ name: 'contrast:rewriter' });