fluent-plugin-condition-checker 0.1.0 → 1.0.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
  SHA256:
3
- metadata.gz: 59770b074ad4850dbf87fae2f59788099ef308948a6d398c9857c56e0c5da8cc
4
- data.tar.gz: 8d44f4e00886b2e41ac95d490f6c67f92fc7fb42b3f818f9cc5437851706de4c
3
+ metadata.gz: 14c83969fa6928655e996db271f6dab4483b32e7eb2c8282455a4664c96ab904
4
+ data.tar.gz: e437510a11585f4d31f69adca9bd9a714cf4d084eec45e89081565a44c9bfb47
5
5
  SHA512:
6
- metadata.gz: dfa60bc60e4e048ddee2df596966ded0da52be0b0a58e5b30b908b1857e55ec5a63fdac0898c14fcf831cd71f358e01ca10df61ea273fa2cb151b57e153cce88
7
- data.tar.gz: c7882cf182ad7c33c8aa2200a5ba489c2eb316949a31071800d9cf87b75a826b07874c64db01e27cfc944092e0607b5cf8ac623b9eb79467086d47eca4961b54
6
+ metadata.gz: eed247f918a990606d53ab539cc11d0c266bc263e3385a34b3db33caa13b60ef6d1f94958ace69debad63ac6355fa1785cf0515692a7029e4d5afb7d518a530a
7
+ data.tar.gz: 17d4ffaa4def66e7baf802da002ef14f70c4e1007d30aab3451b8e949814cdcdbbb5f365ed2c54cef3748ccda3998663fdd89e1af686cc3bc7d372da424c1449
@@ -0,0 +1 @@
1
+ pkg/
@@ -0,0 +1,18 @@
1
+ Style/AsciiComments:
2
+ Enabled: false
3
+ Metrics/LineLength:
4
+ Max: 140
5
+ Naming/UncommunicativeMethodParamName:
6
+ Enabled: false
7
+ Metrics/AbcSize:
8
+ Max: 30
9
+ Metrics/MethodLength:
10
+ Max: 30
11
+ Metrics/PerceivedComplexity:
12
+ Max: 10
13
+ Metrics/CyclomaticComplexity:
14
+ Max: 10
15
+ Metrics/BlockLength:
16
+ Max: 45
17
+ Metrics/ClassLength:
18
+ Max: 120
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-condition-checker (1.0.0)
5
+ fluentd (>= 0.14.10, < 2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ concurrent-ruby (1.1.7)
11
+ cool.io (1.7.0)
12
+ fluentd (1.11.4)
13
+ cool.io (>= 1.4.5, < 2.0.0)
14
+ http_parser.rb (>= 0.5.1, < 0.7.0)
15
+ msgpack (>= 1.3.1, < 2.0.0)
16
+ serverengine (>= 2.0.4, < 3.0.0)
17
+ sigdump (~> 0.2.2)
18
+ strptime (>= 0.2.2, < 1.0.0)
19
+ tzinfo (>= 1.0, < 3.0)
20
+ tzinfo-data (~> 1.0)
21
+ yajl-ruby (~> 1.0)
22
+ http_parser.rb (0.6.0)
23
+ msgpack (1.3.3)
24
+ power_assert (1.2.0)
25
+ rake (12.3.3)
26
+ serverengine (2.2.1)
27
+ sigdump (~> 0.2.2)
28
+ sigdump (0.2.4)
29
+ strptime (0.2.5)
30
+ test-unit (3.3.6)
31
+ power_assert
32
+ tzinfo (2.0.2)
33
+ concurrent-ruby (~> 1.0)
34
+ tzinfo-data (1.2020.2)
35
+ tzinfo (>= 1.0.0)
36
+ yajl-ruby (1.4.1)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bundler (~> 2.0)
43
+ fluent-plugin-condition-checker!
44
+ rake (~> 12.0)
45
+ test-unit (~> 3.0)
46
+
47
+ BUNDLED WITH
48
+ 2.1.4
data/README.md CHANGED
@@ -28,6 +28,26 @@ $ bundle
28
28
 
29
29
  ## Configuration
30
30
 
31
+ ```
32
+ <match **>
33
+ @type condition-checker
34
+ <condition>
35
+ condition record["faceId"] != nil
36
+ tag exists_face
37
+ <data>
38
+ concept exists_face
39
+ </data>
40
+ </condition>
41
+ <condition>
42
+ condition record["faceId"] -= nil
43
+ tag no_face
44
+ <data>
45
+ concept no_face
46
+ </data>
47
+ </condition>
48
+ </match>
49
+ ```
50
+
31
51
  You can generate configuration template:
32
52
 
33
53
  ```
@@ -36,8 +56,16 @@ $ fluent-plugin-config-format output condition-checker
36
56
 
37
57
  You can copy and paste generated documents here.
38
58
 
59
+ ## Development
60
+
61
+ 1. test!
62
+
63
+ ```
64
+ bundle exec rake test
65
+ ```
66
+
39
67
  ## Copyright
40
68
 
41
- * Copyright(c) 2020- wally
42
- * License
43
- * Apache License, Version 2.0
69
+ - Copyright(c) 2020- wally
70
+ - License
71
+ - Apache License, Version 2.0
@@ -0,0 +1,31 @@
1
+ <source>
2
+ @type forward
3
+ port 24224
4
+ </source>
5
+
6
+ <match **>
7
+ @type copy
8
+ <store>
9
+ @type stdout
10
+ </store>
11
+ <store>
12
+ @type condition-checker
13
+ tag "speak_condition"
14
+ <condition>
15
+ rule record["action"] == "speak"
16
+ condition "speak_action"
17
+ <data>
18
+ word record["word"] + "こんにちは"
19
+ aditiona_data 1
20
+ </data>
21
+ </condition>
22
+ <condition>
23
+ rule record["action"] == "alert"
24
+ condition "alert_action"
25
+ <data>
26
+ word record["word"] + "はじめまして"
27
+ </data>
28
+ </condition>
29
+ </store>
30
+ </match>
31
+
@@ -0,0 +1 @@
1
+ {"label":"greeting","priority":2,"limit":30,"action":"greet"}
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-condition-checker"
6
- spec.version = "0.1.0"
6
+ spec.version = "1.0.0"
7
7
  spec.authors = ["wally"]
8
8
  spec.email = ["u.str.gm@gmail.com"]
9
9
 
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = test_files
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.14"
23
+ spec.add_development_dependency "bundler", "~> 2.0"
24
24
  spec.add_development_dependency "rake", "~> 12.0"
25
25
  spec.add_development_dependency "test-unit", "~> 3.0"
26
26
  spec.add_runtime_dependency "fluentd", [">= 0.14.10", "< 2"]
@@ -23,362 +23,336 @@ module Fluent
23
23
  Fluent::Plugin.register_output("condition_checker", self)
24
24
 
25
25
  helpers :event_emitter
26
- PATTERN_MAX_NUM = 20
27
-
28
- config_param :remove_keys, :string, :default => nil,
29
- :desc => 'Specify record keys to be removed by a string separated by , (comma).'
30
- config_param :keep_keys, :string, :default => nil,
31
- :desc => 'Specify record keys to be kept by a string separated by , (comma).'
32
- config_param :renew_record, :bool, :default => false,
33
- :desc => 'Creates an output record newly without extending (merging) the input record fields.'
34
- config_param :renew_time_key, :string, :default => nil,
35
- :desc => 'Overwrites the time of events with a value of the record field.'
36
- # it should always be true
37
- config_param :enable_ruby, :bool, :default => true, # true for lower version compatibility
38
- :desc => 'Enable to use ruby codes in placeholders.'
39
- # it should always be true
40
- config_param :auto_typecast, :bool, :default => true, # false for lower version compatibility
41
- :desc => 'Automatically cast the field types.'
42
-
43
- # 調整中のconfig_param
44
- # これで、何個もconditionを設定して、そして処理を決めることができる。
45
- config_param :tag1, :string,
46
- :desc => 'Specify the output tag name when the condition1 is true.'
47
- config_param :condition1, :string,
48
- :desc => 'Specify the condition1 to evaluate'
49
- (2..PATTERN_MAX_NUM).each do |i|
50
- config_param ('tag' + i.to_s).to_sym, :string, default: nil,
51
- desc: 'Specify tag'+i.to_s+' (not necessary)'
52
- config_param ('condition' + i.to_s).to_sym, :string, default: nil, # NAME REGEXP
53
- desc: 'Specify the condition'+i.to_s+' to evaluate (not necessary)'
54
- end
26
+ PATTERN_MAX_NUM = 20
27
+
28
+ config_param :remove_keys, :string, :default => nil,
29
+ :desc => 'Specify record keys to be removed by a string separated by , (comma).'
30
+ config_param :keep_keys, :string, :default => nil,
31
+ :desc => 'Specify record keys to be kept by a string separated by , (comma).'
32
+ config_param :renew_record, :bool, :default => false,
33
+ :desc => 'Creates an output record newly without extending (merging) the input record fields.'
34
+ config_param :renew_time_key, :string, :default => nil,
35
+ :desc => 'Overwrites the time of events with a value of the record field.'
36
+ # it should always be true
37
+ config_param :enable_ruby, :bool, :default => true, # true for lower version compatibility
38
+ :desc => 'Enable to use ruby codes in placeholders.'
39
+ # it should always be true
40
+ config_param :auto_typecast, :bool, :default => true, # false for lower version compatibility
41
+ :desc => 'Automatically cast the field types.'
42
+ config_param :tag, :string, :default => 'checked_tag', :desc => "new record tag."
43
+
44
+ config_param(
45
+ "condition".to_sym,
46
+ :hash,
47
+ default: nil,
48
+ desc: 'It is Conditions.'
49
+ )
55
50
 
56
- config_param :tag_else, :string,
57
- :desc => 'Specify the output tag name when the no conditions are true.'
51
+ BUILTIN_CONFIGURATIONS = %W(@id @type @label type output_tag remove_keys renew_record keep_keys enable_ruby renew_time_key auto_typecast tag_else record_else tag)
58
52
 
53
+ def configure(conf)
54
+ super
55
+ # ここで、BUILTIN_CONFIGURATIONS に入っていないものがあった場合はerrorをraise
56
+ conf.each_pair { |k, v|
57
+ next if BUILTIN_CONFIGURATIONS.include?(k) || k.match(/^condition\d\d?$/) || k.match(/^tag\d\d?$/)
59
58
 
60
- BUILTIN_CONFIGURATIONS = %W(@id @type @label type output_tag remove_keys renew_record keep_keys enable_ruby renew_time_key auto_typecast tag_else record_else)
59
+ raise Fluent::ConfigError, 'out_condition_checker: some weird config is set {'+k.to_s+':'+v.to_s+'}'
60
+ }
61
61
 
62
- def configure(conf)
63
- super
64
- # ここで、BUILTIN_CONFIGURATIONS に入っていないものがあった場合はerrorをraise
65
- conf.each_pair { |k, v|
66
- # print k.match('^/tag/\d\d?$')
67
- next if BUILTIN_CONFIGURATIONS.include?(k) || k.match(/^condition\d\d?$/) || k.match(/^tag\d\d?$/)
62
+ # conditionsを読み込む
63
+ @conditions = []
64
+ conf.elements.select { |element| element.name.match(/^condition?$/) }
65
+ .each do |param|
66
+ condition = {}
67
+ data_record = {}
68
+
69
+ param.elements.select { |element| element.name.match(/^data?$/) }.each do |data|
70
+ data.each_pair do |key, value|
71
+ data_record.merge!(key => convert_value(value))
72
+ end
73
+ end
68
74
 
69
- raise Fluent::ConfigError, 'out_condition_checker: some weird config is set {'+k.to_s+':'+v.to_s+'}'
70
- }
75
+ param.each_pair do |key, value|
76
+ condition.merge!(key => convert_value(value))
77
+ end
71
78
 
72
- #tagを読み込み
73
- tags = []
74
- (1..PATTERN_MAX_NUM).each do |i|
75
- next unless conf["tag#{i}"]
76
- tags.push(conf["tag#{i}"]) # tags[i+1] で、欲しいtagにアクセスできる
77
- end
79
+ condition.merge!("data" => data_record)
80
+ @conditions.push(condition)
81
+ end
78
82
 
79
- #conditionを読み込み
80
- @conditions = []
81
- (1..PATTERN_MAX_NUM).each do |i|
82
- next unless conf["condition#{i}"]
83
- @conditions.push(conf["condition#{i}"])
84
- end
85
- if tags.size != @conditions.size
86
- raise Fluent::ConfigError, 'match the numbers of tags and conditions; number of tags: '+tags.size.to_s+', number of conditions: '+@conditions.size.to_s
87
- end
88
83
 
84
+ if @remove_keys
85
+ @remove_keys = @remove_keys.split(',')
86
+ end
87
+ if @keep_keys
88
+ raise Fluent::ConfigError, 'out_condition_checker: `renew_record` must be true to use `keep_keys`' unless @renew_record
89
+ @keep_keys = @keep_keys.split(',')
90
+ end
89
91
 
90
- # maps[i] で、欲しいconditionに対応するrecordにアクセスすることができる。
91
- # FIXME: conf.elements.forEachでいい感じに回せそう
92
- maps = []
93
- (1..PATTERN_MAX_NUM).each do |i|
94
- next unless conf["condition#{i}"] # 対応するcondition{i}が定義されているものだけ読み込む
95
- conf.elements.select { |element| element.name == 'record'+i.to_s }.each { |element|
96
- recordTmp = {}
97
- element.each_pair { |k, v|
98
- element.has_key?(k) # to suppress unread configuration warning
99
- recordTmp.merge!({k => parse_value(v)})
100
- # map_if_false[k] = parse_value(v)
92
+ placeholder_expander_params = {
93
+ :log => log,
94
+ :auto_typecast => @auto_typecast, # It should always be true
101
95
  }
102
- maps[i] = recordTmp
103
- }
104
- end
105
96
 
106
- map_else ={}
107
- conf.elements.select { |element| element.name == 'record_else' }.each { |element|
108
- recordTmp = {}
109
- element.each_pair { |k, v|
110
- element.has_key?(k) # to suppress unread configuration warning
111
- recordTmp.merge!({k => parse_value(v)})
112
- }
113
- map_else = recordTmp
114
- }
115
-
116
- if @remove_keys
117
- @remove_keys = @remove_keys.split(',')
118
- end
119
- if @keep_keys
120
- raise Fluent::ConfigError, 'out_condition_checker: `renew_record` must be true to use `keep_keys`' unless @renew_record
121
- @keep_keys = @keep_keys.split(',')
122
- end
97
+ @placeholder_expander =
98
+ if @enable_ruby
99
+ # require utilities which would be used in ruby placeholders
100
+ require 'pathname'
101
+ require 'uri'
102
+ require 'cgi'
103
+ RubyPlaceholderExpander.new(placeholder_expander_params)
104
+ else
105
+ p 'WARN!! Hey! You should enable ruby!!!'
106
+ PlaceholderExpander.new(placeholder_expander_params)
107
+ end
123
108
 
124
- placeholder_expander_params = {
125
- :log => log,
126
- :auto_typecast => @auto_typecast, # It should always be true
127
- }
128
-
129
- @placeholder_expander =
130
- if @enable_ruby
131
- # require utilities which would be used in ruby placeholders
132
- require 'pathname'
133
- require 'uri'
134
- require 'cgi'
135
- RubyPlaceholderExpander.new(placeholder_expander_params)
136
- else
137
- p 'WARN!! Hey! You should enable ruby!!!'
138
- PlaceholderExpander.new(placeholder_expander_params)
139
- end
140
109
 
110
+ @hostname = Socket.gethostname
111
+ end
141
112
 
142
- @maps = @placeholder_expander.preprocess_map(maps)
143
- @tags = @placeholder_expander.preprocess_map(tags)
144
- @tag_else = @placeholder_expander.preprocess_map(conf['tag_else'])
145
- @map_else = @placeholder_expander.preprocess_map(map_else)
113
+ def process(tag, es)
114
+ tag_parts = tag.split('.')
115
+ tag_prefix = tag_prefix(tag_parts)
116
+ tag_suffix = tag_suffix(tag_parts)
117
+ placeholder_values = {
118
+ 'tag' => tag,
119
+ 'tags' => tag_parts, # for old version compatibility
120
+ 'tag_parts' => tag_parts,
121
+ 'tag_prefix' => tag_prefix,
122
+ 'tag_suffix' => tag_suffix,
123
+ 'hostname' => @hostname,
124
+ }
125
+ es.each {|time, record|
126
+ placeholder_values.merge!({
127
+ 'time' => @placeholder_expander.time_value(time),
128
+ 'record' => record,
129
+ })
130
+
131
+ # TODO: ここの処理よくないって evaluate
132
+ matched_conditions, aditional_data = evaluate_condition(@conditions, placeholder_values )
133
+
134
+ if matched_conditions.size > 0
135
+ new_record = reform(record, aditional_data, placeholder_values)
136
+ if @renew_time_key && new_record.has_key?(@renew_time_key)
137
+ time = new_record[@renew_time_key].to_i
138
+ end
139
+ @remove_keys.each {|k| new_record.delete(k) } if @remove_keys
140
+ router.emit(@tag, time, new_record)
141
+ end
142
+ }
143
+ rescue => e
144
+ log.warn "condition_checker: #{e.class} #{e.message} #{e.backtrace.first}"
145
+ end
146
146
 
147
- @hostname = Socket.gethostname
148
- end
147
+ private
149
148
 
150
- def process(tag, es)
151
- tag_parts = tag.split('.')
152
- tag_prefix = tag_prefix(tag_parts)
153
- tag_suffix = tag_suffix(tag_parts)
154
- placeholder_values = {
155
- 'tag' => tag,
156
- 'tags' => tag_parts, # for old version compatibility
157
- 'tag_parts' => tag_parts,
158
- 'tag_prefix' => tag_prefix,
159
- 'tag_suffix' => tag_suffix,
160
- 'hostname' => @hostname,
161
- }
162
- es.each {|time, record|
163
- placeholder_values.merge!({
164
- 'time' => @placeholder_expander.time_value(time),
165
- 'record' => record,
166
- })
167
-
168
- # TODO: ここの処理よくないって evaluate
169
- result, idx = evaluate_condition(@conditions, placeholder_values)
170
- placeholder_values.merge!({ 'result' => result })
171
-
172
- if idx
173
- new_tag, new_record = reform(@tags[idx], @maps[idx+1], record, placeholder_values)
174
- else
175
- # TODO: tag_elseは使えなくするoption作る"
176
- new_tag, new_record = reform(@tag_else, @map_else, record, placeholder_values)
177
- # return
149
+ def evaluate_condition(conditions, placeholders)
150
+ matched_conditions = []
151
+ aditional_data = {}
152
+ conditions.each_with_index{ |condition, idx|
153
+ result = expand_placeholders(condition["rule"], placeholders)
154
+ if result
155
+ matched_conditions.push(condition["condition"])
156
+ aditional_data.merge!(condition["data"])
157
+ end
158
+ }
159
+ return matched_conditions, aditional_data
178
160
  end
179
161
 
180
- if new_tag
181
- if @renew_time_key && new_record.has_key?(@renew_time_key)
182
- time = new_record[@renew_time_key].to_i
162
+ def parse_value(value_str)
163
+ if value_str.start_with?('{', '[')
164
+ JSON.parse(value_str)
165
+ else
166
+ value_str
183
167
  end
184
- @remove_keys.each {|k| new_record.delete(k) } if @remove_keys
185
- router.emit(new_tag, time, new_record)
168
+ rescue => e
169
+ log.warn "failed to parse #{value_str} as json. Assuming #{value_str} is a string", :error_class => e.class, :error => e.message
170
+ value_str # emit as string
186
171
  end
187
- }
188
- rescue => e
189
- log.warn "condition_checker: #{e.class} #{e.message} #{e.backtrace.first}"
190
- end
191
172
 
192
- private
193
-
194
- def evaluate_condition(conditions, placeholders)
195
- conditions.each_with_index{ |condition, idx|
196
- result = expand_placeholders(condition, placeholders)
197
- if result then return [result, idx] end
198
- }
199
- [@map_else, nil]
200
- end
201
-
202
- def parse_value(value_str)
203
- if value_str.start_with?('{', '[')
204
- JSON.parse(value_str)
205
- else
206
- value_str
207
- end
208
- rescue => e
209
- log.warn "failed to parse #{value_str} as json. Assuming #{value_str} is a string", :error_class => e.class, :error => e.message
210
- value_str # emit as string
211
- end
173
+ def reform(record, aditional_data, placeholder_values)
174
+ new_record = @renew_record ? {} : record.dup
175
+ new_record.merge!(create_record(aditional_data, placeholder_values))
176
+ @keep_keys.each {|k| new_record[k] = record[k]} if @keep_keys and @renew_record
177
+ return new_record
178
+ end
212
179
 
213
- def reform(tag, map, record, placeholder_values)
214
- placeholders = @placeholder_expander.prepare_placeholders(placeholder_values)
215
- new_tag = expand_placeholders(tag, placeholders)
216
- new_record = @renew_record ? {} : record.dup
217
- @keep_keys.each {|k| new_record[k] = record[k]} if @keep_keys and @renew_record
218
- new_record.merge!(create_record(map, placeholders)) unless map.nil?
219
- [new_tag, new_record]
220
- end
180
+ def create_record(map, placeholders)
181
+ new_record = {}
182
+ map.each do |k, v|
183
+ value = @placeholder_expander.expand(v, placeholders, true)
184
+ if value.nil?
185
+ new_record.merge!({ k => convert_num(v) })
186
+ else
187
+ new_record.merge!({ k => convert_num(value) })
188
+ end
189
+ end
190
+ pp new_record
221
191
 
222
- def create_record(map, placeholders)
223
- new_record = {}
192
+ new_record
193
+ end
224
194
 
225
- map.each_pair do |k, v|
226
- new_key = @placeholder_expander.expand(k, placeholders, true)
195
+ def convert_num(value)
196
+ # Booleanがチェック
197
+ if value == "true"
198
+ return true
199
+ elsif value == "false"
200
+ return false
201
+ end
202
+
203
+ if value.to_i.to_s == value.to_s
204
+ return value.to_i
205
+ else
206
+ return value
207
+ end
208
+ end
227
209
 
228
- new_record.merge!({ new_key => convert_num(@placeholder_expander.expand(v, placeholders, true)) })
229
- end
210
+ def convert_value(value)
211
+ # Booleanがチェック
212
+ return true if value == 'true'
230
213
 
231
- new_record
232
- end
214
+ return false if value == 'false'
233
215
 
234
- def convert_num(value)
235
- # Booleanがチェック
236
- if value == "true"
237
- return true
238
- elsif value == "false"
239
- return false
240
- end
241
-
242
- if value.to_i.to_s == value.to_s
243
- return value.to_i
244
- else
245
- return value
246
- end
247
- end
216
+ # 数値データなら数値で返す
217
+ return value.to_i if value.to_i.to_s == value.to_s
218
+ return value.to_f if value.to_f.to_s == value.to_s
248
219
 
249
- def expand_placeholders(value, placeholders)
250
- if value.is_a?(String)
251
- new_value = @placeholder_expander.expand(value, placeholders)
252
- elsif value.is_a?(Hash)
253
- new_value = {}
254
- value.each_pair do |k, v|
255
- new_key = @placeholder_expander.expand(k, placeholders, true)
256
- new_value[new_key] = expand_placeholders(v, placeholders)
220
+ value
257
221
  end
258
- elsif value.is_a?(Array)
259
- new_value = []
260
- value.each_with_index do |v, i|
261
- new_value[i] = expand_placeholders(v, placeholders)
222
+
223
+ def expand_placeholders(value, placeholders)
224
+ if value.is_a?(String)
225
+ new_value = @placeholder_expander.expand(value, placeholders)
226
+ elsif value.is_a?(Hash)
227
+ new_value = {}
228
+ value.each_pair do |k, v|
229
+ new_key = @placeholder_expander.expand(k, placeholders, true)
230
+ new_value[new_key] = expand_placeholders(v, placeholders)
231
+ end
232
+ elsif value.is_a?(Array)
233
+ new_value = []
234
+ value.each_with_index do |v, i|
235
+ new_value[i] = expand_placeholders(v, placeholders)
236
+ end
237
+ else
238
+ new_value = value
239
+ end
240
+ new_value
262
241
  end
263
- else
264
- new_value = value
265
- end
266
- new_value
267
- end
268
242
 
269
- def tag_prefix(tag_parts)
270
- return [] if tag_parts.empty?
271
- tag_prefix = [tag_parts.first]
272
- 1.upto(tag_parts.size-1).each do |i|
273
- tag_prefix[i] = "#{tag_prefix[i-1]}.#{tag_parts[i]}"
274
- end
275
- tag_prefix
276
- end
243
+ def tag_prefix(tag_parts)
244
+ return [] if tag_parts.empty?
245
+ tag_prefix = [tag_parts.first]
246
+ 1.upto(tag_parts.size-1).each do |i|
247
+ tag_prefix[i] = "#{tag_prefix[i-1]}.#{tag_parts[i]}"
248
+ end
249
+ tag_prefix
250
+ end
277
251
 
278
- def tag_suffix(tag_parts)
279
- return [] if tag_parts.empty?
280
- rev_tag_parts = tag_parts.reverse
281
- rev_tag_suffix = [rev_tag_parts.first]
282
- 1.upto(tag_parts.size-1).each do |i|
283
- rev_tag_suffix[i] = "#{rev_tag_parts[i]}.#{rev_tag_suffix[i-1]}"
284
- end
285
- rev_tag_suffix.reverse!
286
- end
252
+ def tag_suffix(tag_parts)
253
+ return [] if tag_parts.empty?
254
+ rev_tag_parts = tag_parts.reverse
255
+ rev_tag_suffix = [rev_tag_parts.first]
256
+ 1.upto(tag_parts.size-1).each do |i|
257
+ rev_tag_suffix[i] = "#{rev_tag_parts[i]}.#{rev_tag_suffix[i-1]}"
258
+ end
259
+ rev_tag_suffix.reverse!
260
+ end
287
261
 
288
- # THIS CLASS MUST BE THREAD-SAFE
289
- class RubyPlaceholderExpander
290
- attr_reader :log
262
+ # THIS CLASS MUST BE THREAD-SAFE
263
+ class RubyPlaceholderExpander
264
+ attr_reader :log
291
265
 
292
- def initialize(params)
293
- @log = params[:log]
294
- @auto_typecast = params[:auto_typecast]
295
- @cleanroom_expander = CleanroomExpander.new
296
- end
266
+ def initialize(params)
267
+ @log = params[:log]
268
+ @auto_typecast = params[:auto_typecast]
269
+ @cleanroom_expander = CleanroomExpander.new
270
+ end
297
271
 
298
- def time_value(time)
299
- Time.at(time)
300
- end
272
+ def time_value(time)
273
+ Time.at(time)
274
+ end
301
275
 
302
- # Preprocess record map to convert into ruby string expansion
303
- #
304
- # @param [Hash|String|Array] value record map config
305
- # @param [Boolean] force_stringify the value must be string, used for hash key
306
- def preprocess_map(value, force_stringify = false)
307
- new_value = nil
308
- if value.is_a?(String)
309
- if @auto_typecast and !force_stringify
310
- num_placeholders = value.scan('${').size
311
- if num_placeholders == 1 and value.start_with?('${') && value.end_with?('}')
312
- new_value = value[2..-2] # ${..} => ..
276
+ # Preprocess record map to convert into ruby string expansion
277
+ #
278
+ # @param [Hash|String|Array] value record map config
279
+ # @param [Boolean] force_stringify the value must be string, used for hash key
280
+ def preprocess_map(value, force_stringify = false)
281
+ new_value = nil
282
+ if value.is_a?(String)
283
+ if @auto_typecast and !force_stringify
284
+ num_placeholders = value.scan('${').size
285
+ if num_placeholders == 1 and value.start_with?('${') && value.end_with?('}')
286
+ new_value = value[2..-2] # ${..} => ..
287
+ end
288
+ end
289
+ unless new_value
290
+ new_value = "%Q[#{value.gsub('${', '#{')}]" # xx${..}xx => %Q[xx#{..}xx]
291
+ end
292
+ elsif value.is_a?(Hash)
293
+ new_value = {}
294
+ value.each_pair do |k, v|
295
+ new_value[preprocess_map(k, true)] = preprocess_map(v)
296
+ end
297
+ elsif value.is_a?(Array)
298
+ new_value = []
299
+ value.each_with_index do |v, i|
300
+ new_value[i] = preprocess_map(v)
301
+ end
302
+ else
303
+ new_value = value
313
304
  end
305
+ new_value
314
306
  end
315
- unless new_value
316
- new_value = "%Q[#{value.gsub('${', '#{')}]" # xx${..}xx => %Q[xx#{..}xx]
317
- end
318
- elsif value.is_a?(Hash)
319
- new_value = {}
320
- value.each_pair do |k, v|
321
- new_value[preprocess_map(k, true)] = preprocess_map(v)
322
- end
323
- elsif value.is_a?(Array)
324
- new_value = []
325
- value.each_with_index do |v, i|
326
- new_value[i] = preprocess_map(v)
307
+
308
+ # FIXME: 引数返すだけの関数があるので削除
309
+ def prepare_placeholders(placeholder_values)
310
+ placeholder_values
327
311
  end
328
- else
329
- new_value = value
330
- end
331
- new_value
332
- end
333
312
 
334
- # FIXME: 引数返すだけの関数があるので削除
335
- def prepare_placeholders(placeholder_values)
336
- placeholder_values
337
- end
313
+ # Expand string with placeholders
314
+ #
315
+ # @param [String] str
316
+ def expand(str, placeholders, force_stringify = false)
317
+ # FIXME: tag情報は使用してなさそうなので, 不必要であれば
318
+ @cleanroom_expander.expand(
319
+ str,
320
+ placeholders['tag'],
321
+ placeholders['time'],
322
+ placeholders['record'],
323
+ placeholders['tag_parts'],
324
+ placeholders['tag_prefix'],
325
+ placeholders['tag_suffix'],
326
+ placeholders['hostname']
327
+ )
328
+ rescue => e
329
+ log.warn "record_reformer: failed to expand `#{str}`", :error_class => e.class, :error => e.message
330
+ log.warn_backtrace
331
+ nil
332
+ end
338
333
 
339
- # Expand string with placeholders
340
- #
341
- # @param [String] str
342
- def expand(str, placeholders, force_stringify = false)
343
- # FIXME: tag情報は使用してなさそうなので, 不必要であれば
344
- @cleanroom_expander.expand(
345
- str,
346
- placeholders['tag'],
347
- placeholders['time'],
348
- placeholders['record'],
349
- placeholders['tag_parts'],
350
- placeholders['tag_prefix'],
351
- placeholders['tag_suffix'],
352
- placeholders['hostname']
353
- )
354
- rescue => e
355
- log.warn "record_reformer: failed to expand `#{str}`", :error_class => e.class, :error => e.message
356
- log.warn_backtrace
357
- nil
358
- end
334
+ class CleanroomExpander
335
+ def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname, force_stringify = true)
336
+ Thread.current[:record_reformer_record] = record # for old version compatibility
337
+ instance_eval(__str_to_eval__)
338
+ end
359
339
 
360
- class CleanroomExpander
361
- def expand(__str_to_eval__, tag, time, record, tag_parts, tag_prefix, tag_suffix, hostname, force_stringify = true)
362
- Thread.current[:record_reformer_record] = record # for old version compatibility
363
- instance_eval(__str_to_eval__)
364
- end
340
+ # for old version compatibility
341
+ def method_missing(name)
342
+ key = name.to_s
343
+ record = Thread.current[:record_reformer_record]
344
+ if record.has_key?(key)
345
+ record[key]
346
+ else
347
+ raise NameError, "undefined local variable or method `#{key}'"
348
+ end
349
+ end
365
350
 
366
- # for old version compatibility
367
- def method_missing(name)
368
- key = name.to_s
369
- record = Thread.current[:record_reformer_record]
370
- if record.has_key?(key)
371
- record[key]
372
- else
373
- raise NameError, "undefined local variable or method `#{key}'"
351
+ (Object.instance_methods).each do |m|
352
+ undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
353
+ end
374
354
  end
375
355
  end
376
-
377
- (Object.instance_methods).each do |m|
378
- undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
379
- end
380
- end
381
356
  end
382
357
  end
383
358
  end
384
-
@@ -6,8 +6,65 @@ class ConditionCheckerOutputTest < Test::Unit::TestCase
6
6
  Fluent::Test.setup
7
7
  end
8
8
 
9
- test "failure" do
10
- flunk
9
+ def create_driver(conf)
10
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::ConditionCheckerOutput).configure(conf)
11
+ end
12
+
13
+ test "simple_configure" do
14
+ conf = config_element(
15
+ 'ROOT',
16
+ '',
17
+ {'tag' => "speak_chekc"},
18
+ [
19
+ config_element(
20
+ 'condition',
21
+ '',
22
+ {
23
+ 'rule' => 'record["action"] == "speak"',
24
+ 'condition' => 'speaking'
25
+ },
26
+ [
27
+ config_element(
28
+ 'data',
29
+ '',
30
+ {
31
+ 'new_word' => 'record["word"] + "こんにちは"',
32
+ 'aaa' => 1
33
+ },
34
+ []
35
+ )
36
+ ]
37
+ ),
38
+ config_element(
39
+ 'condition',
40
+ '',
41
+ {
42
+ 'rule' => 'record["action"] != "speak"',
43
+ 'condition' => 'no_speak'
44
+ },
45
+ [
46
+ config_element(
47
+ 'data',
48
+ '',
49
+ {
50
+ 'new_word' => 'record["word"] + "はじめまして"'
51
+ },
52
+ []
53
+ )
54
+ ]
55
+ )
56
+ ]
57
+ )
58
+ d = create_driver(conf)
59
+ d.run(default_tag: 'test') do
60
+ record = {
61
+ 'action' => "speak",
62
+ "word" => "aaa"
63
+ }
64
+ d.feed(record)
65
+ events = d.events
66
+ pp events
67
+ end
11
68
  end
12
69
 
13
70
  private
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-condition-checker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - wally
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-16 00:00:00.000000000 Z
11
+ date: 2020-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.14'
19
+ version: '2.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.14'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -79,10 +79,15 @@ executables: []
79
79
  extensions: []
80
80
  extra_rdoc_files: []
81
81
  files:
82
+ - ".gitignore"
83
+ - ".rubocop.yml"
82
84
  - Gemfile
85
+ - Gemfile.lock
83
86
  - LICENSE
84
87
  - README.md
85
88
  - Rakefile
89
+ - example/fluent.conf
90
+ - example/scenario.json
86
91
  - fluent-plugin-condition-checker.gemspec
87
92
  - lib/fluent/plugin/out_condition_checker.rb
88
93
  - test/helper.rb