fluent-plugin-record-modifier 0.3.0 → 0.4.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: 344506e1d7deb2d3211df17f02386283fa8a30ab
4
- data.tar.gz: 44e6d422823ddf0c686abe066b7da36fc96e4e19
3
+ metadata.gz: 3ff1d6de463980c890752f4eb32719f3f160c026
4
+ data.tar.gz: 4ed772c23ab2316e1bf064a9fd3c1ed498c1aae8
5
5
  SHA512:
6
- metadata.gz: 45f15173d92fa1d91e20c62337ffe757852bf42bd006c7847459ca61521cd21cc63b604715489cfec05555f8ce95ba91d182816e470c64771bb3e81cecacad17
7
- data.tar.gz: 7c63568717b13b17bdec90bf43c6edf30884639dd9d586efe85bd90f02787d99a7cbbd26484f6ab2676bdddb2facae032148307b0a35aec6c36428f0e602f3ca
6
+ metadata.gz: 2477196fe7d51f5d26546107d4b9a01907e97e3dc38a0d5a2a1a4cc8182f298d24abb996b197e3609cae7e0a534781b93f0d5bd802d7afc31c0297f2f5e31924
7
+ data.tar.gz: e0826bc7e9203ea5a6bf24f715b5b63d2b13a95c407a4d298cfd8b9f2f7c781afed10c69248774e8930b7a0f86cc1f569c75a9c2e3c00e689e3dffc4fe2f6e5d
@@ -1,9 +1,10 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 1.9.3
5
4
  - 2.0.0
6
- - 2.1.1
5
+ - 2.1
6
+ - 2.2.3
7
+ - 2.3.0
7
8
  - ruby-head
8
9
  - rbx
9
10
 
@@ -11,9 +12,13 @@ branches:
11
12
  only:
12
13
  - master
13
14
 
15
+ gemfile:
16
+ - Gemfile
17
+
14
18
  matrix:
15
19
  allow_failures:
16
20
  - rvm: ruby-head
17
21
  - rvm: rbx
18
22
 
23
+ before_install: gem update bundler
19
24
  script: bundle exec rake test
data/ChangeLog CHANGED
@@ -1,3 +1,10 @@
1
+ Release 0.4.0 - 2016/01/08
2
+
3
+ * Introduce <record> directive
4
+ * Support ${xxx} placeholders
5
+ https://github.com/repeatedly/fluent-plugin-record-modifier/pull/6
6
+
7
+
1
8
  Release 0.3.0 - 2015/06/09
2
9
 
