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 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