fluentd 1.12.1 → 1.12.2

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.deepsource.toml +13 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +2 -2
  4. data/.github/workflows/linux-test.yaml +36 -0
  5. data/.github/workflows/macos-test.yaml +30 -0
  6. data/.github/workflows/{build.yaml → windows-test.yaml} +7 -6
  7. data/CHANGELOG.md +47 -0
  8. data/MAINTAINERS.md +5 -2
  9. data/fluentd.gemspec +1 -0
  10. data/lib/fluent/command/bundler_injection.rb +1 -1
  11. data/lib/fluent/command/cat.rb +0 -1
  12. data/lib/fluent/command/plugin_config_formatter.rb +2 -1
  13. data/lib/fluent/compat/parser.rb +2 -2
  14. data/lib/fluent/config/section.rb +1 -1
  15. data/lib/fluent/config/types.rb +2 -2
  16. data/lib/fluent/event.rb +3 -13
  17. data/lib/fluent/load.rb +0 -1
  18. data/lib/fluent/plugin/formatter_ltsv.rb +2 -2
  19. data/lib/fluent/plugin/in_http.rb +1 -1
  20. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  21. data/lib/fluent/plugin/in_tail.rb +34 -15
  22. data/lib/fluent/plugin/out_copy.rb +18 -5
  23. data/lib/fluent/plugin/out_exec_filter.rb +3 -3
  24. data/lib/fluent/plugin/out_forward.rb +61 -28
  25. data/lib/fluent/plugin/storage_local.rb +3 -3
  26. data/lib/fluent/supervisor.rb +1 -1
  27. data/lib/fluent/time.rb +57 -1
  28. data/lib/fluent/version.rb +1 -1
  29. data/test/command/test_fluentd.rb +8 -0
  30. data/test/config/test_configurable.rb +1 -1
  31. data/test/plugin/in_tail/test_position_file.rb +4 -4
  32. data/test/plugin/out_forward/test_connection_manager.rb +6 -0
  33. data/test/plugin/test_in_exec.rb +1 -1
  34. data/test/plugin/test_in_tail.rb +54 -16
  35. data/test/plugin/test_out_copy.rb +87 -0
  36. data/test/plugin/test_out_forward.rb +74 -0
  37. data/test/plugin/test_out_http.rb +1 -1
  38. data/test/plugin_helper/test_child_process.rb +5 -2
  39. data/test/test_event.rb +16 -0
  40. data/test/test_formatter.rb +30 -0
  41. data/test/test_time_parser.rb +109 -0
  42. metadata +27 -7
  43. data/.travis.yml +0 -77
  44. data/appveyor.yml +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04be4b818522c222348ba309bccd34f03d0aa79bfc2fbd21f2ce738677d7a5e5
4
- data.tar.gz: '078ce4c3003b74be7356367ff81d96d910a5df322ebe2319d96120cb1e2898b3'
3
+ metadata.gz: 9be763d670c8f331be578f85392cc428502a275a370e3a2b6520a08f22861da8
4
+ data.tar.gz: ffd8aaf0703bad823a2848b1f939d317bbe903ed6ae48196f4a84fc737db73fc
5
5
  SHA512:
6
- metadata.gz: 77298246f6064ddf342765c37efb269236025566b33828cac9c88d69b6dabbbd2881c28ddae699d4620817a44a77310e15c4ac191a0ad51b6aeab51eb7442961
7
- data.tar.gz: 318668fa9fde451292fd3b4284fc513124e6aa29218388a8a7cdfaaeb3943b3d3c4ffa45041cb0b2487da6573a9818f225c81b8769b7c025342bc5a6b5b05b53
6
+ metadata.gz: 7fad389c0066167a21d41c654c2ec74501b21e2dcf35d120e34fff7084b641a9468dcefcf75679ba8e5de5391e4bd58bbd60cbb310d31e3e01119a80408936a5
7
+ data.tar.gz: 8fbd2fbe2d88cb9c9cb35eabfea19706361225381775e08e0b5ee5adc8228b2e65f305d34410aa76d6cbbf773c8b3dd4a123da41f81e36fb294ef948b25ff98f
data/.deepsource.toml ADDED
@@ -0,0 +1,13 @@
1
+ version = 1
2
+
3
+ test_patterns = ["test/**/test_*.rb"]
4
+
5
+ exclude_patterns = [
6
+ "bin/**",
7
+ "docs/**",
8
+ "example/**"
9
+ ]
10
+
11
+ [[analyzers]]
12
+ name = "ruby"
13
+ enabled = true
@@ -1,5 +1,5 @@
1
1
  blank_issues_enabled: false
