fluentd 1.12.4 → 1.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18ac12d4a5dd93864521dae3a8a7db37fbe3bcd385f80a394bd6ddb34ffa6541
4
- data.tar.gz: 105bc856fdf9863e414da2147d53a849d418f6ba6810888eab023d28e2097035
3
+ metadata.gz: 20ece94d6aedf52ed5f7bdefedfda93056ef92bbc44a7b7a27c4b4e4660dc5e0
4
+ data.tar.gz: 76166c17b6018360db1d192c2a9aa8094c1fea780bc74f715264035f0485d601
5
5
  SHA512:
6
- metadata.gz: 16d72d0914ee5eb42ecb9e3957e791ddab88e1a32ed810785615470a0539eb01f0b91085167edac16937ec72b9352582ace8db3fc0adc06b64c3842111b16e3e
7
- data.tar.gz: e928fc8ccaf35460e24b2157d95c3b2a076574fdd90801be94ff39fc86d92770f948425317aa8c1f192d826e190ce5e0abd5770bef922a8ed5e42c0494ca2c38
6
+ metadata.gz: 214cbbef726516095e961786462e33b355fd77ecdcd278f5ada3a6f8d02489620ddbf84b9a7a4ba1de27b925f5455dda3c2b90c024bfa573afda05cc453d8e3a
7
+ data.tar.gz: 75de8aad92959bcb746be2c225c627e3f6590e2ffba38a91d0d0c540c7752bb2ebacc0623132a8ee613775ce63530a8083070fd008bb54646ecc37e4e2f6ca31
@@ -18,9 +18,17 @@ jobs:
18
18
  - windows-latest
19
19
  experimental: [false]
20
20
  include:
21
- - ruby-version: '3.0'
21
+ - ruby-version: '3.0.1'
22
22
  os: windows-latest
23
23
  experimental: true
24
+ # On Ruby 3.0, we need to use fiddle 1.0.8 or later to retrieve correct
25
+ # error code. In addition, we have to specify the path of fiddle by RUBYLIB
26
+ # because RubyInstaller loads Ruby's bundled fiddle before initializing gem.
27
+ # See also:
28
+ # * https://github.com/ruby/fiddle/issues/72
29
+ # * https://bugs.ruby-lang.org/issues/17813
30
+ # * https://github.com/oneclick/rubyinstaller2/blob/8225034c22152d8195bc0aabc42a956c79d6c712/lib/ruby_installer/build/dll_directory.rb
31
+ ruby-lib-opt: RUBYLIB=%RUNNER_TOOL_CACHE%/Ruby/3.0.1/x64/lib/ruby/gems/3.0.0/gems/fiddle-1.0.8/lib
24
32
 
25
33
  name: Unit testing with Ruby ${{ matrix.ruby-version }} on ${{ matrix.os }}
26
34
  steps:
@@ -29,7 +37,10 @@ jobs:
29
37
  uses: ruby/setup-ruby@v1
30
38
  with:
31
39
  ruby-version: ${{ matrix.ruby-version }}
40
+ - name: Add Fiddle 1.0.8
41
+ if: ${{ matrix.ruby-version == '3.0.1' }}
42
+ run: gem install fiddle --version 1.0.8
32
43
  - name: Install dependencies
33
44
  run: ridk exec bundle install
34
45
  - name: Run tests
