Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志

Posted Elastic 中国社区官方博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志相关的知识,希望对你有一定的参考价值。

本指南演示了如何从 Node.js Web 应用程序中提取日志并将它们安全地传送到 Elasticsearch Service 部署中。 你将设置 Filebeat 来监控具有标准 Elastic Common Schema (ECS) 格式字段的 JSON 结构化日志文件,然后你将在向 Node.js 服务器发出请求时查看 Kibana 中日志事件的实时可视化。 虽然此示例使用了 Node.js,但这种监视日志输出的方法适用于许多客户端类型。 检查可用 ECS 日志记录插件的列表

在如下的演示中,我将使用最新的 Elastic Stack 8.5.0 来进行展示。

使用 Filebeat 从 Node.js Web 应用程序提取日志

安装

Elastic Stack

如果你还没有安装好自己的 Elasticsearch 及 Kibana,请参阅我之前的文章:

在安装时,请参考最新的 Elastic Stack 8.x 的指南来进行安装。

Nodejs

你将设置一个简单的 Node.js Web 服务器和客户端应用程序。 查看 Node.js 下载页面以获取安装说明。

提示:对于以下三个包,你可以创建一个工作目录以使用 Node 包管理器 (NPM) 安装这些包。 然后,你可以从同一目录运行你的 Node.js 网络服务器和客户端,以便它可以使用这些包。 或者,你也可以通过运行带有 -g 选项的 Node 包安装命令来全局安装 Node 包。 有关详细信息,请参阅 NPM 包安装说明

winston

这是一个流行的 Node.js 日志记录包。 创建一个新的本地目录并运行以下命令以在其中安装 winston:

npm install winston
$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ npm install winston
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/

added 29 packages, and removed 1 package in 8s

2 packages are looking for funding
  run `npm fund` for details
npm notice 
npm notice New major version of npm available! 8.9.0 -> 9.1.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.1.1
npm notice Run npm install -g npm@9.1.1 to update!
npm notice 

Elastic Common Schema (ECS) formatter

这个是针对 Nodejs winston 日志记录器的。此插件将你的 Node.js 日志格式化为 ECS 结构化 JSON 格式,非常适合摄取到 Elasticsearch 中。 要安装 ECS winston 记录器,请在你的工作目录中运行以下命令,以便将包安装在与 winston 包相同的位置:

npm install @elastic/ecs-winston-format
$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ npm install @elastic/ecs-winston-format
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/

added 12 packages in 8s

3 packages are looking for funding
  run `npm fund` for details

Got

Got 是一个“人性化且功能强大的 Node.js HTTP 请求库”。 - 该插件可用于查询教程中使用的示例 Web 服务器。 要安装 Got 软件包,请在你的工作目录中运行以下命令:

npm install got
$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ npm install got
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/
npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: https://github.blog/2021-08-23-npm-registry-deprecating-tls-1-0-tls-1-1/

added 22 packages in 7s

13 packages are looking for funding
  run `npm fund` for details

安全连接到 Elasticsearch

要连接到 Elasticsearch 集群、将数据流式传输到 Elasticsearch 并发出查询,你需要考虑身份验证。 支持两种身份验证机制,API 密钥和基本身份验证。 在这里,为了让你快速入门,我们将向你展示如何使用基本身份验证,但你也可以生成 API 密钥,如下所示。 API 密钥更安全,更适合生产环境。

如果你对如何连接到 Elasticsearch 还不是很清楚的话,请参阅我之前的文章 “Elasticsearch:使用最新的 Nodejs client 8.x 来创建索引并搜索”。在本篇文章中,我就不再赘述了。

创建带有日志记录的 Node.js Web 应用程序

接下来,创建一个运行 Web 服务器并记录 HTTP 请求的基本 Node.js 脚本。

在安装 winston 和 ECS 格式化程序包的同一本地目录中,创建一个新文件 webserver.js 并将其保存为以下内容:

webserver.js

$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ ls
webserver.js
$ cat webserver.js 
const http = require('http')
const winston = require('winston')
const ecsFormat = require('@elastic/ecs-winston-format')

const logger = winston.createLogger(
  level: 'debug',
  format: ecsFormat( convertReqRes: true ),
  transports: [
    //new winston.transports.Console(),
    new winston.transports.File(
      //path to log file
      filename: 'logs/log.json',
      level: 'debug'
    )
  ]
)

const server = http.createServer(handler)
server.listen(3000, () => 
  logger.info('listening at http://localhost:3000')
)

function handler (req, res) 
 res.setHeader('Foo', 'Bar')
  res.end('ok')
  logger.info('handled request',  req, res )

此 Node.js 脚本在 http://localhost:3000 运行 Web 服务器,并使用 winston 记录器根据 HTTP 请求将记录事件发送到文件 log.json。

接下来,我们使用如下的命令来运行上面的 Node.js 脚本:

node webserver.js

脚本运行后,打开 Web 浏览器访问 http://localhost:3000,应该会出现一条简单的 ok 消息。

在你创建 webserver.js 的目录中,你现在应该找到一个新创建的 log.json 文件。 打开文件并检查内容。 应该有一个日志条目表明 Node.js 正在侦听 localhost 端口,而另一个条目则表明您在浏览器中打开 localhost 时的 HTTP 请求。

暂时让 webserver.js 运行,我们将向它发送一些 HTTP 请求。

