fluentd 1.13.3-x64-mingw32 → 1.14.3-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.

Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.drone.yml +6 -6
  3. data/.github/ISSUE_TEMPLATE/bug_report.yaml +1 -0
  4. data/.github/workflows/windows-test.yaml +3 -3
  5. data/CHANGELOG.md +126 -0
  6. data/README.md +2 -0
  7. data/SECURITY.md +18 -0
  8. data/fluentd.gemspec +3 -3
  9. data/lib/fluent/command/cat.rb +13 -3
  10. data/lib/fluent/command/fluentd.rb +8 -0
  11. data/lib/fluent/compat/output.rb +9 -6
  12. data/lib/fluent/config/parser.rb +1 -1
  13. data/lib/fluent/config/v1_parser.rb +1 -1
  14. data/lib/fluent/event_router.rb +28 -1
  15. data/lib/fluent/plugin/bare_output.rb +49 -8
  16. data/lib/fluent/plugin/buf_file.rb +2 -2
  17. data/lib/fluent/plugin/buffer.rb +123 -27
  18. data/lib/fluent/plugin/filter.rb +35 -1
  19. data/lib/fluent/plugin/in_http.rb +21 -2
  20. data/lib/fluent/plugin/in_monitor_agent.rb +4 -2
  21. data/lib/fluent/plugin/in_syslog.rb +13 -1
  22. data/lib/fluent/plugin/in_tail/position_file.rb +1 -1
  23. data/lib/fluent/plugin/in_tail.rb +47 -8
  24. data/lib/fluent/plugin/input.rb +39 -1
  25. data/lib/fluent/plugin/metrics.rb +119 -0
  26. data/lib/fluent/plugin/metrics_local.rb +96 -0
  27. data/lib/fluent/plugin/multi_output.rb +43 -6
  28. data/lib/fluent/plugin/out_copy.rb +1 -1
  29. data/lib/fluent/plugin/out_forward.rb +15 -7
  30. data/lib/fluent/plugin/output.rb +80 -38
  31. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  32. data/lib/fluent/plugin/storage_local.rb +3 -5
  33. data/lib/fluent/plugin.rb +10 -1
  34. data/lib/fluent/plugin_helper/event_emitter.rb +8 -1
  35. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  36. data/lib/fluent/plugin_helper/server.rb +4 -2
  37. data/lib/fluent/plugin_helper.rb +1 -0
  38. data/lib/fluent/plugin_id.rb +2 -1
  39. data/lib/fluent/root_agent.rb +6 -0
  40. data/lib/fluent/supervisor.rb +4 -2
  41. data/lib/fluent/system_config.rb +9 -1
  42. data/lib/fluent/time.rb +21 -20
  43. data/lib/fluent/version.rb +1 -1
  44. data/test/command/test_cat.rb +31 -2
  45. data/test/config/test_system_config.rb +6 -0
  46. data/test/plugin/in_tail/test_io_handler.rb +12 -4
  47. data/test/plugin/in_tail/test_position_file.rb +26 -4
  48. data/test/plugin/test_bare_output.rb +13 -0
  49. data/test/plugin/test_buffer.rb +80 -3
  50. data/test/plugin/test_filter.rb +11 -0
  51. data/test/plugin/test_in_http.rb +40 -0
  52. data/test/plugin/test_in_monitor_agent.rb +214 -8
  53. data/test/plugin/test_in_syslog.rb +35 -0
  54. data/test/plugin/test_in_tail.rb +83 -35
  55. data/test/plugin/test_input.rb +11 -0
  56. data/test/plugin/test_metrics.rb +294 -0
  57. data/test/plugin/test_metrics_local.rb +96 -0
  58. data/test/plugin/test_multi_output.rb +25 -1
  59. data/test/plugin/test_out_exec_filter.rb +4 -0
  60. data/test/plugin/test_output.rb +16 -0
  61. data/test/plugin_helper/test_child_process.rb +9 -9
  62. data/test/plugin_helper/test_event_emitter.rb +29 -0
  63. data/test/plugin_helper/test_metrics.rb +137 -0
  64. data/test/test_plugin_classes.rb +102 -0
  65. data/test/test_root_agent.rb +30 -1
  66. data/test/test_time_parser.rb +22 -0
  67. metadata +18 -8
