fluent-mixin-rewrite-tag-name 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -2,14 +2,192 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Fluentd mixin plugin to rewrite tag like [rewrite-tag-filter](https://github.com/fluent/fluent-plugin-rewrite-tag-filter) for your any plugins.
5
+ Fluentd mixin plugin to provides placeholder function for rewriting tag for your any plugins as like [fluent-plugin-rewrite-tag-filter](https://github.com/fluent/fluent-plugin-rewrite-tag-filter). It will let you get easy to implement tag placeholder for your own plugins.
6
+
7
+ ## Placeholders
8
+
9
+ It supportes these placeholder for rewriting tag.
10
+
11
+ - `${tag}`
12
+ - `__TAG__`
13
+ - `{$tag_parts[n]}`
14
+ - `__TAG_PARTS[n]__`
15
+ - `${hostname}`
16
+ - `__HOSTNAME__`
17
+
18
+ The placeholder of `{$tag_parts[n]}` and `__TAG_PARTS[n]__` acts accessing the index which split the tag with "." (dot).
19
+ For example with `td.apache.access` tag, it will get `td` by `${tag_parts[0]}` and `apache` by `${tag_parts[1]}`.
20
+
21
+ **Note**
22
+
23
+ * To support upcase placeholder, set `enable_placeholder_upcase true` in configuration.
24
+ * To support hostname placeholder, set `enable_placeholder_upcase true` in configuration.
25
+ * Currently, range expression ```${tag_parts[0..2]}``` is not supported.
26
+
27
+ #### Placeholder Option
28
+
29
+ * `hostname_command`
30
+
31
+ By default, execute command as `hostname` to get full hostname.
32
+ On your needs, it could override hostname command using `hostname_command` option.
33
+ It comes short hostname with `hostname_command hostname -s` configuration specified.
34
+
35
+ ## Configuration
36
+
37
+ Adding this mixin plugin, it will enabled to use these placeholder in your plugins.
38
+
39
+ ```xml
40
+ # input plugin example
41
+ <source>
42
+ type foo_bar
43
+
44
+ # it will be rewrited to be 'customprefix.web10-222' when short hostname is 'web10-222'.
45
+ tag customprefix.${hostname}
46
+
47
+ # to use hostname placeholder, set 'enable_placeholder_hostname true'
48
+ enable_placeholder_hostname true
49
+ hostname_command hostname -s
50
+ </source>
51
+ ```
52
+
53
+ ```xml
54
+ # output plugin example
55
+ <match test.foo>
56
+ type foo_bar
57
+
58
+ # it will be rewrited to be 'customprefix.test.foo'.
59
+ tag customprefix.${tag}
60
+ </match>
61
+ ```
62
+
63
+ Another examples are written in [unit test](https://github.com/y-ken/fluent-mixin-rewrite-tag-name/blob/master/test/mixin/test_rewrite_tag_name.rb).
6
64
 
7
65
  ## Usage
8
66
 
9
- TODO
67
+ #### 1. edit gemspec
68
+
69
+ add dependency for .gemspec file like below. For more detail, see [gemspec example](https://github.com/y-ken/fluent-plugin-anonymizer/blob/master/fluent-plugin-anonymizer.gemspec)
70
+
71
+ ```ruby
72
+ spec.add_runtime_dependency "fluent-mixin-rewrite-tag-name"
73
+ ```
74
+
75
+ #### 2. activate fluent-mixin-rewrite-tag-name for your plugin
76
+
77
+ It is the instruction in the case of adding `fluent-plugin-foobar`.
78
+
79
+ ```
80
+ $ cd fluent-plugin-foobar
81
+ $ vim fluent-plugin-foobar.gemspec # edit gemspec
82
+ $ bundle install --path vendor/bundle # or just type `bundle install`
83
+ ```
84
+
85
+ #### 3. edit your plugin to implement
86
+
87
+ It is a quick guide to enable your plugin to use RewriteTagNameMixin.
88
+ The key points of implmentation is just four below.
89
+
90
+ * add `require 'fluent/mixin/rewrite_tag_name'` at the top of source
91
+ * in the case of output plugin, add `include Fluent::HandleTagNameMixin`
92
+ this is required if you will use 'remove_tag_prefix' option together
93
+ * add `include Fluent::Mixin::RewriteTagName` in class after HandleTagNameMixin
94
+ * add `emit_tag = tag.dup` and `filter_record(emit_tag, time, record)` before `Engine.emit`
95
+
96
+ ##### implement example for input plugin
97
+
98
+ ```ruby
99
+ require 'fluent/mixin/rewrite_tag_name'
100
+
101
+ module Fluent
102
+ class FooBarInput < Fluent::Input
103
+ Plugin.register_input('foo_bar', self)
104
+
105
+ # ...snip...
106
+
107
+ include Fluent::HandleTagNameMixin
108
+ include Fluent::Mixin::RewriteTagName
109
+ config_param :hostname_command, :string, :default => 'hostname'
110
+
111
+ # ...snip...
112
+
113
+ def configure(conf)
114
+ super
115
+
116
+ # ...snip...
117
+
118
+ # add a error handling
119
+ if ( !@tag && !@remove_tag_prefix && !@remove_tag_suffix && !@add_tag_prefix && !@add_tag_suffix )
120
+ raise Fluent::ConfigError, "foo_bar: missing remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
121
+ end
122
+ end
123
+
124
+ # ...snip...
125
+
126
+ def emit_message(tag, message)
127
+ emit_tag = tag.dup
128
+ filter_record(emit_tag, time, message)
129
+ Engine.emit(emit_tag, Engine.now, message)
130
+ end
131
+
132
+ # ...snip...
133
+
134
+ end
135
+ end
136
+ ```
137
+
138
+ ##### implement example for output plugin
139
+
140
+ ```ruby
141
+ require 'fluent/mixin/rewrite_tag_name'
142
+
143
+ class Fluent
144
+ class FooBarOutput < Fluent::Output
145
+ Fluent::Plugin.register_output('foo_bar', self)
146
+
147
+ include Fluent::Mixin::RewriteTagName
148
+ config_param :hostname_command, :string, :default => 'hostname'
149
+
150
+ # ...snip...
151
+
152
+ def configure(conf)
153
+ super
154
+
155
+ # ...snip...
156
+
157
+ # add a error handling
158
+ if ( !@tag && !@remove_tag_prefix && !@remove_tag_suffix && !@add_tag_prefix && !@add_tag_suffix )
159
+ raise Fluent::ConfigError, "foo_bar: missing remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
160
+ end
161
+ end
162
+
163
+ # ...snip...
164
+
165
+ def emit(tag, es, chain)
166
+ es.each do |time, record|
167
+ emit_tag = tag.dup
168
+ filter_record(emit_tag, time, record)
169
+ Fluent::Engine.emit(emit_tag, time, record)
170
+ end
171
+ chain.next
172
+ end
173
+
174
+ # ...snip...
175
+
176
+ end
177
+ end
178
+ ```
179
+
180
+ ## Case Study
181
+
182
+ These cool plugins are using this mixin!
183
+
184
+ * [fluent-plugin-anonymizer](https://github.com/y-ken/fluent-plugin-anonymizer/)
10
185
 
11
186
  ## TODO
12
187
 
188
+ * switchable tag template variable like 'tag', 'tag_format'
189
+ * support range tag_parts like [fluent-plugin-forest](https://github.com/tagomoris/fluent-plugin-forest/compare/v0.2.2...master)
190
+ * support tag_prefix and tag_suffix placeholder like [fluent-plugin-record-reformer](https://github.com/sonots/fluent-plugin-record-reformer)
13
191
  * merge into [fluentd/lib/fluent/mixin.rb](https://github.com/fluent/fluentd/blob/master/lib/fluent/mixin.rb) as RewriteTagNameMixin module.
14
192
 
15
193
  Pull requests are very welcome!!
@@ -4,10 +4,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fluent-mixin-rewrite-tag-name"
7
- spec.version = "0.0.1"
7
+ spec.version = "0.0.2"
8
8
  spec.authors = ["Kentaro Yoshida"]
9
9
  spec.email = ["y.ken.studio@gmail.com"]
10
- spec.summary = %q{Fluentd mixin plugin to rewrite tag like rewrite-tag-filter for your any plugins.}
10
+ spec.summary = %q{Fluentd mixin plugin to provides placeholder function for rewriting tag for your any plugins as like fluent-plugin-rewrite-tag-filter. It will let you get easy to implement tag placeholder for your own plugins.}
11
11
  spec.homepage = "https://github.com/y-ken/fluent-mixin-rewrite-tag-name"
12
12
  spec.license = "Apache License, Version 2.0"
13
13
 
@@ -2,7 +2,33 @@ module Fluent
2
2
  module Mixin
3
3
  module RewriteTagName
4
4
  include RecordFilterMixin
5
- attr_accessor :tag
5
+ attr_accessor :tag, :hostname_command
6
+ attr_accessor :enable_placeholder_upcase, :enable_placeholder_hostname
7
+
8
+ DEFAULT_HOSTNAME_COMMAND = 'hostname'
9
+
10
+ def configure(conf)
11
+ super
12
+
13
+ @placeholder_expander = PlaceholderExpander.new
14
+
15
+ if enable_upcase = conf['enable_placeholder_upcase']
16
+ @enable_placeholder_upcase = enable_upcase
17
+ end
18
+ if @enable_placeholder_upcase
19
+ @placeholder_expander.enable_placeholder_upcase
20
+ end
21
+
22
+ if enable_hostname = conf['enable_placeholder_hostname']
23
+ @enable_placeholder_hostname = enable_hostname
24
+ end
25
+ if @enable_placeholder_hostname
26
+ hostname_command = @hostname_command || DEFAULT_HOSTNAME_COMMAND
27
+ hostname = `#{hostname_command}`.chomp
28
+ @placeholder_expander.enable_placeholder_hostname
29
+ @placeholder_expander.set_hostname(hostname)
30
+ end
31
+ end
6
32
 
7
33
  def filter_record(tag, time, record)
8
34
  super
@@ -12,16 +38,64 @@ module Fluent
12
38
  end
13
39
 
14
40
  def rewrite_tag!(tag)
15
- placeholder = {
16
- '${tag}' => tag,
17
- '__TAG__' => tag
18
- }
19
- emit_tag = @tag.gsub(/(\${[a-z_]+(\[[0-9]+\])?}|__[A-Z_]+__)/) do
20
- $log.warn "RewriteTagNameMixin: unknown placeholder found. :placeholder=>#{$1} :tag=>#{tag} :rewritetag=>#{rewritetag}" unless placeholder.include?($1)
21
- placeholder[$1]
22
- end
41
+
42
+ @placeholder_expander.set_tag(tag)
43
+ emit_tag = @placeholder_expander.expand(@tag)
23
44
  tag.gsub!(tag, emit_tag)
24
45
  end
46
+
47
+ class PlaceholderExpander
48
+ # referenced https://github.com/fluent/fluent-plugin-rewrite-tag-filter, thanks!
49
+ # referenced https://github.com/sonots/fluent-plugin-record-reformer, thanks!
50
+ attr_reader :placeholders
51
+
52
+ def initialize
53
+ @placeholders = {}
54
+ @enable_options = {
55
+ :hostname => false,
56
+ :upcase => false,
57
+ }
58
+ end
59
+
60
+ def expand(str)
61
+ str.gsub(/(\${[a-z_]+(\[-?[0-9]+\])?}|__[A-Z_]+(\[-?[0-9]+\])?__)/) {
62
+ $log.warn "RewriteTagNameMixin: unknown placeholder `#{$1}` found" unless @placeholders.include?($1)
63
+ @placeholders[$1]
64
+ }
65
+ end
66
+
67
+ def enable_placeholder_hostname
68
+ @enable_options[:hostname] = true
69
+ end
70
+
71
+ def enable_placeholder_upcase
72
+ @enable_options[:upcase] = true
73
+ end
74
+
75
+ def set_tag(value)
76
+ set_placeholder('tag', value)
77
+ set_tag_parts(value)
78
+ end
79
+
80
+ def set_hostname(value)
81
+ set_placeholder('hostname', value)
82
+ end
83
+
84
+ def set_tag_parts(tag)
85
+ tag_parts = tag.split('.')
86
+ size = tag_parts.size
87
+ tag_parts.each_with_index { |t, idx|
88
+ set_placeholder("tag_parts[#{idx}]", t)
89
+ set_placeholder("tag_parts[#{idx-size}]", t) # support tag_parts[-1]
90
+ }
91
+ end
92
+
93
+ private
94
+ def set_placeholder(key, value)
95
+ @placeholders.store("${#{key.downcase}}", value)
96
+ @placeholders.store("__#{key.upcase}__", value) if @enable_options[:upcase]
97
+ end
98
+ end
25
99
  end
26
100
  end
27
101
  end
@@ -37,6 +37,22 @@ class RewriteTagNameMixinTest < Test::Unit::TestCase
37
37
  assert_equal 'foo', emits[0][2]['message']
38
38
  end
39
39
 
40
+ def test_emit_upcase
41
+ d1 = create_driver(%[
42
+ tag rewrited.__TAG__
43
+ remove_tag_prefix input.
44
+ enable_placeholder_upcase true
45
+ ], 'input.access')
46
+ d1.run do
47
+ d1.emit({'message' => 'foo'})
48
+ end
49
+ emits = d1.emits
50
+ assert_equal 1, emits.length
51
+ p emits[0]
52
+ assert_equal 'rewrited.access', emits[0][0] # tag
53
+ assert_equal 'foo', emits[0][2]['message']
54
+ end
55
+
40
56
  def test_emit_with_HandleTagNameMixin
41
57
  d1 = create_driver(%[
42
58
  tag rewrited.${tag}
@@ -51,4 +67,77 @@ class RewriteTagNameMixinTest < Test::Unit::TestCase
51
67
  assert_equal 'rewrited.access', emits[0][0] # tag
52
68
  assert_equal 'foo', emits[0][2]['message']
53
69
  end
70
+
71
+ def test_emit_tag_parts
72
+ d1 = create_driver(%[
73
+ tag rewrited.${tag_parts[1]}
74
+ ], 'input.access.foo.bar')
75
+ d1.run do
76
+ d1.emit({'message' => 'foo'})
77
+ end
78
+ emits = d1.emits
79
+ assert_equal 1, emits.length
80
+ p emits[0]
81
+ assert_equal 'rewrited.access', emits[0][0] # tag
82
+ end
83
+
84
+ def test_emit_tag_parts_negative
85
+ d1 = create_driver(%[
86
+ tag rewrited.${tag_parts[-1]}
87
+ ], 'input.access.foo.bar')
88
+ d1.run do
89
+ d1.emit({'message' => 'foo'})
90
+ end
91
+ emits = d1.emits
92
+ assert_equal 1, emits.length
93
+ p emits[0]
94
+ assert_equal 'rewrited.bar', emits[0][0] # tag
95
+ assert_equal 'foo', emits[0][2]['message']
96
+ end
97
+
98
+ def test_emit_tag_parts_negative2
99
+ d1 = create_driver(%[
100
+ tag rewrited.${tag_parts[-2]}
101
+ ], 'input.access.foo.bar')
102
+ d1.run do
103
+ d1.emit({'message' => 'foo'})
104
+ end
105
+ emits = d1.emits
106
+ assert_equal 1, emits.length
107
+ p emits[0]
108
+ assert_equal 'rewrited.foo', emits[0][0] # tag
109
+ assert_equal 'foo', emits[0][2]['message']
110
+ end
111
+
112
+ def test_emit_hostname
113
+ d1 = create_driver(%[
114
+ tag rewrited.${hostname}
115
+ ], 'input.access')
116
+ d1.run do
117
+ d1.emit({'message' => 'foo'})
118
+ end
119
+ emits = d1.emits
120
+ assert_equal 1, emits.length
121
+ p emits[0]
122
+ hostname = `hostname`.chomp
123
+ assert_equal "rewrited.#{hostname}", emits[0][0] # tag
124
+ assert_equal 'foo', emits[0][2]['message']
125
+ end
126
+
127
+ def test_emit_hostname_short
128
+ d1 = create_driver(%[
129
+ tag rewrited.${hostname}
130
+ hostname_command hostname -s
131
+ ], 'input.access')
132
+ d1.run do
133
+ d1.emit({'message' => 'foo'})
134
+ end
135
+ emits = d1.emits
136
+ assert_equal 1, emits.length
137
+ p emits[0]
138
+ hostname_command = d1.instance.config['hostname_command']
139
+ hostname = `#{hostname_command}`.chomp
140
+ assert_equal "rewrited.#{hostname}", emits[0][0] # tag
141
+ assert_equal 'foo', emits[0][2]['message']
142
+ end
54
143
  end
data/test/plugin.rb CHANGED
@@ -2,17 +2,19 @@ class Fluent::RewriteTagNameMixinOutput < Fluent::Output
2
2
  Fluent::Plugin.register_output('rewrite_tag_name_mixin', self)
3
3
 
4
4
  config_param :tag, :string, :default => nil
5
+ config_param :hostname_command, :string, :default => 'hostname'
5
6
 
6
7
  include Fluent::HandleTagNameMixin
7
8
  include Fluent::Mixin::RewriteTagName
9
+ config_set_default :enable_placeholder_upcase, false
10
+ config_set_default :enable_placeholder_hostname, true
8
11
 
9
12
  def configure(conf)
10
13
  super
11
-
12
- if @tag.nil?
13
- raise Fluent::ConfigError, "'tag' parameter is required."
14
- end
15
14
 
15
+ if ( !@tag && !@remove_tag_prefix && !@remove_tag_suffix && !@add_tag_prefix && !@add_tag_suffix )
16
+ raise Fluent::ConfigError, "RewriteTagNameMixin: missing remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
17
+ end
16
18
  end
17
19
 
18
20
  def emit(tag, es, chain)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-mixin-rewrite-tag-name
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-20 00:00:00.000000000 Z
12
+ date: 2014-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -101,8 +101,9 @@ rubyforge_project:
101
101
  rubygems_version: 1.8.23
102
102
  signing_key:
103
103
  specification_version: 3
104
- summary: Fluentd mixin plugin to rewrite tag like rewrite-tag-filter for your any
105
- plugins.
104
+ summary: Fluentd mixin plugin to provides placeholder function for rewriting tag for
105
+ your any plugins as like fluent-plugin-rewrite-tag-filter. It will let you get easy
106
+ to implement tag placeholder for your own plugins.
106
107
  test_files:
107
108
  - test/helper.rb
108
109
  - test/mixin/test_rewrite_tag_name.rb