$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ ls
logs         webserver.js
$ cd logs/
$ ls
log.json
$ cat log.json 
"@timestamp":"2022-11-14T02:47:32.522Z","log.level":"info","message":"listening at http://localhost:3000","ecs":"version":"1.6.0"
"@timestamp":"2022-11-14T02:49:21.182Z","log.level":"info","message":"handled request","ecs":"version":"1.6.0","http":"version":"1.1","request":"method":"GET","headers":"host":"localhost:3000","connection":"keep-alive","sec-ch-ua":"\\"Google Chrome\\";v=\\"107\\", \\"Chromium\\";v=\\"107\\", \\"Not=A?Brand\\";v=\\"24\\"","sec-ch-ua-mobile":"?0","sec-ch-ua-platform":"\\"macOS\\"","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/107.0.0.0 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","sec-fetch-site":"none","sec-fetch-mode":"navigate","sec-fetch-user":"?1","sec-fetch-dest":"document","accept-encoding":"gzip, deflate, br","accept-language":"en,zh-CN;q=0.9,zh;q=0.8,zh-TW;q=0.7,fr;q=0.6,da;q=0.5,de;q=0.4,my;q=0.3,es;q=0.2","cookie":"_st_togo_session=VVc4QnJac1FCeUlpcm9UT0dtWTBYVmVZYkRQbEpnaGJhUGFGQVhpbGwzeVUvUG5SK0pXK3BLOXNQejhiZGE1bForYUQvNkNWS0JQTDVjL2tqYjl5SVhTeFpwNjN2OTk1Q3VpWkFjRDRxS0ttZkhRR3VCaFhhSVBHZS9CRS81NjJzYk5uUWxYVmxBc2s0VzViUDFtaExMb2NNOEs2Y1IrR3l5QmFUNWx3VFViYXEzdjkweTdXbXFtWDQ1L3hIaEdwdWZCRExCcmlscTRuTDlSMTFocFlnUT09LS11SUZyNWpvODlMM3R2S3JSZytWVEhRPT0%3D--bf4dbdb1387208eb9c2bf8b7fe88729532880187; session=eyJjc3JmX3Rva2VuIjoiMTk5ZWM0NzQxNmM1NmY3YTMxYWVhMmVhMTMzNDc3NTc1ZTgzZTZiZSJ9.YwTRag.sYZBSm7Gjku9nGLRw4jw3NAqcgg; sid=Fe26.2**eaf53f0d84a6ecdb87b0646461e906103275daeb125e9a3cdd99038e607dac17*-UEJP8vtsqjk_MYYh0afqQ*2S30rxbYeq-OQh-eNGteqtUVEr8p1Oklg89VWBT4nraxupoKyw6XwYcbdd8J5OxJBrPbfanCOB0iFACq0Ul2Hw_tzikogeiZuodS6kXVreaLViC0gMSLrYPw3Ysk7EbFdEF9G9ZpgYW6ryOSLDuETGiByCnhJ9cT58Aq8zDSPO-ZkfHShYyL1ZXsnM_TmslVn6cpZSP2c6sS-Khi7LVieMbCrd2WTo3NZBUQZ-fmkml26hA921sIHFiCMq91oMuo**3254f523a2ec4d74cac2e09bd74d561c91a54a7e78c4e1ed6e9eee1ac27d546d*OKIM_of3Bl2LWc4FHKCCLOzMut7R-y43Gbnla4gBB-s","response":"status_code":200,"headers":"foo":"Bar","url":"path":"/","full":"http://localhost:3000/","client":"address":"::1","ip":"::1","port":58232,"user_agent":"original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"
"@timestamp":"2022-11-14T02:49:21.379Z","log.level":"info","message":"handled request","ecs":"version":"1.6.0","http":"version":"1.1","request":"method":"GET","headers":"host":"localhost:3000","connection":"keep-alive","sec-ch-ua":"\\"Google Chrome\\";v=\\"107\\", \\"Chromium\\";v=\\"107\\", \\"Not=A?Brand\\";v=\\"24\\"","sec-ch-ua-mobile":"?0","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36","sec-ch-ua-platform":"\\"macOS\\"","accept":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"http://localhost:3000/","accept-encoding":"gzip, deflate, br","accept-language":"en,zh-CN;q=0.9,zh;q=0.8,zh-TW;q=0.7,fr;q=0.6,da;q=0.5,de;q=0.4,my;q=0.3,es;q=0.2","cookie":"_st_togo_session=VVc4QnJac1FCeUlpcm9UT0dtWTBYVmVZYkRQbEpnaGJhUGFGQVhpbGwzeVUvUG5SK0pXK3BLOXNQejhiZGE1bForYUQvNkNWS0JQTDVjL2tqYjl5SVhTeFpwNjN2OTk1Q3VpWkFjRDRxS0ttZkhRR3VCaFhhSVBHZS9CRS81NjJzYk5uUWxYVmxBc2s0VzViUDFtaExMb2NNOEs2Y1IrR3l5QmFUNWx3VFViYXEzdjkweTdXbXFtWDQ1L3hIaEdwdWZCRExCcmlscTRuTDlSMTFocFlnUT09LS11SUZyNWpvODlMM3R2S3JSZytWVEhRPT0%3D--bf4dbdb1387208eb9c2bf8b7fe88729532880187; session=eyJjc3JmX3Rva2VuIjoiMTk5ZWM0NzQxNmM1NmY3YTMxYWVhMmVhMTMzNDc3NTc1ZTgzZTZiZSJ9.YwTRag.sYZBSm7Gjku9nGLRw4jw3NAqcgg; sid=Fe26.2**eaf53f0d84a6ecdb87b0646461e906103275daeb125e9a3cdd99038e607dac17*-UEJP8vtsqjk_MYYh0afqQ*2S30rxbYeq-OQh-eNGteqtUVEr8p1Oklg89VWBT4nraxupoKyw6XwYcbdd8J5OxJBrPbfanCOB0iFACq0Ul2Hw_tzikogeiZuodS6kXVreaLViC0gMSLrYPw3Ysk7EbFdEF9G9ZpgYW6ryOSLDuETGiByCnhJ9cT58Aq8zDSPO-ZkfHShYyL1ZXsnM_TmslVn6cpZSP2c6sS-Khi7LVieMbCrd2WTo3NZBUQZ-fmkml26hA921sIHFiCMq91oMuo**3254f523a2ec4d74cac2e09bd74d561c91a54a7e78c4e1ed6e9eee1ac27d546d*OKIM_of3Bl2LWc4FHKCCLOzMut7R-y43Gbnla4gBB-s","response":"status_code":200,"headers":"foo":"Bar","url":"path":"/favicon.ico","full":"http://localhost:3000/favicon.ico","client":"address":"::1","ip":"::1","port":58232,"user_agent":"original":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"

