fluentd 1.16.6-x64-mingw32 → 1.17.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/DISCUSSION_TEMPLATE/q-a-japanese.yml +50 -0
  3. data/.github/DISCUSSION_TEMPLATE/q-a.yml +47 -0
  4. data/.github/workflows/test-ruby-head.yml +31 -0
  5. data/.github/workflows/test.yml +2 -8
  6. data/CHANGELOG.md +36 -12
  7. data/README.md +1 -1
  8. data/Rakefile +1 -1
  9. data/fluentd.gemspec +10 -5
  10. data/lib/fluent/command/binlog_reader.rb +1 -1
  11. data/lib/fluent/command/fluentd.rb +1 -1
  12. data/lib/fluent/config/configure_proxy.rb +2 -2
  13. data/lib/fluent/config/types.rb +1 -1
  14. data/lib/fluent/config/yaml_parser/parser.rb +0 -4
  15. data/lib/fluent/configurable.rb +2 -2
  16. data/lib/fluent/counter/mutex_hash.rb +1 -1
  17. data/lib/fluent/fluent_log_event_router.rb +0 -2
  18. data/lib/fluent/plugin/buf_file.rb +1 -1
  19. data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
  20. data/lib/fluent/plugin/buffer/file_single_chunk.rb +2 -3
  21. data/lib/fluent/plugin/filter_parser.rb +26 -8
  22. data/lib/fluent/plugin/in_http.rb +18 -53
  23. data/lib/fluent/plugin/in_tail.rb +34 -2
  24. data/lib/fluent/plugin/out_file.rb +0 -8
  25. data/lib/fluent/plugin/out_http.rb +125 -13
  26. data/lib/fluent/plugin/owned_by_mixin.rb +0 -1
  27. data/lib/fluent/plugin/parser_json.rb +34 -9
  28. data/lib/fluent/plugin/parser_msgpack.rb +24 -3
  29. data/lib/fluent/plugin_helper/metrics.rb +2 -2
  30. data/lib/fluent/registry.rb +6 -6
  31. data/lib/fluent/test/output_test.rb +1 -1
  32. data/lib/fluent/unique_id.rb +1 -1
  33. data/lib/fluent/version.rb +1 -1
  34. data/test/command/test_fluentd.rb +9 -56
  35. data/test/log/test_console_adapter.rb +10 -3
  36. data/test/plugin/data/log_numeric/01.log +0 -0
  37. data/test/plugin/data/log_numeric/02.log +0 -0
  38. data/test/plugin/data/log_numeric/12.log +0 -0
  39. data/test/plugin/data/log_numeric/14.log +0 -0
  40. data/test/plugin/in_tail/test_io_handler.rb +14 -13
  41. data/test/plugin/in_tail/test_position_file.rb +7 -6
  42. data/test/plugin/test_in_http.rb +23 -1
  43. data/test/plugin/test_in_tail.rb +141 -0
  44. data/test/plugin/test_out_file.rb +1 -21
  45. data/test/plugin/test_out_http.rb +128 -0
  46. data/test/plugin/test_owned_by.rb +0 -1
  47. data/test/plugin/test_parser_json.rb +106 -31
  48. data/test/plugin/test_parser_msgpack.rb +127 -0
  49. data/test/plugin/test_storage.rb +0 -1
  50. data/test/plugin_helper/test_child_process.rb +4 -4
  51. data/test/test_config.rb +0 -6
  52. metadata +99 -16
@@ -65,6 +65,8 @@ module Fluent::Plugin
65
65
  config_param :path, :string
66
66
  desc 'path delimiter used for spliting path config'
67
67
  config_param :path_delimiter, :string, default: ','
68
+ desc 'Choose using glob patterns. Adding capabilities to handle [] and ?, and {}.'
69
+ config_param :glob_policy, :enum, list: [:backward_compatible, :extended, :always], default: :backward_compatible
68
70
  desc 'The tag of the event.'
69
71
  config_param :tag, :string
70
72
  desc 'The paths to exclude the files from watcher list.'
