Elasticsearch:Node.js ECS 日志记录 - Pino

在我的上一篇文章 "Beats:使用 Filebeat 从 Python 应用程序中提取日志" 里,我详述了如何使用 Python 来生成日志,并使用 Filebeat 来收集日志到 Elasticsearch 中。在今天的文章中,我来详细描述如何使用 Node.js 来生成 ECS 相兼容的日子。ECS 相兼容的日志符合易于 Elasticsearch 对日志进行分析并进行可视化。

介绍

Node.js ECS 记录器是你最喜欢的日志库的格式化插件。它们可轻松将你的日志格式化为与 ECS 兼容的 JSON。结合 filebeat,你可以将日志直接发送到 Elasticsearch,并利用 Kibana 的日志应用程序在一个地方检查所有日志。

Node.js ECS 日志格式化程序记录结构化的 JSON,并支持对来自 Node.js 核心和流行 Web 框架的错误对象和 HTTP 请求和响应对象进行序列化。最小日志记录包括以下字段:

复制代码
{
  "@timestamp": "2021-01-13T21:32:38.095Z",
  "log.level": "info",
  "message": "hi",
  "ecs.version": "8.10.0"
}

提示 :想要了解有关 ECS、ECS 日志记录和其他可用语言插件的更多信息?请参阅 ECS 日志记录指南

有关如何生成 ECS 相兼容的日子,我们有如下的几种方法。

在今天的文章里,我们先来介绍 Pino。

使用 Pino 进行 ECS 日志记录

此 Node.js 包为 pino 记录器提供了格式化程序,与 Elastic Common Schema (ECS) 日志记录兼容。结合 Filebeat 发送器,你可以在 Elastic Stack 中的一处监控所有日志。支持 pino 6.x、7.x 和 8.x 版本。

设置

安装

复制代码
npm install @elastic/ecs-pino-format
npm install pino

配置

复制代码
const { ecsFormat } = require('@elastic/ecs-pino-format');
const pino = require('pino');

const log = pino(ecsFormat(/* options */));  // 1
log.info('hi');
log.error({ err: new Error('boom') }, 'oops there is a problem');
// ...
  • 这将配置 Pino 的 formatters、messageKey 和 timestamp 选项。

配置 filebeat

1)Filebeat 7.16+。

filebeat.yml

复制代码
filebeat.inputs:
- type: filestream # 1
  paths: /path/to/logs.json
  parsers:
    - ndjson:
      overwrite_keys: true # 2  
      add_error_key: true  # 3
      expand_keys: true    # 4

processors: 
  - add_host_metadata: ~
  - add_cloud_metadata: ~
  - add_docker_metadata: ~
  - add_kubernetes_metadata: ~
  1. 使用 filestream 输入从活动日志文件中读取行。
  2. 如果发生冲突,解码的 JSON 对象的值将覆盖 Filebeat 通常添加的字段(type, source, offset 等)。
  3. 如果发生 JSON 解组错误,Filebeat 将添加 "error.message" 和 "error.type: json" 键。
  4. Filebeat 将递归地从解码的 JSON 中去掉点键,并将其扩展为分层对象结构。
  5. 处理器可增强你的数据。请参阅 processors 以了解更多信息。

2)Filebeat < 7.16

filebeat.yml

复制代码
filebeat.inputs:
- type: log
  paths: /path/to/logs.json
  json.keys_under_root: true
  json.overwrite_keys: true
  json.add_error_key: true
  json.expand_keys: true

processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
- add_docker_metadata: ~
- add_kubernetes_metadata: ~

有关更多信息,请参阅 Filebeat 参考

更多关于如何配置 Filebeat,请参考文章 "Beats:使用 Filebeat 从 Python 应用程序中提取日志"。

如何使用

我们创建如下的一个简单的应用:

pino-logging.js

复制代码
const { ecsFormat } = require('@elastic/ecs-pino-format');
const pino = require('pino');

const log = pino(ecsFormat(/* options */)); 
log.info('Hello world');

const child = log.child({ module: 'foo' });
child.warn('From child');

运行上面的代码:

复制代码
node pino-logging.js 

$ node pino-logging.js 
{"log.level":"info","@timestamp":"2024-07-08T01:32:42.947Z","process.pid":43946,"host.hostname":"liuxgm.local","ecs.version":"8.10.0","message":"Hello world"}
{"log.level":"warn","@timestamp":"2024-07-08T01:32:42.947Z","process.pid":43946,"host.hostname":"liuxgm.local","ecs.version":"8.10.0","module":"foo","message":"From child"}

在配置 ecsFormat 时,我们在下面将会看到更多的选项。

Error logging

默认情况下,格式化程序会将 Error 实例的 err 字段转换为 ECS Error 字段。例如:

pino-logging.js

复制代码
const { ecsFormat } = require('@elastic/ecs-pino-format');
const pino = require('pino');
const log = pino(ecsFormat());

const myErr = new Error('boom');
log.info({ err: myErr }, 'oops');

将产生(为了便于阅读,打印得很漂亮):

这类似于并覆盖了 Pino 的默认 err 序列化器。可以通过 convertErr: false 选项禁用对 err 字段的特殊处理:

复制代码
const log = pino(ecsFormat({ convertErr: false }));