创建 Node.js HTTP 请求应用程序

在此步骤中,你将创建一个向你的 Web 服务器发送 HTTP 请求的 Node.js 应用程序。

在你的工作目录中,创建一个文件 webrequests.js 并使用以下内容保存它:

webrequests.js

// const got = require('got');

import got from 'got';

const addresses = [
    'aardvark@the.zoo',
    'crocodile@the.zoo',
    'elephant@the.zoo',
    'emu@the.zoo',
    'hippopotamus@the.zoo',
    'llama@the.zoo',
    'octopus@the.zoo',
    'otter@the.zoo',
    'panda@the.zoo',
    'pangolin@the.zoo',
    'tortoise@the.zoo',
    'walrus@the.zoo'
];

const method = [
    'get',
    'put',
    'post'
];

async function sleep(millis) 
    return new Promise(resolve => setTimeout(resolve, millis));


(async () => 
    while (true) 
        var type = Math.floor(Math.random() * method.length);
        var email = Math.floor(Math.random() * addresses.length);
        var sleeping = Math.floor(Math.random() * 9) + 1;

        switch (method[type]) 
            case 'get':
                try 
                    const response = await got.get('http://localhost:3000/', 
                        headers: 
                            from: addresses[email]
                        
                    ).json();
                    console.log(response.body);
                 catch (error) 
                    // console.log(error.response);
                
                break; // end case 'get'
            case 'put':
                try 
                    const response = await got.put('http://localhost:3000/', 
                        headers: 
                            from: addresses[email]
                        
                    ).json();
                    console.log(response.body);
                 catch (error) 
                    // console.log(error.response);
                
                break; // end case 'put'
            case 'post':
                try 
                    const 
                        data
                     = await got.post('http://localhost:3000/', 
                        headers: 
                            from: addresses[email]
                        
                    ).json();
                    console.log(data);
                 catch (error) 
                    // console.log(error.response);
                
                break; // end case 'post'
         // end switch on method
    await sleep(sleeping * 1000);
    
)();
$ pwd
/Users/liuxg/nodejs/nodejs_logs
$ ls
logs            webrequests.mjs webserver.js

此 Node.js 应用程序使用 GET、POST 或 PUT 类型的随机方法生成 HTTP 请求,并使用各种假冒的电子邮件地址从请求标头中随机生成 HTTP 请求。 请求以 1 到 10 秒之间的随机间隔发送。

Got 包用于发送请求,它们被定向到位于 http://localhost:3000 的 Web 服务器。 要了解如何发送自定义标头(例如本示例中使用的 from 字段),请查看 Got 文档中的标头

我们接下来,在一个新的 terminal 中,打入如下的命令运行上面的脚本:

脚本运行大约 30 秒后,输入 CTRL + C 停止它。 查看您的 Node.js logs/log.json 文件。 它应该包含一些像这样的条目:

"@timestamp":"2022-11-14T03:34:00.667Z","log.level":"info","message":"handled request","ecs":"version":"1.6.0","http":"version":"1.1","request":"method":"PUT","headers":"user-agent":"got (https://github.com/sindresorhus/got)","from":"panda@the.zoo","accept":"application/json","accept-encoding":"gzip, deflate, br","host":"localhost:3000","connection":"keep-alive","content-length":"0","body":"bytes":0,"response":"status_code":200,"headers":"foo":"Bar","url":"path":"/","full":"http://localhost:3000/","client":"address":"::1","ip":"::1","port":59548,"user_agent":"original":"got (https://github.com/sindresorhus/got)"

每个日志条目都包含 HTTP 请求的详细信息。 特别是,在此示例中,你可以找到请求的时间戳、PUT 类型的请求方法以及来自电子邮件地址 octopus@the.zoo 的请求头。 由于请求类型和电子邮件地址是随机生成的,因此你的示例可能会有所不同。