@@ -141,6 +143,14 @@ module Fluent::Plugin
141
143
  raise Fluent::ConfigError, "either of enable_watch_timer or enable_stat_watcher must be true"
142
144
  end
143
145
 
146
+ if @glob_policy == :always && @path_delimiter == ','
147
+ raise Fluent::ConfigError, "cannot use glob_policy as always with the default path_delimitor: `,\""
148
+ end
149
+
150
+ if @glob_policy == :extended && /\{.*,.*\}/.match(@path) && extended_glob_pattern(@path)
151
+ raise Fluent::ConfigError, "cannot include curly braces with glob patterns in `#{@path}\". Use glob_policy always instead."
152
+ end
153
+
144
154
  if RESERVED_CHARS.include?(@path_delimiter)
145
155
  rc = RESERVED_CHARS.join(', ')
146
156
  raise Fluent::ConfigError, "#{rc} are reserved words: #{@path_delimiter}"
@@ -288,6 +298,28 @@ module Fluent::Plugin
288
298
  @capability.have_capability?(:effective, :dac_override)
289
299
  end
290
300
 
301
+ def extended_glob_pattern(path)
302
+ path.include?('*') || path.include?('?') || /\[.*\]/.match(path)
303
+ end
304
+
305
+ # Curly braces is not supported with default path_delimiter
306
+ # because the default delimiter of path is ",".
307
+ # This should be collided for wildcard pattern for curly braces and
308
+ # be handled as an error on #configure.
309
+ def use_glob?(path)
310
+ if @glob_policy == :always
311
+ # For future extensions, we decided to use `always' term to handle
312
+ # regular expressions as much as possible.
313
+ # This is because not using `true' as a returning value
314
+ # when choosing :always here.
315
+ extended_glob_pattern(path) || /\{.*,.*\}/.match(path)
316
+ elsif @glob_policy == :extended
317
+ extended_glob_pattern(path)
318
+ elsif @glob_policy == :backward_compatible
319
+ path.include?('*')
320
+ end
321
+ end
322
+
291
323
  def expand_paths
292
324
  date = Fluent::EventTime.now
293
325
  paths = []
@@ -297,7 +329,7 @@ module Fluent::Plugin
297
329
  else
298
330
  date.to_time.strftime(path)
299
331
  end
300
- if path.include?('*')
332
+ if use_glob?(path)
301
333
  paths += Dir.glob(path).select { |p|
302
334
  begin
303
335
  is_file = !File.directory?(p)
@@ -332,7 +364,7 @@ module Fluent::Plugin
332
364
  else
333
365
  date.to_time.strftime(path)
334
366
  end
335
- path.include?('*') ? Dir.glob(path) : path
367
+ use_glob?(path) ? Dir.glob(path) : path
336
368
  }.flatten.uniq
337
369
  # filter out non existing files, so in case pattern is without '*' we don't do unnecessary work
338
370
  hash = {}
@@ -172,14 +172,6 @@ module Fluent::Plugin
172
172
  log.warn "symlink_path is unavailable on Windows platform. disabled."
173
173
  @symlink_path = nil
174
174
  else
175
- placeholder_validators(:symlink_path, @symlink_path).reject{ |v| v.type == :time }.each do |v|
176
- begin
177
- v.validate!
178
- rescue Fluent::ConfigError => e
179
- log.warn "#{e}. This means multiple chunks are competing for a single symlink_path, so some logs may not be taken from the symlink."
180
- end
181
- end
182
-
183
175
  @buffer.extend SymlinkBufferMixin
184
176
  @buffer.symlink_path = @symlink_path
185
177
  @buffer.output_plugin_for_symlink = self
@@ -37,6 +37,8 @@ module Fluent::Plugin
37
37
 
38
38
  class RetryableResponse < StandardError; end
39
39
 
40
+ ConnectionCache = Struct.new(:uri, :conn)
41
+
40
42
  helpers :formatter
41
43
 
42
44
  desc 'The endpoint for HTTP request, e.g. http://example.com/api'
@@ -60,6 +62,8 @@ module Fluent::Plugin
60
62
  config_param :read_timeout, :integer, default: nil
61
63
  desc 'The TLS timeout in seconds'
62
64
  config_param :ssl_timeout, :integer, default: nil
65
+ desc 'Try to reuse connections'
66
+ config_param :reuse_connections, :bool, default: false
63
67
 
64
68
  desc 'The CA certificate path for TLS'
65
69
  config_param :tls_ca_cert_path, :string, default: nil
@@ -87,11 +91,29 @@ module Fluent::Plugin
87
91
 
88
92
  config_section :auth, required: false, multi: false do
89
93
  desc 'The method for HTTP authentication'
90
- config_param :method, :enum, list: [:basic], default: :basic
94
+ config_param :method, :enum, list: [:basic, :aws_sigv4], default: :basic
91
95
  desc 'The username for basic authentication'
92
96
  config_param :username, :string, default: nil
93
97
  desc 'The password for basic authentication'
94
98
  config_param :password, :string, default: nil, secret: true
99
+ desc 'The AWS service to authenticate against'
100
+ config_param :aws_service, :string, default: nil
101
+ desc 'The AWS region to use when authenticating'
102
+ config_param :aws_region, :string, default: nil
103
+ desc 'The AWS role ARN to assume when authenticating'
104
+ config_param :aws_role_arn, :string, default: nil
105
+ end
106
+
107
+ def connection_cache_id_thread_key
108
+ "#{plugin_id}_connection_cache_id"
109
+ end
110
+
111
+ def connection_cache_id_for_thread
112
+ Thread.current[connection_cache_id_thread_key]
113
+ end
114
+
115
+ def connection_cache_id_for_thread=(id)
116
+ Thread.current[connection_cache_id_thread_key] = id
95
117
  end
96
118
 
97
119
  def initialize
@@ -100,11 +122,23 @@ module Fluent::Plugin
100
122
  @uri = nil
101
123
  @proxy_uri = nil
102
124
  @formatter = nil
125
+
126
+ @connection_cache = []
127
+ @connection_cache_id_mutex = Mutex.new
128
+ @connection_cache_next_id = 0
129
+ end
130
+
131
+ def close
132
+ super
133
+
134
+ @connection_cache.each {|entry| entry.conn.finish if entry.conn&.started? }
103
135
  end
104
136
 
105
137
  def configure(conf)
106
138
  super
107
139
 
140
+ @connection_cache = Array.new(actual_flush_thread_count, ConnectionCache.new("", nil)) if @reuse_connections
141
+
108
142
  if @retryable_response_codes.nil?
109
143
  log.warn('Status code 503 is going to be removed from default `retryable_response_codes` from fluentd v2. Please add it by yourself if you wish')
110
144
  @retryable_response_codes = [503]
@@ -121,6 +155,36 @@ module Fluent::Plugin
121
155
  end
122
156
  define_singleton_method(:format, method(:format_json_array))
123
157
  end
158
+
159
+ if @auth and @auth.method == :aws_sigv4
160
+ begin
161
+ require 'aws-sigv4'
162
+ require 'aws-sdk-core'
163
+ rescue LoadError
164
+ raise Fluent::ConfigError, "The aws-sdk-core and aws-sigv4 gems are required for aws_sigv4 auth. Run: gem install aws-sdk-core -v '~> 3.191'"
165
+ end
166
+
167
+ raise Fluent::ConfigError, "aws_service is required for aws_sigv4 auth" unless @auth.aws_service != nil
168
+ raise Fluent::ConfigError, "aws_region is required for aws_sigv4 auth" unless @auth.aws_region != nil
169
+
170
+ if @auth.aws_role_arn == nil
171
+ aws_credentials = Aws::CredentialProviderChain.new.resolve
172
+ else
173
+ aws_credentials = Aws::AssumeRoleCredentials.new(
174
+ client: Aws::STS::Client.new(
175
+ region: @auth.aws_region
176
+ ),
177
+ role_arn: @auth.aws_role_arn,
178
+ role_session_name: "fluentd"
179
+ )
180
+ end
181
+
182
+ @aws_signer = Aws::Sigv4::Signer.new(
183
+ service: @auth.aws_service,
184
+ region: @auth.aws_region,
185
+ credentials_provider: aws_credentials
186
+ )
187
+ end
124
188
  end