HTTP 请求和响应日志记录

使用 convertReqRes: true 选项,格式化程序将在分别作为 req 和 res 字段传递时自动转换 Node.js 核心 requestresponse 对象。(此选项取代了 req 和 res Pino 序列化器的使用。)

pino-logging.js

复制代码
const http = require('http');
const { ecsFormat } = require('@elastic/ecs-pino-format');
const pino = require('pino');

const log = pino(ecsFormat({ convertReqRes: true }));  // 1

const server = http.createServer(function handler (req, res) {
  res.setHeader('Foo', 'Bar');
  res.end('ok');
  log.info({ req, res }, 'handled request');  // 2
});

server.listen(3000, () => {
  log.info('listening at http://localhost:3000');
})
  1. 使用 convertReqRes 选项
  2. 使用 req 和/或 res 字段进行记录

这将使用 ECS HTTP 字段生成包含请求和响应信息的日志。例如:

为了生成上面的日子,我们需要访问本地的服务器 http://localhost:3000/.

examples/ 目录展示了使用请求和响应日志的示例程序:使用 Express、使用 pino-http 中间件包等。

使用 APM 进行日志关联

此 ECS 日志格式化程序与 Elastic APM 集成。如果你的 Node 应用正在使用 Node.js Elastic APM Agent,则会将多个字段添加到日志记录中,以关联 APM 服务或跟踪和日志数据:

例如,运行 examples/http-with-elastic-apm.js 和 curl -i localhost:3000/ 会产生包含以下内容的日志记录:

复制代码
% node examples/http-with-elastic-apm.js | jq .
...
  "service.name": "http-with-elastic-apm",
  "service.version": "1.4.0",
  "service.environment": "development",
  "event.dataset": "http-with-elastic-apm",
  "trace.id": "9f338eae7211b7993b98929046aed21d",
  "transaction.id": "2afbef5642cc7a3f",
...

这些 ID 与 APM 代理报告的跟踪数据相匹配。

可以通过 apmIntegration: false 选项明确禁用与 Elastic APM 的集成,例如:

复制代码
const log = pino(ecsFormat({ apmIntegration: false }));

限制和注意事项

ecs-logging 规范建议日志记录中的前三个字段必须是 @timestamp、log.level 和 message。Pino 不提供将 message 字段放在前面的机制。鉴于 ecs-logging 字段的排序是为了便于阅读,并且不会影响互操作性,因此这并不是一个重大问题。

Pino 当前提供的钩子(hook)不允许此包转换传递给 <logger>.child({ ... }) 的字段。这意味着,即使使用 convertReqRes 选项,对 <logger>.child({ req }) 的调用也不会将该 req 转换为 ECS HTTP 字段。对于执行此操作的 pino-http 用户来说,这是一个轻微的限制。

参考

ecsFormat([options])

  • options {type-object} 支持以下选项:
    • convertErr {type-boolean} 是否将记录的 err 字段转换为 ECS 错误字段。默认值:true。
    • convertReqRes {type-boolean} 是否将记录的 req 和 res HTTP 请求和响应字段记录到 ECS HTTP、用户代理和 URL 字段。默认值:false。
    • apmIntegration {type-boolean} 是否启用 APM 代理集成。默认值:true。
    • serviceName {type-string} "service.name" 值。如果指定,则覆盖来自活动 APM 代理的任何值。
    • serviceVersion {type-string} "service.version" 值。如果指定,则覆盖来自活动 APM 代理的任何值。
    • serviceEnvironment {type-string} "service.environment" 值。如果指定,则覆盖来自活动 APM 代理的任何值。
    • serviceNodeName {type-string} "service.node.name" 值。如果指定,则将覆盖来自活动 APM 代理的任何值。
    • eventDataset {type-string} "event.dataset"值。如果指定,则将覆盖使用 ${serviceVersion} 的默认设置。

为 pino(...) 创建选项,用于配置 ECS 日志记录格式输出。

相关推荐
20242817李臻3 分钟前
李臻20242817_安全文件传输系统项目报告_第9周
数据库·安全
小白考证进阶中6 分钟前
0基础可以考MySQL OCP么?备考时间需要多久?
数据库·mysql·开闭原则
观无11 分钟前
Redis远程链接应用案例
数据库·redis·缓存·c#
星星点点洲19 分钟前
【缓存与数据库结合方案】伪从技术 vs 直接同步/MQ方案的深度对比
数据库·缓存
努力奋斗的小杨22 分钟前
学习MySQL的第十二天
数据库·笔记·学习·mysql·navicat
涛涛讲AI28 分钟前
当AI浏览器和AI搜索替代掉传统搜索份额时,老牌的搜索引擎市场何去何从。
人工智能·搜索引擎
枫叶20001 小时前
OceanBase数据库-学习笔记1-概论
数据库·笔记·学习·oceanbase
仲夏plus1 小时前
MySQL:慢SQL索引优化-使用explain/analyze进行耗时分析的方法
数据库
Elasticsearch1 小时前
Elastic Platform 8.18 和 9.0:ES|QL Lookup Joins 功能现已推出,Lucene 10!
elasticsearch
tcoding1 小时前
《MySQL 技术内幕-innoDB 存储引擎》笔记
数据库·笔记·mysql