Использование файлов из output path, для восстановления удаленного индекса

Здравствуйте!

Случайно был удален индекс, который не бэкапился. Но все данные, которые отправлялись в эластик, в этот индекс, так же писались в файлы, с помощью конструкции в logstash:

output {
...
file {
path => "/path/to/file"
codec => line
}
}

Возможно ли c помощью logstash или filebeat перечитать эти файлы и, отправив содержимое в эластик, восстановить удаленный индекс со всеми полями? Вернее, перечитать получилось, но вся информация попадает в message. Пока подбираю grok, но, подумал, возможно это тривиальная задача и есть готовое решение.

Версия ELK 6.6.2

Спасибо!

А в каком формате все записалось в эти файлы, просто значения поле через пробел?

Часть информации через пробел, и большой кусок в виде json. Пока, думаю, нужно отрезать лишнее через grok фильтр, а потом фильтровать json с помощью json фильтра.

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

Благодарю за совет, изучу этот вопрос.

Что касается моего начального вопроса, то возникла небольшая проблема, но, возможно я изначально пошел не туда. При парсе логов, я писал следующий грок:

%{TIMESTAMP_ISO0861:@timestamp} {name=%{DATA:beat.name}} %{GREEDYDATA:message}

т.к. первые два значения в логах всегда одинаковые. Это не весь грок, просто часть для примера. Я думал, что json фильтр сам распознает поля, и проставит их в индекс в соответствии со значениями в логе, а именно, что лог будет записан в эластик с датой(@timestamp), которая указана в моем лог файле, у меня это апрель месяц. Но он проставляет текущую дату. Возможно переопределить итоговый @timestamp и записать логи "задним числом"?

https://www.elastic.co/guide/en/logstash/current/plugins-filters-date.html

Игорь, благодарю за ссылку, date filter помог. Но, похоже, я все еще чего-то не понимаю, поэтому попробую попросить вашей помощи еще раз. Дело в том, что не все мои логи, после прохождения фильтра, попадают в эластик. При этом в logstahs-plain, при запуске, logstash ошибок не выдает.

пример лога:
2019-04-27T06:03:44.720Z {name=srv} CLIENT RESPONSE : {"username":"user5","userId":000000055,"accessToken":"token-555","refreshToken":"token-1234","corporateCustomerId":123456788,"error":null}
2019-04-27T06:03:45.118Z {name=srv} CLIENT RESPONSE : {"username":"user5","userId":0000056,"accessToken":"token-token","refreshToken":"token-789","corporateCustomerId":123456789}
2019-05-25T23:59:23.017Z {name=dns-name.ru} {"tags":["response"],"duration":1,"path":"/health","host":"dns-name.ru","code":"200"}
2019-05-25T23:59:23.017Z {name=srv} 23:59:23.017 [reactor-http-epoll-11] INFO LogMessage - {"tags":["response"],"duration":1,"path":"/health","host":"dns-name.ru","code":"200"}
2019-04-27T08:17:48.759Z {name=srv} 08:17:48.759 [parallel-24] INFO LogMessage - {"tags":["request","service","payment-service"],"path":"/payments/bulk/state","host":"host-ip","url":"http://host-ip/payments/bulk/state?userId=00000004&paymentIds=000000000000000"}
2019-05-25T21:29:17.454Z {name=srv} 21:29:17.454 [reactor-http-epoll-11] TRACE serviceRequestLogger - CLIENT RESPONSE : {"username":"user3","userId":000002,"accessToken":"456-token","refreshToken":"token-678","corporateCustomerId":00000000}
2019-05-25T22:07:15.565Z {name=srv} 22:07:15.565 [reactor-http-epoll-11] TRACE serviceRequestLogger - CLIENT RESPONSE : {"username":"user2","userId":00000002,"accessToken":"token-123","refreshToken":"456-token","corporateCustomerId":0000000000}
2019-05-25T22:07:15.219Z {name=srv} CLIENT RESPONSE : {"username":"user","userId":0000000,"accessToken":"token123","refreshToken":"123-token","corporateCustomerId":0000000,"error":null}

Жирным я отметил логи, которые не попадают в эластик.

Для обработки я написал следующий грок:
%{TIMESTAMP_ISO8601:timestamp} {name=%{DATA:beat.name}} (%{TIME:time} [%{DATA:thread}] %{DATA:logtype} ( %{DATA:logger}|%{DATA:logger}) (- CLIENT RESPONSE : %{GREEDYDATA:msg}|- %{GREEDYDATA:msg})|CLIENT RESPONSE : %{GREEDYDATA:msg}|%{GREEDYDATA:msg})

Который парсит любую из строк лога, если проверять ее в грок дебаггере.
Но, как уже было сказано выше, в logstash он пропускает некоторые строки.

Ниже конфиг из logstash pipeline:

input {
  file {
    #type => "log"
    path => "/home/touch/log-file"
    tags => ["recovery"]
    start_position => "beginning"
    sincedb_path => "/home/touch/sincedb_access"
  }
}

