fluent-plugin-parser 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012- TAGOMORI Satoshi
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |gem|
3
3
  gem.name = "fluent-plugin-parser"
4
- gem.version = "0.1.0"
4
+ gem.version = "0.1.1"
5
5
  gem.authors = ["TAGOMORI Satoshi"]
6
6
  gem.email = ["tagomoris@gmail.com"]
7
7
  gem.description = %q{fluentd plugin to parse single field, or to combine log structure into single field}
@@ -13,6 +13,7 @@ Gem::Specification.new do |gem|
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
14
  gem.require_paths = ["lib"]
15
15
 
16
+ gem.add_development_dependency "rake"
16
17
  gem.add_development_dependency "fluentd"
17
18
  gem.add_runtime_dependency "fluentd"
18
19
  end
@@ -0,0 +1,136 @@
1
+ #
2
+ # This module is copied from fluentd/lib/fluent/parser.rb and
3
+ # fixed not to overwrite 'time' (reserve nil) when time not found in parsed string.
4
+ module FluentExt; end
5
+
6
+ class FluentExt::TextParser
7
+ class RegexpParser
8
+ include Fluent::Configurable
9
+
10
+ config_param :time_format, :string, :default => nil
11
+
12
+ def initialize(regexp, conf={})
13
+ super()
14
+ @regexp = regexp
15
+ unless conf.empty?
16
+ configure(conf)
17
+ end
18
+ end
19
+
20
+ def call(text)
21
+ m = @regexp.match(text)
22
+ unless m
23
+ $log.debug "pattern not match: #{text}"
24
+ # TODO?
25
+ return nil, nil
26
+ end
27
+
28
+ time = nil
29
+ record = {}
30
+
31
+ m.names.each {|name|
32
+ if value = m[name]
33
+ case name
34
+ when "time"
35
+ if @time_format
36
+ time = Time.strptime(value, @time_format).to_i
37
+ else
38
+ time = Time.parse(value).to_i
39
+ end
40
+ else
41
+ record[name] = value
42
+ end
43
+ end
44
+ }
45
+
46
+ return time, record
47
+ end
48
+ end
49
+
50
+ class JSONParser
51
+ include Fluent::Configurable
52
+
53
+ config_param :time_key, :string, :default => 'time'
54
+ config_param :time_format, :string, :default => nil
55
+
56
+ def call(text)
57
+ record = Yajl.load(text)
58
+
59
+ time = nil
60
+
61
+ if value = record.delete(@time_key)
62
+ if @time_format
63
+ time = Time.strptime(value, @time_format).to_i
64
+ else
65
+ time = value.to_i
66
+ end
67
+ end
68
+
69
+ return time, record
70
+ end
71
+ end
72
+
73
+ TEMPLATES = {
74
+ 'apache' => RegexpParser.new(/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/, {'time_format'=>"%d/%b/%Y:%H:%M:%S %z"}),
75
+ 'syslog' => RegexpParser.new(/^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/, {'time_format'=>"%b %d %H:%M:%S"}),
76
+ 'json' => JSONParser.new,
77
+ }
78
+
79
+ def self.register_template(name, regexp_or_proc, time_format=nil)
80
+ if regexp_or_proc.is_a?(Regexp)
81
+ pr = regexp_or_proc
82
+ else
83
+ regexp = regexp_or_proc
84
+ pr = RegexpParser.new(regexp, {'time_format'=>time_format})
85
+ end
86
+
87
+ TEMPLATES[name] = pr
88
+ end
89
+
90
+ def initialize
91
+ @parser = nil
92
+ end
93
+
94
+ def configure(conf, required=true)
95
+ format = conf['format']
96
+
97
+ if format == nil
98
+ if required
99
+ raise Fluent::ConfigError, "'format' parameter is required"
100
+ else
101
+ return nil
102
+ end
103
+ end
104
+
105
+ if format[0] == ?/ && format[format.length-1] == ?/
106
+ # regexp
107
+ begin
108
+ regexp = Regexp.new(format[1..-2])
109
+ if regexp.named_captures.empty?
110
+ raise "No named captures"
111
+ end
112
+ rescue
113
+ raise Fluent::ConfigError, "Invalid regexp '#{format[1..-2]}': #{$!}"
114
+ end
115
+
116
+ @parser = RegexpParser.new(regexp)
117
+
118
+ else
119
+ # built-in template
120
+ @parser = TEMPLATES[format]
121
+ unless @parser
122
+ raise ConfigError, "Unknown format template '#{format}'"
123
+ end
124
+ end
125
+
126
+ if @parser.respond_to?(:configure)
127
+ @parser.configure(conf)
128
+ end
129
+
130
+ return true
131
+ end
132
+
133
+ def parse(text)
134
+ return @parser.call(text)
135
+ end
136
+ end
@@ -1,3 +1,5 @@
1
+ require_relative './fixed_parser'
2
+
1
3
  class Fluent::ParserOutput < Fluent::Output
2
4
  Fluent::Plugin.register_output('parser', self)
3
5
 
@@ -29,26 +31,8 @@ class Fluent::ParserOutput < Fluent::Output
29
31
  @added_prefix_string = @add_prefix + '.'
30
32
  end
31
33
 
32
- @parser = Fluent::TextParser.new
34
+ @parser = FluentExt::TextParser.new
33
35
  @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
36
  end
53
37
 
54
38
  def emit(tag, es, chain)
@@ -72,7 +56,7 @@ class Fluent::ParserOutput < Fluent::Output
72
56
  es.each {|time,record|
73
57
  value = record[@key_name]
74
58
  t,values = if value
75
- parse(value)
59
+ @parser.parse(value)
76
60
  else
77
61
  [nil, {}]
78
62
  end
@@ -84,7 +68,7 @@ class Fluent::ParserOutput < Fluent::Output
84
68
  es.each {|time,record|
85
69
  value = record[@key_name]
86
70
  t,values = if value
87
- parse(value)
71
+ @parser.parse(value)
88
72
  else
89
73
  [nil, {}]
90
74
  end
@@ -51,16 +51,6 @@ class ParserOutputTest < Test::Unit::TestCase
51
51
  key_name foo
52
52
  ]
53
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
54
  d = create_driver %[
65
55
  tag foo.bar
66
56
  key_name foo
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-02 00:00:00.000000000 Z
12
+ date: 2012-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
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'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: fluentd
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -53,10 +69,11 @@ extra_rdoc_files: []
53
69
  files:
54
70
  - .gitignore
55
71
  - Gemfile
56
- - LICENSE
72
+ - LICENSE.txt
57
73
  - README.md
58
74
  - Rakefile
59
75
  - fluent-plugin-parser.gemspec
76
+ - lib/fluent/plugin/fixed_parser.rb
60
77
  - lib/fluent/plugin/out_deparser.rb
61
78
  - lib/fluent/plugin/out_parser.rb
62
79
  - test/helper.rb
data/LICENSE DELETED
@@ -1,22 +0,0 @@
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.