data/lib/fluent/time.rb CHANGED
@@ -226,19 +226,16 @@ module Fluent
226
226
 
227
227
  format_with_timezone = format && (format.include?("%z") || format.include?("%Z"))
228
228
 
229
- # unixtime_in_expected_tz = unixtime_in_localtime + offset_diff
230
- offset_diff = case
231
- when format_with_timezone then nil
232
- when timezone then
233
- offset = Fluent::Timezone.utc_offset(timezone)
234
- if offset.respond_to?(:call)
235
- ->(t) { Time.now.localtime.utc_offset - offset.call(t) }
236
- else
237
- Time.now.localtime.utc_offset - offset
238
- end
239
- when localtime then 0
240
- else Time.now.localtime.utc_offset # utc
241
- end
229
+ utc_offset = case
230
+ when format_with_timezone then
231
+ nil
232
+ when timezone then
233
+ Fluent::Timezone.utc_offset(timezone)
234
+ when localtime then
235
+ nil
236
+ else
237
+ 0 # utc
238
+ end
242
239
 
243
240
  strptime = format && (Strptime.new(format) rescue nil)
244
241
 
@@ -247,16 +244,20 @@ module Fluent
247
244
  when format_with_timezone then ->(v){ Fluent::EventTime.from_time(Time.strptime(v, format)) }
248
245
  when format == '%iso8601' then ->(v){ Fluent::EventTime.from_time(Time.iso8601(v)) }
249
246
  when strptime then
250
- if offset_diff.respond_to?(:call)
251
- ->(v) { t = strptime.exec(v); Fluent::EventTime.new(t.to_i + offset_diff.call(t), t.nsec) }
247
+ if utc_offset.nil?
248
+ ->(v){ t = strptime.exec(v); Fluent::EventTime.new(t.to_i, t.nsec) }
249
+ elsif utc_offset.respond_to?(:call)
250
+ ->(v) { t = strptime.exec(v); Fluent::EventTime.new(t.to_i + t.utc_offset - utc_offset.call(t), t.nsec) }
252
251
  else
253
- ->(v) { t = strptime.exec(v); Fluent::EventTime.new(t.to_i + offset_diff, t.nsec) }
252
+ ->(v) { t = strptime.exec(v); Fluent::EventTime.new(t.to_i + t.utc_offset - utc_offset, t.nsec) }
254
253
  end
255
- when format then
256
- if offset_diff.respond_to?(:call)
257
- ->(v){ t = Time.strptime(v, format); Fluent::EventTime.new(t.to_i + offset_diff.call(t), t.nsec) }
254
+ when format then
255
+ if utc_offset.nil?
256
+ ->(v){ t = Time.strptime(v, format); Fluent::EventTime.new(t.to_i, t.nsec) }
257
+ elsif utc_offset.respond_to?(:call)
258
+ ->(v){ t = Time.strptime(v, format); Fluent::EventTime.new(t.to_i + t.utc_offset - utc_offset.call(t), t.nsec) }
258
259
  else
259
- ->(v){ t = Time.strptime(v, format); Fluent::EventTime.new(t.to_i + offset_diff, t.nsec) }
260
+ ->(v){ t = Time.strptime(v, format); Fluent::EventTime.new(t.to_i + t.utc_offset - utc_offset, t.nsec) }
260
261
  end
261
262
  else ->(v){ Fluent::EventTime.parse(v) }
262
263
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.13.3'
19
+ VERSION = '1.14.3'
20
20
 
21
21
  end
@@ -69,7 +69,7 @@ class TestFluentCat < ::Test::Unit::TestCase
69
69
  def test_cat_json
70
70
  d = create_driver
71
71
  d.run(expect_records: 1) do
72
- Open3.pipeline_w("ruby #{FLUENT_CAT_COMMAND} --port #{@port} json") do |stdin|
72
+ Open3.pipeline_w("#{ServerEngine.ruby_bin_path} #{FLUENT_CAT_COMMAND} --port #{@port} json") do |stdin|
73
73
  stdin.puts('{"key":"value"}')
74
74
  stdin.close
75
75
  end
@@ -86,7 +86,7 @@ class TestFluentCat < ::Test::Unit::TestCase
86
86
  path = d.instance.write(@chunk)
87
87
  d = create_driver
88
88
  d.run(expect_records: 1) do
89
- Open3.pipeline_w("ruby #{FLUENT_CAT_COMMAND} --port #{@port} --format msgpack secondary") do |stdin|
89
+ Open3.pipeline_w("#{ServerEngine.ruby_bin_path} #{FLUENT_CAT_COMMAND} --port #{@port} --format msgpack secondary") do |stdin|
90
90
  stdin.write(File.read(path))
91
91
  stdin.close
92
92
  end
@@ -96,4 +96,33 @@ class TestFluentCat < ::Test::Unit::TestCase
96
96
  [d.events.size, event.first, event.last])
97
97
  end
98
98
  end
99
+
100
+ sub_test_case "send specific event time" do
101
+ def test_without_event_time
102
+ event_time = Fluent::EventTime.now
103
+ d = create_driver
104
+ d.run(expect_records: 1) do
105
+ Open3.pipeline_w("#{ServerEngine.ruby_bin_path} #{FLUENT_CAT_COMMAND} --port #{@port} tag") do |stdin|
106
+ stdin.puts('{"key":"value"}')
107
+ stdin.close
108
+ end
109
+ end
110
+ event = d.events.first
111
+ assert_in_delta(event_time.to_f, event[1].to_f, 3.0) # expect command to be finished in 3 seconds
112
+ assert_equal([1, "tag", true, @record],
113
+ [d.events.size, event.first, event_time.to_f < event[1].to_f, event.last])
114
+ end
115
+
116
+ def test_with_event_time
117
+ event_time = "2021-01-02 13:14:15.0+00:00"
118
+ d = create_driver
119
+ d.run(expect_records: 1) do
120
+ Open3.pipeline_w("#{ServerEngine.ruby_bin_path} #{FLUENT_CAT_COMMAND} --port #{@port} --event-time '#{event_time}' tag") do |stdin|
121
+ stdin.puts('{"key":"value"}')
122
+ stdin.close
123
+ end
124
+ end
125
+ assert_equal([["tag", Fluent::EventTime.parse(event_time), @record]], d.events)
126
+ end
127
+ end
99
128
  end
@@ -28,6 +28,8 @@ module Fluent::Config
28
28
  log_event_label: nil,
29
29
  log_event_verbose: nil,
30
30
  without_source: nil,
31
+ enable_input_metrics: nil,
32
+ enable_size_metrics: nil,
31
33
  emit_error_log_interval: nil,
32
34
  file_permission: nil,
33
35
  dir_permission: nil,
@@ -77,6 +79,8 @@ module Fluent::Config
77
79
  assert_nil(sc.emit_error_log_interval)
78
80
  assert_nil(sc.suppress_config_dump)
79
81
  assert_nil(sc.without_source)
82
+ assert_nil(sc.enable_input_metrics)
83
+ assert_nil(sc.enable_size_metrics)
80
84
  assert_nil(sc.enable_msgpack_time_support)
81
85
  assert_equal(:text, sc.log.format)
82
86
  assert_equal('%Y-%m-%d %H:%M:%S %z', sc.log.time_format)
@@ -93,6 +97,8 @@ module Fluent::Config
93
97
  'without_source' => ['without_source', true],
94
98
  'strict_config_value' => ['strict_config_value', true],
95
99
  'enable_msgpack_time_support' => ['enable_msgpack_time_support', true],
100
+ 'enable_input_metrics' => ['enable_input_metrics', true],
101
+ 'enable_size_metrics' => ['enable_size_metrics', true],
96
102
  )
97
103
  test "accepts parameters" do |(k, v)|
98
104
  conf = parse_text(<<-EOS)
@@ -1,11 +1,19 @@
1
1
  require_relative '../../helper'
2
2
 
3
3
  require 'fluent/plugin/in_tail'