将你的日志以带有 ECS 字段的 JSON 格式编写,便于解析和分析,并与其他应用程序进行标准化。 随着日志中捕获的数据量和类型随着时间的推移而扩展,标准、易于解析的格式变得越来越重要。

确认 webserver.mjs 和 webrequests.js 都按预期运行后,输入 CTRL + C 停止 Node.js 脚本,同时删除 log.json。

安装 Filebeat 并配置

Filebeat 提供了一种简单、易于配置的方式来监控您的 Node.js 日志文件并将日志数据移植到 Elasticsearch 服务中。

下载 Filebeat 并将其解压缩到你要从中收集数据的本地服务器上。我们需要做如下的配置。你需要根据自己的安装做相应的修改:

使用基本安全来配置 Filebeat

filebeat.yml

我们在 filebeat.yml 文件的开始部分添加如上的部分。 

我们接下来添加 JSON  input 的选项部分:

Filebeat 的输入配置选项包括几个用于解码 JSON 消息的设置。 日志文件是逐行解码的,因此每行包含一个 JSON 对象很重要。

 我们接下来还需要配置 Elasticsearch 的输出部分:

在上面,我们需要根据自己的用户名及密码进行相应的修改。特别需要指出的是,我们在生产的环境中,千万不要使用上面所示的使用超级用户的账号。另外,我们建议使用 API Key 来进行访问会更好。我们也需要根据自己的 Elasticsearch 的证书路径来做相应的修改。

保存好上面的配置文件,我们使用如下的命令来进行测试配置是否有问题:

$ pwd
/Users/liuxg/elastic/filebeat-8.5.0-darwin-aarch64
$ ls
LICENSE.txt            fields.yml             filebeat.yml           modules.d
NOTICE.txt             filebeat               kibana
README.md              filebeat.reference.yml module
$ ./filebeat test config
Config OK
$ ./filebeat test output
elasticsearch: https://localhost:9200...
  parse url... OK
  connection...
    parse host... OK
    dns lookup... OK
    addresses: ::1, 127.0.0.1
    dial up... OK
  TLS...
    security: server's certificate chain verification is enabled
    handshake... OK
    TLS version: TLSv1.3
    dial up... OK
  talk to server... OK
  version: 8.5.0

如上所示,我们的配置是没有任何问题的(语法层面),另外,我们的 Elasticsearch 的输出配置也是没有任何问题的。

Filebeat 带有用于解析、索引和可视化数据的预定义 assets。 要加载这些 assets,请从 Filebeat 安装目录运行以下命令:

./filebeat setup -e

重要: 根据安装位置、环境和本地权限等变量,你可能需要更改 filebeat.yml 的所有权。 你还可以尝试以 root 身份运行该命令:sudo ./filebeat setup -e 或者你可以通过使用 --strict.perms=false 选项运行该命令来禁用严格权限检查。

设置过程需要几分钟。 如果一切顺利,你应该会收到一条确认消息:

Loaded Ingest pipelines

Filebeat 数据视图现在在 Elasticsearch 中可用。 验证:

使用 API key 来进行鉴权

为了提高安全性,你可以通过 Elasticsearch 控制台生成 Elasticsearch API 密钥,而不是使用基本身份验证,然后将 Filebeat 配置为使用新密钥安全地连接到 Elasticsearch 部署中。

我们在 Kibana 的控制台中打入如下的命令:

POST /_security/api_key

  "name": "filebeat-api-key",
  "role_descriptors": 
    "logstash_read_write": 
      "cluster": [
        "manage_index_templates",
        "monitor"
      ],
      "index": [
        
          "names": [
            "filebeat-*"
          ],
          "privileges": [
            "create_index",
            "write",
            "read",
            "manage"
          ]
        
      ]
    
  