35
- run: bundle exec rake test TESTOPTS=-v
46
+ run: bundle exec rake test TESTOPTS=-v ${{ matrix.ruby-lib-opt }}
data/CHANGELOG.md CHANGED
@@ -1,3 +1,45 @@
1
+ # v1.13
2
+
3
+ ## Release v1.13.0 - 2021/05/29
4
+
5
+ ### Enhancement
6
+
7
+ * in_tail: Handle log throttling per file feature
8
+ https://github.com/fluent/fluentd/pull/3185
9
+ https://github.com/fluent/fluentd/pull/3364
10
+ https://github.com/fluent/fluentd/pull/3379
11
+ * Extend to support service discovery manager in simpler way
12
+ https://github.com/fluent/fluentd/pull/3299
13
+ https://github.com/fluent/fluentd/pull/3362
14
+ * in_http: HTTP GET requests has been supported
15
+ https://github.com/fluent/fluentd/pull/3373
16
+ * The log rotate settings in system configuration has been supported
17
+ https://github.com/fluent/fluentd/pull/3352
18
+
19
+ ### Bug fix
20
+
21
+ * Fix to disable `trace_instruction` when
22
+ `RubyVM::InstructionSequence` is available. It improves
23
+ compatibility with `truffleruby` some extent.
24
+ https://github.com/fluent/fluentd/pull/3376
25
+ * in_tail: Safely skip files which are used by another process on
26
+ Windows. It improves exception handling about
27
+ `ERROR_SHARING_VIOLATION` on Windows.
28
+ https://github.com/fluent/fluentd/pull/3378
29
+ * fluent-cat: the issue resending secondary file in specific format
30
+ has been fixed
31
+ https://github.com/fluent/fluentd/pull/3368
32
+ * in_tail: Shutdown immediately & safely even if reading huge files
33
+ Note that `skip_refresh_on_startup` must be enabled.
34
+ https://github.com/fluent/fluentd/pull/3380
35
+
36
+ ### Misc
37
+
38
+ * example: Change a path to backup_path in counter_server correctly
39
+ https://github.com/fluent/fluentd/pull/3359
40
+ * README: Update link to community forum to discuss.fluentd.org
41
+ https://github.com/fluent/fluentd/pull/3360
42
+
1
43
  # v1.12
2
44
 
3
45
  ## Release v1.12.4 - 2021/05/26
data/CONTRIBUTING.md CHANGED
@@ -6,7 +6,7 @@ We'd love your contribution. Here are the guidelines!
6
6
 