4
+ require 'fluent/plugin/metrics_local'
4
5
  require 'tempfile'
5
6
 
6
7
  class IntailIOHandlerTest < Test::Unit::TestCase
7
8
  setup do
8
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)
9
17
  end
10
18
 
11
19
  teardown do
@@ -30,7 +38,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
30
38
  end
31
39
 
32
40
  returned_lines = ''
33
- r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false) do |lines, _watcher|
41
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false, metrics: @metrics) do |lines, _watcher|
34
42
  returned_lines << lines.join
35
43
  true
36
44
  end
@@ -62,7 +70,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
62
70
  end
63
71
 
64
72
  returned_lines = ''
65
- r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: true) do |lines, _watcher|
73
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 100, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: true, metrics: @metrics) do |lines, _watcher|
66
74
  returned_lines << lines.join
67
75
  true
68
76
  end
@@ -93,7 +101,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
93
101
  end
94
102
 
95
103
  returned_lines = []
96
- r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false) do |lines, _watcher|
104
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false, metrics: @metrics) do |lines, _watcher|
97
105
  returned_lines << lines.dup
98
106
  true
99
107
  end
@@ -119,7 +127,7 @@ class IntailIOHandlerTest < Test::Unit::TestCase
119
127
  end
120
128
 
121
129
  returned_lines = []
122
- r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false) do |lines, _watcher|
130
+ r = Fluent::Plugin::TailInput::TailWatcher::IOHandler.new(watcher, path: @file.path, read_lines_limit: 5, read_bytes_limit_per_second: -1, log: $log, open_on_every_update: false, metrics: @metrics) do |lines, _watcher|
123
131
  returned_lines << lines.dup
124
132
  true
125
133
  end
@@ -22,6 +22,10 @@ class IntailPositionFileTest < Test::Unit::TestCase
22
22
  invalidpath100000000000000000000000000000000
23
23
  unwatched\t#{UNWATCHED_STR}\t0000000000000000
24
24
  EOF
25
+ TEST_CONTENT_PATHS = {
26
+ "valid_path" => Fluent::Plugin::TailInput::TargetInfo.new("valid_path", 1),
27
+ "inode23bit" => Fluent::Plugin::TailInput::TargetInfo.new("inode23bit", 0),
28
+ }
25
29
 
26
30
  def write_data(f, content)
27
31
  f.write(content)
@@ -36,7 +40,11 @@ class IntailPositionFileTest < Test::Unit::TestCase
36
40
 
37
41
  test '.load' do
38
42
  write_data(@file, TEST_CONTENT)
39
- Fluent::Plugin::TailInput::PositionFile.load(@file, false, {}, **{logger: $log})
43
+ paths = {
44
+ "valid_path" => Fluent::Plugin::TailInput::TargetInfo.new("valid_path", 1),
45
+ "inode23bit" => Fluent::Plugin::TailInput::TargetInfo.new("inode23bit", 2),
46
+ }
47
+ Fluent::Plugin::TailInput::PositionFile.load(@file, false, TEST_CONTENT_PATHS, **{logger: $log})
40
48
 
41
49
  @file.seek(0)
42
50
  lines = @file.readlines
@@ -118,7 +126,7 @@ class IntailPositionFileTest < Test::Unit::TestCase
118
126
 
119
127
  test 'should ignore initial existing files on follow_inode' do
120
128
  write_data(@file, TEST_CONTENT)
121
- pos_file = Fluent::Plugin::TailInput::PositionFile.load(@file, true, {}, **{logger: $log})
129
+ pos_file = Fluent::Plugin::TailInput::PositionFile.load(@file, true, TEST_CONTENT_PATHS, **{logger: $log})
122
130
  @file.seek(0)
123
131
  assert_equal([], @file.readlines)
124
132
 
@@ -138,7 +146,12 @@ class IntailPositionFileTest < Test::Unit::TestCase
138
146
  sub_test_case '#load' do
139
147
  test 'compact invalid and convert 32 bit inode value' do
140
148
  write_data(@file, TEST_CONTENT)