2
2
  contact_links:
3
3
  - name: Ask a Question
4
- url: https://groups.google.com/forum/#!forum/fluentd
5
- about: I have questions about Fluentd and plugins. Please ask and answer questions here
4
+ url: https://discuss.fluentd.org/
5
+ about: I have questions about Fluentd and plugins. Please ask and answer questions at https://discuss.fluentd.org/.
@@ -0,0 +1,36 @@
1
+ name: Testing on Ubuntu
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ continue-on-error: ${{ matrix.experimental }}
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby-version: ['3.0', '2.7', '2.6', '2.5']
17
+ os: [ubuntu-latest]
18
+ experimental: [false]
19
+ include:
20
+ - ruby-version: head
21
+ os: ubuntu-latest
22
+ experimental: true
23
+
24
+ name: Unit testing with Ruby ${{ matrix.ruby-version }} on ${{ matrix.os }}
25
+ steps:
26
+ - uses: actions/checkout@v2
27
+ - name: Set up Ruby
28
+ uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby-version }}
31
+ - name: Install addons
32
+ run: sudo apt-get install libgmp3-dev libcap-ng-dev
33
+ - name: Install dependencies
34
+ run: bundle install
35
+ - name: Run tests
36
+ run: bundle exec rake test
@@ -0,0 +1,30 @@
1
+ name: Testing on macOS
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ${{ matrix.os }}
12
+ continue-on-error: ${{ matrix.experimental }}
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ ruby-version: ['head', '2.7']
17
+ os: [macos-latest]
18
+ experimental: [true]
19
+
20
+ name: Unit testing with Ruby ${{ matrix.ruby-version }} on ${{ matrix.os }}
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ - name: Set up Ruby
24
+ uses: ruby/setup-ruby@v1
25
+ with:
26
+ ruby-version: ${{ matrix.ruby-version }}
27
+ - name: Install dependencies
28
+ run: bundle install
29
+ - name: Run tests
30
+ run: bundle exec rake test
@@ -1,4 +1,4 @@
1
- name: build
1
+ name: Testing on Windows
2
2
 
3
3
  on:
4
4
  push:
@@ -8,22 +8,23 @@ on:
8
8
 
9
9
  jobs:
10
10
  test:
11
- runs-on: ubuntu-latest
11
+ runs-on: ${{ matrix.os }}
12
12
 
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- ruby-version: [2.7, 2.6, 2.5]
16
+ ruby-version: ['3.0', '2.7', '2.6', '2.5']
17
+ os:
18
+ - windows-latest
17
19
 
20
+ name: Unit testing with Ruby ${{ matrix.ruby-version }} on ${{ matrix.os }}
18
21
  steps:
19
22
  - uses: actions/checkout@v2
20
23
  - name: Set up Ruby
21
24
  uses: ruby/setup-ruby@v1
22
25
  with:
23
26
  ruby-version: ${{ matrix.ruby-version }}
24
- - name: Install addons
25
- run: sudo apt-get install libgmp3-dev libcap-ng-dev
26
27
  - name: Install dependencies
27
- run: bundle install
28
+ run: ridk exec bundle install
28
29
  - name: Run tests
29
30
  run: bundle exec rake test TESTOPTS=-v
data/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # v1.12
2
2
 
3
+ ## Release v1.12.2 - 2021/03/29
4
+
5
+ ### Enhancement
6
+
7
+ * out_copy: Add ignore_if_prev_successes
8
+ https://github.com/fluent/fluentd/pull/3190
9
+ https://github.com/fluent/fluentd/pull/3287
10
+ * Support multiple kind of timestamp format
11
+ https://github.com/fluent/fluentd/pull/3252
12
+ * formatter_ltsv: suppress delimiters in output
13
+ https://github.com/fluent/fluentd/pull/1666
14
+ https://github.com/fluent/fluentd/pull/3288
15
+ https://github.com/fluent/fluentd/pull/3289
16
+
17
+ ### Bug fix
18
+
19
+ * in_tail: Expect ENOENT during stat
20
+ https://github.com/fluent/fluentd/pull/3275
21
+ * out_forward: Prevent transferring duplicate logs on restart
22
+ https://github.com/fluent/fluentd/pull/3267
23
+ https://github.com/fluent/fluentd/pull/3285
24
+ * in_tail: Handle to send rotated logs when mv is used for rotating
25
+ https://github.com/fluent/fluentd/pull/3294
26
+ * fluent-plugin-config-format: Fill an uninitialized instance variable
27
+ https://github.com/fluent/fluentd/pull/3297
28
+ * Fix MessagePackEventStream issue with Enumerable methods
29
+ https://github.com/fluent/fluentd/pull/2116
30
+
31
+ ### Misc
32
+
33
+ * Add webrick to support Ruby 3.0
34
+ https://github.com/fluent/fluentd/pull/3257
35
+ * Suggest Discource instead of Google Groups
36
+ https://github.com/fluent/fluentd/pull/3261
37
+ * Update MAINTAINERS.md
38
+ https://github.com/fluent/fluentd/pull/3282
39
+ * Introduce DeepSource to check code quality
40
+ https://github.com/fluent/fluentd/pull/3286
41
+ https://github.com/fluent/fluentd/pull/3259
42
+ https://github.com/fluent/fluentd/pull/3291
43
+ * Migrate to GitHub Actions and stabilize tests
44
+ https://github.com/fluent/fluentd/pull/3266
45
+ https://github.com/fluent/fluentd/pull/3268
46
+ https://github.com/fluent/fluentd/pull/3281
47
+ https://github.com/fluent/fluentd/pull/3283
48
+ https://github.com/fluent/fluentd/pull/3290
49
+
3
50
  ## Release v1.12.1 - 2021/02/18
4
51
 
5
52
  ### Enhancement
data/MAINTAINERS.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Fluentd Maintainers
2
2
 
