fluent-plugin-record-reformer 0.6.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: beaea68d997ac0ad945eed7538383648b364365a
4
- data.tar.gz: a09b4a368bda8e78d1d9b302710eb2d64ab0982b
3
+ metadata.gz: db209a964b20147c182f8bb1276a2d867c470859
4
+ data.tar.gz: 78013a0f27ac7e155be2465afaa4d71b8f02a679
5
5
  SHA512:
6
- metadata.gz: 2860304c62904d3805abd0bbae0ae41015c22c046a37219c4834c3d08d986c59c3c53c51c3e1998cbbdb9f169e0e0bcab38a1a567d4dd848c2887b36f3186b69
7
- data.tar.gz: b629578c947c7b663277eafdfecc36bcd034c7d64b8d3c3b44f9940e23907a8bcfe9ab3943e08707aa51a141310f7304346b92a8598ac2e8344c269f0a16e10e
6
+ metadata.gz: 11dd3f611b7534410ca27776b703268d2ffe84db4f4b576d228629e268c2b0d168fbd7e0a96d638dd07a6ef70cbfe153dbfd98912c76d01694b5fe550e28084b
7
+ data.tar.gz: 399ebe1048befb5e396f86d55858e2eec000035dddc327218115bfc262e7fbf31c341d48449f8eedb30775a71ff453f9966cd9265fde9f10dbb0b88538b5c95a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.7.0 (2015/06/19)
2
+
3
+ Enhancements
4
+
5
+ * Add `auto_typecast` option (thanks to @piroor)
6
+
1
7
  ## 0.6.3 (2015/05/27)
2
8
 
3
9
  Fixes:
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` overwrite time of events with value of field `foo` if exist. The value of `foo` must be unix time.
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.3"
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(log)
77
+ RubyPlaceholderExpander.new(placeholder_expander_params)
73
78
  else
74
- PlaceholderExpander.new(log)
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(log)
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
- log.warn "record_reformer: unknown placeholder `#{$1}` found" unless @placeholders.include?($1)
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(log)
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
- d.emit({'eventType0' => 'bar', 'message' => msg}, @time)
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.6.3
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-05-27 00:00:00.000000000 Z
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