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 日志记录格式输出。

相关推荐
阿水实证通17 分钟前
能源经济大赛选题推荐:新能源汽车试点城市政策对能源消耗的负面影响——基于技术替代效应的视角
大数据·人工智能·汽车
TomCode先生1 小时前
SaaS版MES系统PC端后台功能清单与设计说明
大数据
小蒜学长2 小时前
jsp基于JavaWeb的原色蛋糕商城的设计与实现(代码+数据库+LW)
java·开发语言·数据库·spring boot·后端
jason成都2 小时前
postgresql分区表代码创建方案
大数据
RunningShare11 小时前
千万级用户电商平台,Flink实时推荐系统如何实现毫秒级延迟?
大数据·flink·推荐系统·ab测试
摩羯座-1856903059411 小时前
爬坑 10 年!京东店铺全量商品接口实战开发:从分页优化、SKU 关联到数据完整性闭环
linux·网络·数据库·windows·爬虫·python
INFINI Labs11 小时前
如何使用 INFINI Gateway 对比 ES 索引数据
大数据·elasticsearch·gateway·easysearch
编程充电站pro12 小时前
SQL 面试高频:INNER JOIN vs LEFT JOIN 怎么考?
数据库·sql
这周也會开心12 小时前
SQL-窗口函数做题总结
数据库·sql
间彧12 小时前
TiDB详解与Spring Boot实战指南
数据库