Skip to content

Commit bec8e58

Browse files
authored
Merge pull request #74 from fluent/support-timezone
Support timezone
2 parents 0d38c38 + 0bb4d23 commit bec8e58

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ You can use this parser without `multiline_start_regexp` when you know your data
104104
* **grok_name_key** (string) (optional): The key name to store grok section's name
105105
* **multi_line_start_regexp** (string) (optional): The regexp to match beginning of multiline. This is only for "multiline_grok".
106106

107+
### \<grok\> section (optional) (multiple)
108+
109+
* **name** (string) (optional): The name of this grok section
110+
* **pattern** (string) (required): The pattern of grok
111+
* **keep_time_key** (bool) (optional): If true, keep time field in the record.
112+
* **time_key** (string) (optional): Specify time field for event time. If the event doesn't have this field, current time is used.
113+
* Default value: `time`.
114+
* **time_format** (string) (optional): Process value using specified format. This is available only when time_type is string
115+
* **timezone** (string) (optional): Use specified timezone. one can parse/format the time value in the specified timezone.
116+
117+
107118
## Examples
108119

109120
### Using grok\_failure\_key
@@ -183,6 +194,28 @@ This will add keys like following:
183194
Add `grokfailure` key to the record if the record does not match any grok pattern.
184195
See also test code for more details.
185196

197+
## How to parse time value using specific timezone
198+
199+
```aconf
200+
<source>
201+
@type tail
202+
path /path/to/log
203+
tag grokked_log
204+
<parse>
205+
@type grok
206+
<grok>
207+
name mylog-without-timezone
208+
pattern %{DATESTAMP:time} %{GREEDYDATE:message}
209+
timezone Asia/Tokyo
210+
</grok>
211+
</parse>
212+
</source>
213+
```
214+
215+
This will parse the `time` value as "Asia/Tokyo" timezone.
216+
217+
See [Config: Parse Section - Fluentd](https://docs.fluentd.org/configuration/parse-section) for more details about timezone.
218+
186219
## How to write Grok patterns
187220

188221
Grok patterns look like `%{PATTERN_NAME:name}` where ":name" is optional. If "name" is provided, then it

lib/fluent/plugin/grok.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ def initialize(plugin, conf)
2727
@multiline_mode = false
2828
@conf = conf
2929
@plugin = plugin
30+
@time_format = nil
31+
@timezone = nil
3032
if @plugin.respond_to?(:firstline?)
3133
@multiline_mode = true
3234
end
@@ -39,6 +41,9 @@ def initialize(plugin, conf)
3941
if @plugin.respond_to?(:time_format)
4042
@time_format = @plugin.time_format
4143
end
44+
if @plugin.respond_to?(:timezone)
45+
@timezone = @plugin.timezone
46+
end
4247
end
4348

4449
def add_patterns_from_file(path)
@@ -105,6 +110,9 @@ def expand_pattern_expression_grok_section(conf)
105110
if conf["time_format"] || @time_format
106111
_conf["time_format"] = conf["time_format"] || @time_format
107112
end
113+
if conf["timezone"] || @timezone
114+
_conf["timezone"] = conf["timezone"] || @timezone
115+
end
108116
_conf["expression"] = regexp
109117
config = Fluent::Config::Element.new("parse", "", _conf, [])
110118
parser = Fluent::Plugin::RegexpParser.new

lib/fluent/plugin/parser_grok.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ class GrokParser < Parser
2222
config_param :name, :string, default: nil
2323
desc "The pattern of grok"
2424
config_param :pattern, :string
25+
desc "If true, keep time field in the record."
2526
config_param :keep_time_key, :bool, default: false
27+
desc "Specify time field for event time. If the event doesn't have this field, current time is used."
2628
config_param :time_key, :string, default: "time"
29+
desc "Process value using specified format. This is available only when time_type is string"
2730
config_param :time_format, :string, default: nil
31+
desc "Use specified timezone. one can parse/format the time value in the specified timezone."
32+
config_param :timezone, :string, default: nil
2833
end
2934

3035
def initialize

test/test_grok_parser.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,46 @@ class GrokParserTest < ::Test::Unit::TestCase
374374
assert_equal(expected_record, record)
375375
end
376376
end
377+
378+
test "timezone" do
379+
d = create_driver(%[
380+
<grok>
381+
pattern %{TIMESTAMP_ISO8601:time} %{GREEDYDATA:message}
382+
time_key time
383+
time_format %Y-%m-%d %H:%M:%S
384+
timezone Europe/Berlin
385+
</grok>
386+
])
387+
d.instance.parse("2019-02-01 12:34:56 This is test") do |time, record|
388+
assert_equal(event_time("2019-02-01 12:34:56 +0100"), time)
389+
assert_equal({ "message" => "This is test" }, record)
390+
end
391+
end
392+
393+
test "multiple timezone" do
394+
d = create_driver(%[
395+
<grok>
396+
pattern %{TIMESTAMP_ISO8601:time} 1 %{GREEDYDATA:message}
397+
time_key time
398+
time_format %Y-%m-%d %H:%M:%S
399+
timezone Europe/Berlin
400+
</grok>
401+
<grok>
402+
pattern %{TIMESTAMP_ISO8601:time} 2 %{GREEDYDATA:message}
403+
time_key time
404+
time_format %Y-%m-%d %H:%M:%S
405+
timezone Asia/Aden
406+
</grok>
407+
])
408+
d.instance.parse("2019-02-01 12:34:56 1 This is test") do |time, record|
409+
assert_equal(event_time("2019-02-01 12:34:56 +0100"), time)
410+
assert_equal({ "message" => "This is test" }, record)
411+
end
412+
d.instance.parse("2019-02-01 12:34:56 2 This is test") do |time, record|
413+
assert_equal(event_time("2019-02-01 12:34:56 +0300"), time)
414+
assert_equal({ "message" => "This is test" }, record)
415+
end
416+
end
377417
end
378418

379419
private

0 commit comments

Comments
 (0)