fluent-plugin-rewrite 0.0.1

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,18 @@
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
18
+ vendor/bundler
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-rewrite.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,2 @@
1
+ Copyright (c) 2012 Kentaro Kuribayashi
2
+ Apache License, Version 2.0
data/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # fluent-plugin-rewrite
2
+
3
+ ## Component
4
+
5
+ ### RewriteOutput
6
+
7
+ Output plugin to rewrite messages' tags/values along with pattern
8
+ matching and re-emit them.
9
+
10
+ ## Synopsis
11
+
12
+ ```
13
+ <match apache.log.**>
14
+ type rewrite
15
+
16
+ remove_prefix apache.log
17
+ add_prefix filtered
18
+
19
+ <rule>
20
+ key path
21
+ pattern \\?.+$
22
+ replace
23
+ </rule>
24
+ <rule>
25
+ key path
26
+ pattern (/[^/]+)\\?([^=]+)=(\\d)
27
+ replace \\1/\\2/\\3
28
+ </rule>
29
+ <rule>
30
+ key status
31
+ pattern ^500$
32
+ ignore true
33
+ </rule>
34
+ <rule>
35
+ key path
36
+ pattern ^\/(users|entries)
37
+ append_to_tag true
38
+ fallback others
39
+ </rule>
40
+ </match>
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ ### remove_prefix / add_prefix
46
+
47
+ ```
48
+ remove_prefix apache.log
49
+ add_prefix filtered
50
+ ```
51
+
52
+ - remove_prefix: removes the string from a prefix of tag.
53
+ - add_prefix: prepend the string to a tag.
54
+
55
+ ### rule: replace
56
+
57
+ For example, if you want to filter out query string form URL string:
58
+
59
+ ```
60
+ <rule>
61
+ key path
62
+ pattern \\?.+$
63
+ replace
64
+ </rule>
65
+ ```
66
+
67
+ It executes pattern matching against a value related with `key` and replaces it with empty string if it matches.
68
+
69
+ ```
70
+ /foo?bar=baz -> /foo
71
+ ```
72
+
73
+ This time, if you want to rewrite path string along with some pattern:
74
+
75
+ ```
76
+ <rule>
77
+ key path
78
+ pattern (/[^/]+)\\?([^=]+)=(\\d)
79
+ replace \\1/\\2/\\3
80
+ </rule>
81
+ ```
82
+
83
+ It executes pattern matching against a value related with `key` and replaces it with `replace` if it matches.
84
+
85
+ ```
86
+ /foo?bar=1 -> /foo/bar/1
87
+ ```
88
+
89
+ ### rule: ignore
90
+
91
+ For example, if you want to skip a message which matches some pattern:
92
+
93
+ ```
94
+ <rule>
95
+ key status
96
+ pattern ^500$
97
+ ignore true
98
+ </rule>
99
+ ```
100
+
101
+ It executes pattern matching against a value related with `key` and skip emitting the message if it matches.
102
+
103
+ ### rule: append_to_tag
104
+
105
+ ```
106
+ <rule>
107
+ key path
108
+ pattern ^\/(users|entries)
109
+ append_to_tag true
110
+ </rule>
111
+ ```
112
+
113
+ It executes pattern matching against a value related with `key` and append mathed strings to message tag. For example:
114
+
115
+ ```
116
+ apache.log { "path" : "/users/antipop" }
117
+ ```
118
+
119
+ the messabe above will be re-emmited as the message below:
120
+
121
+ ```
122
+ apache.log.users { "path" : "/users/antipop" }
123
+ ```
124
+
125
+ If you set `fallback` option like below:
126
+
127
+ ```
128
+ <rule>
129
+ key path
130
+ pattern ^\/(users|entries)
131
+ append_to_tag true
132
+ fallback others
133
+ </rule>
134
+ ```
135
+
136
+ the value of `fallback` option will be appended to message tag.
137
+
138
+ ```
139
+ apache.log { "path" : "/foo/bar" }
140
+ ```
141
+
142
+ This time, the messabe above will be re-emmited as the message below:
143
+
144
+ ```
145
+ apache.log.others { "path" : "/foo/bar" }
146
+ ```
147
+
148
+ ## Installation
149
+
150
+ Add this line to your application's Gemfile:
151
+
152
+ gem 'fluent-plugin-rewrite'
153
+
154
+ And then execute:
155
+
156
+ $ bundle
157
+
158
+ Or install it yourself as:
159
+
160
+ $ gem install fluent-plugin-rewrite
161
+
162
+ ## Contributing
163
+
164
+ 1. Fork it
165
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
166
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
167
+ 4. Push to the branch (`git push origin my-new-feature`)
168
+ 5. Create new Pull Request
169
+
170
+ ## Copyright
171
+
172
+ ### Copyright
173
+
174
+ Copyright (c) 2012- Kentaro Kuribayashi (@kentaro)
175
+
176
+ ### License
177
+
178
+ Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = "fluent-plugin-rewrite"
3
+ gem.version = '0.0.1'
4
+ gem.authors = ["Kentaro Kuribayashi"]
5
+ gem.email = ["kentarok@gmail.com"]
6
+ gem.homepage = "http://github.com/kentaro/fluent-plugin-rewrite"
7
+ gem.description = %q{Fluentd plugin to rewrite tags/values along with pattern matching and re-emit them.}
8
+ gem.summary = %q{Fluentd plugin to rewrite tags/values along with pattern matching and re-emit them.}
9
+
10
+ gem.files = `git ls-files`.split($\)
11
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.require_paths = ["lib"]
14
+
15
+ gem.add_development_dependency "rake"
16
+ gem.add_development_dependency "fluentd"
17
+ gem.add_runtime_dependency "fluentd"
18
+ end
@@ -0,0 +1,99 @@
1
+ module Fluent
2
+ class RewriteOutput < Output
3
+ Fluent::Plugin.register_output('rewrite', self)
4
+
5
+ config_param :remove_prefix, :string, :default => nil
6
+ config_param :add_prefix, :string, :default => nil
7
+
8
+ attr_reader :rules
9
+
10
+ def configure(conf)
11
+ super
12
+
13
+ if @remove_prefix
14
+ @removed_prefix_string = @remove_prefix + '.'
15
+ @removed_length = @removed_prefix_string.length
16
+ end
17
+ if @add_prefix
18
+ @added_prefix_string = @add_prefix + '.'
19
+ end
20
+
21
+ @rules = conf.elements.select { |element|
22
+ element.name == 'rule'
23
+ }.each { |element|
24
+ if element.has_key?("pattern")
25
+ element["regex"] = Regexp.new(element["pattern"])
26
+ end
27
+ }
28
+ end
29
+
30
+ def start
31
+ super
32
+ end
33
+
34
+ def shutdown
35
+ super
36
+ end
37
+
38
+ def emit(tag, es, chain)
39
+ es.each do |time, record|
40
+ tag, record = rewrite(tag, record)
41
+ Engine.emit(tag, time, record) if tag && record
42
+ end
43
+
44
+ chain.next
45
+ end
46
+
47
+ def length_will_be_removed
48
+ return 0 unless @remove_prefix
49
+ (@remove_prefix + '.').length
50
+ end
51
+
52
+ def rewrite(tag, record)
53
+ if @remove_prefix and
54
+ ((tag.start_with?(@removed_prefix_string) && tag.length > @removed_length) ||
55
+ tag == @remove_prefix)
56
+ tag = tag[@removed_length..-1]
57
+ end
58
+
59
+ if @add_prefix
60
+ tag = tag && tag.length > 0 ? @added_prefix_string + tag : @add_prefix
61
+ end
62
+
63
+ rules.each do |rule|
64
+ tag, record = apply_rule(rule, tag, record)
65
+ return if !tag && !record
66
+ end
67
+
68
+ [tag, record]
69
+ end
70
+
71
+ def apply_rule(rule, tag, record)
72
+ tag = rule["append_to_tag"] ? tag.dup : tag
73
+ key = rule["key"]
74
+ pattern = rule["pattern"]
75
+
76
+ return [tag, record] if !key || !record.has_key?(key)
77
+ return [tag, record] unless pattern
78
+
79
+ if matched = record[key].match(rule["regex"])
80
+ return if rule["ignore"]
81
+
82
+ if rule["replace"]
83
+ replace = rule["replace"].to_s
84
+ record[key] = record[key].gsub(rule["regex"], replace)
85
+ end
86
+
87
+ if rule["append_to_tag"]
88
+ matched.captures.each { |m| tag << ".#{m}" }
89
+ end
90
+ else
91
+ if rule["append_to_tag"] && rule["fallback"]
92
+ tag << ".#{rule["fallback"]}"
93
+ end
94
+ end
95
+
96
+ [tag, record]
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,233 @@
1
+ require 'test_helper'
2
+
3
+ class RewriteOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ def create_driver(conf, tag = 'test')
9
+ Fluent::Test::OutputTestDriver.new(Fluent::RewriteOutput, tag).configure(conf)
10
+ end
11
+
12
+ def test_configure
13
+ d = create_driver(%[
14
+ remove_prefix test
15
+ add_prefix filtered
16
+
17
+ <rule>
18
+ key foo
19
+ </rule>
20
+ <to_be_ignored>
21
+ key bar
22
+ </to_be_ignored>
23
+ <rule>
24
+ key baz
25
+ </rule>
26
+ ])
27
+
28
+ assert_equal "test", d.instance.remove_prefix
29
+ assert_equal "filtered", d.instance.add_prefix
30
+ assert_equal 2, d.instance.rules.size
31
+ end
32
+
33
+ def test_rewrite_replace
34
+ d1 = create_driver(%[
35
+ <rule>
36
+ key path
37
+ pattern \\?.+$
38
+ replace
39
+ </rule>
40
+ ])
41
+
42
+ assert_equal(
43
+ [ "test", { "path" => "/foo" } ],
44
+ d1.instance.rewrite("test", { "path" => "/foo?bar=1" })
45
+ )
46
+
47
+ d2 = create_driver(%[
48
+ <rule>
49
+ key path
50
+ pattern (/[^/]+)\\?([^=]+)=(\\d)
51
+ replace \\1/\\2/\\3
52
+ </rule>
53
+ ])
54
+
55
+ assert_equal(
56
+ [ "test", { "path" => "/foo/bar/1" } ],
57
+ d2.instance.rewrite("test", { "path" => "/foo?bar=1" })
58
+ )
59
+ end
60
+
61
+ def test_rewrite_ignore
62
+ d1 = create_driver(%[
63
+ <rule>
64
+ key status
65
+ pattern ^500$
66
+ ignore true
67
+ </rule>
68
+ ])
69
+
70
+ assert_equal(
71
+ nil,
72
+ d1.instance.rewrite("test", { "status" => "500" })
73
+ )
74
+
75
+ d2 = create_driver(%[
76
+ <rule>
77
+ key status
78
+ pattern ^(?!200)\\d+$
79
+ ignore true
80
+ </rule>
81
+ ])
82
+
83
+ assert_equal(
84
+ [ "test", { "status" => "200" } ],
85
+ d2.instance.rewrite("test", { "status" => "200" })
86
+ )
87
+ %w[301 404 500].each do |status|
88
+ assert_equal(
89
+ nil,
90
+ d2.instance.rewrite("test", { "status" => status })
91
+ )
92
+ end
93
+
94
+ d3 = create_driver(%[
95
+ <rule>
96
+ key flag
97
+ pattern ^$
98
+ ignore true
99
+ </rule>
100
+ ])
101
+
102
+ assert_equal(
103
+ nil,
104
+ d3.instance.rewrite("test", { "flag" => "" })
105
+ )
106
+ end
107
+
108
+ def test_rewrite_append_tag
109
+ d1 = create_driver(%[
110
+ <rule>
111
+ key path
112
+ pattern ^\/(users|entries)
113
+ append_to_tag true
114
+ </rule>
115
+ ])
116
+
117
+ assert_equal(
118
+ [ "test.users", { "path" => "/users/antipop" } ],
119
+ d1.instance.rewrite("test", { "path" => "/users/antipop" })
120
+ )
121
+ assert_equal(
122
+ [ "test", { "path" => "/unmatched/path" } ],
123
+ d1.instance.rewrite("test", { "path" => "/unmatched/path" })
124
+ )
125
+
126
+ d2 = create_driver(%[
127
+ <rule>
128
+ key path
129
+ pattern ^\/(users|entries)
130
+ append_to_tag true
131
+ fallback others
132
+ </rule>
133
+ ])
134
+
135
+ assert_equal(
136
+ [ "test.users", { "path" => "/users/antipop" } ],
137
+ d2.instance.rewrite("test", { "path" => "/users/antipop" })
138
+ )
139
+ assert_equal(
140
+ [ "test.others", { "path" => "/unmatched/path" } ],
141
+ d2.instance.rewrite("test", { "path" => "/unmatched/path" })
142
+ )
143
+ end
144
+
145
+ def test_rewrite_rules
146
+ d = create_driver(%[
147
+ <rule>
148
+ key path
149
+ pattern \\?.+$
150
+ replace
151
+ </rule>
152
+ <rule>
153
+ key status
154
+ pattern ^500$
155
+ ignore true
156
+ </rule>
157
+ <rule>
158
+ key path
159
+ pattern ^\/(users|entries)
160
+ append_to_tag true
161
+ fallback others
162
+ </rule>
163
+ ])
164
+
165
+ assert_equal(
166
+ [ "test.others", { "path" => "/foo" } ],
167
+ d.instance.rewrite("test", { "path" => "/foo?bar=1" })
168
+ )
169
+ assert_equal(
170
+ [ "test.users", { "path" => "/users/antipop" } ],
171
+ d.instance.rewrite("test", { "path" => "/users/antipop?hoge=1" })
172
+ )
173
+ assert_equal(
174
+ nil,
175
+ d.instance.rewrite("test", { "path" => "/foo?bar=1", "status" => "500" })
176
+ )
177
+ end
178
+
179
+ def test_tag_prefix
180
+ d = create_driver(%[
181
+ remove_prefix test
182
+ add_prefix filtered
183
+
184
+ <rule>
185
+ key path
186
+ pattern ^\/(users|entries)
187
+ append_to_tag true
188
+ </rule>
189
+ ])
190
+
191
+ assert_equal(
192
+ [ "filtered.users", { "path" => "/users/antipop" } ],
193
+ d.instance.rewrite("test", { "path" => "/users/antipop" })
194
+ )
195
+ end
196
+
197
+ def test_emit
198
+ d = create_driver(%[
199
+ remove_prefix test
200
+ add_prefix filtered
201
+
202
+ <rule>
203
+ key path
204
+ pattern \\?.+$
205
+ replace
206
+ </rule>
207
+ <rule>
208
+ key status
209
+ pattern ^500$
210
+ ignore true
211
+ </rule>
212
+ <rule>
213
+ key path
214
+ pattern ^\/(users|entries)
215
+ append_to_tag true
216
+ fallback others
217
+ </rule>
218
+ ])
219
+
220
+ d.run do
221
+ d.emit({ "path" => "/foo?bar=1" })
222
+ d.emit({ "path" => "/users/antipop?hoge=1" })
223
+ d.emit({ "path" => "/foo?bar=1", "status" => "500" })
224
+ end
225
+ emits = d.emits
226
+
227
+ assert_equal 2, emits.size
228
+ assert_equal('filtered.others', emits[0][0])
229
+ assert_equal({ "path" => "/foo" }, emits[0][2])
230
+ assert_equal('filtered.users', emits[1][0])
231
+ assert_equal({ "path" => "/users/antipop" }, emits[1][2])
232
+ end
233
+ end
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'test/unit'
13
+
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
16
+
17
+ require 'fluent/test'
18
+
19
+ unless ENV.has_key?('VERBOSE')
20
+ nulllogger = Object.new
21
+ nulllogger.instance_eval {|obj|
22
+ def method_missing(method, *args)
23
+ # pass
24
+ end
25
+ }
26
+ $log = nulllogger
27
+ end
28
+
29
+ require 'fluent/plugin/rewrite'
30
+
31
+ class Test::Unit::TestCase
32
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-rewrite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kentaro Kuribayashi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-30 00:00:00.000000000 Z
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'
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: :development
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
+ - !ruby/object:Gem::Dependency
47
+ name: fluentd
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Fluentd plugin to rewrite tags/values along with pattern matching and
63
+ re-emit them.
64
+ email:
65
+ - kentarok@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - LICENSE
73
+ - README.md
74
+ - Rakefile
75
+ - fluent-plugin-rewrite.gemspec
76
+ - lib/fluent/plugin/rewrite.rb
77
+ - test/plugin/test_out_rewrite.rb
78
+ - test/test_helper.rb
79
+ homepage: http://github.com/kentaro/fluent-plugin-rewrite
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 1.8.23
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Fluentd plugin to rewrite tags/values along with pattern matching and re-emit
103
+ them.
104
+ test_files:
105
+ - test/plugin/test_out_rewrite.rb
106
+ - test/test_helper.rb
107
+ has_rdoc: