fluentd 0.14.17-x64-mingw32 → 1.3.1-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +16 -5
- data/ADOPTERS.md +5 -0
- data/{ChangeLog → CHANGELOG.md} +495 -6
- data/CONTRIBUTING.md +5 -2
- data/GOVERNANCE.md +55 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +7 -5
- data/README.md +17 -10
- data/bin/fluent-ca-generate +6 -0
- data/example/counter.conf +18 -0
- data/example/secondary_file.conf +3 -2
- data/fluentd.gemspec +3 -3
- data/lib/fluent/agent.rb +1 -1
- data/lib/fluent/command/binlog_reader.rb +11 -2
- data/lib/fluent/command/ca_generate.rb +181 -0
- data/lib/fluent/command/cat.rb +28 -15
- data/lib/fluent/command/debug.rb +4 -4
- data/lib/fluent/command/fluentd.rb +2 -2
- data/lib/fluent/command/plugin_config_formatter.rb +24 -2
- data/lib/fluent/command/plugin_generator.rb +26 -8
- data/lib/fluent/config/configure_proxy.rb +7 -1
- data/lib/fluent/config/dsl.rb +8 -5
- data/lib/fluent/config/element.rb +5 -0
- data/lib/fluent/config/literal_parser.rb +7 -1
- data/lib/fluent/config/types.rb +28 -2
- data/lib/fluent/config/v1_parser.rb +1 -2
- data/lib/fluent/configurable.rb +1 -0
- data/lib/fluent/counter.rb +23 -0
- data/lib/fluent/counter/base_socket.rb +46 -0
- data/lib/fluent/counter/client.rb +297 -0
- data/lib/fluent/counter/error.rb +86 -0
- data/lib/fluent/counter/mutex_hash.rb +163 -0
- data/lib/fluent/counter/server.rb +273 -0
- data/lib/fluent/counter/store.rb +205 -0
- data/lib/fluent/counter/validator.rb +145 -0
- data/lib/fluent/env.rb +1 -0
- data/lib/fluent/event_router.rb +1 -1
- data/lib/fluent/log.rb +119 -29
- data/lib/fluent/plugin/base.rb +12 -0
- data/lib/fluent/plugin/buf_file.rb +20 -16
- data/lib/fluent/plugin/buffer.rb +130 -32
- data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
- data/lib/fluent/plugin/compressable.rb +1 -1
- data/lib/fluent/plugin/filter_grep.rb +135 -21
- data/lib/fluent/plugin/filter_parser.rb +13 -2
- data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/formatter_tsv.rb +5 -1
- data/lib/fluent/plugin/in_debug_agent.rb +8 -1
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +84 -3
- data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
- data/lib/fluent/plugin/in_syslog.rb +31 -10
- data/lib/fluent/plugin/in_tail.rb +142 -53
- data/lib/fluent/plugin/in_tcp.rb +5 -6
- data/lib/fluent/plugin/in_udp.rb +6 -2
- data/lib/fluent/plugin/in_unix.rb +1 -1
- data/lib/fluent/plugin/multi_output.rb +1 -0
- data/lib/fluent/plugin/out_copy.rb +25 -2
- data/lib/fluent/plugin/out_file.rb +26 -7
- data/lib/fluent/plugin/out_forward.rb +81 -42
- data/lib/fluent/plugin/out_secondary_file.rb +2 -2
- data/lib/fluent/plugin/out_stdout.rb +0 -1
- data/lib/fluent/plugin/out_stream.rb +1 -1
- data/lib/fluent/plugin/output.rb +221 -57
- data/lib/fluent/plugin/parser_apache.rb +1 -1
- data/lib/fluent/plugin/parser_apache2.rb +5 -1
- data/lib/fluent/plugin/parser_apache_error.rb +1 -1
- data/lib/fluent/plugin/parser_json.rb +10 -3
- data/lib/fluent/plugin/parser_ltsv.rb +7 -0
- data/lib/fluent/plugin/parser_multiline.rb +2 -1
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin/parser_none.rb +1 -0
- data/lib/fluent/plugin/parser_regexp.rb +15 -14
- data/lib/fluent/plugin/parser_syslog.rb +9 -5
- data/lib/fluent/plugin_helper.rb +2 -0
- data/lib/fluent/plugin_helper/cert_option.rb +28 -9
- data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_loop.rb +9 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
- data/lib/fluent/plugin_helper/retry_state.rb +15 -7
- data/lib/fluent/plugin_helper/server.rb +87 -25
- data/lib/fluent/plugin_helper/socket_option.rb +5 -2
- data/lib/fluent/plugin_helper/timer.rb +8 -7
- data/lib/fluent/root_agent.rb +18 -9
- data/lib/fluent/supervisor.rb +63 -23
- data/lib/fluent/system_config.rb +30 -2
- data/lib/fluent/test/helpers.rb +1 -1
- data/lib/fluent/time.rb +15 -7
- data/lib/fluent/timezone.rb +26 -2
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/README.md.erb +2 -2
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +2 -2
- data/test/command/test_plugin_config_formatter.rb +8 -7
- data/test/command/test_plugin_generator.rb +65 -39
- data/test/config/test_config_parser.rb +7 -2
- data/test/config/test_configurable.rb +7 -2
- data/test/config/test_configure_proxy.rb +41 -3
- data/test/config/test_dsl.rb +10 -10
- data/test/config/test_element.rb +10 -0
- data/test/config/test_literal_parser.rb +8 -0
- data/test/config/test_plugin_configuration.rb +56 -0
- data/test/config/test_system_config.rb +19 -1
- data/test/config/test_types.rb +37 -0
- data/test/counter/test_client.rb +559 -0
- data/test/counter/test_error.rb +44 -0
- data/test/counter/test_mutex_hash.rb +179 -0
- data/test/counter/test_server.rb +589 -0
- data/test/counter/test_store.rb +258 -0
- data/test/counter/test_validator.rb +137 -0
- data/test/plugin/test_buf_file.rb +124 -0
- data/test/plugin/test_buffer.rb +3 -2
- data/test/plugin/test_filter_grep.rb +580 -2
- data/test/plugin/test_filter_parser.rb +33 -2
- data/test/plugin/test_filter_record_transformer.rb +22 -1
- data/test/plugin/test_formatter_ltsv.rb +3 -0
- data/test/plugin/test_formatter_tsv.rb +68 -0
- data/test/plugin/test_in_debug_agent.rb +21 -0
- data/test/plugin/test_in_exec.rb +3 -5
- data/test/plugin/test_in_http.rb +178 -0
- data/test/plugin/test_in_monitor_agent.rb +1 -1
- data/test/plugin/test_in_syslog.rb +64 -0
- data/test/plugin/test_in_tail.rb +116 -6
- data/test/plugin/test_in_tcp.rb +21 -0
- data/test/plugin/test_in_udp.rb +78 -0
- data/test/plugin/test_metadata.rb +89 -0
- data/test/plugin/test_out_copy.rb +31 -0
- data/test/plugin/test_out_file.rb +108 -2
- data/test/plugin/test_out_forward.rb +195 -2
- data/test/plugin/test_out_secondary_file.rb +14 -0
- data/test/plugin/test_output.rb +159 -45
- data/test/plugin/test_output_as_buffered.rb +19 -0
- data/test/plugin/test_output_as_buffered_backup.rb +307 -0
- data/test/plugin/test_output_as_buffered_retries.rb +70 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
- data/test/plugin/test_parser_apache2.rb +1 -0
- data/test/plugin/test_parser_labeled_tsv.rb +17 -0
- data/test/plugin/test_parser_nginx.rb +40 -0
- data/test/plugin/test_parser_regexp.rb +6 -7
- data/test/plugin/test_parser_syslog.rb +155 -5
- data/test/plugin_helper/test_child_process.rb +4 -4
- data/test/plugin_helper/test_compat_parameters.rb +22 -0
- data/test/plugin_helper/test_record_accessor.rb +197 -0
- data/test/plugin_helper/test_retry_state.rb +20 -0
- data/test/plugin_helper/test_server.rb +30 -2
- data/test/test_config.rb +3 -3
- data/test/test_configdsl.rb +2 -2
- data/test/test_log.rb +51 -1
- data/test/test_root_agent.rb +33 -0
- data/test/test_supervisor.rb +105 -0
- metadata +68 -8
- data/COPYING +0 -14
@@ -0,0 +1,258 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/counter/store'
|
3
|
+
require 'fluent/time'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
class CounterStoreTest < ::Test::Unit::TestCase
|
7
|
+
setup do
|
8
|
+
@name = 'key_name'
|
9
|
+
@scope = "server\tworker\tplugin"
|
10
|
+
|
11
|
+
# timecop isn't compatible with EventTime
|
12
|
+
t = Time.parse('2016-09-22 16:59:59 +0900')
|
13
|
+
Timecop.freeze(t)
|
14
|
+
@now = Fluent::EventTime.now
|
15
|
+
end
|
16
|
+
|
17
|
+
shutdown do
|
18
|
+
Timecop.return
|
19
|
+
end
|
20
|
+
|
21
|
+
def extract_value_from_counter(counter, key)
|
22
|
+
store = counter.instance_variable_get(:@storage).instance_variable_get(:@store)
|
23
|
+
store[key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def travel(sec)
|
27
|
+
# Since Timecop.travel() causes test failures on Windows/AppVeyor by inducing
|
28
|
+
# rounding errors to Time.now, we need to use Timecop.freeze() instead.
|
29
|
+
Timecop.freeze(Time.now + sec)
|
30
|
+
end
|
31
|
+
|
32
|
+
sub_test_case 'init' do
|
33
|
+
setup do
|
34
|
+
@reset_interval = 10
|
35
|
+
@store = Fluent::Counter::Store.new
|
36
|
+
@data = { 'name' => @name, 'reset_interval' => @reset_interval }
|
37
|
+
@key = Fluent::Counter::Store.gen_key(@scope, @name)
|
38
|
+
end
|
39
|
+
|
40
|
+
test 'create new value in the counter' do
|
41
|
+
v = @store.init(@key, @data)
|
42
|
+
|
43
|
+
assert_equal @name, v['name']
|
44
|
+
assert_equal @reset_interval, v['reset_interval']
|
45
|
+
|
46
|
+
v2 = extract_value_from_counter(@store, @key)
|
47
|
+
v2 = @store.send(:build_response, v2)
|
48
|
+
assert_equal v, v2
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'raise an error when a passed key already exists' do
|
52
|
+
@store.init(@key, @data)
|
53
|
+
|
54
|
+
assert_raise Fluent::Counter::InvalidParams do
|
55
|
+
@store.init(@key, @data)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
test 'return a value when passed key already exists and a ignore option is true' do
|
60
|
+
v = @store.init(@key, @data)
|
61
|
+
v1 = extract_value_from_counter(@store, @key)
|
62
|
+
v1 = @store.send(:build_response, v1)
|
63
|
+
v2 = @store.init(@key, @data, ignore: true)
|
64
|
+
assert_equal v, v2
|
65
|
+
assert_equal v1, v2
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
sub_test_case 'get' do
|
70
|
+
setup do
|
71
|
+
@store = Fluent::Counter::Store.new
|
72
|
+
data = { 'name' => @name, 'reset_interval' => 10 }
|
73
|
+
@key = Fluent::Counter::Store.gen_key(@scope, @name)
|
74
|
+
@store.init(@key, data)
|
75
|
+
end
|
76
|
+
|
77
|
+
test 'return a value from the counter' do
|
78
|
+
v = extract_value_from_counter(@store, @key)
|
79
|
+
expected = @store.send(:build_response, v)
|
80
|
+
assert_equal expected, @store.get(@key)
|
81
|
+
end
|
82
|
+
|
83
|
+
test 'return a raw value from the counter when raw option is true' do
|
84
|
+
v = extract_value_from_counter(@store, @key)
|
85
|
+
assert_equal v, @store.get(@key, raw: true)
|
86
|
+
end
|
87
|
+
|
88
|
+
test "return nil when a passed key doesn't exist" do
|
89
|
+
assert_equal nil, @store.get('unknown_key')
|
90
|
+
end
|
91
|
+
|
92
|
+
test "raise a error when when a passed key doesn't exist and raise_error option is true" do
|
93
|
+
assert_raise Fluent::Counter::UnknownKey do
|
94
|
+
@store.get('unknown_key', raise_error: true)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
sub_test_case 'key?' do
|
100
|
+
setup do
|
101
|
+
@store = Fluent::Counter::Store.new
|
102
|
+
data = { 'name' => @name, 'reset_interval' => 10 }
|
103
|
+
@key = Fluent::Counter::Store.gen_key(@scope, @name)
|
104
|
+
@store.init(@key, data)
|
105
|
+
end
|
106
|
+
|
107
|
+
test 'return true when passed key exists' do
|
108
|
+
assert_true @store.key?(@key)
|
109
|
+
end
|
110
|
+
|
111
|
+
test "return false when passed key doesn't exist" do
|
112
|
+
assert_true !@store.key?('unknown_key')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
sub_test_case 'delete' do
|
117
|
+
setup do
|
118
|
+
@store = Fluent::Counter::Store.new
|
119
|
+
data = { 'name' => @name, 'reset_interval' => 10 }
|
120
|
+
@key = Fluent::Counter::Store.gen_key(@scope, @name)
|
121
|
+
@init_value = @store.init(@key, data)
|
122
|
+
end
|
123
|
+
|
124
|
+
test 'delete a value from the counter' do
|
125
|
+
v = @store.delete(@key)
|
126
|
+
assert_equal @init_value, v
|
127
|
+
assert_nil extract_value_from_counter(@store, @key)
|
128
|
+
end
|
129
|
+
|
130
|
+
test "raise an error when passed key doesn't exist" do
|
131
|
+
assert_raise Fluent::Counter::UnknownKey do
|
132
|
+
@store.delete('unknown_key')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
sub_test_case 'inc' do
|
138
|
+
setup do
|
139
|
+
@store = Fluent::Counter::Store.new
|
140
|
+
@init_data = { 'name' => @name, 'reset_interval' => 10 }
|
141
|
+
@travel_sec = 10
|
142
|
+
end
|
143
|
+
|
144
|
+
data(
|
145
|
+
positive: 10,
|
146
|
+
negative: -10
|
147
|
+
)
|
148
|
+
test 'increment or decrement a value in the counter' do |value|
|
149
|
+
key = Fluent::Counter::Store.gen_key(@scope, @name)
|
150
|
+
@store.init(key, @init_data)
|
151
|
+
travel(@travel_sec)
|
152
|
+
v = @store.inc(key, { 'value' => value })
|
153
|
+
|
154
|
+
assert_equal value, v['total']
|
155
|
+
assert_equal value, v['current']
|
156
|
+
assert_equal @now, v['last_reset_at'] # last_reset_at doesn't change
|
157
|
+
|
158
|
+
v1 = extract_value_from_counter(@store, key)
|
159
|
+
v1 = @store.send(:build_response, v1)
|
160
|
+
assert_equal v, v1
|
161
|
+
end
|
162
|
+
|
163
|
+
test "raise an error when passed key doesn't exist" do
|
164
|
+
assert_raise Fluent::Counter::UnknownKey do
|
165
|
+
@store.inc('unknown_key', { 'value' => 1 })
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
test 'raise an error when a type of passed value is incompatible with a stored value' do
|
170
|
+
key1 = Fluent::Counter::Store.gen_key(@scope, @name)
|
171
|
+
key2 = Fluent::Counter::Store.gen_key(@scope, 'name2')
|
172
|
+
key3 = Fluent::Counter::Store.gen_key(@scope, 'name3')
|
173
|
+
v1 = @store.init(key1, @init_data.merge('type' => 'integer'))
|
174
|
+
v2 = @store.init(key2, @init_data.merge('type' => 'float'))
|
175
|
+
v3 = @store.init(key3, @init_data.merge('type' => 'numeric'))
|
176
|
+
assert_equal 'integer', v1['type']
|
177
|
+
assert_equal 'float', v2['type']
|
178
|
+
assert_equal 'numeric', v3['type']
|
179
|
+
|
180
|
+
assert_raise Fluent::Counter::InvalidParams do
|
181
|
+
@store.inc(key1, { 'value' => 1.1 })
|
182
|
+
end
|
183
|
+
|
184
|
+
assert_raise Fluent::Counter::InvalidParams do
|
185
|
+
@store.inc(key2, { 'value' => 1 })
|
186
|
+
end
|
187
|
+
|
188
|
+
assert_nothing_raised do
|
189
|
+
@store.inc(key3, { 'value' => 1 })
|
190
|
+
@store.inc(key3, { 'value' => 1.0 })
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
sub_test_case 'reset' do
|
196
|
+
setup do
|
197
|
+
@store = Fluent::Counter::Store.new
|
198
|
+
@travel_sec = 10
|
199
|
+
|
200
|
+
@inc_value = 10
|
201
|
+
@key = Fluent::Counter::Store.gen_key(@scope, @name)
|
202
|
+
@store.init(@key, { 'name' => @name, 'reset_interval' => 10 })
|
203
|
+
@store.inc(@key, { 'value' => 10 })
|
204
|
+
end
|
205
|
+
|
206
|
+
test 'reset a value in the counter' do
|
207
|
+
travel(@travel_sec)
|
208
|
+
|
209
|
+
v = @store.reset(@key)
|
210
|
+
assert_equal @travel_sec, v['elapsed_time']
|
211
|
+
assert_true v['success']
|
212
|
+
counter = v['counter_data']
|
213
|
+
|
214
|
+
assert_equal @name, counter['name']
|
215
|
+
assert_equal @inc_value, counter['total']
|
216
|
+
assert_equal @inc_value, counter['current']
|
217
|
+
assert_equal 'numeric', counter['type']
|
218
|
+
assert_equal @now, counter['last_reset_at']
|
219
|
+
assert_equal 10, counter['reset_interval']
|
220
|
+
|
221
|
+
v1 = extract_value_from_counter(@store, @key)
|
222
|
+
assert_equal 0, v1['current']
|
223
|
+
assert_true v1['current'].is_a?(Integer)
|
224
|
+
assert_equal @inc_value, v1['total']
|
225
|
+
assert_equal (@now + @travel_sec), Fluent::EventTime.new(*v1['last_reset_at'])
|
226
|
+
assert_equal (@now + @travel_sec), Fluent::EventTime.new(*v1['last_modified_at'])
|
227
|
+
end
|
228
|
+
|
229
|
+
test 'reset a value after `reset_interval` passed' do
|
230
|
+
first_travel_sec = 5
|
231
|
+
travel(first_travel_sec) # jump time less than reset_interval
|
232
|
+
v = @store.reset(@key)
|
233
|
+
|
234
|
+
assert_equal false, v['success']
|
235
|
+
assert_equal first_travel_sec, v['elapsed_time']
|
236
|
+
store = extract_value_from_counter(@store, @key)
|
237
|
+
assert_equal 10, store['current']
|
238
|
+
assert_equal @now, Fluent::EventTime.new(*store['last_reset_at'])
|
239
|
+
|
240
|
+
# time is passed greater than reset_interval
|
241
|
+
travel(@travel_sec)
|
242
|
+
v = @store.reset(@key)
|
243
|
+
assert_true v['success']
|
244
|
+
assert_equal @travel_sec + first_travel_sec, v['elapsed_time']
|
245
|
+
|
246
|
+
v1 = extract_value_from_counter(@store, @key)
|
247
|
+
assert_equal 0, v1['current']
|
248
|
+
assert_equal (@now + @travel_sec + first_travel_sec), Fluent::EventTime.new(*v1['last_reset_at'])
|
249
|
+
assert_equal (@now + @travel_sec + first_travel_sec), Fluent::EventTime.new(*v1['last_modified_at'])
|
250
|
+
end
|
251
|
+
|
252
|
+
test "raise an error when passed key doesn't exist" do
|
253
|
+
assert_raise Fluent::Counter::UnknownKey do
|
254
|
+
@store.reset('unknown_key')
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'fluent/counter/validator'
|
3
|
+
|
4
|
+
class CounterValidatorTest < ::Test::Unit::TestCase
|
5
|
+
data(
|
6
|
+
invalid_name1: '',
|
7
|
+
invalid_name3: '_',
|
8
|
+
invalid_name4: 'A',
|
9
|
+
invalid_name5: 'a*',
|
10
|
+
invalid_name6: "a\t",
|
11
|
+
invalid_name7: "\n",
|
12
|
+
)
|
13
|
+
test 'invalid name' do |invalid_name|
|
14
|
+
assert_nil(Fluent::Counter::Validator::VALID_NAME =~ invalid_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
sub_test_case 'request' do
|
18
|
+
test 'return an empty array' do
|
19
|
+
data = { 'id' => 0, 'method' => 'init' }
|
20
|
+
errors = Fluent::Counter::Validator.request(data)
|
21
|
+
assert_empty errors
|
22
|
+
end
|
23
|
+
|
24
|
+
data(
|
25
|
+
missing_id: [
|
26
|
+
{ 'method' => 'init' },
|
27
|
+
{ 'code' => 'invalid_request', 'message' => 'Request should include `id`' }
|
28
|
+
],
|
29
|
+
missing_method: [
|
30
|
+
{ 'id' => 0 },
|
31
|
+
{ 'code' => 'invalid_request', 'message' => 'Request should include `method`' }
|
32
|
+
],
|
33
|
+
invalid_method: [
|
34
|
+
{ 'id' => 0, 'method' => "A\t" },
|
35
|
+
{ 'code' => 'invalid_request', 'message' => '`method` is the invalid format' }
|
36
|
+
],
|
37
|
+
unknown_method: [
|
38
|
+
{ 'id' => 0, 'method' => 'unknown_method' },
|
39
|
+
{ 'code' => 'method_not_found', 'message' => 'Unknown method name passed: unknown_method' }
|
40
|
+
]
|
41
|
+
)
|
42
|
+
test 'return an error array' do |(data, expected_error)|
|
43
|
+
errors = Fluent::Counter::Validator.request(data)
|
44
|
+
assert_equal [expected_error], errors
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
sub_test_case 'call' do
|
49
|
+
test "return an error hash when passed method doesn't exist" do
|
50
|
+
v = Fluent::Counter::Validator.new(:unknown)
|
51
|
+
success, errors = v.call(['key1'])
|
52
|
+
assert_empty success
|
53
|
+
assert_equal 'internal_server_error', errors.first.to_hash['code']
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'validate_empty!' do
|
58
|
+
v = Fluent::Counter::Validator.new(:empty)
|
59
|
+
success, errors = v.call([])
|
60
|
+
assert_empty success
|
61
|
+
assert_equal [Fluent::Counter::InvalidParams.new('One or more `params` are required')], errors
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class CounterArrayValidatorTest < ::Test::Unit::TestCase
|
66
|
+
test 'validate_key!' do
|
67
|
+
ary = ['key', 100, '_']
|
68
|
+
error_expected = [
|
69
|
+
{ 'code' => 'invalid_params', 'message' => 'The type of `key` should be String' },
|
70
|
+
{ 'code' => 'invalid_params', 'message' => '`key` is the invalid format' }
|
71
|
+
]
|
72
|
+
v = Fluent::Counter::ArrayValidator.new(:key)
|
73
|
+
valid_params, errors = v.call(ary)
|
74
|
+
|
75
|
+
assert_equal ['key'], valid_params
|
76
|
+
assert_equal error_expected, errors.map(&:to_hash)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class CounterHashValidatorTest < ::Test::Unit::TestCase
|
81
|
+
test 'validate_name!' do
|
82
|
+
hash = [
|
83
|
+
{ 'name' => 'key' },
|
84
|
+
{},
|
85
|
+
{ 'name' => 10 },
|
86
|
+
{ 'name' => '_' }
|
87
|
+
]
|
88
|
+
error_expected = [
|
89
|
+
{ 'code' => 'invalid_params', 'message' => '`name` is required' },
|
90
|
+
{ 'code' => 'invalid_params', 'message' => 'The type of `name` should be String' },
|
91
|
+
{ 'code' => 'invalid_params', 'message' => '`name` is the invalid format' },
|
92
|
+
]
|
93
|
+
v = Fluent::Counter::HashValidator.new(:name)
|
94
|
+
success, errors = v.call(hash)
|
95
|
+
|
96
|
+
assert_equal [{ 'name' => 'key' }], success
|
97
|
+
assert_equal error_expected, errors.map(&:to_hash)
|
98
|
+
end
|
99
|
+
|
100
|
+
test 'validate_value!' do
|
101
|
+
hash = [
|
102
|
+
{ 'value' => 1 },
|
103
|
+
{ 'value' => -1 },
|
104
|
+
{},
|
105
|
+
{ 'value' => 'str' }
|
106
|
+
]
|
107
|
+
error_expected = [
|
108
|
+
{ 'code' => 'invalid_params', 'message' => '`value` is required' },
|
109
|
+
{ 'code' => 'invalid_params', 'message' => 'The type of `value` type should be Numeric' },
|
110
|
+
]
|
111
|
+
v = Fluent::Counter::HashValidator.new(:value)
|
112
|
+
valid_params, errors = v.call(hash)
|
113
|
+
|
114
|
+
assert_equal [{ 'value' => 1 }, { 'value' => -1 }], valid_params
|
115
|
+
assert_equal error_expected, errors.map(&:to_hash)
|
116
|
+
end
|
117
|
+
|
118
|
+
test 'validate_reset_interval!' do
|
119
|
+
hash = [
|
120
|
+
{ 'reset_interval' => 1 },
|
121
|
+
{ 'reset_interval' => 1.0 },
|
122
|
+
{},
|
123
|
+
{ 'reset_interval' => -1 },
|
124
|
+
{ 'reset_interval' => 'str' }
|
125
|
+
]
|
126
|
+
error_expected = [
|
127
|
+
{ 'code' => 'invalid_params', 'message' => '`reset_interval` is required' },
|
128
|
+
{ 'code' => 'invalid_params', 'message' => '`reset_interval` should be a positive number' },
|
129
|
+
{ 'code' => 'invalid_params', 'message' => 'The type of `reset_interval` should be Numeric' },
|
130
|
+
]
|
131
|
+
v = Fluent::Counter::HashValidator.new(:reset_interval)
|
132
|
+
valid_params, errors = v.call(hash)
|
133
|
+
|
134
|
+
assert_equal [{ 'reset_interval' => 1 }, { 'reset_interval' => 1.0 }], valid_params
|
135
|
+
assert_equal error_expected.map(&:to_hash), errors.map(&:to_hash)
|
136
|
+
end
|
137
|
+
end
|
@@ -840,4 +840,128 @@ class FileBufferTest < Test::Unit::TestCase
|
|
840
840
|
assert File.exist?(@not_chunk)
|
841
841
|
end
|
842
842
|
end
|
843
|
+
|
844
|
+
sub_test_case 'there are existing broken file chunks' do
|
845
|
+
setup do
|
846
|
+
@bufdir = File.expand_path('../../tmp/broken_buffer_file', __FILE__)
|
847
|
+
FileUtils.mkdir_p @bufdir unless File.exist?(@bufdir)
|
848
|
+
@bufpath = File.join(@bufdir, 'broken_test.*.log')
|
849
|
+
|
850
|
+
Fluent::Test.setup
|
851
|
+
@d = FluentPluginFileBufferTest::DummyOutputPlugin.new
|
852
|
+
@p = Fluent::Plugin::FileBuffer.new
|
853
|
+
@p.owner = @d
|
854
|
+
@p.configure(config_element('buffer', '', {'path' => @bufpath}))
|
855
|
+
end
|
856
|
+
|
857
|
+
teardown do
|
858
|
+
if @p
|
859
|
+
@p.stop unless @p.stopped?
|
860
|
+
@p.before_shutdown unless @p.before_shutdown?
|
861
|
+
@p.shutdown unless @p.shutdown?
|
862
|
+
@p.after_shutdown unless @p.after_shutdown?
|
863
|
+
@p.close unless @p.closed?
|
864
|
+
@p.terminate unless @p.terminated?
|
865
|
+
end
|
866
|
+
if @bufdir
|
867
|
+
Dir.glob(File.join(@bufdir, '*')).each do |path|
|
868
|
+
next if ['.', '..'].include?(File.basename(path))
|
869
|
+
File.delete(path)
|
870
|
+
end
|
871
|
+
end
|
872
|
+
end
|
873
|
+
|
874
|
+
def create_first_chunk(mode)
|
875
|
+
cid = Fluent::UniqueId.generate
|
876
|
+
path = File.join(@bufdir, "broken_test.#{mode}#{Fluent::UniqueId.hex(cid)}.log")
|
877
|
+
File.open(path, 'wb') do |f|
|
878
|
+
f.write ["t1.test", event_time('2016-04-17 14:00:15 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
879
|
+
f.write ["t2.test", event_time('2016-04-17 14:00:17 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
880
|
+
f.write ["t3.test", event_time('2016-04-17 14:00:21 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
881
|
+
f.write ["t4.test", event_time('2016-04-17 14:00:28 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
882
|
+
end
|
883
|
+
write_metadata(
|
884
|
+
path + '.meta', cid, metadata(timekey: event_time('2016-04-17 14:00:00 -0700').to_i),
|
885
|
+
4, event_time('2016-04-17 14:00:00 -0700').to_i, event_time('2016-04-17 14:00:28 -0700').to_i
|
886
|
+
)
|
887
|
+
|
888
|
+
return cid, path
|
889
|
+
end
|
890
|
+
|
891
|
+
def create_second_chunk(mode)
|
892
|
+
cid = Fluent::UniqueId.generate
|
893
|
+
path = File.join(@bufdir, "broken_test.#{mode}#{Fluent::UniqueId.hex(cid)}.log")
|
894
|
+
File.open(path, 'wb') do |f|
|
895
|
+
f.write ["t1.test", event_time('2016-04-17 14:01:15 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
896
|
+
f.write ["t2.test", event_time('2016-04-17 14:01:17 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
897
|
+
f.write ["t3.test", event_time('2016-04-17 14:01:21 -0700').to_i, {"message" => "yay"}].to_json + "\n"
|
898
|
+
end
|
899
|
+
write_metadata(
|
900
|
+
path + '.meta', cid, metadata(timekey: event_time('2016-04-17 14:01:00 -0700').to_i),
|
901
|
+
3, event_time('2016-04-17 14:01:00 -0700').to_i, event_time('2016-04-17 14:01:25 -0700').to_i
|
902
|
+
)
|
903
|
+
|
904
|
+
return cid, path
|
905
|
+
end
|
906
|
+
|
907
|
+
def compare_staged_chunk(staged, id, time, num, mode)
|
908
|
+
assert_equal 1, staged.size
|
909
|
+
m = metadata(timekey: event_time(time).to_i)
|
910
|
+
assert_equal id, staged[m].unique_id
|
911
|
+
assert_equal num, staged[m].size
|
912
|
+
assert_equal mode, staged[m].state
|
913
|
+
end
|
914
|
+
|
915
|
+
def compare_queued_chunk(queued, id, num, mode)
|
916
|
+
assert_equal 1, queued.size
|
917
|
+
assert_equal id, queued[0].unique_id
|
918
|
+
assert_equal num, queued[0].size
|
919
|
+
assert_equal mode, queued[0].state
|
920
|
+
end
|
921
|
+
|
922
|
+
def compare_log(plugin, msg)
|
923
|
+
logs = plugin.log.out.logs
|
924
|
+
assert { logs.any? { |log| log.include?(msg) } }
|
925
|
+
end
|
926
|
+
|
927
|
+
test '#resume ignores staged empty chunk' do
|
928
|
+
_, p1 = create_first_chunk('b')
|
929
|
+
File.open(p1, 'wb') { |f| } # create staged empty chunk file
|
930
|
+
c2id, _ = create_second_chunk('b')
|
931
|
+
|
932
|
+
@p.start
|
933
|
+
compare_staged_chunk(@p.stage, c2id, '2016-04-17 14:01:00 -0700', 3, :staged)
|
934
|
+
compare_log(@p, 'staged file chunk is empty')
|
935
|
+
end
|
936
|
+
|
937
|
+
test '#resume ignores staged broken metadata' do
|
938
|
+
c1id, _ = create_first_chunk('b')
|
939
|
+
_, p2 = create_second_chunk('b')
|
940
|
+
File.open(p2 + '.meta', 'wb') { |f| f.write("\0" * 70) } # create staged broken meta file
|
941
|
+
|
942
|
+
@p.start
|
943
|
+
compare_staged_chunk(@p.stage, c1id, '2016-04-17 14:00:00 -0700', 4, :staged)
|
944
|
+
compare_log(@p, 'staged meta file is broken')
|
945
|
+
end
|
946
|
+
|
947
|
+
test '#resume ignores enqueued empty chunk' do
|
948
|
+
_, p1 = create_first_chunk('q')
|
949
|
+
File.open(p1, 'wb') { |f| } # create enqueued empty chunk file
|
950
|
+
c2id, _ = create_second_chunk('q')
|
951
|
+
|
952
|
+
@p.start
|
953
|
+
compare_queued_chunk(@p.queue, c2id, 3, :queued)
|
954
|
+
compare_log(@p, 'enqueued file chunk is empty')
|
955
|
+
end
|
956
|
+
|
957
|
+
test '#resume ignores enqueued broken metadata' do
|
958
|
+
c1id, _ = create_first_chunk('q')
|
959
|
+
_, p2 = create_second_chunk('q')
|
960
|
+
File.open(p2 + '.meta', 'wb') { |f| f.write("\0" * 70) } # create enqueued broken meta file
|
961
|
+
|
962
|
+
@p.start
|
963
|
+
compare_queued_chunk(@p.queue, c1id, 4, :queued)
|
964
|
+
compare_log(@p, 'enqueued meta file is broken')
|
965
|
+
end
|
966
|
+
end
|
843
967
|
end
|