125
189
 
126
190
  def multi_workers_ready?
@@ -215,7 +279,7 @@ module Fluent::Plugin
215
279
  URI.parse(endpoint)
216
280
  end
217
281
 
218
- def set_headers(req, chunk)
282
+ def set_headers(req, uri, chunk)
219
283
  if @headers
220
284
  @headers.each do |k, v|
221
285
  req[k] = v
@@ -229,6 +293,28 @@ module Fluent::Plugin
229
293
  req['Content-Type'] = @content_type
230
294
  end
231
295
 
296
+ def set_auth(req, uri)
297
+ return unless @auth
298
+
299
+ if @auth.method == :basic
300
+ req.basic_auth(@auth.username, @auth.password)
301
+ elsif @auth.method == :aws_sigv4
302
+ signature = @aws_signer.sign_request(
303
+ http_method: req.method,
304
+ url: uri.request_uri,
305
+ headers: {
306
+ 'Content-Type' => @content_type,
307
+ 'Host' => uri.host
308
+ },
309
+ body: req.body
310
+ )
311
+ req.add_field('x-amz-date', signature.headers['x-amz-date'])
312
+ req.add_field('x-amz-security-token', signature.headers['x-amz-security-token'])
313
+ req.add_field('x-amz-content-sha256', signature.headers['x-amz-content-sha256'])
314
+ req.add_field('authorization', signature.headers['authorization'])
315
+ end
316
+ end
317
+
232
318
  def create_request(chunk, uri)
233
319
  req = case @http_method
234
320
  when :post
@@ -236,23 +322,49 @@ module Fluent::Plugin
236
322
  when :put
237
323
  Net::HTTP::Put.new(uri.request_uri)
238
324
  end
239
- if @auth
240
- req.basic_auth(@auth.username, @auth.password)
241
- end
242
- set_headers(req, chunk)
325
+ set_headers(req, uri, chunk)
243
326
  req.body = @json_array ? "[#{chunk.read.chop}]" : chunk.read
327
+
328
+ # At least one authentication method requires the body and other headers, so the order of this call matters
329
+ set_auth(req, uri)
244
330
  req
245
331
  end
246
332
 
333
+ def make_request_cached(uri, req)
334
+ id = self.connection_cache_id_for_thread
335
+ if id.nil?
336
+ @connection_cache_id_mutex.synchronize {
337
+ id = @connection_cache_next_id
338
+ @connection_cache_next_id += 1
339
+ }
340
+ self.connection_cache_id_for_thread = id
341
+ end
342
+ uri_str = uri.to_s
343
+ if @connection_cache[id].uri != uri_str
344
+ @connection_cache[id].conn.finish if @connection_cache[id].conn&.started?
345
+ http = if @proxy_uri
346
+ Net::HTTP.start(uri.host, uri.port, @proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password, @http_opt)
347
+ else
348
+ Net::HTTP.start(uri.host, uri.port, @http_opt)
349
+ end
350
+ @connection_cache[id] = ConnectionCache.new(uri_str, http)
351
+ end
352
+ @connection_cache[id].conn.request(req)
353
+ end
354
+
355
+ def make_request(uri, req, &block)
356
+ if @proxy_uri
357
+ Net::HTTP.start(uri.host, uri.port, @proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password, @http_opt, &block)
358
+ else
359
+ Net::HTTP.start(uri.host, uri.port, @http_opt, &block)
360
+ end
361
+ end
362
+
247
363
  def send_request(uri, req)
248
- res = if @proxy_uri
249
- Net::HTTP.start(uri.host, uri.port, @proxy_uri.host, @proxy_uri.port, @proxy_uri.user, @proxy_uri.password, @http_opt) { |http|
250
- http.request(req)
251
- }
364
+ res = if @reuse_connections
365
+ make_request_cached(uri, req)
252
366
  else
253
- Net::HTTP.start(uri.host, uri.port, @http_opt) { |http|
254
- http.request(req)
255
- }
367
+ make_request(uri, req) { |http| http.request(req) }
256
368
  end
257
369
 
258
370
  if res.is_a?(Net::HTTPSuccess)
@@ -21,7 +21,6 @@ module Fluent
21
21
  @_owner = plugin
22
22
 
23
23
  @_plugin_id = plugin.plugin_id
24
- @_plugin_id_configured = plugin.plugin_id_configured?
25
24
 
26
25
  @log = plugin.log
27
26
  end
@@ -50,28 +50,53 @@ module Fluent
50
50
  def configure_json_parser(name)
51
51
  case name
52
52
  when :oj
53
- return [Oj.method(:load), Oj::ParseError] if Fluent::OjOptions.available?
54
-
55
- log&.info "Oj is not installed, and failing back to Yajl for json parser"
56
- configure_json_parser(:yajl)
53
+ raise LoadError unless Fluent::OjOptions.available?
54
+ [Oj.method(:load), Oj::ParseError]
57
55
  when :json then [JSON.method(:load), JSON::ParserError]
58
56
  when :yajl then [Yajl.method(:load), Yajl::ParseError]
59
57
  else
60
58
  raise "BUG: unknown json parser specified: #{name}"
61
59
  end
60
+ rescue LoadError => ex
61
+ name = :yajl
62
+ if log
63
+ if /\boj\z/.match?(ex.message)
64
+ log.info "Oj is not installed, and failing back to Yajl for json parser"
65
+ else
66
+ log.warn ex.message
67
+ end
68
+ end
69
+ retry
62
70
  end
63
71
 
64
72
  def parse(text)
65
- record = @load_proc.call(text)
66
- time = parse_time(record)
67
- if @execute_convert_values
68
- time, record = convert_values(time, record)
73
+ parsed_json = @load_proc.call(text)
74
+
75
+ if parsed_json.is_a?(Hash)
76
+ time, record = parse_one_record(parsed_json)
77
+ yield time, record
78
+ elsif parsed_json.is_a?(Array)
79
+ parsed_json.each do |record|
80
+ unless record.is_a?(Hash)
81
+ yield nil, nil
82
+ next
83
+ end
84
+ time, parsed_record = parse_one_record(record)
85
+ yield time, parsed_record
86
+ end
87
+ else
88
+ yield nil, nil
69
89
  end
70
- yield time, record
90
+
71
91
  rescue @error_class, EncodingError # EncodingError is for oj 3.x or later
72
92
  yield nil, nil
73
93
  end
74
94
 
95
+ def parse_one_record(record)
96
+ time = parse_time(record)
97
+ convert_values(time, record)
98
+ end
99
+
75
100
  def parser_type
76
101
  :text
77
102
  end
@@ -31,9 +31,9 @@ module Fluent
31
31
  :binary
32
32
  end
33
33
 
34
- def parse(data)
34
+ def parse(data, &block)
35
35
  @unpacker.feed_each(data) do |obj|
36
- yield convert_values(parse_time(obj), obj)
36
+ parse_unpacked_data(obj, &block)
37
37
  end
38
38
  end
39
39
  alias parse_partial_data parse
@@ -41,8 +41,29 @@ module Fluent
41
41
  def parse_io(io, &block)
42
42
  u = Fluent::MessagePackFactory.engine_factory.unpacker(io)
43
43
  u.each do |obj|
44
- time, record = convert_values(parse_time(obj), obj)
44
+ parse_unpacked_data(obj, &block)
45
+ end
46
+ end
47
+
48
+ def parse_unpacked_data(data)
49
+ if data.is_a?(Hash)
50
+ time, record = convert_values(parse_time(data), data)
45
51
  yield time, record