141
- Fluent::Plugin::TailInput::PositionFile.load(@file, false, {}, **{logger: $log})
149
+ invalid_path = "invalidpath100000000000000000000000000000000"
150
+ paths = TEST_CONTENT_PATHS.merge({
151
+ invalid_path => Fluent::Plugin::TailInput::TargetInfo.new(invalid_path, 0),
152
+ "unwatched" => Fluent::Plugin::TailInput::TargetInfo.new("unwatched", 0),
153
+ })
154
+ Fluent::Plugin::TailInput::PositionFile.load(@file, false, TEST_CONTENT_PATHS, **{logger: $log})
142
155
 
143
156
  @file.seek(0)
144
157
  lines = @file.readlines
@@ -147,6 +160,15 @@ class IntailPositionFileTest < Test::Unit::TestCase
147
160
  assert_equal "inode23bit\t0000000000000000\t0000000000000000\n", lines[1]
148
161
  end
149
162
 
163
+ test 'compact deleted paths' do
164
+ write_data(@file, TEST_CONTENT)
165
+ Fluent::Plugin::TailInput::PositionFile.load(@file, false, {}, **{logger: $log})
166
+
167
+ @file.seek(0)
168
+ lines = @file.readlines
169
+ assert_equal [], lines
170
+ end
171
+
150
172
  test 'compact data if duplicated line' do
151
173
  write_data(@file, <<~EOF)
152
174
  valid_path\t0000000000000002\t0000000000000001
@@ -163,7 +185,7 @@ class IntailPositionFileTest < Test::Unit::TestCase
163
185
  sub_test_case '#[]' do
164
186
  test 'return entry' do
165
187
  write_data(@file, TEST_CONTENT)
166
- pf = Fluent::Plugin::TailInput::PositionFile.load(@file, false, {}, **{logger: $log})
188
+ pf = Fluent::Plugin::TailInput::PositionFile.load(@file, false, TEST_CONTENT_PATHS, **{logger: $log})
167
189
 
168
190
  valid_target_info = Fluent::Plugin::TailInput::TargetInfo.new('valid_path', File.stat(@file).ino)
169
191
  f = pf[valid_target_info]
@@ -95,6 +95,19 @@ class BareOutputTest < Test::Unit::TestCase
95
95
  end
96
96
  end
97
97
 
98
+ test 'can use metrics plugins and fallback methods' do
99
+ @p.configure(config_element('ROOT', '', {'@log_level' => 'debug'}))
100
+
101
+ %w[num_errors_metrics emit_count_metrics emit_size_metrics emit_records_metrics].each do |metric_name|
102
+ assert_true @p.instance_variable_get(:"@#{metric_name}").is_a?(Fluent::Plugin::Metrics)
103
+ end
104
+
105
+ assert_equal 0, @p.num_errors
106
+ assert_equal 0, @p.emit_count
107
+ assert_equal 0, @p.emit_size
108
+ assert_equal 0, @p.emit_records
109
+ end
110
+
98
111
  test 'can get input event stream to write' do
99
112
  @p.configure(config_element('ROOT'))
100
113
  @p.start
@@ -18,7 +18,7 @@ module FluentPluginBufferTest
18
18
  end
19
19
  class DummyMemoryChunkError < StandardError; end
20
20
  class DummyMemoryChunk < Fluent::Plugin::Buffer::MemoryChunk
21
- attr_reader :append_count, :rollbacked, :closed, :purged
21
+ attr_reader :append_count, :rollbacked, :closed, :purged, :chunk
22
22
  attr_accessor :failing
23
23
  def initialize(metadata, compress: :text)
24
24
  super
@@ -238,8 +238,14 @@ class BufferTest < Test::Unit::TestCase
238
238
  assert_nil @p.queue
239
239
  assert_nil @p.dequeued
240
240
  assert_nil @p.queued_num
241
- assert_equal 0, @p.stage_size
242
- assert_equal 0, @p.queue_size
241
+ assert_nil @p.stage_length_metrics
242
+ assert_nil @p.stage_size_metrics
243
+ assert_nil @p.queue_length_metrics
244
+ assert_nil @p.queue_size_metrics
245
+ assert_nil @p.available_buffer_space_ratios_metrics
246
+ assert_nil @p.total_queued_size_metrics
247
+ assert_nil @p.newest_timekey_metrics
248
+ assert_nil @p.oldest_timekey_metrics
243
249
  assert_equal [], @p.timekeys
