fluent-plugin-flatten 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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