fluent-plugin-grok-parser 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a517f65e8155156ff9151628ddead36b679d3105
4
- data.tar.gz: 7a034a4e0b8d28234ba30612bcf7fd205aa3fbb3
3
+ metadata.gz: 74360bb48589acb735b21ef7fc33da8e1e8ea1d5
4
+ data.tar.gz: 6f0b32cff96d5f45fbea166e819132f262c204da
5
5
  SHA512:
6
- metadata.gz: a16eb5eff0997a710e4dcb7d92ec60ebea27d151d8a85b61c7b7230f4579aeabaf3f54c42d0789f564d579c14eb25c4adbb5c9af0e2527336b9d3e6cb030527b
7
- data.tar.gz: 65b1cef569bcf821cdee87dc322088448cc5dfd6fdff08bb4fe9330867e2094a4e848fe660b41d7302b8cc682c537d7d458286083d3566783d04b152c4db5723
6
+ metadata.gz: af2ee3177353159e23af8d67561294c30b3ac97f7c99ad92e197670689a836c7b029568bf48450782536bc3f59c0a5ab59300a9e4fba11acfb2c29528a669c0c
7
+ data.tar.gz: 812f3f366210ceda6deec4af94c4da8cc4e401d664cacd6a6e3927b43f55ec30ce6b60be46ef7e8a035f2890c43a59f1b7e54b6492a0d8135a8eab77576368b1
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1
6
+ - 2.2
7
+
data/README.md CHANGED
@@ -44,6 +44,40 @@ extracts the first IP address that matches in the log.
44
44
  </source>