这将创建一个具有集群监控权限的 API 密钥,它提供只读访问权限以确定集群状态,以及 manage_index_templates 允许对索引模板的所有操作。 一些额外的权限还允许对指定索引进行创建索引、写入和管理操作。 添加了索引管理权限以启用索引刷新。

将您的 API 密钥信息添加到 filebeat.yml 的 Elasticsearch 输出部分,就在 output.elasticsearch: 下方。 使用格式 <id>:<api_key>。 如果你的结果如本示例所示,请输入 KCJNdIQB8eIGGIhj_MkN:zpeQptZ6Rdmo4kQmyvKLYg。

我们可以在 filebeat.yml 中做如下的配置:

很显然,这样做的好处是我们不暴露自己用户的密码,而且我们可以为这个 API key 设置权限及时间期限。当然我们也可以在 Kibana 中随时删除这个 API key,如果我们不想让这个 API key 继续起作用的话。

把日志数据发送到 Elasticsearch

是时候向 Elasticsearch 发送一些日志数据了!通过从 Filebeat 安装目录运行以下命令来启动 Filebeat:

./filebeat -e -c filebeat.yml 

在上面的命令中:

  • -e 标志将输出发送到标准错误而不是配置的日志输出。
  • -c 标志指定 Filebeat 配置文件的路径。

注意:万一该命令无法按预期工作,请查看 Filebeat 快速入门以了解适用于您操作系统的详细命令语法。 你也可以尝试以 root 身份运行命令:sudo ./filebeat -e -c filebeat.yml。

 Filebeat 现在应该正在运行并监控 log.json 的内容,实际上它还不存在。 所以,让我们创建它。 打开一个新的终端实例并运行 webserver.js Node.js 脚本:

node webserver.js

接下来,运行 Node.js webrequests.mjs 脚本以向 Node.js Web 服务器发送随机请求。

node webrequests.mjs 

让脚本运行几分钟,然后冲泡一杯咖啡或茶☕。 之后,确保 log.json 文件按预期生成并填充了多个日志条目。

在 Kibana 中创建日志可视化

我们首先在 Kibana 的控制台中,查看有没有数据进入到 Elasticsearch:

GET filebeat-8.5.0/_count

上面的命令会显示:


  "count": 34,
  "_shards": 
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  

我们也可以在 Kibana 中的 Discover 来查看数据:

现在是时候根据应用程序日志数据创建可视化了。我们按照如下的步骤来进行:

我们可以通过拖拽左边的字段到 visualization builder 来创建如上所示的可视化:

选择 Save and return 按钮:

我们接下来创建第二个可视化图:

我们接下来创建第三个可视化图:

 你现在拥有一个具有三个可视化效果的 Kibana 仪表板:一个显示每个 HTTP 请求方法随时间变化的频率的堆叠条形图,另一个显示来自标头的各种 HTTP 随时间变化的频率的堆叠条形图,以及一个显示每个 HTTP 请求方法的相对频率的 Donut HTTP 请求方法类型。

你可以为可视化添加标题,根据需要调整它们的大小和位置,然后保存更改。

实时查看日志数据更新

在 Kibana 仪表板上选择 refresh。 由于应用程序 webrequests.mjs 继续运行并向 Node.js 服务器发送 HTTP 请求,因此 webserver.js 继续生成日志数据,并且每次页面刷新时,你的 Kibana 可视化都会使用该数据进行更新。

作为最后一步,请记住停止 Filebeat、Node.js Web 服务器和客户端。 在每个应用程序的终端窗口中输入 CTRL + C 以停止它们。

以上是关于Elasticsearch:使用 Filebeat 从 Node.js Web 应用程序提取日志的主要内容,如果未能解决你的问题,请参考以下文章

使用elasticsearch和filebeat做日志收集

Filebeat实现MySQL日志轻量化发送至Elasticsearch

Filebeat实现MySQL日志轻量化发送至Elasticsearch

filebeat+logstash+elasticsearch收集haproxy日志

FileBeat向elasticsearch传入数据,并使用GROK处理

最简化 Elasticsearch & Kibana & Filebeat 安装说明