如何从客户端记录JS错误到kibana

How to to log JS errors from a client into kibana?

本文关键字:错误 kibana JS 记录 客户端      更新时间:2023-09-26

我在NodeJS和logstash/elasticsearch/kibana中有web应用程序后端来处理系统日志,如(access_error.log, messages.log etc)

现在我需要将所有JavaScript客户端错误记录到kibana中。最好的方法是什么?

编辑:我必须在这个问题上添加额外的信息。@Jackie Xu为我的问题提供了部分解决方案,以下是我的评论:

我对实现服务器端错误处理最感兴趣。我认为把每个错误都写入文件是不有效的。我正在寻找如何使它更性能的最佳实践。

我需要在服务器端处理js错误记录比仅仅写入文件更有效。您能否提供一些如何提高服务器端日志记录性能的场景?

当你说客户端,我假设这里你是指一个日志客户端,而不是一个web客户端

首先,养成以通用格式记录错误的习惯。Logstash喜欢一致性,所以如果将文本和JSON放在同一个输出日志中,就会遇到问题。提示:登录JSON。它很棒,而且非常灵活。

整个过程是这样的:

  1. 应用程序出现错误
  2. 将错误记录到文件、套接字或通过网络
  3. 告诉logstash如何获取(输入)错误(即从文件,通过网络侦听等)
  4. 告诉logstash发送(输出)错误到Elasticsearch(可以在同一台机器上运行)

在你的应用中,尝试为node使用bunyan记录器。https://github.com/trentm/node-bunyan

node app index.js

var bunyan = require('bunyan');
var log = bunyan.createLogger({
  name: 'myapp',
  streams: [{
    level: 'info',
    stream: process.stdout // log INFO and above to stdout
  }, {
    level: 'error',
    path: '/var/log/myapp-error.log' // log ERROR and above to a file
  }]
});
// Log stuff like this
log.info({status: 'started'}, 'foo bar message');
// Also, in express you can catch all errors like this
app.use(function(err, req, res, next) {
   log.error(err);
   res.send(500, 'An error occurred');
});

然后你需要配置logstash来读取这些JSON日志文件并发送到Elasticsearch/Kibana。创建一个名为myapp.conf的文件,并尝试以下操作:

logstash config myapp.conf

# Input can read from many places, but here we're just reading the app error log
input {
    file {
        type => "my-app"
        path => [ "/var/log/myapp/*.log" ]
        codec => "json"
    }   
}
# Output can go many places, here we send to elasticsearch (pick one below)
output {
  elasticsearch {
    # Do this if elasticsearch is running somewhere else
    host => "your.elasticsearch.hostname"
    # Do this if elasticsearch is running on the same machine
    host => "localhost"
    # Do this if you want to run an embedded elastic search in logstash
    embedded => true   
  }
}

然后启动/重启logstash如下:bin/logstash agent -f myapp.conf web

转到http://your-elasticsearch-host:9292上的elasticsearch查看传入的日志。

如果我理解正确,您遇到的问题不是关于将日志发送回服务器(或者如果是@Jackie-xu提供了一些提示),而是关于如何将它们最有效地发送到elastisscsearch。

实际上,绝大多数经典堆栈Logstash/Elasticsearch/Kibana的用户都习惯于有一个应用程序记录到一个文件,然后使用Logstash的插件读取文件来解析该文件并将结果发送给ElasticSearch。既然@methai给出了很好的解释,我就不再往下说了。

但是我想说的是:

不强制使用Logstash
实际上,Logstash的主要作用是收集日志,解析它们以识别它们的结构和循环字段,最后以JSON格式输出它们,以便它们可以发送给ElasticSearch。但是,由于您已经在客户端操作javascript,因此很容易想象您将直接与Elasticsearch服务器进行通信。例如,一旦捕获了javascript异常,您可以执行以下操作:

var xhr = new XMLHttpRequest();
xhr.open("PUT", http://your-elasticsearch-host:9292, true);
var data = {
    lineNumber: lineNumber,
    message: message,
    url: url
}
xhr.send(JSON.stringify(data));

通过这样做,您可以直接从客户端与ElasticSearch服务器通信。我无法想象一个更简单和更快的方法来做到这一点(但请注意,这只是理论,我从来没有尝试过,所以现实可能更复杂,特别是如果你想要生成特殊字段,如日期时间戳;))。在生产环境中,您可能会遇到安全问题,可能在客户机和ES服务器之间有一个代理服务器,但原则是存在的。

如果你绝对想使用Logstash,你不强制使用文件输入
如果出于协调的目的,与每个人做相同的事情,或者为了使用高级logstash解析配置,您希望坚持使用logstash,那么您应该查看基本文件输入的所有可选输入。例如,我自己曾经使用一个管道,其中有一个进程负责收集日志并将其输出到标准输出。还可以读取打开的tcp套接字,甚至可以添加自己的套接字。

您必须首先捕获所有客户端错误(并将这些错误发送给您的服务器):

window.onerror = function (message, url, lineNumber) {
    // Send error to server for storage
    yourAjaxImplementation('http://domain.com/error-logger/', {
        lineNumber: lineNumber,
        message: message,
        url: url
    })
    // Allow default error handling, set to true to disable
    return false
}

之后,你可以使用NodeJS将这些错误信息写入日志。Logstash可以收集这些,然后你可以使用Kibana来可视化。

注意,根据Mozilla窗口。Onerror似乎并不适用于所有错误。你可能想要切换到类似Sentry的东西(如果你不想付费,你可以直接从GitHub获得源代码)。

通过默认的内置文件日志记录错误可以保留错误,还可以让内核为您优化写操作。

如果你真的认为它不够快(你得到那么多错误?)你可以把它们放到redis中。

Logstash有一个redis pub/sub输入,所以你可以将错误存储在redis中,Logstash会将它们拉出来并存储在你的案例中elasticsearch。

我假设logstash/es在另一台服务器上,否则真的没有必要这样做,es必须将数据存储在磁盘上,而且它几乎没有写日志文件那么高效。

无论您使用什么解决方案,您都需要存储数据,例如:写入磁盘。只添加到单个(日志)文件是非常高效的,当保存数据时,您可以处理更多数据的唯一方法是将其分片到多个磁盘/节点。