fluent-plugin-record-reformer 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +23 -6
- data/fluent-plugin-record-reformer.gemspec +1 -1
- data/lib/fluent/plugin/out_record_reformer.rb +54 -19
- data/spec/out_record_reformer_spec.rb +64 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f79ddbaecca21d91a17132b991c9f031b5a19b01
|
4
|
+
data.tar.gz: e6f3777a3a2fdc0fe14887c3d745dfd38e39c60a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5193f5ee853ff6af02e119759bc8ec6a6c018f1a69bad34511757f62bd95918c2c3dc766eb3bc485ad47e65829a88e44da16e63a5238150314b9dca4f137e678
|
7
|
+
data.tar.gz: dc3313b3754851512e110247fd0c184c9130e9c2137f5c6adc39c62c173e9c6f2a3379b55b29dd2bf453c88e036722817a19455e72389e05e25f00e02da77585
|
data/CHANGELOG.md
CHANGED
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}
|
102
|
-
* ${tag}
|
103
|
-
* ${time}
|
104
|
-
* ${tags[N]}
|
105
|
-
* ${tag\_parts[N]}
|
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.
|
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.
|
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
|
-
|
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
|
-
|
100
|
-
|
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
|
-
|
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
|
-
|
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_]+__)/)
|
115
|
-
$log.warn "record_reformer: unknown placeholder `#{$1}` found
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2014-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|