fluent-plugin-flatten 0.0.2 → 0.0.3

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.
data/README.md CHANGED
@@ -4,17 +4,20 @@
4
4
 
5
5
  ### FlattenOutput
6
6
 
7
- Fluentd output plugin to flatten JSON-formatted string values in records to top level key/value-s.
7
+ Fluentd plugin to extract values for nested key paths and re-emit them as flat tag/record pairs.
8
8
 
9
9
  ## Synopsis
10
10
 
11
- When you have a config as below:
11
+ Imagin you have a config as below:
12
12
 
13
13
  ```
14
14
  <match test.**>
15
15
  type flatten
16
+
16
17
  key foo
17
- add_tag_prefix flattened.
18
+ add_tag_prefix flattened.
19
+ remove_tag_prefix test.
20
+ inner_key value_for_flat_key
18
21
  </match>
19
22
  ```
20
23
 
@@ -27,20 +30,20 @@ And you feed such a value into fluentd:
27
30
  }
28
31
  ```
29
32
 
30
- Then you'll get:
33
+ Then you'll get re-emmited tag/record-s below:
31
34
 
32
35
  ```
33
- "flattened.test" => {
34
- "foo" => '{"bar" : {"qux" : "quux", "hoe" : "poe" }, "baz" : "bazz" }',
35
- "hoge" => "fuga",
36
-
37
- "foo.bar.qux" => "quux",
38
- "foo.bar.hoe" => "poe",
39
- "foo.baz" => "bazz"
40
- }
36
+ "flattened.foo.bar.qux" => { "value_for_flat_key" => "quux" }
37
+ "flattened.foo.bar.hoe" => { "value_for_flat_key" => "poe" }
38
+ "flattened.foo.baz" => { "value_for_flat_key" => "bazz" }
41
39
  ```
42
40
 
43
- That is, JSON-formatted string in the value of the key `foo` is flattened and now put into the top level of the hash.
41
+ That is to say:
42
+
43
+ 1. The JSON-formatted string in the value related to the key `foo` is inflated to a `Hash`.
44
+ 2. The values are extracted as to be related to the nested key paths (`foo.bar.baz`).
45
+ 3. This plugin re-emits them as new tag/record pairs.
46
+ 4. Key/value pairs whose keys don't match `foo` are ignored (`"hoge" => "fuga"`).
44
47
 
45
48
  ## Configuration
46
49
 
@@ -55,6 +58,10 @@ These params are included from `Fluent::HandleTagNameMixin`. See that code for d
55
58
 
56
59
  You must add at least one of these params.
57
60
 
61
+ ### inner_key
62
+
63
+ This plugin sets `value` for this option as a default if it's not set.
64
+
58
65
  ## Installation
59
66
 
60
67
  Add this line to your application's Gemfile:
@@ -1,11 +1,11 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'fluent-plugin-flatten'
3
- gem.version = '0.0.2'
3
+ gem.version = '0.0.3'
4
4
  gem.authors = ['Kentaro Kuribayashi']
5
5
  gem.email = ['kentarok@gmail.com']
6
6
  gem.homepage = 'http://github.com/kentaro/fluent-plugin-flatten'
7
- gem.description = %q{Fluentd plugin to flatten JSON-formatted string values to top level key/value-s.}
8
- gem.summary = %q{Fluentd plugin to flatten JSON-formatted string values to top level key/value-s.}
7
+ gem.description = %q{Fluentd plugin to extract values for nested key paths and re-emit them as flat tag/record pairs.}
8
+ gem.summary = %q{Fluentd plugin to extract values for nested key paths and re-emit them as flat tag/record pairs.}
9
9
 
10
10
  gem.files = `git ls-files`.split($\)
11
11
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -4,27 +4,34 @@ module Fluent
4
4
  class FlattenOutput < Output
5
5
  include Fluent::HandleTagNameMixin
6
6
  class Error < StandardError; end
7
+
7
8
  Fluent::Plugin.register_output('flatten', self)
8
9
 
9
- config_param :key, :string
10
+ config_param :key, :string
11
+ config_param :inner_key, :string, :default => 'value'
10
12
 
11
13
  def configure(conf)
12
14
  super
13
15
 
14
- if !self.remove_tag_prefix && !self.remove_tag_suffix && !self.add_tag_prefix && !self.add_tag_suffix
15
- raise ConfigError, "out_flatten: Set remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix."
16
+ if (
17
+ !remove_tag_prefix &&
18
+ !remove_tag_suffix &&
19
+ !add_tag_prefix &&
20
+ !add_tag_suffix
21
+ )
22
+ raise ConfigError, "out_flatten: At least one of remove_tag_prefix/remove_tag_suffix/add_tag_prefix/add_tag_suffix is required to be set"
16
23
  end
17
24
  end
18
25
 
19
26
  def emit(tag, es, chain)
20
27
  es.each do |time, record|
21
- _tag = tag.clone
22
28
  flattened = flatten(record)
23
- filter_record(_tag, time, flattened)
24
- if tag != _tag
25
- Engine.emit(_tag, time, flattened)
26
- else
27
- $log.warn "Drop record #{record} tag '#{tag}' was not replaced. Can't emit record, cause infinity looping. Set remove_tag_prefix, remove_tag_suffix, add_tag_prefix or add_tag_suffix correctly."
29
+
30
+ flattened.each do |keypath, value|
31
+ tag_with_keypath = [tag.clone, keypath].join('.')
32
+ filter_record(tag_with_keypath, time, value)
33
+
34
+ Engine.emit(tag_with_keypath, time, value)
28
35
  end
29
36
  end
30
37
 
@@ -32,31 +39,34 @@ module Fluent
32
39
  end
33
40
 
34
41
  def flatten(record)
35
- if record.has_key?(@key)
36
- hash = JSON.parse(record[@key])
37
- record = record.merge(_flatten(@key, hash))
38
- end
42
+ flattend = {}
39
43
 
40
- record
41
- end
44
+ if record.has_key?(key)
45
+ hash = JSON.parse(record[key])
46
+ processor = lambda do |root, hash|
47
+ unless hash.is_a?(Hash)
48
+ raise Error.new('The value to be flattened must be a Hash: #{hash}')
49
+ end
42
50
 
43
- def _flatten(root, hash)
44
- unless hash.is_a?(Hash)
45
- raise Error.new('The value to be flattened must be a Hash: #{hash}')
46
- end
51
+ flattened = {}
47
52
 
48
- flattened = {}
49
- hash.each do |path, value|
50
- key = [root, path].join('.')
53
+ hash.each do |path, value|
54
+ keypath = [root, path].join('.')
51
55
 
52
- if value.is_a?(String)
53
- flattened[key] = value
54
- else
55
- flattened = flattened.merge(_flatten(key, value))
56
+ if value.is_a?(Hash)
57
+ flattened = flattened.merge(processor.call(keypath, value))
58
+ else
59
+ flattened[keypath] = { inner_key => value }
60
+ end
61
+ end
62
+
63
+ flattened
56
64
  end
65
+
66
+ flattend = processor.call(key, hash)
57
67
  end
58
68
 
59
- flattened
69
+ flattend
60
70
  end
61
71
  end
62
72
  end
@@ -5,19 +5,57 @@ class FlattenOutputTest < Test::Unit::TestCase
5
5
  Fluent::Test.setup
6
6
  end
7
7
 
8
- CONFIG = %[
9
- key foo
10
- add_tag_prefix flattened.
8
+ DEFAULT_CONFIG = %[
9
+ key foo
10
+ add_tag_prefix flattened.
11
+ remove_tag_prefix test.
11
12
  ]
12
13
 
13
- def create_driver(conf = CONFIG, tag = 'test')
14
+ def create_driver(conf = DEFAULT_CONFIG, tag = 'test')
14
15
  Fluent::Test::OutputTestDriver.new(Fluent::FlattenOutput, tag).configure(conf)
15
16
  end
16
17
 
17
18
  def test_configure
19
+ # when `inner_key` option is not set
20
+ d1 = create_driver
21
+
22
+ assert_equal 'foo', d1.instance.key
23
+ assert_equal 'flattened.', d1.instance.add_tag_prefix
24
+ assert_equal /^test\./, d1.instance.remove_tag_prefix
25
+ assert_equal 'value', d1.instance.inner_key # default value
26
+
27
+ # when `inner_key` is set
28
+ d2 = create_driver(%[
29
+ key foo
30
+ add_tag_prefix flattened.
31
+ remove_tag_prefix test.
32
+ inner_key value_for_flat_key
33
+ ])
34
+
35
+ assert_equal 'foo', d2.instance.key
36
+ assert_equal 'flattened.', d2.instance.add_tag_prefix
37
+ assert_equal /^test\./, d2.instance.remove_tag_prefix
38
+ assert_equal 'value_for_flat_key', d2.instance.inner_key
39
+
40
+ # when mandatory keys not set
41
+ assert_raise(Fluent::ConfigError) do
42
+ create_driver(%[
43
+ key foo
44
+ inner_key value_for_keypath
45
+ ])
46
+ end
47
+ end
48
+
49
+ def test_flatten
18
50
  d = create_driver
19
- assert_equal 'foo', d.instance.key
20
- assert_equal 'flattened.', d.instance.add_tag_prefix
51
+
52
+ flattened = d.instance.flatten({ 'foo' => '{"bar" : "baz"}', 'hoge' => 'fuga' })
53
+ assert_equal({ 'foo.bar' => { 'value' => 'baz' } }, flattened)
54
+
55
+ # when not hash value is passed
56
+ assert_raise(Fluent::FlattenOutput::Error) do
57
+ d.instance.flatten({ 'foo' => '["bar", "baz"]' })
58
+ end
21
59
  end
22
60
 
23
61
  def test_emit
@@ -29,15 +67,22 @@ class FlattenOutputTest < Test::Unit::TestCase
29
67
  end
30
68
  emits = d.emits
31
69
 
32
- assert_equal 3, emits[0][2].count
33
- assert_equal 'baz', emits[0][2]['foo.bar']
70
+ assert_equal 4, emits.count
71
+
72
+ # ["flattened.foo.bar", 1354689632, {"value"=>"baz"}]
73
+ assert_equal 'flattened.foo.bar', emits[0][0]
74
+ assert_equal 'baz', emits[0][2]['value']
75
+
76
+ # ["flattened.foo.bar.qux", 1354689632, {"value"=>"quux"}]
77
+ assert_equal 'flattened.foo.bar.qux', emits[1][0]
78
+ assert_equal 'quux', emits[1][2]['value']
34
79
 
35
- assert_equal 5, emits[1][2].count
36
- assert_equal 'quux', emits[1][2]['foo.bar.qux']
37
- assert_equal 'poe', emits[1][2]['foo.bar.hoe']
38
- assert_equal 'bazz', emits[1][2]['foo.baz']
80
+ # ["flattened.foo.bar.hoe", 1354689632, {"value"=>"poe"}]
81
+ assert_equal 'flattened.foo.bar.hoe', emits[2][0]
82
+ assert_equal 'poe', emits[2][2]['value']
39
83
 
40
- assert_equal 'flattened.test', emits[0][0]
41
- assert_equal 'flattened.test', emits[1][0]
84
+ # ["flattened.foo.bar.baz", 1354689632, {"value"=>"bazz"}]
85
+ assert_equal 'flattened.foo.baz', emits[3][0]
86
+ assert_equal 'bazz', emits[3][2]['value']
42
87
  end
43
88
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-flatten
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-29 00:00:00.000000000 Z
12
+ date: 2012-12-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -59,7 +59,8 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
- description: Fluentd plugin to flatten JSON-formatted string values to top level key/value-s.
62
+ description: Fluentd plugin to extract values for nested key paths and re-emit them
63
+ as flat tag/record pairs.
63
64
  email:
64
65
  - kentarok@gmail.com
65
66
  executables: []
@@ -98,7 +99,8 @@ rubyforge_project:
98
99
  rubygems_version: 1.8.23
99
100
  signing_key:
100
101
  specification_version: 3
101
- summary: Fluentd plugin to flatten JSON-formatted string values to top level key/value-s.
102
+ summary: Fluentd plugin to extract values for nested key paths and re-emit them as
103
+ flat tag/record pairs.
102
104
  test_files:
103
105
  - test/plugin/test_out_flatten.rb
104
106
  - test/test_helper.rb