244
250
  end
245
251
 
@@ -938,6 +944,52 @@ class BufferTest < Test::Unit::TestCase
938
944
  @p.write({@dm0 => es}, format: @format)
939
945
  end
940
946
  end
947
+
948
+ data(
949
+ first_chunk: Fluent::ArrayEventStream.new([[event_time('2016-04-11 16:00:02 +0000'), {"message" => "x" * 1_280_000}],
950
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "a"}],
951
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "b"}]]),
952
+ intermediate_chunk: Fluent::ArrayEventStream.new([[event_time('2016-04-11 16:00:02 +0000'), {"message" => "a"}],
953
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "x" * 1_280_000}],
954
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "b"}]]),
955
+ last_chunk: Fluent::ArrayEventStream.new([[event_time('2016-04-11 16:00:02 +0000'), {"message" => "a"}],
956
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "b"}],
957
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "x" * 1_280_000}]]),
958
+ multiple_chunks: Fluent::ArrayEventStream.new([[event_time('2016-04-11 16:00:02 +0000'), {"message" => "a"}],
959
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "x" * 1_280_000}],
960
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "b"}],
961
+ [event_time('2016-04-11 16:00:02 +0000'), {"message" => "x" * 1_280_000}]])
962
+ )
963
+ test '#write exceeds chunk_limit_size, raise BufferChunkOverflowError, but not lost whole messages' do |(es)|
964
+ assert_equal [@dm0], @p.stage.keys
965
+ assert_equal [], @p.queue.map(&:metadata)
966
+
967
+ assert_equal 1_280_000, @p.chunk_limit_size
968
+
969
+ nth = []
970
+ es.entries.each_with_index do |entry, index|
971
+ if entry.last["message"].size == @p.chunk_limit_size
972
+ nth << index
973
+ end
974
+ end
975
+ messages = []
976
+ nth.each do |n|
977
+ messages << "a 1280025 bytes record (nth: #{n}) is larger than buffer chunk limit size (1280000)"
978
+ end
979
+
980
+ assert_raise Fluent::Plugin::Buffer::BufferChunkOverflowError.new(messages.join(", ")) do
981
+ @p.write({@dm0 => es}, format: @format)
982
+ end
983
+ # message a and b are concatenated and staged
984
+ staged_messages = Fluent::MessagePackFactory.msgpack_unpacker.feed_each(@p.stage[@dm0].chunk).collect do |record|
985
+ record.last
986
+ end
987
+ assert_equal([2, [{"message" => "a"}, {"message" => "b"}]],
988
+ [@p.stage[@dm0].size, staged_messages])
989
+ # only es0 message is queued
990
+ assert_equal [@dm0], @p.queue.map(&:metadata)
991
+ assert_equal [5000], @p.queue.map(&:size)
992
+ end
941
993
  end
942
994
 
943
995
  sub_test_case 'custom format with configuration for test with lower chunk limit size' do
@@ -1195,6 +1247,7 @@ class BufferTest < Test::Unit::TestCase
1195
1247
  sub_test_case 'when compress is gzip' do
1196
1248
  setup do
1197
1249
  @p = create_buffer({'compress' => 'gzip'})
1250
+ @dm0 = create_metadata(Time.parse('2016-04-11 16:00:00 +0000').to_i, nil, nil)
1198
1251
  end
1199
1252
 
1200
1253
  test '#compress returns :gzip' do
@@ -1205,6 +1258,30 @@ class BufferTest < Test::Unit::TestCase
1205
1258
  chunk = @p.generate_chunk(create_metadata)
1206
1259
  assert chunk.singleton_class.ancestors.include?(Fluent::Plugin::Buffer::Chunk::Decompressable)
1207
1260
  end
