Как регистрировать ошибки JS от клиента в кибане?

У меня есть конец веб-приложения в NodeJS и logstash/elasticsearch/kibana для обработки системных журналов, таких как (access_error.log, messages.log etc).

Сейчас мне нужно также записывать все ошибки на стороне клиента JavaScript в kibana. Каков наилучший способ сделать это?

EDIT: Мне нужно добавить дополнительную информацию по этому вопросу. Поскольку @Jackie Xu обеспечивает частичное решение моей проблемы и как следует из моего комментария:

Меня больше всего интересует обработка ошибок на стороне сервера. Я думаю, что это не эффективная запись каждой ошибки в файл. Я ищу лучшие практики, чтобы повысить производительность.

Мне нужно обрабатывать записи ошибок js на стороне сервера более эффективно, чем просто записывать в файл. Можете ли вы предоставить некоторые сценарии, как я могу увеличить производительность ведения журнала на стороне сервера?

Ответы

Ответ 1

Когда вы говорите клиент, я предполагаю, что вы имеете в виду клиент регистрации, а не веб-клиент.

Во-первых, сделайте привычкой регистрировать свои ошибки в общем формате. Logstash любит согласованность, поэтому, если вы помещаете текст и JSON в один и тот же журнал вывода, вы столкнетесь с проблемами. Подсказка: войдите в JSON. Это потрясающе и невероятно гибко.

Общий процесс будет выглядеть следующим образом:

  • Ошибка в вашем приложении.
  • Запишите ошибку в файл, сокет или через сеть.
  • Скажите logstash, как получить (ввести) эту ошибку (т.е. из файла, прослушать через сеть и т.д.)
  • Сообщите logstash для отправки (вывода) ошибки в Elasticsearch (который может работать на одном компьютере)

В вашем приложении попробуйте использовать bunyan logger для node. 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

Перейдите в поиск elasticsearch на http://your-elasticsearch-host:9292, чтобы увидеть входящие журналы.

Ответ 2

Сначала вам придется сначала поймать все ошибки на стороне клиента (и отправить их на ваш сервер):

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 window.onerror не работает для каждой ошибки. Возможно, вам захочется переключиться на что-то вроде Sentry (если вы не хотите платить, вы можете напрямую получить источник из GitHub).

Ответ 3

Ошибки регистрации через встроенное ведение журнала по умолчанию позволяют сохранять ваши ошибки, а также позволяют вашему ядру оптимизировать записи для вас.

Если вы действительно думаете, что это недостаточно быстро (вы получаете много ошибок?), вы могли бы просто поместить их в redis.

Logstash имеет redis pub/sub input, поэтому вы можете хранить ошибки в redis, а logstash вытаскивает их и сохраняет их в вашем случае в elasticsearch.

Я предполагаю, что logstash/es находятся на другом сервере, иначе действительно нет смысла делать это, es также должен хранить данные на диске, и это не так эффективно, как запись файла журнала.

С любым решением, с которым вы работаете, вы хотите сохранить данные, например. записывая его на диск. Добавление только к одному (журнальному) файлу очень эффективно, и при сохранении данных единственный способ, которым вы можете обрабатывать больше, - это обмануть его на нескольких дисках/узлах.

Ответ 4

Если я правильно понимаю, проблема заключается в том, что вы не отправляете свои журналы на сервер (или @Jackie-xu предоставили некоторые подсказки), а скорее о том, как отправить их в elastiscsearch наиболее эффективно.

На самом деле подавляющее большинство пользователей классического стека 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 Server. Я не могу представить себе более простой и быстрый способ сделать это (но обратите внимание, что это просто теория, я никогда не пробовал себя, поэтому реальность может быть более сложной, особенно если вы хотите, чтобы были созданы специальные поля, такие как отметки времени даты;)). В рабочем контексте вы, вероятно, будете иметь проблемы с безопасностью, возможно, прокси-сервер между клиентом и ES-сервером, но принцип существует.

Если вы абсолютно хотите использовать Logstash, вы не будете вынуждены использовать ввод файла
Если в целях согласования, делая то же самое, что и у всех, или для использования расширенного разбора синтаксического анализа логсташей, который вы хотите придерживаться в Logstash, вы должны взглянуть на все альтернативные входы для ввода основного файла. Например, я использовал сам канал, с процессом, ответственным за сбор журналов и вывод их на стандартный вывод. Существует также возможность читать на открытом tcp-сокете и многое другое, вы даже можете добавить свой собственный.