3
3
  - [Naotoshi Seo](https://github.com/sonots), [ZOZO Technologies](https://tech.zozo.com/en/)
4
- - [Okkez](https://github.com/okkez), [Clearcode](https://www.clear-code.com/)
5
- - [Hiroshi Hatake](https://github.com/cosmo0920), [Clearcode](https://www.clear-code.com/)
4
+ - [Okkez](https://github.com/okkez)
5
+ - [Hiroshi Hatake](https://github.com/cosmo0920), [ClearCode](https://www.clear-code.com/)
6
6
  - [Masahiro Nakagawa](https://github.com/repeatedly), [Treasure Data](https://www.treasuredata.com/)
7
7
  - [Satoshi Tagomori](https://github.com/tagomoris), [Treasure Data](https://www.treasuredata.com/)
8
8
  - [Eduardo Silva](https://github.com/edsiper), [Arm Treasure Data](https://www.treasuredata.com/)
9
+ - [Fujimoto Seiji](https://github.com/fujimots), [ClearCode](https://www.clear-code.com/)
10
+ - [Takuro Ashie](https://github.com/ashie), [ClearCode](https://www.clear-code.com/)
11
+ - [Kentaro Hayashi](https://github.com/kenhys), [ClearCode](https://www.clear-code.com/)
data/fluentd.gemspec CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |gem|
28
28
  gem.add_runtime_dependency("tzinfo", [">= 1.0", "< 3.0"])
29
29
  gem.add_runtime_dependency("tzinfo-data", ["~> 1.0"])
30
30
  gem.add_runtime_dependency("strptime", [">= 0.2.2", "< 1.0.0"])
31
+ gem.add_runtime_dependency("webrick", [">= 1.4.2", "< 1.8.0"])
31
32
 
32
33
  # build gem for a certain platform. see also Rakefile
33
34
  fake_platform = ENV['GEM_BUILD_FAKE_PLATFORM'].to_s
@@ -40,6 +40,6 @@ else
40
40
  File.expand_path(File.join(File.dirname(__FILE__), 'fluentd.rb')),
41
41
  ] + ARGV
42
42
 
43
- exec *cmdline
43
+ exec(*cmdline)
44
44
  exit! 127
45
45
  end
@@ -101,7 +101,6 @@ rescue
101
101
  usage $!.to_s
102
102
  end
103
103
 
104
- require 'thread'
105
104
  require 'socket'
106
105
  require 'yajl'
107
106
  require 'msgpack'
@@ -44,6 +44,7 @@ class FluentPluginConfigFormatter
44
44
  @verbose = false
45
45
  @libs = []
46
46
  @plugin_dirs = []
47
+ @table = false
47
48
  @options = {}
48
49
 
49
50
  prepare_option_parser
@@ -162,7 +163,7 @@ class FluentPluginConfigFormatter
162
163
  else
163
164
  sections, params = base_section.partition {|_name, value| value[:section] }
164
165
  end
165
- if @table and not params.empty?
166
+ if @table && (not params.empty?)
166
167
  dumped << "### Configuration\n\n"
167
168
  dumped << "|parameter|type|description|default|\n"
168
169
  dumped << "|---|---|---|---|\n"
@@ -244,10 +244,10 @@ module Fluent
244
244
  end
245
245
 
246
246
  def convert_value_to_nil(value)
247
- if value and @null_empty_string
247
+ if value && @null_empty_string
248
248
  value = (value == '') ? nil : value
249
249
  end
250
- if value and @null_value_pattern
250
+ if value && @null_value_pattern
251
251
  value = ::Fluent::StringUtil.match_regexp(@null_value_pattern, value) ? nil : value
252
252
  end
253
253
  value
@@ -179,7 +179,7 @@ module Fluent
179
179
  end
180
180
 
181
181
  if section_params[varname].nil?
182
- unless proxy.defaults.has_key?(varname) and proxy.defaults[varname].nil?
182
+ unless proxy.defaults.has_key?(varname) && proxy.defaults[varname].nil?
183
183
  logger.error "config error in:\n#{conf}" if logger
184
184
  raise ConfigError, "'#{name}' parameter is required but nil is specified"
185
185
  end
@@ -186,7 +186,7 @@ module Fluent
186
186
  return nil if val.nil?
187
187
 
188
188
  param = if val.is_a?(String)
189
- val.start_with?('{') ? JSON.load(val) : Hash[val.strip.split(/\s*,\s*/).map{|v| v.split(':', 2)}]
189
+ val.start_with?('{') ? JSON.parse(val) : Hash[val.strip.split(/\s*,\s*/).map{|v| v.split(':', 2)}]
190
190
  else
191
191
  val
192
192
  end
@@ -213,7 +213,7 @@ module Fluent
213
213
  return nil if val.nil?
214
214
 
215
215
  param = if val.is_a?(String)
216
- val.start_with?('[') ? JSON.load(val) : val.strip.split(/\s*,\s*/)
216
+ val.start_with?('[') ? JSON.parse(val) : val.strip.split(/\s*,\s*/)
217
217
  else
218
218
  val
219
219
  end
data/lib/fluent/event.rb CHANGED
@@ -254,19 +254,9 @@ module Fluent
254
254
  end
255
255
 
256
256
  def each(unpacker: nil, &block)
257
- if @unpacked_times
258
- @unpacked_times.each_with_index do |time, i|
259
- block.call(time, @unpacked_records[i])
260
- end
261
- else
262
- @unpacked_times = []
263
- @unpacked_records = []
264
- (unpacker || Fluent::MessagePackFactory.msgpack_unpacker).feed_each(@data) do |time, record|
265
- @unpacked_times << time
266
- @unpacked_records << record
267
- block.call(time, record)
268
- end
269
- @size = @unpacked_times.size
257
+ ensure_unpacked!(unpacker: unpacker)
258
+ @unpacked_times.each_with_index do |time, i|
259
+ block.call(time, @unpacked_records[i])
270
260
  end
271
261
  nil
272
262
  end
data/lib/fluent/load.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'thread'
2
1
  require 'socket'
3
2
  require 'fcntl'
4
3
  require 'time'
@@ -27,14 +27,14 @@ module Fluent
27
27
 
28
28
  config_param :delimiter, :string, default: "\t".freeze
29
29
  config_param :label_delimiter, :string, default: ":".freeze
30
+ config_param :replacement, :string, default: " ".freeze
30
31
  config_param :add_newline, :bool, default: true
31
32
 
32
- # TODO: escaping for \t in values
33
33
  def format(tag, time, record)
34
34
  formatted = ""
35
35
  record.each do |label, value|
36
36
  formatted << @delimiter if formatted.length.nonzero?
37
- formatted << "#{label}#{@label_delimiter}#{value}"
37
+ formatted << "#{label}#{@label_delimiter}#{value.to_s.gsub(@delimiter, @replacement)}"
38
38
  end
39
39
  formatted << @newline if @add_newline
40
40
  formatted
@@ -503,7 +503,7 @@ module Fluent::Plugin
503
503
  # For every incoming request, we check if we have some CORS
504
504
  # restrictions and allow listed origins through @cors_allow_origins.
505
505
  unless @cors_allow_origins.nil?
506
- unless @cors_allow_origins.include?('*') or include_cors_allow_origin
506
+ unless @cors_allow_origins.include?('*') || include_cors_allow_origin
507
507
  send_response_and_close(RES_403_STATUS, {'Connection' => 'close'}, "")
508
508
  return
509
509
  end
@@ -338,7 +338,7 @@ module Fluent::Plugin
338
338
  obj.merge!(pe.statistics['output'] || {})
339
339
  end
340
340
 
341
- obj['retry'] = get_retry_info(pe.retry) if opts[:with_retry] and pe.instance_variable_defined?(:@retry)
341
+ obj['retry'] = get_retry_info(pe.retry) if opts[:with_retry] && pe.instance_variable_defined?(:@retry)
342
342
 
343
343
  # include all instance variables if :with_debug_info is set
344
344
  if opts[:with_debug_info]
@@ -313,11 +313,17 @@ module Fluent::Plugin
313
313
  (paths - excluded).select { |path|
314
314
  FileTest.exist?(path)
315
315
  }.each { |path|
316
- target_info = TargetInfo.new(path, Fluent::FileWrapper.stat(path).ino)
317
- if @follow_inodes
318
- hash[target_info.ino] = target_info
319
- else
320
- hash[target_info.path] = target_info
316
+ # Even we just checked for existence, there is a race condition here as
317
+ # of which stat() might fail with ENOENT. See #3224.
318
+ begin
319
+ target_info = TargetInfo.new(path, Fluent::FileWrapper.stat(path).ino)
320
+ if @follow_inodes
321
+ hash[target_info.ino] = target_info
322
+ else
323
+ hash[target_info.path] = target_info
324
+ end
325
+ rescue Errno::ENOENT
326
+ $log.warn "expand_paths: stat() for #{path} failed with ENOENT. Skip file."
321
327
  end
322
328
  }
323
329
  hash
@@ -406,8 +412,15 @@ module Fluent::Plugin
406
412
  log.warn "Skip #{target_info.path} because unexpected setup error happens: #{e}"
407
413
  next
408
414
  end
409
- target_info = TargetInfo.new(target_info.path, Fluent::FileWrapper.stat(target_info.path).ino)
410
- @tails[target_info] = tw
415
+
416
+ begin
417
+ target_info = TargetInfo.new(target_info.path, Fluent::FileWrapper.stat(target_info.path).ino)
418
+ @tails[target_info] = tw
419
+ rescue Errno::ENOENT
420
+ $log.warn "stat() for #{target_info.path} failed with ENOENT. Drop tail watcher for now."
421
+ # explicitly detach and unwatch watcher `tw`.
422
+ stop_watchers(target_info, immediate: true, unwatched: true)
423
+ end
411
424
  }
412
425
  end
413
426
 
@@ -767,16 +780,22 @@ module Fluent::Plugin
767
780
  end
768
781
 
769
782
  if watcher_needs_update
770
- # No need to update a watcher if stat is nil (file not present), because moving to inodes will create
771
- # new watcher, and old watcher will be closed by stop_watcher in refresh_watchers method
772
- if stat
773
- target_info = TargetInfo.new(@path, stat.ino)
774
- if @follow_inodes
775
- # don't want to swap state because we need latest read offset in pos file even after rotate_wait
783
+ if @follow_inodes
784
+ # No need to update a watcher if stat is nil (file not present), because moving to inodes will create
785
+ # new watcher, and old watcher will be closed by stop_watcher in refresh_watchers method
786
+ # don't want to swap state because we need latest read offset in pos file even after rotate_wait
787
+ if stat
788
+ target_info = TargetInfo.new(@path, stat)
776
789
  @update_watcher.call(target_info, @pe)
777
- else
778
- @update_watcher.call(target_info, swap_state(@pe))
779
790
  end
791
+ else
792
+ # Permit to handle if stat is nil (file not present).
793
+ # If a file is mv-ed and a new file is created during
794
+ # calling `#refresh_watchers`s, and `#refresh_watchers` won't run `#start_watchers`
795
+ # and `#stop_watchers()` for the path because `target_paths_hash`
796
+ # always contains the path.
797
+ target_info = TargetInfo.new(@path, stat ? stat.ino : nil)
798
+ @update_watcher.call(target_info, swap_state(@pe))
780
799
  end
781
800
  else
782
801
  @log.info "detected rotation of #{@path}"
@@ -27,20 +27,28 @@ module Fluent::Plugin
27
27
  desc 'Pass different record to each `store` plugin by specified method'
28
28
  config_param :copy_mode, :enum, list: [:no_copy, :shallow, :deep, :marshal], default: :no_copy
29
29
 
30
- attr_reader :ignore_errors
30
+ attr_reader :ignore_errors, :ignore_if_prev_successes
31
31
 
32
32
  def initialize
33
33
  super
34
34
  @ignore_errors = []
35
+ @ignore_if_prev_successes = []
35
36
  end
36
37
 
37
38
  def configure(conf)
38
39
  super
39
40
 
40
41
  @copy_proc = gen_copy_proc
41
- @stores.each { |store|
42
- @ignore_errors << (store.arg == 'ignore_error')
42
+ @stores.each_with_index { |store, i|
43
+ if i == 0 && store.arg.include?('ignore_if_prev_success')
44
+ raise Fluent::ConfigError, "ignore_if_prev_success must specify 2nd or later <store> directives"
45
+ end
46
+ @ignore_errors << (store.arg.include?('ignore_error'))
47
+ @ignore_if_prev_successes << (store.arg.include?('ignore_if_prev_success'))
43
48
  }
49
+ if @ignore_errors.uniq.size == 1 && @ignore_errors.include?(true) && @ignore_if_prev_successes.include?(false)
50
+ log.warn "ignore_errors are specified in all <store>, but ignore_if_prev_success is not specified. Is this intended?"
51
+ end
44
52
  end
45
53
 
46
54
  def multi_workers_ready?
@@ -55,10 +63,15 @@ module Fluent::Plugin
55
63
  }
56
64
  es = m
57
65
  end
58
-
66
+ success = Array.new(outputs.size)
59
67
  outputs.each_with_index do |output, i|
60
68
  begin
61
- output.emit_events(tag, @copy_proc ? @copy_proc.call(es) : es)
69
+ if i > 0 && success[i - 1] && @ignore_if_prev_successes[i]
70
+ log.debug "ignore copy because prev_success in #{output.plugin_id}", index: i
71
+ else
72
+ output.emit_events(tag, @copy_proc ? @copy_proc.call(es) : es)
73
+ success[i] = true
74
+ end
62
75
  rescue => e
63
76
  if @ignore_errors[i]
64
77
  log.error "ignore emit error in #{output.plugin_id}", error: e