45
45
  ```
46
46
 
47
+ ### Multiline support
48
+
49
+ You can parse multiple line text.
50
+
51
+ ```aconf
52
+ <source>
53
+ type tail
54
+ path /path/to/log
55
+ format multiline_grok
56
+ grok_pattern %{IP:ip_address}\n%{GREEDYDATA:message}
57
+ multiline_start_regex /^\s/
58
+ tag grokked_log
59
+ </source>
60
+ ```
61
+
62
+ You can use multiple grok patterns to parse your data.
63
+
64
+ ```aconf
65
+ <source>
66
+ type tail
67
+ path /path/to/log
68
+ format multiline_grok
69
+ <grok>
70
+ pattern Started %{WORD:verb} "%{URIPATH:pathinfo}" for %{IP:ip} at %{TIMESTAMP_ISO8601:timestamp}\nProcessing by %{WORD:controller}#%{WORD:action} as %{WORD:format}%{DATA:message}Completed %{NUMBER:response} %{WORD} in %{NUMBER:elapsed} (%{DATA:elapsed_details})
71
+ </grok>
72
+ tag grokked_log
73
+ </source>
74
+ ```
75
+
76
+ Fluentd accumulates data in the buffer forever to parse complete data when no pattern matches.
77
+
78
+ You can use this parser without `multiline_start_regex` when you know your data structure perfectly.
79
+
80
+
47
81
  ## How to write Grok patterns
48
82
 
49
83
  Grok patterns look like `%{PATTERN_NAME:name}` where ":name" is optional. If "name" is provided, then it
@@ -80,6 +114,54 @@ This is what the `custom_pattern_path` parameter is for.
80
114
 
81
115
  `custom_pattern_path` can be either a directory or file. If it's a directory, it reads all the files in it.
82
116
 
117
+ ## FAQs
118
+
119
+ ### 1. How can I convert types of the matched patterns like Logstash's Grok?
120
+
121
+ Although every parsed field has type `string` by default, you can specify other types. This is useful when filtering particular fields numerically or storing data with sensible type information.
122
+
123
+ The syntax is
124
+
125
+ ```
126
+ types <field_name_1>:<type_name_1>,<field_name_2>:<type_name_2>,...
127
+ ```
128
+
129
+ e.g.,
130
+
131
+ ```
132
+ types user_id:integer,paid:bool,paid_usd_amount:float
133
+ ```
134
+
135
+ As demonstrated above, "," is used to delimit field-type pairs while ":" is used to separate a field name with its intended type.
136
+
137
+ Unspecified fields are parsed at the default string type.
138
+
139
+ The list of supported types are shown below:
140
+
141
+ * `string`
142
+ * `bool`
143
+ * `integer` ("int" would NOT work!)
144
+ * `float`
145
+ * `time`
146
+ * `array`
147
+
148
+ For the `time` and `array` types, there is an optional third field after the type name. For the "time" type, you can specify a time format like you would in `time_format`.
149
+
150
+ For the "array" type, the third field specifies the delimiter (the default is ","). For example, if a field called "item\_ids" contains the value "3,4,5", `types item_ids:array` parses it as ["3", "4", "5"]. Alternatively, if the value is "Adam|Alice|Bob", `types item_ids:array:|` parses it as ["Adam", "Alice", "Bob"].
151
+
152
+ Here is a sample config using the Grok parser with `in_tail` and the `types` parameter:
153
+
154
+ ```aconf
155
+ <source>
156
+ type tail
157
+ path /path/to/log
158
+ format grok
159
+ grok_pattern %{INT:user_id} paid %{NUMBER:paid_amount}
160
+ types user_id:integer,paid_amount:float
161
+ tag payment
162
+ </source>
163
+ ```
164
+
83
165
  ## License
84
166
 
85
167
  Apache 2.0 License
@@ -4,12 +4,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fluent-plugin-grok-parser"
7
- spec.version = "0.0.2"
7
+ spec.version = "0.0.3"
8
8
  spec.authors = ["kiyoto"]
9
9
  spec.email = ["kiyoto@treasure-data.com"]
10
- spec.summary = %q{Fluentd plugin to suppor Logstash-inspired Grok format for parsing logs}
10
+ spec.summary = %q{Fluentd plugin to support Logstash-inspired Grok format for parsing logs}
11
11
  spec.homepage = "https://github.com/kiyoto/fluent-plugin-grok-parser"
12
- spec.license = "Apache License, Version 2.0"
12
+ spec.license = "Apache-2.0"
13
13
 
14
14
  spec.files = `git ls-files`.split($/)
15
15
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
@@ -18,5 +18,6 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_development_dependency "bundler"
20
20
  spec.add_development_dependency "rake"
21
+ spec.add_development_dependency "test-unit", ">=3.1.5"
21
22
  spec.add_runtime_dependency "fluentd", ">=0.10.58"
22
23
  end
@@ -0,0 +1,84 @@
1
+ module Fluent
2
+ class Grok
3
+ class GrokPatternNotFoundError < StandardError
4
+ end
5
+
6
+ # Much of the Grok implementation is based on Jordan Sissel's jls-grok
7
+ # See https://github.com/jordansissel/ruby-grok/blob/master/lib/grok-pure.rb
8
+ PATTERN_RE = \
9
+ /%\{ # match '%{' not prefixed with '\'
10
+ (?<name> # match the pattern name
11
+ (?<pattern>[A-z0-9]+)
12
+ (?::(?<subname>[@\[\]A-z0-9_:.-]+))?
13
+ )
14
+ \}/x
15
+
16
+ attr_reader :parsers
17
+
18
+ def initialize(plugin, conf)
19
+ @pattern_map = {}
20
+ @parsers = []
21
+ @multiline_mode = false
22
+ @conf = conf
23
+ if plugin.instance_of?(Fluent::TextParser::MultilineGrokParser)
24
+ @multiline_mode = true
25
+ end
26
+ if @conf['multiline_start_regexp']
27
+ @multiline_start_regexp = Regexp.compile(@conf['multiline_start_regexp'][1..-2])
28
+ end
29
+ end
30
+
31
+ def add_patterns_from_file(path)
32
+ File.new(path).each_line do |line|
33
+ next if line[0] == '#' || /^$/ =~ line
34
+ name, pat = line.chomp.split(/\s+/, 2)
35
+ @pattern_map[name] = pat
36
+ end
37
+ end
38
+
39
+ def setup
40
+ if @conf['grok_pattern']
41
+ @parsers << expand_pattern_expression(@conf['grok_pattern'], @conf)
42
+ else
43
+ grok_confs = @conf.elements.select {|e| e.name == 'grok'}
44
+ grok_confs.each do |grok_conf|
45
+ @parsers << expand_pattern_expression(grok_conf['pattern'], grok_conf)
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def expand_pattern_expression(grok_pattern, conf)
53
+ regexp = expand_pattern(grok_pattern)
54
+ $log.info "Expanded the pattern #{conf['grok_pattern']} into #{regexp}"
55
+ options = nil
56
+ if @multiline_mode
57
+ options = Regexp::MULTILINE
58
+ end
59
+ TextParser::RegexpParser.new(Regexp.new(regexp, options), conf)
60
+ rescue GrokPatternNotFoundError => e
61
+ raise e
62
+ rescue => e
63
+ $log.error e.backtrace.join("\n")
64
+ end
65
+
66
+ def expand_pattern(pattern)
67
+ # It's okay to modify in place. no need to expand it more than once.
68
+ while true
69
+ m = PATTERN_RE.match(pattern)
70
+ break unless m
71
+ curr_pattern = @pattern_map[m["pattern"]]
72
+ raise GrokPatternNotFoundError unless curr_pattern
73
+ replacement_pattern = if m["subname"]
74
+ "(?<#{m["subname"]}>#{curr_pattern})"
75
+ else
76
+ curr_pattern
77
+ end
78
+ pattern.sub!(m[0]) do |s| replacement_pattern end
79
+ end
80
+
81
+ pattern
82
+ end
83
+ end
84
+ end
@@ -1,3 +1,5 @@
1
+ require "fluent/plugin/grok"
2
+
1
3
  module Fluent
2
4
  class TextParser
3
5
  class GrokPatternNotFoundError < Exception; end
@@ -8,87 +10,37 @@ module Fluent
8
10
  config_param :grok_pattern, :string, :default => nil
9
11
  config_param :custom_pattern_path, :string, :default => nil
10
12
 
11
- # Much of the Grok implementation is based on Jordan Sissel's jls-grok
12
- # See https://github.com/jordansissel/ruby-grok/blob/master/lib/grok-pure.rb
13
- PATTERN_RE = \
14
- /%\{ # match '%{' not prefixed with '\'
15
- (?<name> # match the pattern name
16
- (?<pattern>[A-z0-9]+)
17
- (?::(?<subname>[@\[\]A-z0-9_:.-]+))?
18
- )
19
- \}/x
20
-
21
13
  def initialize
22
14
  super
23
- @pattern_map = {}
24
- default_pattern_dir = File.expand_path('../../../../patterns/*', __FILE__)
25
- Dir.glob(default_pattern_dir) do |pattern_file_path|
26
- add_patterns_from_file(pattern_file_path)
27
- end
28
15
  @default_parser = NoneParser.new
29
- @parsers = []
30
16
  end
31
17
 
32
18
  def configure(conf={})
33
19
  super
34
20
 
21
+ @grok = Grok.new(self, conf)
22
+
23
+ default_pattern_dir = File.expand_path('../../../../patterns/*', __FILE__)
24
+ Dir.glob(default_pattern_dir) do |pattern_file_path|
25
+ @grok.add_patterns_from_file(pattern_file_path)
26
+ end
27
+
35
28
  if @custom_pattern_path
36
29
  if Dir.exists? @custom_pattern_path
37
30
  Dir.glob(@custom_pattern_path + '/*') do |pattern_file_path|
38
- add_patterns_from_file(pattern_file_path)
31
+ @grok.add_patterns_from_file(pattern_file_path)
39
32
  end
40
33
  elsif File.exists? @custom_pattern_path
41
- add_patterns_from_file(@custom_pattern_path)
34
+ @grok.add_patterns_from_file(@custom_pattern_path)
42
35
  end
43
36
  end
44
37
 
45
- if @grok_pattern
46
- @parsers = [expand_pattern_exn(@grok_pattern, conf)]
47
- else
48
- grok_confs = conf.elements.select {|e| e.name == 'grok'}
49
- grok_confs.each do |grok_conf|
50
- @parsers << expand_pattern_exn(grok_conf['pattern'], grok_conf)
51
- end
52
- end
53
- end
54
-
55
- def add_patterns_from_file(path)
56
- File.new(path).each_line do |line|
57
- next if line[0] == '#' || /^$/ =~ line
58
- name, pat = line.chomp.split(/\s+/, 2)
59
- @pattern_map[name] = pat
60
- end
61
- end
62
-
63
- def expand_pattern_exn(pattern, conf)
64
- regexp = expand_pattern(pattern)
65
- $log.info "Expanded the pattern #{conf['grok_pattern']} into #{regexp}"
66
- RegexpParser.new(Regexp.new(regexp), conf)
67
- rescue => e
68
- $log.error e.backtrace.join("\n")
69
- end
70
-
71
- def expand_pattern(pattern)
72
- # It's okay to modify in place. no need to expand it more than once.
73
- while true
74
- m = PATTERN_RE.match(pattern)
75
- break if not m
76
- curr_pattern = @pattern_map[m["pattern"]]
77
- raise GrokPatternNotFoundError if not curr_pattern
78
- replacement_pattern = if m["subname"]
79
- "(?<#{m["subname"]}>#{curr_pattern})"
80
- else
81
- curr_pattern
82
- end
83
- pattern.sub!(m[0]) do |s| replacement_pattern end
84
- end
85
-
86
- pattern
38
+ @grok.setup
87
39
  end
88
40
 
89
- def parse(text)
41
+ def parse(text, &block)
90
42
  if block_given?
91
- @parsers.each do |parser|
43
+ @grok.parsers.each do |parser|
92
44
  parser.parse(text) do |time, record|
93
45
  if time and record
94
46
  yield time, record
@@ -98,7 +50,7 @@ module Fluent
98
50
  end
99
51
  yield @default_parser.parse(text)
100
52
  else
101
- @parsers.each do |parser|
53
+ @grok.parsers.each do |parser|
102
54
  parser.parse(text) do |time, record|
103
55
  if time and record
104
56
  return time, record
@@ -0,0 +1,48 @@
1
+ require 'fluent/plugin/parser_grok'
2
+
3
+ module Fluent
4
+ class TextParser
5
+ class MultilineGrokParser < GrokParser
6
+ Plugin.register_parser('multiline_grok', self)
7
+ config_param :multiline_start_regexp, :string, :default => nil
8
+
9
+
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ def configure(conf={})
15
+ super
16
+ end
17
+
18
+ def has_firstline?
19
+ !!@multiline_start_regexp
20
+ end
21
+
22
+ def firstline?(text)
23
+ @multiline_start_regexp && !@multiline_start_regexp.match(text)
24
+ end
25
+
26
+ def parse(text, &block)
27
+ if block_given?
28
+ @grok.parsers.each do |parser|
29
+ parser.parse(text) do |time, record|
30
+ if time and record
31
+ yield time, record
32
+ return
33
+ end
34
+ end
35
+ end
36
+ else
37
+ @grok.parsers.each do |parser|
38
+ parser.parse(text) do |time, record|
39
+ if time and record
40
+ return time, record
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+
2
+ def unused_port
3
+ s = TCPServer.open(0)
4
+ port = s.addr[1]
5
+ s.close
6
+ port
7
+ end
8
+
9
+ def ipv6_enabled?
10
+ require 'socket'
11
+
12
+ begin
13
+ TCPServer.open("::1", 0)
14
+ true
15
+ rescue
16
+ false
17
+ end
18
+ end
@@ -15,22 +15,6 @@ def str2time(str_time, format = nil)
15
15
  end
16
16
 
17
17
  class GrokParserTest < ::Test::Unit::TestCase
18
- def internal_test_grok_pattern(grok_pattern, text, expected_time, expected_record, options = {})
19
- parser = TextParser::GrokParser.new
20
- parser.configure({"grok_pattern" => grok_pattern}.merge(options))
21
-
22
- # for the old, return based API
23
- time, record = parser.parse(text)
24
- assert_equal(expected_time, time) if expected_time
25
- assert_equal(expected_record, record)
26
-
27
- # for the new API
28
- parser.parse(text) {|time, record|
29
- assert_equal(expected_time, time) if expected_time
30
- assert_equal(expected_record, record)
31
- }
32
- end
33
-
34
18
  def test_call_for_timestamp
35
19
  internal_test_grok_pattern('%{TIMESTAMP_ISO8601:time}', 'Some stuff at 2014-01-01T00:00:00+0900',
36
20
  str2time('2014-01-01T00:00:00+0900'), {})
@@ -43,7 +27,7 @@ class GrokParserTest < ::Test::Unit::TestCase
43
27
  end
44
28
 
45
29
  def test_call_for_grok_pattern_not_found
46
- assert_raise TextParser::GrokPatternNotFoundError do
30
+ assert_raise Grok::GrokPatternNotFoundError do
47
31
  internal_test_grok_pattern('%{THIS_PATTERN_DOESNT_EXIST}', 'Some stuff at somewhere', nil, {})
48
32
  end
49
33
  end
@@ -85,4 +69,22 @@ class GrokParserTest < ::Test::Unit::TestCase
85
69
  File.delete(pattern_file.path)
86
70
  end
87
71
  end
72
+
73
+ private
74
+
75
+ def internal_test_grok_pattern(grok_pattern, text, expected_time, expected_record, options = {})
76
+ parser = TextParser::GrokParser.new
77
+ parser.configure(Config::Element.new('ROOT', '', {"grok_pattern" => grok_pattern}.merge(options), []))
78
+
79
+ # for the old, return based API
80
+ time, record = parser.parse(text)
81
+ assert_equal(expected_time, time) if expected_time
82
+ assert_equal(expected_record, record)
83
+
84
+ # for the new API
85
+ parser.parse(text) {|time, record|
86
+ assert_equal(expected_time, time) if expected_time
87
+ assert_equal(expected_record, record)
88
+ }
89
+ end
88
90
  end
@@ -0,0 +1,60 @@
1
+ require 'fluent/plugin/parser_multiline_grok'
2
+ require 'fluent/config/parser'
3
+
4
+ require 'stringio'
5
+
6
+ class MultilineGrokParserTest < Test::Unit::TestCase
7
+ def test_multiline
8
+ text=<<TEXT.chomp
9
+ host1 message1
10
+ message2
11
+ message3
12
+ TEXT
13
+ message =<<MESSAGE.chomp
14
+ message1
15
+ message2
16
+ message3
17
+ MESSAGE
18
+ conf = %[
19
+ grok_pattern %{HOSTNAME:hostname} %{GREEDYDATA:message}
20
+ multiline_start_regexp /^\s/
21
+ ]
22
+ parser = create_parser(conf)
23
+
24
+ parser.parse(text) do |time, record|
25
+ assert_equal({ "hostname" => "host1", "message" => message }, record)
26
+ end
27
+ end
28
+
29
+ def test_without_multiline_start_regexp
30
+ text = <<TEXT.chomp
31
+ host1 message1
32
+ message2
33
+ message3
34
+ end
35
+ TEXT
36
+ conf = %[
37
+ grok_pattern %{HOSTNAME:hostname} %{DATA:message1}\\n %{DATA:message2}\\n %{DATA:message3}\\nend
38
+ ]
39
+ parser = create_parser(conf)
40
+
41
+ expected = {
42
+ "hostname" => "host1",
43
+ "message1" => "message1",
44
+ "message2" => "message2",
45
+ "message3" => "message3"
46
+ }
47
+ parser.parse(text) do |time, record|
48
+ assert_equal(expected, record)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def create_parser(conf)
55
+ parser = TextParser::MultilineGrokParser.new
56
+ io = StringIO.new(conf)
57
+ parser.configure(Config::Parser.parse(io, "fluent.conf"))
58
+ parser
59
+ end
60
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-grok-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - kiyoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-22 00:00:00.000000000 Z
11
+ date: 2015-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.5
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.5
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: fluentd
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -59,20 +73,24 @@ executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
76
+ - ".travis.yml"
62
77
  - Gemfile
63
- - Gemfile.lock
64
78
  - LICENSE
65
79
  - README.md
66
80
  - Rakefile
67
81
  - fluent-plugin-grok-parser.gemspec
82
+ - lib/fluent/plugin/grok.rb
68
83
  - lib/fluent/plugin/parser_grok.rb
84
+ - lib/fluent/plugin/parser_multiline_grok.rb
69
85
  - patterns/grok-patterns
70
86
  - patterns/nagios
87
+ - test/helper.rb
71
88
  - test/test_grok_parser.rb
72
89
  - test/test_grok_parser_in_tcp.rb
90
+ - test/test_multiline_grok_parser.rb
73
91
  homepage: https://github.com/kiyoto/fluent-plugin-grok-parser
74
92
  licenses:
75
- - Apache License, Version 2.0
93
+ - Apache-2.0
76
94
  metadata: {}
77
95
  post_install_message:
78
96
  rdoc_options: []
@@ -90,10 +108,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
108
  version: '0'
91
109
  requirements: []
92
110
  rubyforge_project:
93
- rubygems_version: 2.2.2
111
+ rubygems_version: 2.4.5.1
94
112
  signing_key:
95
113
  specification_version: 4
96
- summary: Fluentd plugin to suppor Logstash-inspired Grok format for parsing logs
114
+ summary: Fluentd plugin to support Logstash-inspired Grok format for parsing logs
97
115
  test_files:
116
+ - test/helper.rb
98
117
  - test/test_grok_parser.rb
99
118
  - test/test_grok_parser_in_tcp.rb
119
+ - test/test_multiline_grok_parser.rb
data/Gemfile.lock DELETED
@@ -1,40 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- fluent-plugin-grok-parser (0.0.2)
5
- fluentd (>= 0.10.58)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- cool.io (1.2.4)
11
- fluentd (0.12.1)
12
- cool.io (>= 1.2.2, < 2.0.0)
13
- http_parser.rb (>= 0.5.1, < 0.7.0)
14
- json (>= 1.4.3)
15
- msgpack (>= 0.5.4, < 0.6.0)
16
- sigdump (~> 0.2.2)
17
- string-scrub (>= 0.0.3)
18
- tzinfo (>= 1.0.0)
19
- tzinfo-data (>= 1.0.0)
20
- yajl-ruby (~> 1.0)
21
- http_parser.rb (0.6.0)
22
- json (1.8.1)
23
- msgpack (0.5.9)
24
- rake (10.1.1)
25
- sigdump (0.2.2)
26
- string-scrub (0.0.5)
27
- thread_safe (0.3.4)
28
- tzinfo (1.2.2)
29
- thread_safe (~> 0.1)
30
- tzinfo-data (1.2014.10)
31
- tzinfo (>= 1.0.0)
32
- yajl-ruby (1.2.1)
33
-
34
- PLATFORMS
35
- ruby
36
-
37
- DEPENDENCIES
38
- bundler
39
- fluent-plugin-grok-parser!
40
- rake