filter {
  if "recovery" in [tags] {
    grok {
        match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} \{name=(%{DATA:beat.name})\} (%{TIME:time} \[%{DATA:thread}\] %{DATA:level} ( %{DATA:logger}|%{DATA:logger}) (- CLIENT RESPONSE : %{GREEDYDATA:msg}|- %{GREEDYDATA:msg})|CLIENT RESPONSE : %{GREEDYDATA:msg}|%{GREEDYDATA:msg})" }
    }

    date {
        match => ["timestamp", "ISO8601", "YYYY-MM-dd HH:mm:ss,SSS"]
    }

  json {
       source => "msg"
  }

   #mutate {
   #    remove_field => ["msg"]
   #     replace => { "[host][name]" => "%{[beat][name]}" }
   #}

  }
}

output {
    if "recovery" in [tags] {
      elasticsearch {
        hosts => "127.0.0.1:9200"
        index => "example-file.log"
    }
  }
}

Я уже второй день бьюсь над этой проблемой, и у меня кончились идеи. Если совсем убрать json фильтр, то все логи попадают в эластик, но лог, понятное дело, "сырой". Т.е. проблема, видимо, на этапе работы json фильтра.

А что у вас в msg появляется для строк, которые не работают?

Я не уверен, что знаю, как посмотреть. Обычно это видно в логах, когда есть ошибки парсинга Json, или в кибане, когда данные пришли. Поэтому я просто вывел все, после грок фильтра, в файл, перед этим выключив json фильтр.

output {
    if "recovery" in [tags] {
    #  elasticsearch {
    #    hosts => "127.0.0.1:9200"
    #    index => "example-file.log"
    #}
    #stdout { codec => rubydebug }
    file {
        path => "/home/logstash/test-output"
        codec => rubydebug
    }
  }
}

В результате в файле выводится, для строк которые не работают:
{
"message" => "2019-05-25T23:59:23.017Z {name=dns-name.ru} {"tags":["response"],"duration":1,"path":"/health","host":"dns-name.ru","code":"200"}",
"timestamp" => "2019-05-25T23:59:23.017Z",
"host" => "log-collector",
"msg" => "{"tags":["response"],"duration":1,"path":"/health","host":"dns-name.ru","code":"200"}",
"@version" => "1",
"path" => "/home/touch/log-file",
"tags" => [
[0] "recovery"
],
"@timestamp" => 2019-05-25T23:59:23.017Z,
"beat.name" => "srv"
}
{
"message" => "2019-04-27T08:17:48.759Z {name=srv} 08:17:48.759 [parallel-24] INFO LogMessage - {"tags":["request","service","payment-service"],"path":"/payments/bulk/state","host":"host-ip","url":"http://host-ip/payments/bulk/state?userId=00000004&paymentIds=000000000000000"}",
"level" => "INFO",
"timestamp" => "2019-04-27T08:17:48.759Z",
"time" => "08:17:48.759",
"@version" => "1",
"tags" => [
[0] "recovery"
],
"@timestamp" => 2019-04-27T08:17:48.759Z,
"host" => "srv",
"thread" => "parallel-24",
"logger" => "LogMessage",
"msg" => "{"tags":["request","service","payment-service"],"path":"/payments/bulk/state","host":"host-ip","url":"http://host-ip/payments/bulk/state?userId=00000004&paymentIds=000000000000000"}",
"path" => "/home/touch/bspb-middleware-example",
"beat.name" => "srv"
}

Если включить json фильтр, то этот лог не попадает в файл.

Я разобрался в чем было дело. В строках лога, которые "не работают", в json'е есть поле host, которое конфликтует с системным, не знаю как это еще назвать, полем host, которое сам logstash проставляет. В общем я прогнал msg через json фильтр, записал результат в поле jsonlog и вывел все это в файл. И там видно два поля host. Вот пример вывода:

{
          **"host" => "srv"**,
          "tags" => [
        [0] "recovery"
    ],
          "path" => "/home/touch/log-example",
     "timestamp" => "2019-05-25T23:59:23.017Z",
     "beat.name" => "dns-name.ru",
           "msg" => "{\"tags\":[\"response\"],\"duration\":1,\"path\":\"/health\",\"host\":\"dns-name.ru\",\"code\":\"200\"}",
      "@version" => "1",
    "@timestamp" => 2019-05-25T23:59:23.017Z,
       "message" => "2019-05-25T23:59:23.017Z {name=dns-name.ru} {\"tags\":[\"response\"],\"duration\":1,\"path\":\"/health\",\"host\":\"dns-name.ru\",\"code\":\"200\"}",
       "jsonlog" => {
            **"host" => "dns-name.ru"**,
            "code" => "200",
        "duration" => 1,
            "tags" => [
            [0] "response"
        ],
            "path" => "/health"
    }
}

Возможно, мне уже стоит создать отдельную тему для моих вопросов, т.к. они уже не имеют ничего общего с первоначальной темой. И тем не менее, как перезаписать "системное" поле host кастомным? До этого, я уже пробовал это делать, с помощью mutate, но получал ошибку при старте logstash.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.