fluent-plugin-record-reformer 0.6.3 → 0.7.0
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +20 -1
- data/example.conf +20 -0
- data/fluent-plugin-record-reformer.gemspec +1 -1
- data/lib/fluent/plugin/out_record_reformer.rb +39 -11
- data/test/test_out_record_reformer.rb +114 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db209a964b20147c182f8bb1276a2d867c470859
|
4
|
+
data.tar.gz: 78013a0f27ac7e155be2465afaa4d71b8f02a679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11dd3f611b7534410ca27776b703268d2ffe84db4f4b576d228629e268c2b0d168fbd7e0a96d638dd07a6ef70cbfe153dbfd98912c76d01694b5fe550e28084b
|
7
|
+
data.tar.gz: 399ebe1048befb5e396f86d55858e2eec000035dddc327218115bfc262e7fbf31c341d48449f8eedb30775a71ff453f9966cd9265fde9f10dbb0b88538b5c95a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -92,7 +92,7 @@ This results in same, but please note that following option parameters are reser
|
|
92
92
|
|
93
93
|
- renew\_time\_key *string*
|
94
94
|
|
95
|
-
`renew_time_key foo`
|
95
|
+
`renew_time_key foo` overwrites the time of events with a value of the record field `foo` if exists. The value of `foo` must be a unix time.
|
96
96
|
|
97
97
|
- keep_keys
|
98
98
|
|
@@ -105,6 +105,25 @@ This results in same, but please note that following option parameters are reser
|
|
105
105
|
Enable to use ruby codes in placeholders. See `Placeholders` section.
|
106
106
|
Default is `true` (just for lower version compatibility).
|
107
107
|
|
108
|
+
- auto_typecast *bool*
|
109
|
+
|
110
|
+
Automatically cast the field types. Default is false.
|
111
|
+
NOTE: This option is effective only for field values comprised of a single placeholder.
|
112
|
+
|
113
|
+
Effective Examples:
|
114
|
+
|
115
|
+
foo ${foo}
|
116
|
+
|
117
|
+
Non-Effective Examples:
|
118
|
+
|
119
|
+
foo ${foo}${bar}
|
120
|
+
foo ${foo}bar
|
121
|
+
foo 1
|
122
|
+
|
123
|
+
Internally, this **keeps** the type of value if the value text is comprised of a single placeholder, otherwise, values are treated as strings.
|
124
|
+
|
125
|
+
When you need to cast field types manually, [out_typecast](https://github.com/tarom/fluent-plugin-typecast) and [filter_typecast](https://github.com/sonots/fluent-plugin-filter_typecast) are available.
|
126
|
+
|
108
127
|
## Placeholders
|
109
128
|
|
110
129
|
The keys of input json are available as placeholders. In the above example,
|
data/example.conf
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
<source>
|
2
|
+
type dummy
|
3
|
+
tag dummy
|
4
|
+
dummy {"message":"foo","time":1432732710,"members":["Alice"]}
|
5
|
+
</source>
|
6
|
+
|
7
|
+
<match dummy>
|
8
|
+
type record_reformer
|
9
|
+
renew_time_key time
|
10
|
+
tag reformed.${tag}
|
11
|
+
enable_ruby true
|
12
|
+
auto_typecast true
|
13
|
+
<record>
|
14
|
+
members ${members + ["Bob"]}
|
15
|
+
</record>
|
16
|
+
</match>
|
17
|
+
|
18
|
+
<match reformed.**>
|
19
|
+
type stdout
|
20
|
+
</match>
|
@@ -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.
|
6
|
+
gem.version = "0.7.0"
|
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"
|
@@ -16,8 +16,9 @@ module Fluent
|
|
16
16
|
config_param :renew_record, :bool, :default => false
|
17
17
|
config_param :renew_time_key, :string, :default => nil
|
18
18
|
config_param :enable_ruby, :bool, :default => true # true for lower version compatibility
|
19
|
+
config_param :auto_typecast, :bool, :default => false # false for lower version compatibility
|
19
20
|
|
20
|
-
BUILTIN_CONFIGURATIONS = %W(type tag output_tag remove_keys renew_record keep_keys enable_ruby renew_time_key)
|
21
|
+
BUILTIN_CONFIGURATIONS = %W(type tag output_tag remove_keys renew_record keep_keys enable_ruby renew_time_key auto_typecast)
|
21
22
|
|
22
23
|
# To support log_level option implemented by Fluentd v0.10.43
|
23
24
|
unless method_defined?(:log)
|
@@ -63,15 +64,19 @@ module Fluent
|
|
63
64
|
raise Fluent::ConfigError, "out_record_reformer: `tag` must be specified"
|
64
65
|
end
|
65
66
|
|
67
|
+
placeholder_expander_params = {
|
68
|
+
:log => log,
|
69
|
+
:auto_typecast => @auto_typecast,
|
70
|
+
}
|
66
71
|
@placeholder_expander =
|
67
72
|
if @enable_ruby
|
68
73
|
# require utilities which would be used in ruby placeholders
|
69
74
|
require 'pathname'
|
70
75
|
require 'uri'
|
71
76
|
require 'cgi'
|
72
|
-
RubyPlaceholderExpander.new(
|
77
|
+
RubyPlaceholderExpander.new(placeholder_expander_params)
|
73
78
|
else
|
74
|
-
PlaceholderExpander.new(
|
79
|
+
PlaceholderExpander.new(placeholder_expander_params)
|
75
80
|
end
|
76
81
|
|
77
82
|
@hostname = Socket.gethostname
|
@@ -137,7 +142,7 @@ module Fluent
|
|
137
142
|
elsif value.is_a?(Hash)
|
138
143
|
new_value = {}
|
139
144
|
value.each_pair do |k, v|
|
140
|
-
new_value[@placeholder_expander.expand(k)] = expand_placeholders(v)
|
145
|
+
new_value[@placeholder_expander.expand(k, true)] = expand_placeholders(v)
|
141
146
|
end
|
142
147
|
elsif value.is_a?(Array)
|
143
148
|
new_value = []
|
@@ -172,8 +177,9 @@ module Fluent
|
|
172
177
|
class PlaceholderExpander
|
173
178
|
attr_reader :placeholders, :log
|
174
179
|
|
175
|
-
def initialize(
|
176
|
-
@log = log
|
180
|
+
def initialize(params)
|
181
|
+
@log = params[:log]
|
182
|
+
@auto_typecast = params[:auto_typecast]
|
177
183
|
end
|
178
184
|
|
179
185
|
def prepare_placeholders(time, record, opts)
|
@@ -195,19 +201,34 @@ module Fluent
|
|
195
201
|
@placeholders = placeholders
|
196
202
|
end
|
197
203
|
|
198
|
-
def expand(str)
|
204
|
+
def expand(str, force_stringify=false)
|
205
|
+
if @auto_typecast and !force_stringify
|
206
|
+
single_placeholder_matched = str.match(/\A(\${[^}]+}|__[A-Z_]+__)\z/)
|
207
|
+
if single_placeholder_matched
|
208
|
+
log_unknown_placeholder($1)
|
209
|
+
return @placeholders[single_placeholder_matched[1]]
|
210
|
+
end
|
211
|
+
end
|
199
212
|
str.gsub(/(\${[^}]+}|__[A-Z_]+__)/) {
|
200
|
-
|
213
|
+
log_unknown_placeholder($1)
|
201
214
|
@placeholders[$1]
|
202
215
|
}
|
203
216
|
end
|
217
|
+
|
218
|
+
private
|
219
|
+
def log_unknown_placeholder(placeholder)
|
220
|
+
unless @placeholders.include?(placeholder)
|
221
|
+
log.warn "record_reformer: unknown placeholder `#{placeholder}` found"
|
222
|
+
end
|
223
|
+
end
|
204
224
|
end
|
205
225
|
|
206
226
|
class RubyPlaceholderExpander
|
207
227
|
attr_reader :placeholders, :log
|
208
228
|
|
209
|
-
def initialize(
|
210
|
-
@log = log
|
229
|
+
def initialize(params)
|
230
|
+
@log = params[:log]
|
231
|
+
@auto_typecast = params[:auto_typecast]
|
211
232
|
end
|
212
233
|
|
213
234
|
# Get placeholders as a struct
|
@@ -225,7 +246,14 @@ module Fluent
|
|
225
246
|
# Replace placeholders in a string
|
226
247
|
#
|
227
248
|
# @param [String] str the string to be replaced
|
228
|
-
def expand(str)
|
249
|
+
def expand(str, force_stringify=false)
|
250
|
+
if @auto_typecast and !force_stringify
|
251
|
+
single_placeholder_matched = str.match(/\A\${([^}]+)}\z/)
|
252
|
+
if single_placeholder_matched
|
253
|
+
code = single_placeholder_matched[1]
|
254
|
+
return eval code, @placeholders.instance_eval { binding }
|
255
|
+
end
|
256
|
+
end
|
229
257
|
interpolated = str.gsub(/\$\{([^}]+)\}/, '#{\1}') # ${..} => #{..}
|
230
258
|
eval "\"#{interpolated}\"", @placeholders.instance_eval { binding }
|
231
259
|
rescue => e
|
@@ -27,7 +27,12 @@ class RecordReformerOutputTest < Test::Unit::TestCase
|
|
27
27
|
d = create_driver(config, use_v1)
|
28
28
|
d.run do
|
29
29
|
msgs.each do |msg|
|
30
|
-
|
30
|
+
record = {
|
31
|
+
'eventType0' => 'bar',
|
32
|
+
'message' => msg,
|
33
|
+
}
|
34
|
+
record = record.merge(msg) if msg.is_a?(Hash)
|
35
|
+
d.emit(record, @time)
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
@@ -357,6 +362,114 @@ EOC
|
|
357
362
|
end
|
358
363
|
end
|
359
364
|
end
|
365
|
+
|
366
|
+
test "disabled autodetectction of value type with enable_ruby #{enable_ruby}" do
|
367
|
+
config = %[
|
368
|
+
tag tag
|
369
|
+
enable_ruby #{enable_ruby}
|
370
|
+
auto_typecast false
|
371
|
+
<record>
|
372
|
+
single ${source}
|
373
|
+
multiple ${source}${source}
|
374
|
+
with_prefix prefix-${source}
|
375
|
+
with_suffix ${source}-suffix
|
376
|
+
</record>
|
377
|
+
]
|
378
|
+
msgs = [
|
379
|
+
{ "source" => "string" },
|
380
|
+
{ "source" => 123 },
|
381
|
+
{ "source" => [1, 2] },
|
382
|
+
{ "source" => {a:1, b:2} },
|
383
|
+
{ "source" => nil },
|
384
|
+
]
|
385
|
+
expected_results = [
|
386
|
+
{ :single => "string",
|
387
|
+
:multiple => "stringstring",
|
388
|
+
:with_prefix => "prefix-string",
|
389
|
+
:with_suffix => "string-suffix" },
|
390
|
+
{ :single => 123.to_s,
|
391
|
+
:multiple => "#{123.to_s}#{123.to_s}",
|
392
|
+
:with_prefix => "prefix-#{123.to_s}",
|
393
|
+
:with_suffix => "#{123.to_s}-suffix" },
|
394
|
+
{ :single => [1, 2].to_s,
|
395
|
+
:multiple => "#{[1, 2].to_s}#{[1, 2].to_s}",
|
396
|
+
:with_prefix => "prefix-#{[1, 2].to_s}",
|
397
|
+
:with_suffix => "#{[1, 2].to_s}-suffix" },
|
398
|
+
{ :single => {a:1, b:2}.to_s,
|
399
|
+
:multiple => "#{{a:1, b:2}.to_s}#{{a:1, b:2}.to_s}",
|
400
|
+
:with_prefix => "prefix-#{{a:1, b:2}.to_s}",
|
401
|
+
:with_suffix => "#{{a:1, b:2}.to_s}-suffix" },
|
402
|
+
{ :single => nil.to_s,
|
403
|
+
:multiple => "#{nil.to_s}#{nil.to_s}",
|
404
|
+
:with_prefix => "prefix-#{nil.to_s}",
|
405
|
+
:with_suffix => "#{nil.to_s}-suffix" },
|
406
|
+
]
|
407
|
+
actual_results = []
|
408
|
+
es = emit(config, use_v1, msgs)
|
409
|
+
es.each_with_index do |(tag, time, record), i|
|
410
|
+
actual_results << {
|
411
|
+
:single => record["single"],
|
412
|
+
:multiple => record["multiple"],
|
413
|
+
:with_prefix => record["with_prefix"],
|
414
|
+
:with_suffix => record["with_suffix"],
|
415
|
+
}
|
416
|
+
end
|
417
|
+
assert_equal(expected_results, actual_results)
|
418
|
+
end
|
419
|
+
|
420
|
+
test "enabled autodetectction of value type with enable_ruby #{enable_ruby}" do
|
421
|
+
config = %[
|
422
|
+
tag tag
|
423
|
+
enable_ruby #{enable_ruby}
|
424
|
+
auto_typecast true
|
425
|
+
<record>
|
426
|
+
single ${source}
|
427
|
+
multiple ${source}${source}
|
428
|
+
with_prefix prefix-${source}
|
429
|
+
with_suffix ${source}-suffix
|
430
|
+
</record>
|
431
|
+
]
|
432
|
+
msgs = [
|
433
|
+
{ "source" => "string" },
|
434
|
+
{ "source" => 123 },
|
435
|
+
{ "source" => [1, 2] },
|
436
|
+
{ "source" => {a:1, b:2} },
|
437
|
+
{ "source" => nil },
|
438
|
+
]
|
439
|
+
expected_results = [
|
440
|
+
{ :single => "string",
|
441
|
+
:multiple => "stringstring",
|
442
|
+
:with_prefix => "prefix-string",
|
443
|
+
:with_suffix => "string-suffix" },
|
444
|
+
{ :single => 123,
|
445
|
+
:multiple => "#{123.to_s}#{123.to_s}",
|
446
|
+
:with_prefix => "prefix-#{123.to_s}",
|
447
|
+
:with_suffix => "#{123.to_s}-suffix" },
|
448
|
+
{ :single => [1, 2],
|
449
|
+
:multiple => "#{[1, 2].to_s}#{[1, 2].to_s}",
|
450
|
+
:with_prefix => "prefix-#{[1, 2].to_s}",
|
451
|
+
:with_suffix => "#{[1, 2].to_s}-suffix" },
|
452
|
+
{ :single => {a:1, b:2},
|
453
|
+
:multiple => "#{{a:1, b:2}.to_s}#{{a:1, b:2}.to_s}",
|
454
|
+
:with_prefix => "prefix-#{{a:1, b:2}.to_s}",
|
455
|
+
:with_suffix => "#{{a:1, b:2}.to_s}-suffix" },
|
456
|
+
{ :single => nil,
|
457
|
+
:multiple => "#{nil.to_s}#{nil.to_s}",
|
458
|
+
:with_prefix => "prefix-#{nil.to_s}",
|
459
|
+
:with_suffix => "#{nil.to_s}-suffix" },
|
460
|
+
]
|
461
|
+
actual_results = []
|
462
|
+
es = emit(config, use_v1, msgs)
|
463
|
+
es.each_with_index do |(tag, time, record), i|
|
464
|
+
actual_results << {
|
465
|
+
:single => record["single"],
|
466
|
+
:multiple => record["multiple"],
|
467
|
+
:with_prefix => record["with_prefix"],
|
468
|
+
:with_suffix => record["with_suffix"],
|
469
|
+
}
|
470
|
+
end
|
471
|
+
assert_equal(expected_results, actual_results)
|
472
|
+
end
|
360
473
|
end
|
361
474
|
|
362
475
|
test 'unknown placeholder (enable_ruby no)' do
|
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.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Naotoshi Seo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- LICENSE
|
123
123
|
- README.md
|
124
124
|
- Rakefile
|
125
|
+
- example.conf
|
125
126
|
- fluent-plugin-record-reformer.gemspec
|
126
127
|
- lib/fluent/plugin/out_record_reformer.rb
|
127
128
|
- test/bench_out_record_reformer.rb
|