52
+ return
53
+ end
54
+
55
+ unless data.is_a?(Array)
56
+ yield nil, nil
57
+ return
58
+ end
59
+
60
+ data.each do |record|
61
+ unless record.is_a?(Hash)
62
+ yield nil, nil
63
+ next
64
+ end
65
+ time, converted_record = convert_values(parse_time(record), record)
66
+ yield time, converted_record
46
67
  end
47
68
  end
48
69
  end
@@ -65,9 +65,9 @@ module Fluent
65
65
  metrics.configure(config)
66
66
  # For multi workers environment, cmetrics should be distinguish with static labels.
67
67
  if Fluent::Engine.system_config.workers > 1
68
- labels.merge!(worker_id: fluentd_worker_id.to_s)
68
+ labels[:worker_id] = fluentd_worker_id.to_s
69
69
  end
70
- labels.merge!(plugin: @plugin_type_or_id)
70
+ labels[:plugin] = @plugin_type_or_id
71
71
  metrics.create(namespace: namespace, subsystem: subsystem, name: name, help_text: help_text, labels: labels)
72
72
 
73
73
  @_metrics["#{@plugin_type_or_id}_#{namespace}_#{subsystem}_#{name}"] = metrics
@@ -60,13 +60,13 @@ module Fluent
60
60
  # search from additional plugin directories
61
61
  if @dir_search_prefix
62
62
  path = "#{@dir_search_prefix}#{type}"
63
- files = @paths.map { |lp|
63
+ files = @paths.filter_map { |lp|
64
64
  lpath = File.expand_path(File.join(lp, "#{path}.rb"))
65
65
  File.exist?(lpath) ? lpath : nil
66
- }.compact
66
+ }
67
67
  unless files.empty?
68
68
  # prefer newer version
69
- require files.sort.last
69
+ require files.max
70
70
  return
71
71
  end
72
72
  end
@@ -74,17 +74,17 @@ module Fluent
74
74
  path = "#{@search_prefix}#{type}"
75
75
 
76
76
  # prefer LOAD_PATH than gems
77
- files = $LOAD_PATH.map { |lp|
77
+ files = $LOAD_PATH.filter_map { |lp|
78
78
  if lp == FLUENT_LIB_PATH
79
79
  nil
80
80
  else
81
81
  lpath = File.expand_path(File.join(lp, "#{path}.rb"))
82
82
  File.exist?(lpath) ? lpath : nil
83
83
  end
84
- }.compact
84
+ }
85
85
  unless files.empty?
86
86
  # prefer newer version
87
- require files.sort.last
87
+ require files.max
88
88
  return
89
89
  end
90
90
 
@@ -139,7 +139,7 @@ module Fluent
139
139
  assert_equal(@expected_buffer, buffer)
140
140
  end
141
141
 
142
- lines.keys.each do |meta|
142
+ lines.each_key do |meta|
143
143
  chunk = @instance.buffer.generate_chunk(meta).staged!
144
144
  chunk.append(lines[meta])
145
145
  begin
@@ -23,7 +23,7 @@ module Fluent
23
23
  end
24
24
 
25
25
  def self.hex(unique_id)
26
- unique_id.unpack('H*').first
26
+ unique_id.unpack1('H*')
27
27
  end
28
28
 
29
29
  module Mixin
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.16.6'
19
+ VERSION = '1.17.0'
20
20
 
21
21
  end
@@ -128,14 +128,11 @@ class TestFluentdCommand < ::Test::Unit::TestCase
128
128
 
129
129
  # ATTENTION: This stops taking logs when all `pattern_list` match or timeout,
130
130
  # so `patterns_not_match` can test only logs up to that point.
131
- # You can pass a block to assert something after log matching.
132
131
  def assert_log_matches(cmdline, *pattern_list, patterns_not_match: [], timeout: 20, env: {})
133
132
  matched = false
134
133
  matched_wrongly = false
135
- error_msg_match = ""
134
+ assert_error_msg = ""
136
135
  stdio_buf = ""
137
- succeeded_block = true
138
- error_msg_block = ""
139
136
  begin
