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 +4 -4
- data/.travis.yml +7 -2
- data/ChangeLog +7 -0
- data/README.md +45 -12
- data/VERSION +1 -1
- data/fluent-plugin-record-modifier.gemspec +1 -0
- data/lib/fluent/plugin/filter_record_modifier.rb +85 -20
- data/test/test_filter_record_modifier.rb +11 -8
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ff1d6de463980c890752f4eb32719f3f160c026
|
4
|
+
data.tar.gz: 4ed772c23ab2316e1bf064a9fd3c1ed498c1aae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2477196fe7d51f5d26546107d4b9a01907e97e3dc38a0d5a2a1a4cc8182f298d24abb996b197e3609cae7e0a534781b93f0d5bd802d7afc31c0297f2f5e31924
|
7
|
+
data.tar.gz: e0826bc7e9203ea5a6bf24f715b5b63d2b13a95c407a4d298cfd8b9f2f7c781afed10c69248774e8930b7a0f86cc1f569c75a9c2e3c00e689e3dffc4fe2f6e5d
|
data/.travis.yml
CHANGED
@@ -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
|
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
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
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
|
-
|
17
|
-
type record_modifier
|
18
|
-
tag foo.filtered
|
16
|
+
Use `record_modifier` filter.
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
<
|
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
|
-
</
|
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
|
-
<
|
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
|
-
</
|
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.
|
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
|
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
|
-
|
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
|
-
|
48
|
-
|
49
|
-
modify_record(record)
|
59
|
+
# Collect DynamicExpander related garbage instructions
|
60
|
+
GC.start
|
50
61
|
end
|
51
62
|
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
60
|
-
@
|
61
|
-
record.
|
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
|
-
|
66
|
-
|
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
|
-
|
37
|
-
|
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.
|
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:
|
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: []
|