使用 Morgan 进行 ECS 日志记录编辑

这个 Node.js 包为 morgan 日志记录中间件(通常与 Express 配合使用)提供了一种格式化程序,它与 Elastic Common Schema (ECS) 日志记录 兼容。与 Filebeat 发货程序结合使用,您可以在 Elastic Stack 中的一个位置 监控所有日志

设置编辑

步骤 1:安装编辑

$ npm install @elastic/ecs-morgan-format

步骤 2:配置编辑

const app = require('express')();
const morgan = require('morgan');
const { ecsFormat } = require('@elastic/ecs-morgan-format');

app.use(morgan(ecsFormat(/* options */))); 

// ...
app.get('/', function (req, res) {
  res.send('hello, world!');
})
app.listen(3000);

将 ECS 格式化程序传递给 morgan()

步骤 3:配置 Filebeat编辑

将 ECS 格式化的日志收集起来的最佳方式是使用 Filebeat

  1. 按照 Filebeat 快速入门 操作
  2. 将以下配置添加到您的 filebeat.yaml 文件中。

对于 Filebeat 7.16+

filebeat.yaml。

filebeat.inputs:
- type: filestream 
  paths: /path/to/logs.json
  parsers:
    - ndjson:
      overwrite_keys: true 
      add_error_key: true 
      expand_keys: true 

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

使用 filestream 输入从活动日志文件中读取行。

解码后的 JSON 对象中的值会覆盖 Filebeat 通常添加的字段(type、source、offset 等),以解决冲突。

Filebeat 在发生 JSON 反序列化错误时会添加 "error.message" 和 "error.type: json" 键。

Filebeat 会递归地取消解码后的 JSON 中的点分隔键,并将它们扩展为分层对象结构。

处理器会增强您的数据。请参阅 处理器 以了解更多信息。

对于 Filebeat < 7.16

filebeat.yaml。

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 参考

用法编辑

const app = require('express')();
const morgan = require('morgan');
const { ecsFormat } = require('@elastic/ecs-morgan-format');

app.use(morgan(ecsFormat(/* options */))); 

app.get('/', function (req, res) {
  res.send('hello, world!');
})
app.get('/error', function (req, res, next) {
  next(new Error('boom'));
})

app.listen(3000)

请参阅 以下 提供的可用选项。

运行此脚本(完整示例 在此),并发出请求(通过 curl -i localhost:3000/)将生成类似于以下内容的日志输出

% node examples/express.js | jq .  # piping to jq for pretty-printing
{
  "@timestamp": "2021-01-16T00:03:23.279Z",
  "log.level": "info",
  "message": "::1 - - [16/Jan/2021:00:03:23 +0000] \"GET / HTTP/1.1\" 200 13 \"-\" \"curl/7.64.1\"",
  "ecs.version": "8.10.0",
  "http": {
    "version": "1.1",
    "request": {
      "method": "GET",
      "headers": {
        "host": "localhost:3000",
        "accept": "*/*"
      }
    },
    "response": {
      "status_code": 200,
      "headers": {
        "x-powered-by": "Express",
        "content-type": "text/html; charset=utf-8",
        "etag": "W/\"d-HwnTDHB9U/PRbFMN1z1wps51lqk\""
      },
      "body": {
        "bytes": 13
      }
    }
  },
  "url": {
    "path": "/",
    "domain": "localhost",
    "full": "https://127.0.0.1:3000/"
  },
  "user_agent": {
    "original": "curl/7.64.1"
  }
}

格式选项编辑

您可以传递任何您通常会传递给 morgan()format 参数,日志 "message" 字段将使用指定的格式。默认值为 combined

const app = require('express')();
const morgan = require('morgan');
const { ecsFormat } = require('@elastic/ecs-morgan-format');

app.use(morgan(ecsFormat({ format: 'tiny' }))); 
// ...

如果 "format" 是您正在使用的唯一选项,则可以将其作为 ecsFormat('tiny') 传递。

log.level编辑

对于响应代码 >= 500,log.level 字段将为 "error",否则为 "info"。例如,再次运行 examples/express.jscurl -i localhost:3000/error 将生成以下结果

% node examples/express.js | jq .
{
  "@timestamp": "2021-01-18T17:52:12.810Z",
  "log.level": "error",
  "message": "::1 - - [18/Jan/2021:17:52:12 +0000] \"GET /error HTTP/1.1\" 500 1416 \"-\" \"curl/7.64.1\"",
  "http": {
    "response": {
      "status_code": 500,
  ...

与 APM 的日志关联编辑

此 ECS 日志记录格式化程序与 Elastic APM 集成。如果您的 Node 应用程序正在使用 Node.js Elastic APM 代理,则将向日志记录记录中添加一些字段,以在 APM 服务或跟踪与日志记录数据之间建立关联

  • 在存在当前跟踪跨度的情况下调用的日志语句(例如 logger.info(...))将包括 跟踪字段 - trace.idtransaction.id
  • 由 APM 代理确定或在 APM 代理上配置的一些服务标识符字段允许在 Kibana 中的跨度服务和日志之间进行交叉链接 - service.nameservice.versionservice.environmentservice.node.name
  • event.dataset 启用 Elastic 可观测性应用程序中的日志速率异常检测

例如,运行 examples/express-with-apm.jscurl -i localhost:3000/ 会导致日志记录记录包含以下内容

% node examples/express-with-apm.js | jq .
{
  // The same fields as before, plus:
  "service.name": "express-with-elastic-apm",
  "service.version": "1.1.0",
  "service.environment": "development",
  "event.dataset": "express-with-elastic-apm",
  "trace.id": "116d46f667a7600deed9c41fa015f7de",
  "transaction.id": "b84fb72d7bf42866"
}

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

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

app.use(morgan(ecsFormat({ apmIntegration: false })));

参考编辑

ecsFormat([options])编辑

  • options {type-object} 支持以下选项

    • format {type-string} 格式 名称(例如 combined)、格式函数(例如 morgan.combined)或格式字符串(例如 :method :url :status)。这用于格式化 "message" 字段。默认值为 morgan.combined
    • convertErr {type-boolean} 是否将记录的 err 字段转换为 ECS 错误字段。 默认值: true
    • 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} 的默认值。

创建用于 morgan 的格式化程序,该格式化程序以 ECS 日志记录格式输出。