140
137
  execute_command(cmdline, @tmp_dir, env) do |pid, stdout|
141
138
  begin
@@ -166,13 +163,6 @@ class TestFluentdCommand < ::Test::Unit::TestCase
166
163
  end
167
164
  end
168
165
  end
169
-
170
- begin
171
- yield if block_given?
172
- rescue => e
173
- succeeded_block = false
174
- error_msg_block = "failed block execution after matching: #{e}"
175
- end
176
166
  ensure
177
167
  if SUPERVISOR_PID_PATTERN =~ stdio_buf
178
168
  @supervisor_pid = $1.to_i
@@ -183,19 +173,19 @@ class TestFluentdCommand < ::Test::Unit::TestCase
183
173
  end
184
174
  end
185
175
  rescue Timeout::Error
186
- error_msg_match = "execution timeout"
176
+ assert_error_msg = "execution timeout"
187
177
  # https://github.com/fluent/fluentd/issues/4095
188
178
  # On Windows, timeout without `@supervisor_pid` means that the test is invalid,
189
179
  # since the supervisor process will survive without being killed correctly.
190
180
  flunk("Invalid test: The pid of supervisor could not be taken, which is necessary on Windows.") if Fluent.windows? && @supervisor_pid.nil?
191
181
  rescue => e
192
- error_msg_match = "unexpected error in launching fluentd: #{e.inspect}"
182
+ assert_error_msg = "unexpected error in launching fluentd: #{e.inspect}"
193
183
  else
194
- error_msg_match = "log doesn't match" unless matched
184
+ assert_error_msg = "log doesn't match" unless matched
195
185
  end
196
186
 
197
187
  if patterns_not_match.empty?
198
- error_msg_match = build_message(error_msg_match,
188
+ assert_error_msg = build_message(assert_error_msg,
199
189
  "<?>\nwas expected to include:\n<?>",
200
190
  stdio_buf, pattern_list)
201
191
  else
@@ -207,17 +197,16 @@ class TestFluentdCommand < ::Test::Unit::TestCase
207
197
  lines.any?{|line| line.include?(ptn) }
208
198
  end
209
199
  if matched_wrongly
210
- error_msg_match << "\n" unless error_msg_match.empty?
211
- error_msg_match << "pattern exists in logs wrongly: #{ptn}"
200
+ assert_error_msg << "\n" unless assert_error_msg.empty?
201
+ assert_error_msg << "pattern exists in logs wrongly: #{ptn}"
212
202
  end
213
203
  end
214
- error_msg_match = build_message(error_msg_match,
204
+ assert_error_msg = build_message(assert_error_msg,
215
205
  "<?>\nwas expected to include:\n<?>\nand not include:\n<?>",
216
206
  stdio_buf, pattern_list, patterns_not_match)
217
207
  end
218
208
 
219
- assert matched && !matched_wrongly, error_msg_match
220
- assert succeeded_block, error_msg_block if block_given?
209
+ assert matched && !matched_wrongly, assert_error_msg
221
210
  end
222
211
 
223
212
  def assert_fluentd_fails_to_start(cmdline, *pattern_list, timeout: 20)
@@ -1299,40 +1288,4 @@ CONF
1299
1288
  "[debug]")
1300
1289
  end
1301
1290
  end
1302
-
1303
- sub_test_case "plugin option" do
1304
- test "should be the default value when not specifying" do
1305
- conf_path = create_conf_file('test.conf', <<~CONF)
1306
- <source>
1307
- @type monitor_agent
1308
- </source>
1309
- CONF
1310
- assert File.exist?(conf_path)
1311
- cmdline = create_cmdline(conf_path)
1312
-
1313
- assert_log_matches(cmdline, "fluentd worker is now running") do
1314
- response = Net::HTTP.get(URI.parse("http://localhost:24220/api/config.json"))
1315
- actual_conf = JSON.parse(response)
1316
- assert_equal Fluent::Supervisor.default_options[:plugin_dirs], actual_conf["plugin_dirs"]
1317
- end
1318
- end
1319
-
1320
- data(short: "-p")
1321
- data(long: "--plugin")
1322
- test "can be added by specifying the option" do |option_name|
1323
- conf_path = create_conf_file('test.conf', <<~CONF)
1324
- <source>
1325
- @type monitor_agent
1326
- </source>
1327
- CONF
1328
- assert File.exist?(conf_path)
1329
- cmdline = create_cmdline(conf_path, option_name, @tmp_dir, option_name, @tmp_dir)
1330
-
1331
- assert_log_matches(cmdline, "fluentd worker is now running") do
1332
- response = Net::HTTP.get(URI.parse("http://localhost:24220/api/config.json"))
1333
- actual_conf = JSON.parse(response)
1334
- assert_equal Fluent::Supervisor.default_options[:plugin_dirs] + [@tmp_dir, @tmp_dir], actual_conf["plugin_dirs"]
1335
- end
1336
- end
1337
- end
1338
1291
  end
@@ -72,11 +72,18 @@ class ConsoleAdapterTest < Test::Unit::TestCase
72
72
  fatal: :fatal)