3
10
  * Add record_modifier filter
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Output filter plugin for modifying each event record for [Fluentd](http://fluentd.org)
1
+ # Filter plugin for modifying each event record for [Fluentd](http://fluentd.org)
2
2
 
3
3
  Adding arbitary field to event record without custmizing existence plugin.
4
4
 
@@ -13,13 +13,16 @@ Use RubyGems:
13
13
 
14
14
  ## Configuration
15
15
 
16
- <match pattern>
17
- type record_modifier
18
- tag foo.filtered
16
+ Use `record_modifier` filter.
19
17
 
20
- gen_host ${hostname}
21
- foo bar
22
- </match>
18
+ <filter pattern>
19
+ @type record_modifier
20
+
21
+ <record>
22
+ gen_host ${hostname}
23
+ foo bar
24
+ </record>
25
+ </filter>
23
26
 
24
27
  If following record is passed:
25
28
 
@@ -33,6 +36,37 @@ then you got new record like below:
33
36
  {"message":"hello world!", "gen_host":"oreore-mac.local", "foo":"bar"}
34
37
  ```
35
38
 
39
+ You can also use `record_transformer` like `${xxx}` placeholders and access `tag`, `time`, `record` and `tag_parts` values by Ruby code.
40
+
41
+ <filter pattern>
42
+ @type record_modifier
43
+
44
+ <record>
45
+ tag ${tag}
46
+ tag_extract ${tag_parts[0]}-${tag_pars[1]}-foo
47
+ formatted_time ${Time.at(time).to_s}
48
+ new_field foo:${record['key1'] + record['dict']['key']}
49
+ </record>
50
+ </filter>
51
+
52
+ `record_modifier` is faster than `record_transformer`. See [this comment](https://github.com/repeatedly/fluent-plugin-record-modifier/pull/7#issuecomment-169843012).
53
+ But unlike `record_transformer`, `record_modifier` doesn't support following features for now.
54
+
55
+ - tag_suffix and tag_prefix
56
+ - dynamic key placeholder
57
+
58
+ ### record_modifier output
59
+
60
+ In v0.10, you can use `record_modifier` output to emulate filter. `record_modifier` output doesn't support `<record>` way.
61
+
62
+ <match pattern>
63
+ type record_modifier
64
+ tag foo.filtered
65
+
66
+ gen_host ${hostname}
67
+ foo bar
68
+ </match>
69
+
36
70
  ### char_encoding
37
71
 
38
72
  Fluentd including some plugins treats the logs as a BINARY by default to forward.
@@ -41,7 +75,7 @@ But an user sometimes processes the logs depends on their requirements, e.g. han
41
75
  `char_encoding` parameter is useful for this case.
42
76
 
43
77
  ```conf
44
- <match pattern>
78
+ <filter pattern>
45
79
  type record_modifier
46
80
 
47
81
  # set UTF-8 encoding information to string.
@@ -49,7 +83,7 @@ But an user sometimes processes the logs depends on their requirements, e.g. han
49
83
 
50
84
  # change char encoding from 'UTF-8' to 'EUC-JP'
51
85
  char_encoding utf-8:euc-jp
52
- </match>
86
+ </filter>
53
87
  ```
54
88
 
55
89
  ### remove_keys
@@ -58,12 +92,12 @@ The logs include needless record keys in some cases.
58
92
  You can remove it by using `remove_keys` parameter.
59
93
 
60
94
  ```conf
61
- <match pattern>
95
+ <filter pattern>
62
96
  type record_modifier
63
97
 
64
98
  # remove key1 and key2 keys from record
65
99
  remove_keys key1,key2
66
- </match>
100
+ </filter>
67
101
  ```
68
102
 
69
103
  If following record is passed:
@@ -80,7 +114,6 @@ then you got new record like below:
80
114
 
81
115
  ### Mixins
82
116
 
83
- * [SetTagKeyMixin](https://github.com/fluent/fluentd/blob/master/lib/fluent/mixin.rb#L181)
84
117
  * [fluent-mixin-config-placeholders](https://github.com/tagomoris/fluent-mixin-config-placeholders)
85
118
 
86
119
  ## TODO
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -20,4 +20,5 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency "fluentd", [">= 0.10.58", "< 2"]
21
21
  gem.add_dependency "fluent-mixin-config-placeholders", ">= 0.3.0"
22
22
  gem.add_development_dependency "rake", ">= 0.9.2"
23
+ gem.add_development_dependency("test-unit", ["~> 3.1.4"])
23
24
  end
@@ -7,19 +7,23 @@ module Fluent
7
7
  config_param :char_encoding, :string, :default => nil
8
8
  config_param :remove_keys, :string, :default => nil
9
9
 
10
- include SetTagKeyMixin
11
10
  include Fluent::Mixin::ConfigPlaceholders
12
11
 
13
- BUILTIN_CONFIGURATIONS = %W(type @type log_level @log_level id @id include_tag_key tag_key char_encoding remove_keys)
12
+ BUILTIN_CONFIGURATIONS = %W(type @type log_level @log_level id @id char_encoding remove_keys)
14
13
 
15
14
  def configure(conf)
16
15
  super
17
16
 
17
+ if conf.has_key?('include_tag_key')
18
+ raise ConfigError, "include_tag_key and tag_key parameters are removed. Use 'tag ${tag}' in <record> section"
19
+ end
20
+
18
21
  @map = {}
19
22
  conf.each_pair { |k, v|
20
23
  unless BUILTIN_CONFIGURATIONS.include?(k)
21
24
  conf.has_key?(k)
22
- @map[k] = v
25
+ $log.warn "top level definition is deprecated. Please put parameters inside <record>: '#{k} #{v}'"
26
+ @map[k] = DynamicExpander.new(k, v)
23
27
  end
24
28
  }
25
29
 
@@ -39,33 +43,46 @@ module Fluent
39
43
  end
40
44
  end
41
45
 
46
+ @has_tag_parts = false
47
+ conf.elements.select { |element| element.name == 'record' }.each do |element|
48
+ element.each_pair do |k, v|
49
+ element.has_key?(k) # to suppress unread configuration warning
50
+ @has_tag_parts = true if v.include?('tag_parts')
51
+ @map[k] = DynamicExpander.new(k, v)
52
+ end
53
+ end
54
+
42
55
  if @remove_keys
43
- @remove_keys = @remove_keys.split(',').map {|e| e.strip }
56
+ @remove_keys = @remove_keys.split(',').map { |e| e.strip }
44
57
  end
45
- end
46
58
 
47
- def filter(tag, time, record)
48
- filter_record(tag, time, record)
49
- modify_record(record)
59
+ # Collect DynamicExpander related garbage instructions
60
+ GC.start
50
61
  end
51
62
 
52
- private
53
-
54
- def modify_record(record)
55
- @map.each_pair { |k, v|
56
- record[k] = v
57
- }
63
+ def filter_stream(tag, es)
64
+ new_es = MultiEventStream.new
65
+ tag_parts = @has_tag_parts ? tag.split('.') : nil
58
66
 
59
- if @remove_keys
60
- @remove_keys.each { |v|
61
- record.delete(v)
67
+ es.each { |time, record|
68
+ @map.each_pair { |k, v|
69
+ record[k] = v.expand(tag, time, record, tag_parts)
62
70
  }
63
- end
64
71
 
65
- record = change_encoding(record) if @char_encoding
66
- record
72
+ if @remove_keys
73
+ @remove_keys.each { |v|
74
+ record.delete(v)
75
+ }
76
+ end
77
+
78
+ record = change_encoding(record) if @char_encoding
79
+ new_es.add(time, record)
80
+ }
81
+ new_es
67
82
  end
68
83
 
84
+ private
85
+
69
86
  def set_encoding(record)
70
87
  record.each_pair { |k, v|
71
88
  if v.is_a?(String)
@@ -82,5 +99,53 @@ module Fluent
82
99
  end
83
100
  }
84
101
  end
102
+
103
+ class DynamicExpander
104
+ def initialize(param_key, param_value)
105
+ if param_value.include?('${')
106
+ __str_eval_code__ = parse_parameter(param_value)
107
+
108
+ # Use class_eval with string instead of define_method for performance.
109
+ # It can't share instructions but this is 2x+ faster than define_method in filter case.
110
+ # Refer: http://tenderlovemaking.com/2013/03/03/dynamic_method_definitions.html
111
+ (class << self; self; end).class_eval <<-EORUBY, __FILE__, __LINE__ + 1
112
+ def expand(tag, time, record, tag_parts)
113
+ #{__str_eval_code__}
114
+ end
115
+ EORUBY
116
+ else
117
+ @param_value = param_value
118
+ end
119
+
120
+ begin
121
+ # check eval genarates wrong code or not
122
+ expand(nil, nil, nil, nil)
123
+ rescue SyntaxError
124
+ raise ConfigError, "Pass invalid syntax parameter : key = #{param_key}, value = #{param_value}"
125
+ rescue
126
+ # Ignore other runtime errors
127
+ end
128
+ end
129
+
130
+ # Default implementation for fixed value. This is overwritten when parameter contains '${xxx}' placeholder
131
+ def expand(tag, time, record, tag_parts)
132
+ @param_value
133
+ end
134
+
135
+ private
136
+
137
+ def parse_parameter(value)
138
+ num_placeholders = value.scan('${').size
139
+ if num_placeholders == 1
140
+ if value.start_with?('${') && value.end_with?('}')
141
+ return value[2..-2]
142
+ else
143
+ "\"#{value.gsub('${', '#{')}\""
144
+ end
145
+ else
146
+ "\"#{value.gsub('${', '#{')}\""
147
+ end
148
+ end
149
+ end
85
150
  end if defined?(Filter)
86
151
  end
@@ -12,12 +12,14 @@ class RecordModifierFilterTest < Test::Unit::TestCase
12
12
 
13
13
  CONFIG = %[
14
14
  type record_modifier
15
-
16
- gen_host ${hostname}
17
- foo bar
18
- include_tag_key
19
- tag_key included_tag
20
15
  remove_keys hoge
16
+
17
+ <record>
18
+ gen_host ${hostname}
19
+ foo bar
20
+ included_tag ${tag}
21
+ tag_wrap -${tag_parts[0]}-${tag_parts[1]}-
22
+ </record>
21
23
  ]
22
24
 
23
25
  def create_driver(conf = CONFIG)
@@ -33,8 +35,9 @@ class RecordModifierFilterTest < Test::Unit::TestCase
33
35
  d = create_driver
34
36
  map = d.instance.instance_variable_get(:@map)
35
37
 
36
- assert_equal get_hostname, map['gen_host']
37
- assert_equal 'bar', map['foo']
38
+ map.each_pair { |k, v|
39
+ assert v.is_a?(Fluent::RecordModifierFilter::DynamicExpander)
40
+ }
38
41
  end
39
42
 
40
43
  def test_format
@@ -45,7 +48,7 @@ class RecordModifierFilterTest < Test::Unit::TestCase
45
48
  d.emit("a" => 2)
46
49
  end
47
50
 
48
- mapped = {'gen_host' => get_hostname, 'foo' => 'bar', 'included_tag' => @tag}
51
+ mapped = {'gen_host' => get_hostname, 'foo' => 'bar', 'included_tag' => @tag, 'tag_wrap' => "-#{@tag.split('.')[0]}-#{@tag.split('.')[1]}-"}
49
52
  assert_equal [
50
53
  {"a" => 1}.merge(mapped),
51
54
  {"a" => 2}.merge(mapped),
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-record-modifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro Nakagawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-09 00:00:00.000000000 Z
11
+ date: 2016-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.9.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: test-unit
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 3.1.4
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 3.1.4
61
75
  description: Output filter plugin for modifying each event record
62
76
  email: repeatedly@gmail.com
63
77
  executables: []