fluent-plugin-record-reformer 0.2.1 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 55ba6719a96af4f1c33c52d970579a9006ef9a7c
4
- data.tar.gz: 15cd6f42ed2f5b0b995f20560cf9974d12e23bda
3
+ metadata.gz: f79ddbaecca21d91a17132b991c9f031b5a19b01
4
+ data.tar.gz: e6f3777a3a2fdc0fe14887c3d745dfd38e39c60a
5
5
  SHA512:
6
- metadata.gz: 8758e09cd82e2f2fd50076811bf7a25961a2782f5ac6081185567ff8e874b1bb312aeaae546acfa17411a26f6c0af2c85ed47af99416cb7448ac4a65176e5815
7
- data.tar.gz: 4ae98eedf0aafea25057b67a9d2f2f189f54c1063d00ecd70f90075c317171089e614bc3f00115f027037ca5a23eee51c0c7b3c75f6f8b150174792f1c0cf972
6
+ metadata.gz: 5193f5ee853ff6af02e119759bc8ec6a6c018f1a69bad34511757f62bd95918c2c3dc766eb3bc485ad47e65829a88e44da16e63a5238150314b9dca4f137e678
7
+ data.tar.gz: dc3313b3754851512e110247fd0c184c9130e9c2137f5c6adc39c62c173e9c6f2a3379b55b29dd2bf453c88e036722817a19455e72389e05e25f00e02da77585
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.2 (2014/01/20)
2
+
3
+ Enhancement:
4
+
5
+ * Add `tag_prefix` and `tag_suffix` placeholders. Thanks to [xthexder](https://github.com/xthexder).
6
+
1
7
  ## 0.2.1 (2014/01/15)
2
8
 
3
9
  Enhancement:
data/README.md CHANGED
@@ -67,7 +67,7 @@ Example:
67
67
 
68
68
  This results in same, but please note that following option parameters are reserved, so can not be used as a record key.
69
69
 
70
- ## Parameters
70
+ ## Option Parameters
71
71
 
72
72
  - output_tag
73
73
 
@@ -98,11 +98,28 @@ The keys of input json are available as placeholders. In the above example,
98
98
 
99
99
  shall be available. In addition, following placeholders are reserved:
100
100
 
101
- * ${hostname} hostname
102
- * ${tag} input tag
103
- * ${time} time of the event
104
- * ${tags[N]} input tag splitted by '.' (obsolete. use tag\_parts)
105
- * ${tag\_parts[N]} input tag splitted by '.' indexed with N such as `${tag_parts[0]}`, `${tag_parts[-1]}`.
101
+ * ${hostname} Hostname of the running machine
102
+ * ${tag} Input tag
103
+ * ${time} Time of the event
104
+ * ${tags[N]} (Obsolete. Use tag\_parts) Input tag splitted by '.'
105
+ * ${tag\_parts[N]} Input tag splitted by '.' indexed with N such as `${tag_parts[0]}`, `${tag_parts[-1]}`.
106
+ * ${tag\_prefix[N]} Tag parts before and on the index N. For example,
107
+
108
+ Input tag: prefix.test.tag.suffix
109
+
110
+ ${tag_prefix[0]} => prefix
111
+ ${tag_prefix[1]} => prefix.test
112
+ ${tag_prefix[-2]} => prefix.test.tag
113
+ ${tag_prefix[-1]} => prefix.test.tag.suffix
114
+
115
+ * ${tag\_suffix[N]} Tag parts after and on the index N. For example,
116
+
117
+ Input tag: prefix.test.tag.suffix
118
+
119
+ ${tag_suffix[0]} => prefix.test.tag.suffix
120
+ ${tag_suffix[1]} => test.tag.suffix
121
+ ${tag_suffix[-2]} => tag.suffix
122
+ ${tag_suffix[-1]} => suffix
106
123
 
107
124
  It is also possible to write a ruby code in placeholders if you set `enable_ruby true` option, so you may write some codes as
108
125
 
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.name = "fluent-plugin-record-reformer"
6
- gem.version = "0.2.1"
6
+ gem.version = "0.2.2"
7
7
  gem.authors = ["Naotoshi Seo"]
8
8
  gem.email = "sonots@gmail.com"
9
9
  gem.homepage = "https://github.com/sonots/fluent-plugin-record-reformer"
@@ -6,10 +6,6 @@ module Fluent
6
6
 
7
7
  def initialize
8
8
  super
9
- # require utilities for placeholder
10
- require 'pathname'
11
- require 'uri'
12
- require 'cgi'
13
9
  end
14
10
 
15
11
  config_param :output_tag, :string
@@ -42,6 +38,10 @@ module Fluent
42
38
 
43
39
  @placeholder_expander =
44
40
  if @enable_ruby
41
+ # require utilities which would be used in ruby placeholders
42
+ require 'pathname'
43
+ require 'uri'
44
+ require 'cgi'
45
45
  RubyPlaceholderExpander.new
46
46
  else
47
47
  PlaceholderExpander.new
@@ -59,19 +59,21 @@ module Fluent
59
59
 
60
60
  def emit(tag, es, chain)
61
61
  tag_parts = tag.split('.')
62
+ tag_prefix = tag_prefix(tag_parts)
63
+ tag_suffix = tag_suffix(tag_parts)
62
64
  es.each { |time, record|
63
- new_tag, new_record = reform(@output_tag, record, tag, tag_parts, @time_proc.call(time))
65
+ new_tag, new_record = reform(@output_tag, record, tag, tag_parts, tag_prefix, tag_suffix, @time_proc.call(time))
64
66
  Engine.emit(new_tag, time, new_record)
65
67
  }
66
68
  chain.next
67
69
  rescue => e
68
- $log.warn "record_reformer: #{e.class} #{e.message} #{e.backtrace.join(', ')}"
70
+ $log.warn "record_reformer: #{e.class} #{e.message} #{e.backtrace.first}"
69
71
  end
70
72
 
71
73
  private
72
74
 
73
- def reform(output_tag, record, tag, tag_parts, time)
74
- @placeholder_expander.prepare_placeholders(record, tag, tag_parts, @hostname, time)
75
+ def reform(output_tag, record, tag, tag_parts, tag_prefix, tag_suffix, time)
76
+ @placeholder_expander.prepare_placeholders(record, tag, tag_parts, tag_prefix, tag_suffix, @hostname, time)
75
77
  new_tag = @placeholder_expander.expand(output_tag)
76
78
 
77
79
  new_record = @renew_record ? {} : record.dup
@@ -81,11 +83,30 @@ module Fluent
81
83
  [new_tag, new_record]
82
84
  end
83
85
 
86
+ def tag_prefix(tag_parts)
87
+ return [] if tag_parts.empty?
88
+ tag_prefix = [tag_parts.first]
89
+ 1.upto(tag_parts.size-1).each do |i|
90
+ tag_prefix[i] = "#{tag_prefix[i-1]}.#{tag_parts[i]}"
91
+ end
92
+ tag_prefix
93
+ end
94
+
95
+ def tag_suffix(tag_parts)
96
+ return [] if tag_parts.empty?
97
+ rev_tag_parts = tag_parts.reverse
98
+ rev_tag_suffix = [rev_tag_parts.first]
99
+ 1.upto(tag_parts.size-1).each do |i|
100
+ rev_tag_suffix[i] = "#{rev_tag_parts[i]}.#{rev_tag_suffix[i-1]}"
101
+ end
102
+ rev_tag_suffix.reverse
103
+ end
104
+
84
105
  class PlaceholderExpander
85
106
  # referenced https://github.com/fluent/fluent-plugin-rewrite-tag-filter, thanks!
86
107
  attr_reader :placeholders
87
108
 
88
- def prepare_placeholders(record, tag, tag_parts, hostname, time)
109
+ def prepare_placeholders(record, tag, tag_parts, tag_prefix, tag_suffix, hostname, time)
89
110
  placeholders = {
90
111
  '${time}' => time,
91
112
  '${tag}' => tag,
@@ -93,17 +114,27 @@ module Fluent
93
114
  }
94
115
 
95
116
  size = tag_parts.size
96
- tag_parts.each_with_index do |t, idx|
117
+
118
+ tag_parts.each_with_index { |t, idx|
97
119
  placeholders.store("${tag_parts[#{idx}]}", t)
98
120
  placeholders.store("${tag_parts[#{idx-size}]}", t) # support tag_parts[-1]
99
- end
100
- # tags is just for old version compatibility
101
- tag_parts.each_with_index do |t, idx|
121
+
122
+ # tags is just for old version compatibility
102
123
  placeholders.store("${tags[#{idx}]}", t)
103
124
  placeholders.store("${tags[#{idx-size}]}", t) # support tags[-1]
104
- end
125
+ }
126
+
127
+ tag_prefix.each_with_index { |t, idx|
128
+ placeholders.store("${tag_prefix[#{idx}]}", t)
129
+ placeholders.store("${tag_prefix[#{idx-size}]}", t) # support tag_prefix[-1]
130
+ }
105
131
 
106
- record.each {|k, v|
132
+ tag_suffix.each_with_index { |t, idx|
133
+ placeholders.store("${tag_suffix[#{idx}]}", t)
134
+ placeholders.store("${tag_suffix[#{idx-size}]}", t) # support tag_suffix[-1]
135
+ }
136
+
137
+ record.each { |k, v|
107
138
  placeholders.store("${#{k}}", v)
108
139
  }
109
140
 
@@ -111,10 +142,10 @@ module Fluent
111
142
  end
112
143
 
113
144
  def expand(str)
114
- str.gsub(/(\${[a-z_]+(\[-?[0-9]+\])?}|__[A-Z_]+__)/) do
115
- $log.warn "record_reformer: unknown placeholder `#{$1}` found in a tag `#{tag}`" unless @placeholders.include?($1)
145
+ str.gsub(/(\${[a-z_]+(\[-?[0-9]+\])?}|__[A-Z_]+__)/) {
146
+ $log.warn "record_reformer: unknown placeholder `#{$1}` found" unless @placeholders.include?($1)
116
147
  @placeholders[$1]
117
- end
148
+ }
118
149
  end
119
150
  end
120
151
 
@@ -126,12 +157,16 @@ module Fluent
126
157
  # @param [Hash] record the record, one of information
127
158
  # @param [String] tag the tag
128
159
  # @param [Array] tag_parts the tag parts (tag splitted by .)
160
+ # @param [Array] tag_prefix the tag prefix parts
161
+ # @param [Array] tag_suffix the tag suffix parts
129
162
  # @param [String] hostname the hostname
130
163
  # @param [Time] time the time
131
- def prepare_placeholders(record, tag, tag_parts, hostname, time)
164
+ def prepare_placeholders(record, tag, tag_parts, tag_prefix, tag_suffix, hostname, time)
132
165
  struct = UndefOpenStruct.new(record)
133
166
  struct.tag = tag
134
167
  struct.tags = struct.tag_parts = tag_parts # tags is for old version compatibility
168
+ struct.tag_prefix = tag_prefix
169
+ struct.tag_suffix = tag_suffix
135
170
  struct.time = time
136
171
  struct.hostname = hostname
137
172
  @placeholders = struct
@@ -10,7 +10,7 @@ describe Fluent::RecordReformerOutput do
10
10
  hostname ${hostname}
11
11
  tag ${tag}
12
12
  time ${time.strftime('%S')}
13
- message ${hostname} ${tag_parts.last} ${message}
13
+ message ${hostname} ${tag_parts.last} ${URI.escape(message)}
14
14
  ]
15
15
  let(:tag) { 'test.tag' }
16
16
  let(:tag_parts) { tag.split('.') }
@@ -31,8 +31,8 @@ describe Fluent::RecordReformerOutput do
31
31
  let(:time) { Time.now }
32
32
  let(:emit) do
33
33
  driver.run do
34
- driver.emit({'foo'=>'bar', 'message' => 1}, time.to_i)
35
- driver.emit({'foo'=>'bar', 'message' => 2}, time.to_i)
34
+ driver.emit({'foo'=>'bar', 'message' => '1'}, time.to_i)
35
+ driver.emit({'foo'=>'bar', 'message' => '2'}, time.to_i)
36
36
  end
37
37
  end
38
38
 
@@ -176,5 +176,66 @@ describe Fluent::RecordReformerOutput do
176
176
  end
177
177
  it { emit }
178
178
  end
179
+
180
+ context '${tag_prefix[N]} and ${tag_suffix[N]}' do
181
+ let(:config) {%[
182
+ type reformed
183
+ output_tag ${tag_suffix[-2]}
184
+ enable_ruby no
185
+
186
+ hostname ${hostname}
187
+ tag ${tag}
188
+ time ${time}
189
+ message ${tag_prefix[1]} ${tag_prefix[-2]} ${tag_suffix[2]} ${tag_suffix[-3]} ${message}
190
+ ]}
191
+ let(:tag) { 'prefix.test.tag.suffix' }
192
+ let(:tag_parts) { tag.split('.') }
193
+ before do
194
+ Fluent::Engine.stub(:now).and_return(time)
195
+ Fluent::Engine.should_receive(:emit).with("tag.suffix", time.to_i, {
196
+ 'foo' => 'bar',
197
+ 'message' => "prefix.test prefix.test.tag tag.suffix test.tag.suffix 1",
198
+ 'hostname' => hostname,
199
+ 'tag' => tag,
200
+ 'time' => time.to_i.to_s, # hmm, want to remove ${time} placeholder
201
+ })
202
+ Fluent::Engine.should_receive(:emit).with("tag.suffix", time.to_i, {
203
+ 'foo' => 'bar',
204
+ 'message' => "prefix.test prefix.test.tag tag.suffix test.tag.suffix 2",
205
+ 'hostname' => hostname,
206
+ 'tag' => tag,
207
+ 'time' => time.to_i.to_s, # hmm, want to remove ${time} placeholder
208
+ })
209
+ end
210
+ it { emit }
211
+ end
212
+
213
+ context '${tag_prefix[N]} and ${tag_suffix[N]} with ruby enabled' do
214
+ let(:config) { CONFIG + %[
215
+ test_tag ${tag_prefix[1]} ${tag_prefix[-2]} ${tag_suffix[2]} ${tag_suffix[-3]}
216
+ ]}
217
+ let(:tag) { 'prefix.test.tag.suffix' }
218
+ let(:tag_parts) { tag.split('.') }
219
+ before do
220
+ Fluent::Engine.stub(:now).and_return(time)
221
+ Fluent::Engine.should_receive(:emit).with("reformed.#{tag}", time.to_i, {
222
+ 'foo' => 'bar',
223
+ 'message' => "#{hostname} #{tag_parts.last} 1",
224
+ 'hostname' => hostname,
225
+ 'tag' => tag,
226
+ 'time' => time.strftime('%S'),
227
+ 'test_tag' => "prefix.test prefix.test.tag tag.suffix test.tag.suffix",
228
+ })
229
+ Fluent::Engine.should_receive(:emit).with("reformed.#{tag}", time.to_i, {
230
+ 'foo' => 'bar',
231
+ 'message' => "#{hostname} #{tag_parts.last} 2",
232
+ 'hostname' => hostname,
233
+ 'tag' => tag,
234
+ 'time' => time.strftime('%S'),
235
+ 'test_tag' => "prefix.test prefix.test.tag tag.suffix test.tag.suffix",
236
+ })
237
+ end
238
+ it { emit }
239
+ end
179
240
  end
180
241
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-record-reformer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-15 00:00:00.000000000 Z
11
+ date: 2014-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd