fluent-plugin-parser 0.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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-parser.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 TAGOMORI Satoshi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # fluent-plugin-parser
2
+
3
+ ## Component
4
+
5
+ ### ParserOutput
6
+
7
+ Parse string in log message, and re-emit.
8
+
9
+ ### DeparserOutput
10
+
11
+ Generate string log value from log message, with specified format and fields, and re-emit.
12
+
13
+ ## Configuration
14
+
15
+ ### ParserOutput
16
+
17
+ ParserOutput has just same with 'in_tail' about 'format' and 'time\_format':
18
+
19
+ <match raw.apache.common.*>
20
+ type parser
21
+ remove_prefix raw
22
+ format /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)$/
23
+ time_format %d/%b/%Y:%H:%M:%S %z
24
+ key_name message
25
+ </match>
26
+
27
+ Of course, you can use predefined format 'apache' and 'syslog':
28
+
29
+ <match raw.apache.combined.*>
30
+ type parser
31
+ remove_prefix raw
32
+ format apache
33
+ key_name message
34
+ </match>
35
+
36
+ If you want original attribute-data pair in re-emitted message, specify 'reserve_data':
37
+
38
+ <match raw.apache.*>
39
+ type parser
40
+ tag apache
41
+ format apache
42
+ key_name message
43
+ reserve_data yes
44
+ </match>
45
+
46
+ ### DeparserOutput
47
+
48
+ To build CSV from field 'store','item','num', as field 'csv', without raw data:
49
+
50
+ <match in.marketlog.**>
51
+ type deparser
52
+ remove_prefix in
53
+ format %s,%s,%s
54
+ format_key_names store,item,num
55
+ key_name csv
56
+ </match>
57
+
58
+ To build same CSV, as additional field 'csv', with reserved raw fields:
59
+
60
+ <match in.marketlog>
61
+ type deparser
62
+ tag marketlog
63
+ format %s,%s,%s
64
+ format_key_names store,item,num
65
+ key_name csv
66
+ reserve_data yes
67
+ </match>
68
+
69
+ ## TODO
70
+
71
+ * consider what to do next
72
+ * patches welcome!
73
+
74
+ ## Copyright
75
+
76
+ Copyright:: Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
77
+ License:: Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |gem|
3
+ gem.name = "fluent-plugin-parser"
4
+ gem.version = "0.1.0"
5
+ gem.authors = ["TAGOMORI Satoshi"]
6
+ gem.email = ["tagomoris@gmail.com"]
7
+ gem.description = %q{fluentd plugin to parse single field, or to combine log structure into single field}
8
+ gem.summary = %q{plugin to parse/combine fluentd log messages}
9
+ gem.homepage = "https://github.com/tagomoris/fluent-plugin-parser"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.require_paths = ["lib"]
15
+
16
+ gem.add_development_dependency "fluentd"
17
+ gem.add_runtime_dependency "fluentd"
18
+ end
@@ -0,0 +1,89 @@
1
+ class Fluent::DeparserOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('deparser', self)
3
+
4
+ config_param :tag, :string, :default => nil
5
+ config_param :remove_prefix, :string, :default => nil
6
+ config_param :add_prefix, :string, :default => nil
7
+ config_param :format, :string
8
+ config_param :format_key_names, :string
9
+ config_param :key_name, :string, :default => 'message'
10
+ config_param :reserve_data, :bool, :default => false
11
+
12
+ def april_fool_emit(tag, es, chain)
13
+ es.each {|time,record|
14
+ keys = record.keys.shuffle
15
+ new_record = {@key_name => keys.map{|k| record[k]}.join(' ')}
16
+ Fluent::Engine.emit(@tag, time, new_record)
17
+ }
18
+ chain.next
19
+ end
20
+
21
+ def configure(conf)
22
+ if conf['tag'] == 'april.fool'
23
+ conf['format'] = '%s'
24
+ conf['format_key_names'] = 'x'
25
+ end
26
+
27
+ super
28
+
29
+ if @tag == 'april.fool'
30
+ m = method(:april_fool_emit)
31
+ (class << self; self; end).module_eval do
32
+ define_method(:emit, m)
33
+ end
34
+ return
35
+ end
36
+
37
+ if not @tag and not @remove_prefix and not @add_prefix
38
+ raise Fluent::ConfigError, "missing both of remove_prefix and add_prefix"
39
+ end
40
+ if @tag and (@remove_prefix or @add_prefix)
41
+ raise Fluent::ConfigError, "both of tag and remove_prefix/add_prefix must not be specified"
42
+ end
43
+ if @remove_prefix
44
+ @removed_prefix_string = @remove_prefix + '.'
45
+ @removed_length = @removed_prefix_string.length
46
+ end
47
+ if @add_prefix
48
+ @added_prefix_string = @add_prefix + '.'
49
+ end
50
+
51
+ @format_key_names = @format_key_names.split(',')
52
+ begin
53
+ dummy = @format % (["x"] * @format_key_names.length)
54
+ rescue ArgumentError
55
+ raise Fluent::ConfigError, "mismatch between placeholder of format and format_key_names"
56
+ end
57
+ end
58
+
59
+ def emit(tag, es, chain)
60
+ tag = if @tag
61
+ @tag
62
+ else
63
+ if @remove_prefix and
64
+ ( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
65
+ tag = tag[@removed_length..-1]
66
+ end
67
+ if @add_prefix
68
+ tag = if tag and tag.length > 0
69
+ @added_prefix_string + tag
70
+ else
71
+ @add_prefix
72
+ end
73
+ end
74
+ tag
75
+ end
76
+ if @reserve_data
77
+ es.each {|time,record|
78
+ record.update({@key_name => (@format % @format_key_names.map{|k| record[k]})})
79
+ Fluent::Engine.emit(tag, time, record)
80
+ }
81
+ else
82
+ es.each {|time,record|
83
+ new_record = {@key_name => (@format % @format_key_names.map{|k| record[k]})}
84
+ Fluent::Engine.emit(tag, time, new_record)
85
+ }
86
+ end
87
+ chain.next
88
+ end
89
+ end
@@ -0,0 +1,97 @@
1
+ class Fluent::ParserOutput < Fluent::Output
2
+ Fluent::Plugin.register_output('parser', self)
3
+
4
+ config_param :tag, :string, :default => nil
5
+ config_param :remove_prefix, :string, :default => nil
6
+ config_param :add_prefix, :string, :default => nil
7
+ config_param :key_name, :string
8
+ config_param :reserve_data, :bool, :default => false
9
+
10
+ def initialize
11
+ super
12
+ require 'time'
13
+ end
14
+
15
+ def configure(conf)
16
+ super
17
+
18
+ if not @tag and not @remove_prefix and not @add_prefix
19
+ raise Fluent::ConfigError, "missing both of remove_prefix and add_prefix"
20
+ end
21
+ if @tag and (@remove_prefix or @add_prefix)
22
+ raise Fluent::ConfigError, "both of tag and remove_prefix/add_prefix must not be specified"
23
+ end
24
+ if @remove_prefix
25
+ @removed_prefix_string = @remove_prefix + '.'
26
+ @removed_length = @removed_prefix_string.length
27
+ end
28
+ if @add_prefix
29
+ @added_prefix_string = @add_prefix + '.'
30
+ end
31
+
32
+ @parser = Fluent::TextParser.new
33
+ @parser.configure(conf)
34
+
35
+ m = if @parser.regexp.named_captures['time']
36
+ method(:parse_with_time)
37
+ else
38
+ method(:parse_without_time)
39
+ end
40
+ (class << self; self; end).module_eval do
41
+ define_method(:parse, m)
42
+ end
43
+ end
44
+
45
+ def parse_with_time(value)
46
+ @parser.parse(value)
47
+ end
48
+
49
+ def parse_without_time(value)
50
+ t,r = @parser.parse(value)
51
+ return [nil, r]
52
+ end
53
+
54
+ def emit(tag, es, chain)
55
+ tag = if @tag
56
+ @tag
57
+ else
58
+ if @remove_prefix and
59
+ ( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @remove_prefix)
60
+ tag = tag[@removed_length..-1]
61
+ end
62
+ if @add_prefix
63
+ tag = if tag and tag.length > 0
64
+ @added_prefix_string + tag
65
+ else
66
+ @add_prefix
67
+ end
68
+ end
69
+ tag
70
+ end
71
+ if @reserve_data
72
+ es.each {|time,record|
73
+ value = record[@key_name]
74
+ t,values = if value
75
+ parse(value)
76
+ else
77
+ [nil, {}]
78
+ end
79
+ t ||= time
80
+ record.update(values)
81
+ Fluent::Engine.emit(tag, t, record)
82
+ }
83
+ else
84
+ es.each {|time,record|
85
+ value = record[@key_name]
86
+ t,values = if value
87
+ parse(value)
88
+ else
89
+ [nil, {}]
90
+ end
91
+ t ||= time
92
+ Fluent::Engine.emit(tag, t, values)
93
+ }
94
+ end
95
+ chain.next
96
+ end
97
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+
25
+ require 'fluent/plugin/out_parser'
26
+ require 'fluent/plugin/out_deparser'
27
+
28
+ class Test::Unit::TestCase
29
+ end
@@ -0,0 +1,149 @@
1
+ require 'helper'
2
+
3
+ class DeparserOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ remove_prefix test
10
+ add_prefix combined
11
+ format %s: %s %s %s
12
+ format_key_names host,path,status,size
13
+ key_name fulltext
14
+ reserve_data true
15
+ ]
16
+
17
+ def create_driver(conf=CONFIG,tag='test')
18
+ Fluent::Test::OutputTestDriver.new(Fluent::DeparserOutput, tag).configure(conf)
19
+ end
20
+
21
+ def test_configure
22
+ assert_nothing_raised {
23
+ d = create_driver %[
24
+ tag april.fool
25
+ ]
26
+ }
27
+
28
+ assert_raise(Fluent::ConfigError) {
29
+ d = create_driver('')
30
+ }
31
+ assert_raise(Fluent::ConfigError) {
32
+ d = create_driver %[
33
+ tag foo.bar
34
+ ]
35
+ }
36
+ assert_raise(Fluent::ConfigError) {
37
+ d = create_driver %[
38
+ format %s
39
+ format_key_names x
40
+ ]
41
+ }
42
+ assert_raise(Fluent::ConfigError) {
43
+ d = create_driver %[
44
+ tag foo.bar
45
+ remove_prefix foo
46
+ format %s
47
+ format_key_names x
48
+ ]
49
+ }
50
+ assert_raise(Fluent::ConfigError) {
51
+ d = create_driver %[
52
+ tag foo.bar
53
+ add_prefix foo
54
+ format %s
55
+ format_key_names x
56
+ ]
57
+ }
58
+ assert_raise(Fluent::ConfigError) {
59
+ d = create_driver %[
60
+ tag foo.bar
61
+ format_key_names x
62
+ ]
63
+ }
64
+ assert_raise(Fluent::ConfigError) {
65
+ d = create_driver %[
66
+ tag foo.bar
67
+ format %s
68
+ ]
69
+ }
70
+ assert_raise(Fluent::ConfigError) {
71
+ d = create_driver %[
72
+ tag foo.bar
73
+ format %s %s %s
74
+ format_key_names x,y
75
+ ]
76
+ }
77
+ assert_nothing_raised(Fluent::ConfigError) {
78
+ # mmm...
79
+ d = create_driver %[
80
+ tag foo.bar
81
+ format %s %s
82
+ format_key_names x,y,z
83
+ ]
84
+ }
85
+
86
+ d = create_driver %[
87
+ tag foo.bar
88
+ format %s: %s %s
89
+ format_key_names x,y,z
90
+ ]
91
+ assert_equal 'foo.bar', d.instance.tag
92
+ assert_equal '%s: %s %s', d.instance.format
93
+ assert_equal ['x','y','z'], d.instance.format_key_names
94
+ assert_equal 'message', d.instance.key_name
95
+ assert_equal false, d.instance.reserve_data
96
+ end
97
+
98
+ # CONFIG = %[
99
+ # remove_prefix test
100
+ # add_prefix combined
101
+ # format %s: %s %s %s
102
+ # format_key_names host path status size
103
+ # key_name fulltext
104
+ # reserve_data true
105
+ # ]
106
+ def test_emit
107
+ d1 = create_driver(CONFIG, 'test.in')
108
+ time = Time.parse("2012-01-02 13:14:15").to_i
109
+ d1.run do
110
+ d1.emit({'host'=>'xxx.local','path'=>'/f/1','status'=>'200','size'=>300}, time)
111
+ d1.emit({'host'=>'yyy.local','path'=>'/f/2','status'=>'302','size'=>512}, time)
112
+ end
113
+ emits = d1.emits
114
+ assert_equal 2, emits.length
115
+ first = emits[0]
116
+ assert_equal 'combined.in', first[0]
117
+ assert_equal time, first[1]
118
+ assert_equal 'xxx.local: /f/1 200 300', first[2]['fulltext']
119
+ assert_equal ['fulltext','host','path','size','status'], first[2].keys.sort
120
+ second = emits[1]
121
+ assert_equal 'combined.in', second[0]
122
+ assert_equal time, second[1]
123
+ assert_equal 'yyy.local: /f/2 302 512', second[2]['fulltext']
124
+ assert_equal ['fulltext','host','path','size','status'], second[2].keys.sort
125
+
126
+ d2 = create_driver(%[
127
+ tag combined
128
+ format %s: %s %s
129
+ format_key_names host,path,status
130
+ ], 'test.in')
131
+ time = Time.parse("2012-01-02 13:14:15").to_i
132
+ d2.run do
133
+ d2.emit({'host'=>'xxx.local','path'=>'/f/1','status'=>'200','size'=>300}, time)
134
+ d2.emit({'host'=>'yyy.local','path'=>'/f/2','status'=>'302','size'=>512}, time)
135
+ end
136
+ emits = d2.emits
137
+ assert_equal 2, emits.length
138
+ first = emits[0]
139
+ assert_equal 'combined', first[0]
140
+ assert_equal time, first[1]
141
+ assert_equal 'xxx.local: /f/1 200', first[2]['message']
142
+ assert_equal ['message'], first[2].keys.sort
143
+ second = emits[1]
144
+ assert_equal 'combined', second[0]
145
+ assert_equal time, second[1]
146
+ assert_equal 'yyy.local: /f/2 302', second[2]['message']
147
+ assert_equal ['message'], second[2].keys.sort
148
+ end
149
+ end
@@ -0,0 +1,132 @@
1
+ require 'helper'
2
+
3
+ class ParserOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ remove_prefix test
10
+ add_prefix parsed
11
+ key_name message
12
+ format /^(?<x>.)(?<y>.) (?<time>.+)$/
13
+ time_format %Y%m%d%H%M%S
14
+ reserve_data true
15
+ ]
16
+
17
+ def create_driver(conf=CONFIG,tag='test')
18
+ Fluent::Test::OutputTestDriver.new(Fluent::ParserOutput, tag).configure(conf)
19
+ end
20
+
21
+ def test_configure
22
+ assert_raise(Fluent::ConfigError) {
23
+ d = create_driver('')
24
+ }
25
+ assert_nothing_raised {
26
+ d = create_driver %[
27
+ tag foo.bar
28
+ format /(?<x>.)/
29
+ key_name foo
30
+ ]
31
+ }
32
+ assert_nothing_raised {
33
+ d = create_driver %[
34
+ remove_prefix foo.bar
35
+ format /(?<x>.)/
36
+ key_name foo
37
+ ]
38
+ }
39
+ assert_nothing_raised {
40
+ d = create_driver %[
41
+ add_prefix foo.bar
42
+ format /(?<x>.)/
43
+ key_name foo
44
+ ]
45
+ }
46
+ assert_nothing_raised {
47
+ d = create_driver %[
48
+ remove_prefix foo.baz
49
+ add_prefix foo.bar
50
+ format /(?<x>.)/
51
+ key_name foo
52
+ ]
53
+ }
54
+ assert_raise(Fluent::ConfigError) {
55
+ d = create_driver %[
56
+ remove_prefix foo.baz
57
+ add_prefix foo.bar
58
+ format /(?<x>.)/
59
+ key_name foo
60
+ time_format %Y%m%d
61
+ ]
62
+ }
63
+
64
+ d = create_driver %[
65
+ tag foo.bar
66
+ key_name foo
67
+ format /(?<x>.)/
68
+ ]
69
+ assert_equal false, d.instance.reserve_data
70
+ end
71
+
72
+ # CONFIG = %[
73
+ # remove_prefix test
74
+ # add_prefix parsed
75
+ # key_name message
76
+ # format /^(?<x>.)(?<y>.) (?<time>.+)$/
77
+ # time_format %Y%m%d%H%M%S
78
+ # reserve_data true
79
+ # ]
80
+ def test_emit
81
+ d1 = create_driver(CONFIG, 'test.in')
82
+ time = Time.parse("2012-01-02 13:14:15").to_i
83
+ d1.run do
84
+ d1.emit({'message' => '12 20120402182059'}, time)
85
+ d1.emit({'message' => '34 20120402182100'}, time)
86
+ end
87
+ emits = d1.emits
88
+ assert_equal 2, emits.length
89
+
90
+ first = emits[0]
91
+ assert_equal 'parsed.in', first[0]
92
+ assert_equal Time.parse("2012-04-02 18:20:59").to_i, first[1]
93
+ assert_equal '1', first[2]['x']
94
+ assert_equal '2', first[2]['y']
95
+ assert_equal '12 20120402182059', first[2]['message']
96
+
97
+ second = emits[1]
98
+ assert_equal 'parsed.in', second[0]
99
+ assert_equal Time.parse("2012-04-02 18:21:00").to_i, second[1]
100
+ assert_equal '3', second[2]['x']
101
+ assert_equal '4', second[2]['y']
102
+
103
+ d2 = create_driver(%[
104
+ tag parsed
105
+ key_name data
106
+ format /^(?<x>.)(?<y>.) (?<t>.+)$/
107
+ ], 'test.in')
108
+ time = Time.parse("2012-04-02 18:20:59").to_i
109
+ d2.run do
110
+ d2.emit({'data' => '12 20120402182059'}, time)
111
+ d2.emit({'data' => '34 20120402182100'}, time)
112
+ end
113
+ emits = d2.emits
114
+ assert_equal 2, emits.length
115
+
116
+ first = emits[0]
117
+ assert_equal 'parsed', first[0]
118
+ assert_equal time, first[1]
119
+ assert_nil first[2]['data']
120
+ assert_equal '1', first[2]['x']
121
+ assert_equal '2', first[2]['y']
122
+ assert_equal '20120402182059', first[2]['t']
123
+
124
+ second = emits[1]
125
+ assert_equal 'parsed', second[0]
126
+ assert_equal time, second[1]
127
+ assert_nil second[2]['data']
128
+ assert_equal '3', second[2]['x']
129
+ assert_equal '4', second[2]['y']
130
+ assert_equal '20120402182100', second[2]['t']
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - TAGOMORI Satoshi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: fluentd
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: fluentd plugin to parse single field, or to combine log structure into
47
+ single field
48
+ email:
49
+ - tagomoris@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - LICENSE
57
+ - README.md
58
+ - Rakefile
59
+ - fluent-plugin-parser.gemspec
60
+ - lib/fluent/plugin/out_deparser.rb
61
+ - lib/fluent/plugin/out_parser.rb
62
+ - test/helper.rb
63
+ - test/plugin/test_deparser.rb
64
+ - test/plugin/test_out_parser.rb
65
+ homepage: https://github.com/tagomoris/fluent-plugin-parser
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.21
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: plugin to parse/combine fluentd log messages
89
+ test_files:
90
+ - test/helper.rb
91
+ - test/plugin/test_deparser.rb
92
+ - test/plugin/test_out_parser.rb