73
73
  def test_options(level)
74
74
  @console_logger.send(level, "subject", kwarg1: "opt1", kwarg2: "opt2")
75
+ lines = @logdev.logs[0].split("\n")
76
+ args = JSON.load(lines[1..].collect { |str| str.sub(/\s+\|/, "") }.join("\n"));
75
77
  assert_equal([
76
- "#{@timestamp_str} [#{level}]: 0.0s: subject\n" +
77
- " | {\"kwarg1\":\"opt1\",\"kwarg2\":\"opt2\"}\n"
78
+ 1,
79
+ "#{@timestamp_str} [#{level}]: 0.0s: subject",
80
+ { "kwarg1" => "opt1", "kwarg2" => "opt2" }
78
81
  ],
79
- @logdev.logs)
82
+ [
83
+ @logdev.logs.size,
84
+ lines[0],
85
+ args
86
+ ])
80
87
  end
81
88
 
82
89
  data(debug: :debug,
File without changes
File without changes
File without changes
File without changes
@@ -5,19 +5,20 @@ require 'fluent/plugin/metrics_local'
5
5
  require 'tempfile'
6
6
 
7
7
  class IntailIOHandlerTest < Test::Unit::TestCase
8
- def setup
9
- Tempfile.create('intail_io_handler') do |file|
10
- file.binmode
11
- @file = file
12
- opened_file_metrics = Fluent::Plugin::LocalMetrics.new
13
- opened_file_metrics.configure(config_element('metrics', '', {}))
14
- closed_file_metrics = Fluent::Plugin::LocalMetrics.new
15
- closed_file_metrics.configure(config_element('metrics', '', {}))
16
- rotated_file_metrics = Fluent::Plugin::LocalMetrics.new
17
- rotated_file_metrics.configure(config_element('metrics', '', {}))
18
- @metrics = Fluent::Plugin::TailInput::MetricsInfo.new(opened_file_metrics, closed_file_metrics, rotated_file_metrics)
19
- yield
20
- end
8
+ setup do
9
+ @file = Tempfile.new('intail_io_handler').binmode
10
+ opened_file_metrics = Fluent::Plugin::LocalMetrics.new
11
+ opened_file_metrics.configure(config_element('metrics', '', {}))
12
+ closed_file_metrics = Fluent::Plugin::LocalMetrics.new
13
+ closed_file_metrics.configure(config_element('metrics', '', {}))
14
+ rotated_file_metrics = Fluent::Plugin::LocalMetrics.new
15
+ rotated_file_metrics.configure(config_element('metrics', '', {}))
16
+ @metrics = Fluent::Plugin::TailInput::MetricsInfo.new(opened_file_metrics, closed_file_metrics, rotated_file_metrics)
17
+ end
18
+
19
+ teardown do
20
+ @file.close rescue nil
21
+ @file.unlink rescue nil
21
22
  end
22
23
 
23
24
  def create_target_info