2016-08-19 6 views
2

Я запрашиваю каждую минуту в базе данных MSSQL с помощью jdbc-plugin. В этой базе данных моя временная метка хранится в тиках. Имя поля lastupdate. Теперь я хотел преобразовать поле lastupdate в формат timestamp, а затем перезаписать поле @timestamp с преобразованным полем lastvalue. Я попробовал модуль ruby ​​filter-plugin с методом, предоставленным из другого сообщения, при преобразовании от тиков к дате (Parse ticks to datetime), но не смог достичь конверсии и получил _rubyexception и _dateparsefailure.Преобразование Ticks в @timestamp в logstash с Ruby-plugin

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

filter { 
    if [type] == "mydb" { 
    ruby { 
     init => "require 'time'" 
     code => "lastupdate = Time.at(event['lastupdate'].to_s)" 
    } 
    date { 
     match => [ "lastupdate", "MM/dd/YY HH:mm:ss,SSS" ] 
    } 
    } 
} 

Пример lastupdate: 636062509024728064

Дата после преобразования с http://tickstodatetime.com/: 2016-08-08 T11: 01: 42.472Z

Дополнительная Информация в Ticks: https://msdn.microsoft.com/en-us/library/system.datetime.ticks%28v=vs.110%29.aspx

+0

Пожалуйста, измените вопрос с журнальным сообщением в качестве примера вы пытаетесь разобрать – pandaadb

+0

@pandaadb Добавлен пример. С указанным выше фильтром значение поля lastupdate не изменяется вообще. Заранее спасибо! – cvanhalt

+0

Вы не назначаете его. Какая такая временная карта? :) Time.at дает мне: «281182817-11-03 04:01:49 +0000» – pandaadb

ответ

2

Используемая здесь величина тиков specified следующим образом:

Значение этого свойства представляет количество 100-наносекундных интервалов, прошедших с полуночи 12:00:00, 1 января, 0001 (0:00:00 UTC 1 января 0001 , в григорианском календаре), который представляет DateTime.MinValue. Он не включает количество тиков, которые относятся к скачкам секунд.

В Ruby внутреннее представление времени следует за соглашением Unix подсчета секунд с 1 января 1970 года, 00:00:00 по UTC. Таким образом, чтобы преобразовать значение, вам нужно выполнить несколько дополнительных шагов. В развернутом Ruby, это выглядит следующим образом:

epoch = 621_355_968_000_000_000 # 1970-01-01T00:00:00Z in ticks 
ticks_per_second = 10_000_000.0 

lastupdate = 636062509024728064 # the value in ticks we would like to convert 
seconds_since_epoch = (lastupdate - epoch)/ticks_per_second 
Time.at(seconds_since_epoch).utc 
# => 2016-08-08 11:01:42 UTC 

Для того, чтобы применить это к logstash, вы можете уплотнить его немного:

filter { 
    if [type] == "mydb" { 
    ruby { 
     code => "event['@timestamp'] = LogStash::Timestamp.at((event['lastupdate'].to_i - 621355968000000000)/10_000_000.0)" 
    } 
    } 
} 

Этот код отрезала выполняет расчет, показанный выше, и передает результат как аргумент Time.at. Наконец, он принимает результирующий объект времени, formats его в формате, используемом logstash, и сохраняет его в поле @timestamp.

+0

Для вышеприведенной команды я получаю rubyexception. Таким образом, значение lastupdate не изменяется, а поле @timestamp не обновляется. Спасибо за вашу помощь :) – cvanhalt

+0

У меня есть аналогичное решение, но продолжайте видеть «невозможно разобрать fixnum», и, к сожалению, мой рубин недостаточно хорош, чтобы понять, почему:/ – pandaadb

+0

@cvanhalt: Пожалуйста, проверьте свой лог-файл журнала. Он должен содержать больше информации о повышенном освобождении. –

1

С ответом Хольгера я исправил свою. (спасибо!)

Он полностью прав насчет конверсии. Клещи - странная единица времени: P Я не буду повторять его совершенно прекрасное объяснение здесь.

Это будет разбирать строку (!!!) клещ значение и создать Logstash объект времени, чтобы написать в поле @timestamp:

ruby { 
     init => "require 'time'" 
     code => " 
     ts = (event['message'].to_i - 621355968000000000)/10000000 
     event['@timestamp'] = LogStash::Timestamp.new(Time.at(ts)) 
     " 
    } 

Fun проблема :) Тем не менее думаю, что Хольгер заслуживает клеща;)

Примечание: вам не нужна часть «требуемого времени». Он уже импортируется, когда лямбда выполняется в logstash.

Note2: logstash 5.0 разбивает событие (становится явным компонентом Java), поэтому вместо доступа к нему в виде массива вам необходимо получить доступ к нему с помощью метода set.

С уважением,

Артур

P.S. Пример:

[email protected]:~/dev/logstash$ ./logstash-2.3.2/bin/logstash -f conf2/ 
Settings: Default pipeline workers: 8 
Pipeline main started 
636062509024728064 
{ 
     "message" => "636062509024728064", 
     "@version" => "1", 
    "@timestamp" => "2016-08-08T11:01:42.000Z", 
      "host" => "pandaadb" 
} 

Ps2: Я думаю, что «не может DUP Fixnum» был от меня пытаюсь вызвать синтаксический анализ на целом значении (не уверен, хотя)

+0

Вы правы, logstash использует собственный класс Timestamp (основанный на классе Ruby 'Time') вместо String. Я соответствующим образом адаптировал свой ответ и добавил +1: –

+0

Да, это немного странно, они это делают :) Я не думаю, что это очень документировано, я столкнулся с ним только при написании плагина и задаюсь вопросом, почему он дует up :) – pandaadb

+0

@HolgerJust и pandaadb Спасибо большое! Теперь он работает как charm =) – cvanhalt

Смежные вопросы