1261
+
1262
+ test '#write compressed data which exceeds chunk_limit_size, it raises BufferChunkOverflowError' do
1263
+ @p = create_buffer({'compress' => 'gzip', 'chunk_limit_size' => 70})
1264
+ timestamp = event_time('2016-04-11 16:00:02 +0000')
1265
+ es = Fluent::ArrayEventStream.new([[timestamp, {"message" => "012345"}], # overflow
1266
+ [timestamp, {"message" => "aaa"}],
1267
+ [timestamp, {"message" => "bbb"}]])
1268
+ assert_equal [], @p.queue.map(&:metadata)
1269
+ assert_equal 70, @p.chunk_limit_size
1270
+
1271
+ # calculate the actual boundary value. it varies on machine
1272
+ c = @p.generate_chunk(create_metadata)
1273
+ c.append(Fluent::ArrayEventStream.new([[timestamp, {"message" => "012345"}]]), compress: :gzip)
1274
+ overflow_bytes = c.bytesize
1275
+
1276
+ messages = "concatenated/appended a #{overflow_bytes} bytes record (nth: 0) is larger than buffer chunk limit size (70)"
1277
+ assert_raise Fluent::Plugin::Buffer::BufferChunkOverflowError.new(messages) do
1278
+ # test format == nil && compress == :gzip
1279
+ @p.write({@dm0 => es})
1280
+ end
1281
+ # message a and b occupies each chunks in full, so both of messages are queued (no staged chunk)
1282
+ assert_equal([2, [@dm0, @dm0], [1, 1], nil],
1283
+ [@p.queue.size, @p.queue.map(&:metadata), @p.queue.map(&:size), @p.stage[@dm0]])
1284
+ end
1208
1285
  end
1209
1286
 
1210
1287
  sub_test_case '#statistics' do
@@ -165,6 +165,17 @@ class FilterPluginTest < Test::Unit::TestCase
165
165
  end
166
166
  end
167
167
 
168
+ test 'can use metrics plugins and fallback methods' do
169
+ @p.configure(config_element('ROOT', '', {'@log_level' => 'debug'}))
170
+
171
+ %w[emit_size_metrics emit_records_metrics].each do |metric_name|
172
+ assert_true @p.instance_variable_get(:"@#{metric_name}").is_a?(Fluent::Plugin::Metrics)
173
+ end
174
+
175
+ assert_equal 0, @p.emit_size
176
+ assert_equal 0, @p.emit_records
177
+ end
178
+
168
179
  test 'are available with multi worker configuration in default' do
169
180
  assert @p.multi_workers_ready?
170
181
  end
@@ -856,6 +856,46 @@ class HttpInputTest < Test::Unit::TestCase
856
856
  end
857
857
  end
858
858
 
859
+ def test_cors_allow_credentials
860
+ d = create_driver(config + %[
861
+ cors_allow_origins ["http://foo.com"]
862
+ cors_allow_credentials
863
+ ])
864
+ assert_equal true, d.instance.cors_allow_credentials
865
+
866
+ time = event_time("2011-01-02 13:14:15 UTC")
867
+ event = ["tag1", time, {"a"=>1}]
868
+ res_code = nil
869
+ res_header = nil
870
+
871
+ d.run do
872
+ res = post("/#{event[0]}", {"json"=>event[2].to_json, "time"=>time.to_i.to_s}, {"Origin"=>"http://foo.com"})
873
+ res_code = res.code
874
+ res_header = res["Access-Control-Allow-Credentials"]
875
+ end
876
+ assert_equal(
877
+ {
878
+ response_code: "200",
879
+ allow_credentials_header: "true",
880
+ events: [event]
881
+ },
882
+ {
883
+ response_code: res_code,
884
+ allow_credentials_header: res_header,
885
+ events: d.events
886
+ }
887
+ )
888
+ end
889
+
890
+ def test_cors_allow_credentials_for_wildcard_origins
891
+ assert_raise(Fluent::ConfigError) do
892
+ create_driver(config + %[
893
+ cors_allow_origins ["*"]
894
+ cors_allow_credentials
895
+ ])
896
+ end
897
+ end
898
+
859
899
  def test_content_encoding_gzip
860
900
  d = create_driver
861
901