7
7
  RESOURCES of [Official site](https://www.fluentd.org/) and [Fluentd documentation](https://docs.fluentd.org/) may help you.
8
8
 
9
- If you have further questions about Fluentd and plugins, please direct these to [Mailing List](https://groups.google.com/forum/#!forum/fluentd).
9
+ If you have further questions about Fluentd and plugins, please direct these to [Community Forum](https://discuss.fluentd.org/).
10
10
  Don't use Github issue for asking questions. Here are examples:
11
11
 
12
12
  - I installed xxx plugin but it doesn't work. Why?
@@ -16,7 +16,7 @@ Don't use Github issue for asking questions. Here are examples:
16
16
  We may close such questions to keep clear repository for developers and users.
17
17
  Github issue is mainly for submitting a bug report or feature request. See below.
18
18
 
19
- If you can't judge your case is a bug or not, use mailing list or slack first.
19
+ If you can't judge your case is a bug or not, use community forum or slack first.
20
20
 
21
21
  ## Found a bug?
22
22
 
data/MAINTAINERS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  - [Naotoshi Seo](https://github.com/sonots), [ZOZO Technologies](https://tech.zozo.com/en/)
4
4
  - [Okkez](https://github.com/okkez)
5
- - [Hiroshi Hatake](https://github.com/cosmo0920), [ClearCode](https://www.clear-code.com/)
5
+ - [Hiroshi Hatake](https://github.com/cosmo0920), [Calyptia](https://www.calyptia.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/)
data/README.md CHANGED
@@ -77,7 +77,7 @@ You can run specified test via `TEST` environment variable:
77
77
  - Website: https://www.fluentd.org/
78
78
  - Documentation: https://docs.fluentd.org/
79
79
  - Project repository: https://github.com/fluent
80
- - Discussion: https://groups.google.com/group/fluentd
80
+ - Discussion: https://discuss.fluentd.org/
81
81
  - Slack / Community: https://slack.fluentd.org
82
82
  - Newsletters: https://www.fluentd.org/newsletter
83
83
  - Author: [Sadayuki Furuhashi](https://github.com/frsyuki)
data/example/counter.conf CHANGED
@@ -3,7 +3,7 @@
3
3
  scope server1
4
4
  bind 127.0.0.1
5
5
  port 24321
6
- path tmp/back
6
+ backup_path tmp/back
7
7
  </counter_server>
8
8
  </system>
9
9
 
@@ -152,14 +152,30 @@ class Writer
152
152
  super()
153
153
  end
154
154
 
155
+ def secondary_record?(record)
156
+ record.class != Hash &&
157
+ record.size == 2 &&
158
+ record.first.class == Fluent::EventTime &&
159
+ record.last.class == Hash
160
+ end
161
+
155
162
  def write(record)
156
- if record.class != Hash
157
- raise ArgumentError, "Input must be a map (got #{record.class})"
163
+ unless secondary_record?(record)
164
+ if record.class != Hash
165
+ raise ArgumentError, "Input must be a map (got #{record.class})"
166
+ end
158
167
  end
159
168
 
160
169
  time = Fluent::EventTime.now
161
170
  time = time.to_i if @time_as_integer
162
- entry = [time, record]
171
+ entry = if secondary_record?(record)
172
+ # Even though secondary contains Fluent::EventTime in record,
173
+ # fluent-cat just ignore it and set Fluent::EventTime.now instead.
174
+ # This specification is adopted to keep consistency.
175
+ [time, record.last]
176
+ else
177
+ [time, record]
178
+ end
163
179
  synchronize {
164
180
  unless write_impl([entry])
165
181
  # write failed
@@ -85,9 +85,8 @@ op.on('-o', '--log PATH', "log file path") {|s|
85
85
  opts[:log_path] = s
86
86
  }
87
87
 
88
- ROTATE_AGE = %w(daily weekly monthly)
89
88
  op.on('--log-rotate-age AGE', 'generations to keep rotated log files') {|age|
90
- if ROTATE_AGE.include?(age)
89
+ if Fluent::Log::LOG_ROTATE_AGE.include?(age)
91
90
  opts[:log_rotate_age] = age
92
91
  else
93
92
  begin
data/lib/fluent/log.rb CHANGED
@@ -49,6 +49,7 @@ module Fluent
49
49
  LOG_TYPE_DEFAULT = :default # show logs in all supervisor/workers, with worker id in workers (default)
50
50
 
51
51
  LOG_TYPES = [LOG_TYPE_SUPERVISOR, LOG_TYPE_WORKER0, LOG_TYPE_DEFAULT].freeze
52
+ LOG_ROTATE_AGE = %w(daily weekly monthly)
52
53
 
53
54
  def self.str_to_level(log_level_str)
54
55
  case log_level_str.downcase
@@ -52,6 +52,8 @@ module Fluent
52
52
 
53
53
  attr_reader :errcode, :msg
54
54
 
55
+ WSABASEERR = 10000
56
+
55
57
  def initialize(errcode, msg = nil)
56
58
  @errcode = errcode
57
59
  @msg = msg
@@ -80,6 +82,10 @@ module Fluent
80
82
  return false if other.class != Win32Error
81
83
  @errcode == other.errcode && @msg == other.msg
82
84
  end
85
+
86
+ def wsaerr?
87
+ @errcode >= WSABASEERR
88
+ end
83
89
  end
84
90
 
85
91
  # To open and get stat with setting FILE_SHARE_DELETE
@@ -113,11 +119,14 @@ module Fluent
113
119
  @file_handle = CreateFile.call(@path, access, sharemode,
114
120
  0, creationdisposition, FILE_ATTRIBUTE_NORMAL, 0)
115
121
  if @file_handle == INVALID_HANDLE_VALUE
116
- err = Win32::API.last_error
117
- if err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND || err == ERROR_ACCESS_DENIED
118
- raise Errno::ENOENT
122
+ win32err = Win32Error.new(Win32::API.last_error, path)
123
+ errno = ServerEngine::RbWinSock.rb_w32_map_errno(win32err.errcode)
124
+ if errno == Errno::EINVAL::Errno || win32err.wsaerr?
125
+ # maybe failed to map
126
+ raise win32err
127
+ else
128
+ raise SystemCallError.new(win32err.message, errno)
119
129
  end
120
- raise Win32Error.new(err, path)
121
130
  end
122
131
  end
123
132
 
@@ -461,6 +461,12 @@ module Fluent::Plugin
461
461
  RES_200_STATUS = "200 OK".freeze
462
462
  RES_403_STATUS = "403 Forbidden".freeze
463
463
 
464
+ # Azure App Service sends GET requests for health checking purpose.
465
+ # Respond with `200 OK` to accommodate it.
466
+ def handle_get_request
467
+ return send_response_and_close(RES_200_STATUS, {}, "")
468
+ end
469
+
464
470
  # Web browsers can send an OPTIONS request before performing POST
465
471
  # to check if cross-origin requests are supported.
466
472
  def handle_options_request
@@ -494,6 +500,10 @@ module Fluent::Plugin
494
500
  def on_message_complete
495
501
  return if closing?
496
502
 
503
+ if @parser.http_method == 'GET'.freeze
504
+ return handle_get_request()
505
+ end
506
+
497
507
  if @parser.http_method == 'OPTIONS'.freeze
498
508
  return handle_options_request()
499
509
  end
@@ -56,6 +56,7 @@ module Fluent::Plugin
56
56
  @pf_file = nil
57
57
  @pf = nil
58
58
  @ignore_list = []
59
+ @shutdown_start_time = nil
59
60
  end
60
61
 
61
62
  desc 'The paths to read. Multiple paths can be specified, separated by comma.'
@@ -81,6 +82,8 @@ module Fluent::Plugin
81
82
  config_param :refresh_interval, :time, default: 60
82
83
  desc 'The number of reading lines at each IO.'
83
84
  config_param :read_lines_limit, :integer, default: 1000
85
+ desc 'The number of reading bytes per second'
86
+ config_param :read_bytes_limit_per_second, :size, default: -1
84
87
  desc 'The interval of flushing the buffer for multiline format'
85
88
  config_param :multiline_flush_interval, :time, default: nil
86
89
  desc 'Enable the option to emit unmatched lines.'
@@ -178,6 +181,16 @@ module Fluent::Plugin
178
181
  # parser is already created by parser helper
179
182
  @parser = parser_create(usage: parser_config['usage'] || @parser_configs.first.usage)
180
183
  @capability = Fluent::Capability.new(:current_process)
184
+ if @read_bytes_limit_per_second > 0
185
+ if !@enable_watch_timer
186
+ raise Fluent::ConfigError, "Need to enable watch timer when using log throttling feature"
187
+ end
188
+ min_bytes = TailWatcher::IOHandler::BYTES_TO_READ
189
+ if @read_bytes_limit_per_second < min_bytes
190
+ log.warn "Should specify greater equal than #{min_bytes}. Use #{min_bytes} for read_bytes_limit_per_second"
191
+ @read_bytes_limit_per_second = min_bytes
192
+ end
193
+ end
181
194
  end
182
195
 
183
196
  def configure_tag
@@ -244,6 +257,7 @@ module Fluent::Plugin
244
257
  end
245
258
 
246
259
  def shutdown
260
+ @shutdown_start_time = Fluent::Clock.now
247
261
  # during shutdown phase, don't close io. It should be done in close after all threads are stopped. See close.
248
262
  stop_watchers(existence_path, immediate: true, remove_watcher: false)
249
263
  @pf_file.close if @pf_file
@@ -290,7 +304,7 @@ module Fluent::Plugin
290
304
  end
291
305
  false
292
306
  end
293
- rescue Errno::ENOENT
307
+ rescue Errno::ENOENT, Errno::EACCES
294
308
  log.debug("#{p} is missing after refresh file list")
295
309
  false
296
310
  end
@@ -322,8 +336,8 @@ module Fluent::Plugin
322
336
  else
323
337
  hash[target_info.path] = target_info
324
338
  end
325
- rescue Errno::ENOENT
326
- $log.warn "expand_paths: stat() for #{path} failed with ENOENT. Skip file."
339
+ rescue Errno::ENOENT, Errno::EACCES => e
340
+ $log.warn "expand_paths: stat() for #{path} failed with #{e.class.name}. Skip file."
327
341
  end
328
342
  }
329
343
  hash
@@ -373,8 +387,6 @@ module Fluent::Plugin
373
387
  tw.register_watcher(tt)
374
388
  end
375
389
 
376
- tw.on_notify
377
-
378
390
  tw.watchers.each do |watcher|
379
391
  event_loop_attach(watcher)
380
392
  end
@@ -386,42 +398,48 @@ module Fluent::Plugin
386
398
  event_loop_detach(watcher)
387
399
  end
388
400
 
389
- tw.detach
401
+ tw.detach(@shutdown_start_time)
390
402
  tw.close
391
403
  end
392
404
  raise e
393
405
  end
394
406
 
395
- def start_watchers(targets_info)
396
- targets_info.each_value { |target_info|
397
- pe = nil
398
- if @pf
399
- pe = @pf[target_info]
400
- if @read_from_head && pe.read_inode.zero?
401
- begin
402
- pe.update(Fluent::FileWrapper.stat(target_info.path).ino, 0)
403
- rescue Errno::ENOENT
404
- $log.warn "#{target_info.path} not found. Continuing without tailing it."
405
- end
407
+ def construct_watcher(target_info)
408
+ pe = nil
409
+ if @pf
410
+ pe = @pf[target_info]
411
+ if @read_from_head && pe.read_inode.zero?
412
+ begin
413
+ pe.update(Fluent::FileWrapper.stat(target_info.path).ino, 0)
414
+ rescue Errno::ENOENT, Errno::EACCES
415
+ $log.warn "stat() for #{target_info.path} failed. Continuing without tailing it."
406
416
  end
407
417
  end
418
+ end
408
419
 
409
- begin
410
- tw = setup_watcher(target_info, pe)
411
- rescue WatcherSetupError => e
412
- log.warn "Skip #{target_info.path} because unexpected setup error happens: #{e}"
413
- next
414
- end
420
+ begin
421
+ tw = setup_watcher(target_info, pe)
422
+ rescue WatcherSetupError => e
423
+ log.warn "Skip #{target_info.path} because unexpected setup error happens: #{e}"
424
+ return
425
+ end
415
426
 
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
- tw.unwatched = true
423
- detach_watcher(tw, target_info.ino, false)
424
- end
427
+ begin
428
+ target_info = TargetInfo.new(target_info.path, Fluent::FileWrapper.stat(target_info.path).ino)
429
+ @tails[target_info] = tw
430
+ tw.on_notify
431
+ rescue Errno::ENOENT, Errno::EACCES => e
432
+ $log.warn "stat() for #{target_info.path} failed with #{e.class.name}. Drop tail watcher for now."
433
+ # explicitly detach and unwatch watcher `tw`.
434
+ tw.unwatched = true
435
+ detach_watcher(tw, target_info.ino, false)
436
+ end
437
+ end
438
+
439
+ def start_watchers(targets_info)
440
+ targets_info.each_value {|target_info|
441
+ construct_watcher(target_info)
442
+ break if before_shutdown?
425
443
  }
426
444
  end
427
445
 
@@ -474,9 +492,11 @@ module Fluent::Plugin
474
492
 
475
493
  if new_position_entry.read_inode == 0
476
494
  @tails[new_target_info] = setup_watcher(new_target_info, new_position_entry)
495
+ @tails[new_target_info].on_notify
477
496
  end
478
497
  else
479
498
  @tails[new_target_info] = setup_watcher(new_target_info, pe)
499
+ @tails[new_target_info].on_notify
480
500
  end
481
501
  detach_watcher_after_rotate_wait(rotated_tw, pe.read_inode) if rotated_tw
482
502
  end
@@ -489,7 +509,7 @@ module Fluent::Plugin
489
509
  tw.watchers.each do |watcher|
490
510
  event_loop_detach(watcher)
491
511
  end
492
- tw.detach
512
+ tw.detach(@shutdown_start_time)
493
513
 
494
514
  tw.close if close_io
495
515
 
@@ -633,6 +653,7 @@ module Fluent::Plugin
633
653
  path: path,
634
654
  log: log,
635
655
  read_lines_limit: @read_lines_limit,
656
+ read_bytes_limit_per_second: @read_bytes_limit_per_second,
636
657
  open_on_every_update: @open_on_every_update,
637
658
  from_encoding: @from_encoding,
638
659
  encoding: @encoding,
@@ -700,8 +721,11 @@ module Fluent::Plugin
700
721
  @watchers << watcher
701
722
  end
702
723
 
703
- def detach
704
- @io_handler.on_notify if @io_handler
724
+ def detach(shutdown_start_time = nil)
725
+ if @io_handler
726
+ @io_handler.ready_to_shutdown(shutdown_start_time)
727
+ @io_handler.on_notify
728
+ end
705
729
  @line_buffer_timer_flusher&.close(self)
706
730
  end
707
731
 
@@ -715,7 +739,7 @@ module Fluent::Plugin
715
739
  def on_notify
716
740
  begin
717
741
  stat = Fluent::FileWrapper.stat(@path)
718
- rescue Errno::ENOENT
742
+ rescue Errno::ENOENT, Errno::EACCES
719
743
  # moved or deleted
720
744
  stat = nil
721
745
  end
@@ -876,10 +900,16 @@ module Fluent::Plugin
876
900
  end
877
901
 
878
902
  class IOHandler
879
- def initialize(watcher, path:, read_lines_limit:, log:, open_on_every_update:, from_encoding: nil, encoding: nil, &receive_lines)
903
+ BYTES_TO_READ = 8192
904
+ SHUTDOWN_TIMEOUT = 5
905
+
906
+ attr_accessor :shutdown_timeout
907
+
908
+ def initialize(watcher, path:, read_lines_limit:, read_bytes_limit_per_second:, log:, open_on_every_update:, from_encoding: nil, encoding: nil, &receive_lines)
880
909
  @watcher = watcher
881
910
  @path = path
882
911
  @read_lines_limit = read_lines_limit
912
+ @read_bytes_limit_per_second = read_bytes_limit_per_second
883
913
  @receive_lines = receive_lines
884
914
  @open_on_every_update = open_on_every_update
885
915
  @fifo = FIFO.new(from_encoding || Encoding::ASCII_8BIT, encoding || Encoding::ASCII_8BIT)
@@ -888,6 +918,11 @@ module Fluent::Plugin
888
918
  @io = nil
889
919
  @notify_mutex = Mutex.new
890
920
  @log = log
921
+ @start_reading_time = nil
922
+ @number_bytes_read = 0
923
+ @shutdown_start_time = nil
924
+ @shutdown_timeout = SHUTDOWN_TIMEOUT
925
+ @shutdown_mutex = Mutex.new
891
926
 
892
927
  @log.info "following tail of #{@path}"
893
928
  end
@@ -896,6 +931,13 @@ module Fluent::Plugin
896
931
  @notify_mutex.synchronize { handle_notify }
897
932
  end
898
933
 
934
+ def ready_to_shutdown(shutdown_start_time = nil)
935
+ @shutdown_mutex.synchronize {
936
+ @shutdown_start_time =
937
+ shutdown_start_time || Fluent::Clock.now
938
+ }
939
+ end
940
+
899
941
  def close
900
942
  if @io && !@io.closed?
901
943
  @io.close
@@ -909,7 +951,35 @@ module Fluent::Plugin
909
951
 
910
952
  private
911
953
 
954
+ def limit_bytes_per_second_reached?
955
+ return false if @read_bytes_limit_per_second < 0 # not enabled by conf
956
+ return false if @number_bytes_read < @read_bytes_limit_per_second
957
+
958
+ @start_reading_time ||= Fluent::Clock.now
959
+ time_spent_reading = Fluent::Clock.now - @start_reading_time
960
+ @log.debug("time_spent_reading: #{time_spent_reading} #{ @watcher.path}")
961
+
962
+ if time_spent_reading < 1
963
+ true
964
+ else
965
+ @start_reading_time = nil
966
+ @number_bytes_read = 0
967
+ false
968
+ end
969
+ end
970
+
971
+ def should_shutdown_now?
972
+ # Ensure to read all remaining lines, but abort immediately if it
973
+ # seems to take too long time.
974
+ @shutdown_mutex.synchronize {
975
+ return false if @shutdown_start_time.nil?
976
+ return Fluent::Clock.now - @shutdown_start_time > @shutdown_timeout
977
+ }
978
+ end
979
+
912
980
  def handle_notify
981
+ return if limit_bytes_per_second_reached?
982
+
913
983
  with_io do |io|
914
984
  begin
915
985
  read_more = false
@@ -917,8 +987,18 @@ module Fluent::Plugin
917
987
  if !io.nil? && @lines.empty?
918
988
  begin
919
989
  while true
920
- @fifo << io.readpartial(8192, @iobuf)
990
+ @start_reading_time ||= Fluent::Clock.now
991
+ data = io.readpartial(BYTES_TO_READ, @iobuf)
992
+ @number_bytes_read += data.bytesize
993
+ @fifo << data
921
994
  @fifo.read_lines(@lines)
995
+
996
+ @log.debug("reading file: #{@path}")
997
+ if limit_bytes_per_second_reached? || should_shutdown_now?
998
+ # Just get out from tailing loop.
999
+ read_more = false
1000
+ break
1001
+ end
922
1002
  if @lines.size >= @read_lines_limit
923
1003
  # not to use too much memory in case the file is very large
924
1004
  read_more = true
@@ -948,7 +1028,7 @@ module Fluent::Plugin
948
1028
  rescue RangeError
949
1029
  io.close if io
950
1030
  raise WatcherSetupError, "seek error with #{@path}: file position = #{@watcher.pe.read_pos.to_s(16)}, reading bytesize = #{@fifo.bytesize.to_s(16)}"
951
- rescue Errno::ENOENT
1031
+ rescue Errno::ENOENT, Errno::EACCES
952
1032
  nil
953
1033
  end
954
1034