Логирование nginx средствами Filebeat и Logstash без ошибок

Сегодня настраивал логирование nginx средствами Filebeat и Logstash, установленного в оставе ELK-стека, используя официальное руководство.

В результате у меня получилось два конфигурационных файла:

  • /etc/logstash/conf.d/11-nginx-access.conf для логов обращений к nginx
  • /etc/logstash/conf.d/12-nginx-error.conf для логов ошибок nginx

Однако после перезапуска Logstash в файле /var/log/logstash/logstash-plain.log появились ошибки:

[2017-08-09T08:44:47,010][FATAL][logstash.runner          ] An unexpected error occurred! {:error=>#, :backtrace=>["org/logstash/ext/JrubyEventExtLibrary.java:202:in `sprintf'", "/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-7.3.7-java/lib/logstash/outputs/elasticsearch/common.rb:173:in `event_action_params'", "/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-7.3.7-java/lib/logstash/outputs/elasticsearch/common.rb:48:in `event_action_tuple'", "/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-7.3.7-java/lib/logstash/outputs/elasticsearch/common.rb:42:in `multi_receive'", "org/jruby/RubyArray.java:2414:in `map'", "/usr/share/logstash/vendor/bundle/jruby/1.9/gems/logstash-output-elasticsearch-7.3.7-java/lib/logstash/outputs/elasticsearch/common.rb:42:in `multi_receive'", "/usr/share/logstash/logstash-core/lib/logstash/output_delegator_strategies/shared.rb:13:in `multi_receive'", "/usr/share/logstash/logstash-core/lib/logstash/output_delegator.rb:47:in `multi_receive'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:420:in `output_batch'", "org/jruby/RubyHash.java:1342:in `each'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:419:in `output_batch'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:365:in `worker_loop'", "/usr/share/logstash/logstash-core/lib/logstash/pipeline.rb:330:in `start_workers'"]}

Основная часть, которая помогла мне разобраться в причине возникновения ошибки: timestamp field is missing

Оказалось, что иногда, по непонятной причине, у такого рода записей может не быть поля @timestamp, что ломает следующую конструкцию из примеров:

   mutate {
      rename => { "@timestamp" => "read_timestamp" }
   }

Можно её закомментировать или удалить, но я пошёл дальше и добавил проверку для корректной обработки поля, если оно всё-таки встретится:

  if ("" in [@timestamp]) {
    mutate {
      rename => { "@timestamp" => "read_timestamp" }
    }
  }

Кроме того, в примерах из руководства неправильно указан формат даты и времени.

Для access-логов

Формат из лога nginx: 09/Aug/2017:06:09:05 +0000

Неправильный формат из руководства:

   date {
      match => [ "[nginx][access][time]", "dd/MMM/YYYY:H:m:s Z" ]
      remove_field => "[nginx][access][time]"
   }

Правильный формат:

   date {
      match => [ "[nginx][access][time]", "dd/MMM/yyyy:HH:mm:ss Z" ]
      remove_field => "[nginx][access][time]"
   }

Для error-логов

Формат из лога nginx: 2017/08/09 09:06:03

Неправильный формат из руководства:

   date {
      match => [ "[nginx][error][time]", "YYYY/MM/dd H:m:s" ]
      remove_field => "[nginx][error][time]"
   }

Правильный формат:

   date {
      match => [ "[nginx][error][time]", "yyyy/MM/dd HH:mm:ss" ]
      remove_field => "[nginx][error][time]"
   }

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

Ниже привожу примеры итоговых конфигурационных файлов:

Файл /etc/logstash/conf.d/11-nginx-access.conf

filter {
  grok {
    match => { "message" => ["%{IPORHOST:[nginx][access][remote_ip]} - %{DATA:[nginx][access][user_name]} \[%{HTTPDATE:[nginx][access][time]}\] \"%{WORD:[nginx][access][method]} %{DATA:[nginx][access][url]} HTTP/%{NUMBER:[nginx][access][http_version]}\" %{NUMBER:[nginx][access][response_code]} %{NUMBER:[nginx][access][body_sent][bytes]} \"%{DATA:[nginx][access][referrer]}\" \"%{DATA:[nginx][access][agent]}\""] }
    remove_field => "message"
  }
  if ("" in [@timestamp]) {
    mutate {
      rename => { "@timestamp" => "read_timestamp" }
    }
  }
  date {
    match => [ "[nginx][access][time]", "dd/MMM/yyyy:HH:mm:ss Z" ]
    remove_field => "[nginx][access][time]"
  }
  useragent {
    source => "[nginx][access][agent]"
    target => "[nginx][access][user_agent]"
    remove_field => "[nginx][access][agent]"
  }
  geoip {
    source => "[nginx][access][remote_ip]"
    target => "[nginx][access][geoip]"
  }
}

Файл /etc/logstash/conf.d/12-nginx-error.conf

filter {
  grok {
    match => { "message" => ["%{DATA:[nginx][error][time]} \[%{DATA:[nginx][error][level]}\] %{NUMBER:[nginx][error][pid]}#%{NUMBER:[nginx][error][tid]}: (\*%{NUMBER:[nginx][error][connection_id]} )?%{GREEDYDATA:[nginx][error][message]}"] }
    remove_field => "message"
  }
  if ("" in [@timestamp]) {
    mutate {
      rename => { "@timestamp" => "read_timestamp" }
    }
  }
  date {
    match => [ "[nginx][error][time]", "yyyy/MM/dd HH:mm:ss" ]
    remove_field => "[nginx][error][time]"
  }
}

А вот так красиво отображает обработанные логи Kibana

Нет комментариев Логирование nginx средствами Filebeat и Logstash без ошибок

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *