logstash-filter-date 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +3 -0
- data/lib/logstash/filters/date.rb +48 -22
- data/logstash-filter-date.gemspec +1 -1
- data/spec/filters/date_spec.rb +65 -0
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90514b78e723a6637fbf1f1225cd43d043ecdcb5
|
4
|
+
data.tar.gz: 7129c219a98c1486b73cc715471619cf1393728f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3fc8119ad011c783c2d13bbbe30b463db520477d752a2a0268c7a6baef22872fd18628109044121d0da2292216706c40260da90c2eda2b51479ce047ad25833
|
7
|
+
data.tar.gz: b2340da5d6ec579266aa4b76db2398490bcb3e19bc5bc152d0a0a5cd58dd58cc662b9cb8bf66232fd6fa2aca8d28fd278c78f11d78411399d2a2d4f4d32cc6a1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 2.1.0
|
2
|
+
- New year rollover should be handled better now when a year is not present in
|
3
|
+
the time format. If local time is December, and event time is January, the
|
4
|
+
year will be set to next year. Similar for if local time is January and
|
5
|
+
Event time is December, the year will be set to the previous year. This
|
6
|
+
should help keep times correct in the upcoming year rollover. (#33, #4)
|
7
|
+
- The `timezone` setting now supports sprintf format (#31)
|
8
|
+
- use Event#tag, relax specs for Java Event, code cleanups
|
9
|
+
|
1
10
|
## 2.0.0
|
2
11
|
- Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
|
3
12
|
instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Logstash Plugin
|
2
2
|
|
3
|
+
[](http://build-eu-00.elastic.co/view/LS%20Plugins/view/LS%20Filters/job/logstash-plugin-filter-date-unit/)
|
5
|
+
|
3
6
|
This is a plugin for [Logstash](https://github.com/elastic/logstash).
|
4
7
|
|
5
8
|
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
@@ -35,6 +35,7 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
35
35
|
# If this is not specified the platform default will be used.
|
36
36
|
# Canonical ID is good as it takes care of daylight saving time for you
|
37
37
|
# For example, `America/Los_Angeles` or `Europe/Paris` are valid IDs.
|
38
|
+
# This field can be dynamic and include parts of the event using the `%{field}` syntax
|
38
39
|
config :timezone, :validate => :string
|
39
40
|
|
40
41
|
# Specify a locale to be used for date parsing using either IETF-BCP47 or POSIX language tag.
|
@@ -87,7 +88,7 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
87
88
|
|
88
89
|
# Store the matching timestamp into the given target field. If not provided,
|
89
90
|
# default to updating the `@timestamp` field of the event.
|
90
|
-
config :target, :validate => :string, :default =>
|
91
|
+
config :target, :validate => :string, :default => LogStash::Event::TIMESTAMP
|
91
92
|
|
92
93
|
# Append values to the `tags` field when there has been no
|
93
94
|
# successful match
|
@@ -96,14 +97,12 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
96
97
|
# LOGSTASH-34
|
97
98
|
DATEPATTERNS = %w{ y d H m s S }
|
98
99
|
|
99
|
-
public
|
100
100
|
def initialize(config = {})
|
101
101
|
super
|
102
102
|
|
103
103
|
@parsers = Hash.new { |h,k| h[k] = [] }
|
104
104
|
end # def initialize
|
105
105
|
|
106
|
-
public
|
107
106
|
def register
|
108
107
|
require "java"
|
109
108
|
if @match.length < 2
|
@@ -120,6 +119,9 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
120
119
|
end
|
121
120
|
locale = java.util.Locale.forLanguageTag(@locale)
|
122
121
|
end
|
122
|
+
|
123
|
+
@sprintf_timezone = @timezone && !@timezone.index("%{").nil?
|
124
|
+
|
123
125
|
setupMatcher(@config["match"].shift, locale, @config["match"] )
|
124
126
|
end
|
125
127
|
|
@@ -129,7 +131,7 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
129
131
|
case format
|
130
132
|
when "ISO8601"
|
131
133
|
iso_parser = org.joda.time.format.ISODateTimeFormat.dateTimeParser
|
132
|
-
if @timezone
|
134
|
+
if @timezone && !@sprintf_timezone
|
133
135
|
iso_parser = iso_parser.withZone(org.joda.time.DateTimeZone.forID(@timezone))
|
134
136
|
else
|
135
137
|
iso_parser = iso_parser.withOffsetParsed
|
@@ -138,10 +140,12 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
138
140
|
#Fall back solution of almost ISO8601 date-time
|
139
141
|
almostISOparsers = [
|
140
142
|
org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZ").getParser(),
|
141
|
-
org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").getParser()
|
143
|
+
org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").getParser(),
|
144
|
+
org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSSZ").getParser(),
|
145
|
+
org.joda.time.format.DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSS").getParser()
|
142
146
|
].to_java(org.joda.time.format.DateTimeParser)
|
143
147
|
joda_parser = org.joda.time.format.DateTimeFormatterBuilder.new.append( nil, almostISOparsers ).toFormatter()
|
144
|
-
if @timezone
|
148
|
+
if @timezone && !@sprintf_timezone
|
145
149
|
joda_parser = joda_parser.withZone(org.joda.time.DateTimeZone.forID(@timezone))
|
146
150
|
else
|
147
151
|
joda_parser = joda_parser.withOffsetParsed
|
@@ -158,15 +162,16 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
158
162
|
date.to_i
|
159
163
|
end
|
160
164
|
when "TAI64N" # TAI64 with nanoseconds, -10000 accounts for leap seconds
|
161
|
-
parsers << lambda do |date|
|
165
|
+
parsers << lambda do |date|
|
162
166
|
# Skip leading "@" if it is present (common in tai64n times)
|
163
167
|
date = date[1..-1] if date[0, 1] == "@"
|
164
168
|
return (date[1..15].hex * 1000 - 10000)+(date[16..23].hex/1000000)
|
165
169
|
end
|
166
170
|
else
|
167
171
|
begin
|
168
|
-
|
169
|
-
|
172
|
+
format_has_year = format.match(/y|Y/)
|
173
|
+
joda_parser = org.joda.time.format.DateTimeFormat.forPattern(format)
|
174
|
+
if @timezone && !@sprintf_timezone
|
170
175
|
joda_parser = joda_parser.withZone(org.joda.time.DateTimeZone.forID(@timezone))
|
171
176
|
else
|
172
177
|
joda_parser = joda_parser.withOffsetParsed
|
@@ -174,7 +179,28 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
174
179
|
if locale
|
175
180
|
joda_parser = joda_parser.withLocale(locale)
|
176
181
|
end
|
177
|
-
|
182
|
+
if @sprintf_timezone
|
183
|
+
parsers << lambda { |date , tz|
|
184
|
+
joda_parser.withZone(org.joda.time.DateTimeZone.forID(tz)).parseMillis(date)
|
185
|
+
}
|
186
|
+
end
|
187
|
+
parsers << lambda do |date|
|
188
|
+
return joda_parser.parseMillis(date) if format_has_year
|
189
|
+
now = Time.now
|
190
|
+
now_month = now.month
|
191
|
+
result = joda_parser.parseDateTime(date)
|
192
|
+
event_month = result.getMonthOfYear
|
193
|
+
|
194
|
+
if (event_month == now_month)
|
195
|
+
result.with_year(now.year)
|
196
|
+
elsif (event_month == 12 && now_month == 1)
|
197
|
+
result.with_year(now.year-1)
|
198
|
+
elsif (event_month == 1 && now_month == 12)
|
199
|
+
result.with_year(now.year+1)
|
200
|
+
else
|
201
|
+
result.with_year(now.year)
|
202
|
+
end.get_millis
|
203
|
+
end
|
178
204
|
|
179
205
|
#Include a fallback parser to english when default locale is non-english
|
180
206
|
if !locale &&
|
@@ -199,12 +225,9 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
199
225
|
end
|
200
226
|
end
|
201
227
|
|
202
|
-
# def register
|
203
|
-
|
204
|
-
public
|
205
228
|
def filter(event)
|
206
229
|
@logger.debug? && @logger.debug("Date filter: received event", :type => event["type"])
|
207
|
-
|
230
|
+
|
208
231
|
@parsers.each do |field, fieldparsers|
|
209
232
|
@logger.debug? && @logger.debug("Date filter looking for field",
|
210
233
|
:type => event["type"], :field => field)
|
@@ -221,7 +244,11 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
221
244
|
fieldparsers.each do |parserconfig|
|
222
245
|
parserconfig[:parser].each do |parser|
|
223
246
|
begin
|
224
|
-
|
247
|
+
if @sprintf_timezone
|
248
|
+
epochmillis = parser.call(value, event.sprintf(@timezone))
|
249
|
+
else
|
250
|
+
epochmillis = parser.call(value)
|
251
|
+
end
|
225
252
|
success = true
|
226
253
|
break # success
|
227
254
|
rescue StandardError, JavaException => e
|
@@ -247,13 +274,12 @@ class LogStash::Filters::Date < LogStash::Filters::Base
|
|
247
274
|
# Tag this event if we can't parse it. We can use this later to
|
248
275
|
# reparse+reindex logs if we improve the patterns given.
|
249
276
|
@tag_on_failure.each do |tag|
|
250
|
-
event
|
251
|
-
event["tags"] << tag unless event["tags"].include?(tag)
|
277
|
+
event.tag(tag)
|
252
278
|
end
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
256
282
|
|
257
283
|
return event
|
258
|
-
end
|
259
|
-
end
|
284
|
+
end
|
285
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-filter-date'
|
4
|
-
s.version = '2.0
|
4
|
+
s.version = '2.1.0'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "The date filter is used for parsing dates from fields, and then using that date or timestamp as the logstash timestamp for the event."
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
data/spec/filters/date_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
require "logstash/devutils/rspec/spec_helper"
|
2
4
|
require "logstash/filters/date"
|
3
5
|
|
@@ -48,15 +50,18 @@ RUBY_ENGINE == "jruby" and describe LogStash::Filters::Date do
|
|
48
50
|
"2001-09-05T16:36:36.123+0700" => "2001-09-05T09:36:36.123Z",
|
49
51
|
"2001-11-06T20:45:45.123-0000" => "2001-11-06T20:45:45.123Z",
|
50
52
|
"2001-12-07T23:54:54.123Z" => "2001-12-07T23:54:54.123Z",
|
53
|
+
"2001-12-07T23:54:54,123Z" => "2001-12-07T23:54:54.123Z",
|
51
54
|
|
52
55
|
#Almost ISO8601 support, with timezone
|
53
56
|
|
54
57
|
"2001-11-06 20:45:45.123-0000" => "2001-11-06T20:45:45.123Z",
|
55
58
|
"2001-12-07 23:54:54.123Z" => "2001-12-07T23:54:54.123Z",
|
59
|
+
"2001-12-07 23:54:54,123Z" => "2001-12-07T23:54:54.123Z",
|
56
60
|
|
57
61
|
#Almost ISO8601 support, without timezone
|
58
62
|
|
59
63
|
"2001-11-06 20:45:45.123" => "2001-11-06T20:45:45.123Z",
|
64
|
+
"2001-11-06 20:45:45,123" => "2001-11-06T20:45:45.123Z",
|
60
65
|
|
61
66
|
}
|
62
67
|
|
@@ -357,6 +362,30 @@ RUBY_ENGINE == "jruby" and describe LogStash::Filters::Date do
|
|
357
362
|
end # times.each
|
358
363
|
end
|
359
364
|
|
365
|
+
describe "parsing with timezone from event" do
|
366
|
+
config <<-CONFIG
|
367
|
+
filter {
|
368
|
+
date {
|
369
|
+
match => ["mydate", "yyyy MMM dd HH:mm:ss"]
|
370
|
+
locale => "en"
|
371
|
+
timezone => "%{mytz}"
|
372
|
+
}
|
373
|
+
}
|
374
|
+
CONFIG
|
375
|
+
|
376
|
+
require 'java'
|
377
|
+
times = {
|
378
|
+
"2013 Nov 24 01:29:01" => "2013-11-24T09:29:01.000Z",
|
379
|
+
"2013 Jun 24 01:29:01" => "2013-06-24T08:29:01.000Z",
|
380
|
+
}
|
381
|
+
times.each do |input, output|
|
382
|
+
sample("mydate" => input, "mytz" => "America/Los_Angeles") do
|
383
|
+
insist { subject["mydate"] } == input
|
384
|
+
insist { subject["@timestamp"].time } == Time.iso8601(output).utc
|
385
|
+
end
|
386
|
+
end # times.each
|
387
|
+
end
|
388
|
+
|
360
389
|
describe "LOGSTASH-34 - Default year should be this year" do
|
361
390
|
config <<-CONFIG
|
362
391
|
filter {
|
@@ -372,6 +401,42 @@ RUBY_ENGINE == "jruby" and describe LogStash::Filters::Date do
|
|
372
401
|
end
|
373
402
|
end
|
374
403
|
|
404
|
+
describe "fill last year if december events arrive in january" do
|
405
|
+
config <<-CONFIG
|
406
|
+
filter {
|
407
|
+
date {
|
408
|
+
match => [ "message", "MMM dd HH:mm:ss" ]
|
409
|
+
locale => "en"
|
410
|
+
timezone => "UTC"
|
411
|
+
}
|
412
|
+
}
|
413
|
+
CONFIG
|
414
|
+
|
415
|
+
sample "Dec 31 23:59:00" do
|
416
|
+
logstash_time = Time.utc(2014,1,1,00,30,50)
|
417
|
+
expect(Time).to receive(:now).at_most(:twice).and_return(logstash_time)
|
418
|
+
insist { subject["@timestamp"].year } == 2013
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
describe "fill next year if january events arrive in december" do
|
423
|
+
config <<-CONFIG
|
424
|
+
filter {
|
425
|
+
date {
|
426
|
+
match => [ "message", "MMM dd HH:mm:ss" ]
|
427
|
+
locale => "en"
|
428
|
+
timezone => "UTC"
|
429
|
+
}
|
430
|
+
}
|
431
|
+
CONFIG
|
432
|
+
|
433
|
+
sample "Jan 01 01:00:00" do
|
434
|
+
logstash_time = Time.utc(2013,12,31,23,59,50)
|
435
|
+
expect(Time).to receive(:now).at_most(:twice).and_return(logstash_time)
|
436
|
+
insist { subject["@timestamp"].year } == 2014
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
375
440
|
describe "Supporting locale only" do
|
376
441
|
config <<-CONFIG
|
377
442
|
filter {
|
metadata
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-filter-date
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
|
-
- -
|
16
|
+
- - ">="
|
17
17
|
- !ruby/object:Gem::Version
|
18
18
|
version: 2.0.0.beta2
|
19
|
-
- - <
|
19
|
+
- - "<"
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: 3.0.0
|
22
22
|
name: logstash-core
|
@@ -24,16 +24,16 @@ dependencies:
|
|
24
24
|
type: :runtime
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 2.0.0.beta2
|
30
|
-
- - <
|
30
|
+
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 3.0.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
35
35
|
requirements:
|
36
|
-
- -
|
36
|
+
- - ">="
|
37
37
|
- !ruby/object:Gem::Version
|
38
38
|
version: '0'
|
39
39
|
name: logstash-input-generator
|
@@ -41,13 +41,13 @@ dependencies:
|
|
41
41
|
type: :runtime
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
49
49
|
requirements:
|
50
|
-
- -
|
50
|
+
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: '0'
|
53
53
|
name: logstash-codec-json
|
@@ -55,13 +55,13 @@ dependencies:
|
|
55
55
|
type: :runtime
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
|
-
- -
|
58
|
+
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
requirement: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
|
-
- -
|
64
|
+
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '0'
|
67
67
|
name: logstash-output-null
|
@@ -69,13 +69,13 @@ dependencies:
|
|
69
69
|
type: :runtime
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
|
-
- -
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
|
-
- -
|
78
|
+
- - ">="
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
81
|
name: logstash-devutils
|
@@ -83,7 +83,7 @@ dependencies:
|
|
83
83
|
type: :development
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- -
|
86
|
+
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
|
@@ -113,12 +113,12 @@ require_paths:
|
|
113
113
|
- lib
|
114
114
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- -
|
116
|
+
- - ">="
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '0'
|
119
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- -
|
121
|
+
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '0'
|
124
124
|
requirements: []
|