fluentd 1.13.3 → 1.16.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/{bug_report.yaml → bug_report.yml} +2 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +2 -2
  4. data/.github/ISSUE_TEMPLATE/{feature_request.yaml → feature_request.yml} +1 -0
  5. data/.github/workflows/stale-actions.yml +11 -9
  6. data/.github/workflows/test.yml +32 -0
  7. data/CHANGELOG.md +490 -10
  8. data/CONTRIBUTING.md +2 -2
  9. data/MAINTAINERS.md +7 -5
  10. data/README.md +3 -23
  11. data/Rakefile +1 -1
  12. data/SECURITY.md +14 -0
  13. data/fluentd.gemspec +7 -8
  14. data/lib/fluent/command/cat.rb +13 -3
  15. data/lib/fluent/command/ctl.rb +6 -3
  16. data/lib/fluent/command/fluentd.rb +73 -65
  17. data/lib/fluent/command/plugin_config_formatter.rb +1 -1
  18. data/lib/fluent/compat/output.rb +9 -6
  19. data/lib/fluent/config/dsl.rb +1 -1
  20. data/lib/fluent/config/error.rb +12 -0
  21. data/lib/fluent/config/literal_parser.rb +2 -2
  22. data/lib/fluent/config/parser.rb +1 -1
  23. data/lib/fluent/config/v1_parser.rb +3 -3
  24. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  25. data/lib/fluent/config/yaml_parser/loader.rb +108 -0
  26. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  27. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  28. data/lib/fluent/config/yaml_parser.rb +56 -0
  29. data/lib/fluent/config.rb +14 -1
  30. data/lib/fluent/counter/server.rb +1 -1
  31. data/lib/fluent/counter/validator.rb +3 -3
  32. data/lib/fluent/daemon.rb +2 -4
  33. data/lib/fluent/engine.rb +1 -1
  34. data/lib/fluent/env.rb +4 -0
  35. data/lib/fluent/error.rb +3 -0
  36. data/lib/fluent/event.rb +8 -4
  37. data/lib/fluent/event_router.rb +47 -2
  38. data/lib/fluent/file_wrapper.rb +137 -0
  39. data/lib/fluent/log/console_adapter.rb +66 -0
  40. data/lib/fluent/log.rb +44 -5
  41. data/lib/fluent/match.rb +1 -1
  42. data/lib/fluent/msgpack_factory.rb +6 -1
  43. data/lib/fluent/oj_options.rb +1 -2
  44. data/lib/fluent/plugin/bare_output.rb +49 -8
  45. data/lib/fluent/plugin/base.rb +26 -9
  46. data/lib/fluent/plugin/buf_file.rb +34 -5
  47. data/lib/fluent/plugin/buf_file_single.rb +32 -3
  48. data/lib/fluent/plugin/buffer/file_chunk.rb +1 -1
  49. data/lib/fluent/plugin/buffer.rb +216 -70
  50. data/lib/fluent/plugin/filter.rb +35 -1
  51. data/lib/fluent/plugin/filter_record_transformer.rb +1 -1
  52. data/lib/fluent/plugin/in_forward.rb +2 -2
  53. data/lib/fluent/plugin/in_http.rb +39 -10
  54. data/lib/fluent/plugin/in_monitor_agent.rb +4 -2
  55. data/lib/fluent/plugin/in_sample.rb +1 -1
  56. data/lib/fluent/plugin/in_syslog.rb +13 -1
  57. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  58. data/lib/fluent/plugin/in_tail/position_file.rb +33 -33
  59. data/lib/fluent/plugin/in_tail.rb +216 -84
  60. data/lib/fluent/plugin/in_tcp.rb +47 -2
  61. data/lib/fluent/plugin/input.rb +39 -1
  62. data/lib/fluent/plugin/metrics.rb +119 -0
  63. data/lib/fluent/plugin/metrics_local.rb +96 -0
  64. data/lib/fluent/plugin/multi_output.rb +43 -6
  65. data/lib/fluent/plugin/out_copy.rb +1 -1
  66. data/lib/fluent/plugin/out_exec_filter.rb +2 -2
  67. data/lib/fluent/plugin/out_file.rb +20 -2
  68. data/lib/fluent/plugin/out_forward/ack_handler.rb +19 -4
  69. data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
  70. data/lib/fluent/plugin/out_forward.rb +17 -9
  71. data/lib/fluent/plugin/out_secondary_file.rb +39 -22
  72. data/lib/fluent/plugin/output.rb +167 -78
  73. data/lib/fluent/plugin/parser.rb +3 -4
  74. data/lib/fluent/plugin/parser_apache2.rb +1 -1
  75. data/lib/fluent/plugin/parser_json.rb +1 -1
  76. data/lib/fluent/plugin/parser_syslog.rb +1 -1
  77. data/lib/fluent/plugin/storage_local.rb +3 -5
  78. data/lib/fluent/plugin.rb +10 -1
  79. data/lib/fluent/plugin_helper/child_process.rb +3 -0
  80. data/lib/fluent/plugin_helper/event_emitter.rb +8 -1
  81. data/lib/fluent/plugin_helper/event_loop.rb +2 -2
  82. data/lib/fluent/plugin_helper/http_server/server.rb +2 -1
  83. data/lib/fluent/plugin_helper/metrics.rb +129 -0
  84. data/lib/fluent/plugin_helper/record_accessor.rb +1 -1
  85. data/lib/fluent/plugin_helper/retry_state.rb +14 -4
  86. data/lib/fluent/plugin_helper/server.rb +35 -6
  87. data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
  88. data/lib/fluent/plugin_helper/socket.rb +13 -2
  89. data/lib/fluent/plugin_helper/thread.rb +3 -3
  90. data/lib/fluent/plugin_helper.rb +1 -0
  91. data/lib/fluent/plugin_id.rb +3 -2
  92. data/lib/fluent/registry.rb +2 -1
  93. data/lib/fluent/root_agent.rb +6 -0
  94. data/lib/fluent/rpc.rb +4 -3
  95. data/lib/fluent/supervisor.rb +283 -259
  96. data/lib/fluent/system_config.rb +13 -3
  97. data/lib/fluent/test/driver/base.rb +11 -5
  98. data/lib/fluent/test/driver/filter.rb +4 -0
  99. data/lib/fluent/test/startup_shutdown.rb +6 -8
  100. data/lib/fluent/time.rb +21 -20
  101. data/lib/fluent/version.rb +1 -1
  102. data/lib/fluent/win32api.rb +38 -0
  103. data/lib/fluent/winsvc.rb +5 -8
  104. data/templates/new_gem/test/helper.rb.erb +0 -1
  105. data/test/command/test_cat.rb +31 -2
  106. data/test/command/test_ctl.rb +1 -2
  107. data/test/command/test_fluentd.rb +209 -24
  108. data/test/command/test_plugin_config_formatter.rb +0 -1
  109. data/test/compat/test_parser.rb +6 -6
  110. data/test/config/test_system_config.rb +13 -11
  111. data/test/config/test_types.rb +1 -1
  112. data/test/log/test_console_adapter.rb +110 -0
  113. data/test/plugin/in_tail/test_io_handler.rb +26 -8
  114. data/test/plugin/in_tail/test_position_file.rb +48 -59
  115. data/test/plugin/out_forward/test_ack_handler.rb +39 -0
  116. data/test/plugin/out_forward/test_socket_cache.rb +26 -1
  117. data/test/plugin/test_bare_output.rb +14 -1
  118. data/test/plugin/test_base.rb +133 -1
  119. data/test/plugin/test_buf_file.rb +62 -23
  120. data/test/plugin/test_buf_file_single.rb +65 -0
  121. data/test/plugin/test_buffer.rb +267 -3
  122. data/test/plugin/test_buffer_chunk.rb +11 -0
  123. data/test/plugin/test_filter.rb +12 -1
  124. data/test/plugin/test_filter_parser.rb +1 -1
  125. data/test/plugin/test_filter_stdout.rb +2 -2
  126. data/test/plugin/test_in_forward.rb +9 -11
  127. data/test/plugin/test_in_http.rb +65 -3
  128. data/test/plugin/test_in_monitor_agent.rb +216 -11
  129. data/test/plugin/test_in_object_space.rb +9 -3
  130. data/test/plugin/test_in_syslog.rb +35 -0
  131. data/test/plugin/test_in_tail.rb +1393 -385
  132. data/test/plugin/test_in_tcp.rb +87 -2
  133. data/test/plugin/test_in_udp.rb +28 -0
  134. data/test/plugin/test_in_unix.rb +2 -2
  135. data/test/plugin/test_input.rb +12 -1
  136. data/test/plugin/test_metrics.rb +294 -0
  137. data/test/plugin/test_metrics_local.rb +96 -0
  138. data/test/plugin/test_multi_output.rb +25 -1
  139. data/test/plugin/test_out_exec.rb +6 -4
  140. data/test/plugin/test_out_exec_filter.rb +6 -2
  141. data/test/plugin/test_out_file.rb +34 -17
  142. data/test/plugin/test_out_forward.rb +78 -77
  143. data/test/plugin/test_out_http.rb +1 -0
  144. data/test/plugin/test_out_stdout.rb +2 -2
  145. data/test/plugin/test_output.rb +297 -12
  146. data/test/plugin/test_output_as_buffered.rb +44 -44
  147. data/test/plugin/test_output_as_buffered_compress.rb +32 -18
  148. data/test/plugin/test_output_as_buffered_retries.rb +54 -7
  149. data/test/plugin/test_output_as_buffered_secondary.rb +4 -4
  150. data/test/plugin/test_parser_regexp.rb +1 -6
  151. data/test/plugin/test_parser_syslog.rb +1 -1
  152. data/test/plugin_helper/test_cert_option.rb +1 -1
  153. data/test/plugin_helper/test_child_process.rb +38 -16
  154. data/test/plugin_helper/test_event_emitter.rb +29 -0
  155. data/test/plugin_helper/test_http_server_helper.rb +1 -1
  156. data/test/plugin_helper/test_metrics.rb +137 -0
  157. data/test/plugin_helper/test_retry_state.rb +602 -38
  158. data/test/plugin_helper/test_server.rb +78 -6
  159. data/test/plugin_helper/test_timer.rb +2 -2
  160. data/test/test_config.rb +191 -24
  161. data/test/test_event_router.rb +17 -0
  162. data/test/test_file_wrapper.rb +53 -0
  163. data/test/test_formatter.rb +24 -21
  164. data/test/test_log.rb +122 -40
  165. data/test/test_msgpack_factory.rb +32 -0
  166. data/test/test_plugin_classes.rb +102 -0
  167. data/test/test_root_agent.rb +30 -1
  168. data/test/test_supervisor.rb +477 -257
  169. data/test/test_time_parser.rb +22 -0
  170. metadata +55 -34
  171. data/.drone.yml +0 -35
  172. data/.github/workflows/issue-auto-closer.yml +0 -12
  173. data/.github/workflows/linux-test.yaml +0 -36
  174. data/.github/workflows/macos-test.yaml +0 -30
  175. data/.github/workflows/windows-test.yaml +0 -46
  176. data/.gitlab-ci.yml +0 -103
  177. data/lib/fluent/plugin/file_wrapper.rb +0 -187
  178. data/test/plugin/test_file_wrapper.rb +0 -126
  179. data/test/test_logger_initializer.rb +0 -46
data/lib/fluent/plugin.rb CHANGED
@@ -36,8 +36,9 @@ module Fluent
36
36
  FORMATTER_REGISTRY = Registry.new(:formatter, 'fluent/plugin/formatter_', dir_search_prefix: 'formatter_')
37
37
  STORAGE_REGISTRY = Registry.new(:storage, 'fluent/plugin/storage_', dir_search_prefix: 'storage_')
38
38
  SD_REGISTRY = Registry.new(:sd, 'fluent/plugin/sd_', dir_search_prefix: 'sd_')
39
+ METRICS_REGISTRY = Registry.new(:metrics, 'fluent/plugin/metrics_', dir_search_prefix: 'metrics_')
39
40
 
40
- REGISTRIES = [INPUT_REGISTRY, OUTPUT_REGISTRY, FILTER_REGISTRY, BUFFER_REGISTRY, PARSER_REGISTRY, FORMATTER_REGISTRY, STORAGE_REGISTRY, SD_REGISTRY]
41
+ REGISTRIES = [INPUT_REGISTRY, OUTPUT_REGISTRY, FILTER_REGISTRY, BUFFER_REGISTRY, PARSER_REGISTRY, FORMATTER_REGISTRY, STORAGE_REGISTRY, SD_REGISTRY, METRICS_REGISTRY]
41
42
 
42
43
  def self.register_input(type, klass)
43
44
  register_impl('input', INPUT_REGISTRY, type, klass)
@@ -59,6 +60,10 @@ module Fluent
59
60
  register_impl('sd', SD_REGISTRY, type, klass)
60
61
  end
61
62
 
63
+ def self.register_metrics(type, klass)
64
+ register_impl('metrics', METRICS_REGISTRY, type, klass)
65
+ end
66
+
62
67
  def self.register_parser(type, klass_or_proc)
63
68
  if klass_or_proc.is_a?(Regexp)
64
69
  # This usage is not recommended for new API
@@ -121,6 +126,10 @@ module Fluent
121
126
  new_impl('sd', SD_REGISTRY, type, parent)
122
127
  end
123
128
 
129
+ def self.new_metrics(type, parent: nil)
130
+ new_impl('metrics', METRICS_REGISTRY, type, parent)
131
+ end
132
+
124
133
  class << self
125
134
  # This should be defined for fluent-plugin-config-formatter type arguments.
126
135
  alias_method :new_service_discovery, :new_sd
@@ -346,6 +346,9 @@ module Fluent
346
346
  if cb
347
347
  cb.call(process_info.exit_status) rescue nil
348
348
  end
349
+ process_info.readio&.close rescue nil
350
+ process_info.writeio&.close rescue nil
351
+ process_info.stderrio&.close rescue nil
349
352
  end
350
353
  thread[:_fluentd_plugin_helper_child_process_running] = true
351
354
  thread[:_fluentd_plugin_helper_child_process_pid] = pid
@@ -29,6 +29,9 @@ module Fluent
29
29
  if @_event_emitter_lazy_init
30
30
  @router = @primary_instance.router
31
31
  end
32
+ if @router.respond_to?(:caller_plugin_id=)
33
+ @router.caller_plugin_id = self.plugin_id
34
+ end
32
35
  @router
33
36
  end
34
37
 
@@ -47,7 +50,11 @@ module Fluent
47
50
 
48
51
  def event_emitter_router(label_name)
49
52
  if label_name
50
- Engine.root_agent.find_label(label_name).event_router
53
+ if label_name == "@ROOT"
54
+ Engine.root_agent.event_router
55
+ else
56
+ Engine.root_agent.find_label(label_name).event_router
57
+ end
51
58
  elsif self.respond_to?(:as_secondary) && self.as_secondary
52
59
  if @primary_instance.has_router?
53
60
  @_event_emitter_lazy_init = true
@@ -99,7 +99,7 @@ module Fluent
99
99
 
100
100
  def shutdown
101
101
  @_event_loop_mutex.synchronize do
102
- @_event_loop_attached_watchers.reverse.each do |w|
102
+ @_event_loop_attached_watchers.reverse_each do |w|
103
103
  if w.attached?
104
104
  begin
105
105
  w.detach
@@ -116,7 +116,7 @@ module Fluent
116
116
  def after_shutdown
117
117
  timeout_at = Fluent::Clock.now + EVENT_LOOP_SHUTDOWN_TIMEOUT
118
118
  @_event_loop_mutex.synchronize do
119
- @_event_loop.watchers.reverse.each do |w|
119
+ @_event_loop.watchers.reverse_each do |w|
120
120
  begin
121
121
  w.detach
122
122
  rescue => e
@@ -21,6 +21,7 @@ require 'async/http/endpoint'
21
21
  require 'fluent/plugin_helper/http_server/app'
22
22
  require 'fluent/plugin_helper/http_server/router'
23
23
  require 'fluent/plugin_helper/http_server/methods'
24
+ require 'fluent/log/console_adapter'
24
25
 
25
26
  module Fluent
26
27
  module PluginHelper
@@ -38,7 +39,7 @@ module Fluent
38
39
  scheme = tls_context ? 'https' : 'http'
39
40
  @uri = URI("#{scheme}://#{@addr}:#{@port}").to_s
40
41
  @router = Router.new(default_app)
41
- @reactor = Async::Reactor.new(nil, logger: @logger)
42
+ @reactor = Async::Reactor.new(nil, logger: Fluent::Log::ConsoleAdapter.wrap(@logger))
42
43
 
43
44
  opts = if tls_context
44
45
  { ssl_context: tls_context }
@@ -0,0 +1,129 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'forwardable'
18
+
19
+ require 'fluent/plugin'
20
+ require 'fluent/plugin/metrics'
21
+ require 'fluent/plugin_helper/timer'
22
+ require 'fluent/config/element'
23
+ require 'fluent/configurable'
24
+ require 'fluent/system_config'
25
+
26
+ module Fluent
27
+ module PluginHelper
28
+ module Metrics
29
+ include Fluent::SystemConfig::Mixin
30
+
31
+ attr_reader :_metrics # For tests.
32
+
33
+ def initialize
34
+ super
35
+ @_metrics_started = false
36
+ @_metrics = {} # usage => metrics_state
37
+ end
38
+
39
+ def configure(conf)
40
+ super
41
+
42
+ @plugin_type_or_id = if self.plugin_id_configured?
43
+ self.plugin_id
44
+ else
45
+ if type = (conf["@type"] || conf["type"])
46
+ "#{type}.#{self.plugin_id}"
47
+ else
48
+ "#{self.class.to_s.split("::").last.downcase}.#{self.plugin_id}"
49
+ end
50
+ end
51
+ end
52
+
53
+ def metrics_create(namespace: "fluentd", subsystem: "metrics", name:, help_text:, labels: {}, prefer_gauge: false)
54
+ metrics = if system_config.metrics
55
+ Fluent::Plugin.new_metrics(system_config.metrics[:@type], parent: self)
56
+ else
57
+ Fluent::Plugin.new_metrics(Fluent::Plugin::Metrics::DEFAULT_TYPE, parent: self)
58
+ end
59
+ config = if system_config.metrics
60
+ system_config.metrics.corresponding_config_element
61
+ else
62
+ Fluent::Config::Element.new('metrics', '', {'@type' => Fluent::Plugin::Metrics::DEFAULT_TYPE}, [])
63
+ end
64
+ metrics.use_gauge_metric = prefer_gauge
65
+ metrics.configure(config)
66
+ # For multi workers environment, cmetrics should be distinguish with static labels.
67
+ if Fluent::Engine.system_config.workers > 1
68
+ labels.merge!(worker_id: fluentd_worker_id.to_s)
69
+ end
70
+ labels.merge!(plugin: @plugin_type_or_id)
71
+ metrics.create(namespace: namespace, subsystem: subsystem, name: name, help_text: help_text, labels: labels)
72
+
73
+ @_metrics["#{@plugin_type_or_id}_#{namespace}_#{subsystem}_#{name}"] = metrics
74
+
75
+ metrics
76
+ end
77
+
78
+ def metrics_operate(method_name, &block)
79
+ @_metrics.each_pair do |key, m|
80
+ begin
81
+ block.call(s) if block_given?
82
+ m.__send__(method_name)
83
+ rescue => e
84
+ log.error "unexpected error while #{method_name}", key: key, metrics: m, error: e
85
+ end
86
+ end
87
+ end
88
+
89
+ def start
90
+ super
91
+
92
+ metrics_operate(:start)
93
+ @_metrics_started = true
94
+ end
95
+
96
+ def stop
97
+ super
98
+ # timer stops automatically in super
99
+ metrics_operate(:stop)
100
+ end
101
+
102
+ def before_shutdown
103
+ metrics_operate(:before_shutdown)
104
+ super
105
+ end
106
+
107
+ def shutdown
108
+ metrics_operate(:shutdown)
109
+ super
110
+ end
111
+
112
+ def after_shutdown
113
+ metrics_operate(:after_shutdown)
114
+ super
115
+ end
116
+
117
+ def close
118
+ metrics_operate(:close)
119
+ super
120
+ end
121
+
122
+ def terminate
123
+ metrics_operate(:terminate)
124
+ @_metrics = {}
125
+ super
126
+ end
127
+ end
128
+ end
129
+ end
@@ -119,7 +119,7 @@ module Fluent
119
119
  def self.validate_dot_keys(keys)
120
120
  keys.each { |key|
121
121
  next unless key.is_a?(String)
122
- if /\s+/.match(key)
122
+ if /\s+/.match?(key)
123
123
  raise Fluent::ConfigError, "whitespace character is not allowed in dot notation. Use bracket notation: #{key}"
124
124
  end
125
125
  }
@@ -44,6 +44,8 @@ module Fluent
44
44
 
45
45
  @timeout = timeout
46
46
  @timeout_at = @start + timeout
47
+ @has_reached_timeout = false
48
+ @has_timed_out = false
47
49
  @current = :primary
48
50
 
49
51
  if randomize_width < 0 || randomize_width > 0.5
@@ -98,7 +100,7 @@ module Fluent
98
100
  naive
99
101
  end
100
102
  elsif @current == :secondary
101
- naive = naive_next_time(@steps - @secondary_transition_steps + 1)
103
+ naive = naive_next_time(@steps - @secondary_transition_steps)
102
104
  if naive >= @timeout_at
103
105
  @timeout_at
104
106
  else
@@ -123,7 +125,15 @@ module Fluent
123
125
  @current = :secondary
124
126
  @secondary_transition_steps = @steps
125
127
  end
128
+
126
129
  @next_time = calc_next_time
130
+
131
+ if @has_reached_timeout
132
+ @has_timed_out = @next_time >= @timeout_at
133
+ else
134
+ @has_reached_timeout = @next_time >= @timeout_at
135
+ end
136
+
127
137
  nil
128
138
  end
129
139
 
@@ -135,7 +145,7 @@ module Fluent
135
145
  if @forever
136
146
  false
137
147
  else
138
- @next_time >= @timeout_at || !!(@max_steps && @steps >= @max_steps)
148
+ @has_timed_out || !!(@max_steps && @steps >= @max_steps)
139
149
  end
140
150
  end
141
151
  end
@@ -165,7 +175,7 @@ module Fluent
165
175
  end
166
176
 
167
177
  def calc_interval(num)
168
- interval = raw_interval(num - 1)
178
+ interval = raw_interval(num)
169
179
  if @max_interval && interval > @max_interval
170
180
  @max_interval
171
181
  else
@@ -175,7 +185,7 @@ module Fluent
175
185
  # Calculate previous finite value to avoid inf related errors. If this re-computing is heavy, use cache.
176
186
  until interval.finite?
177
187
  num -= 1
178
- interval = raw_interval(num - 1)
188
+ interval = raw_interval(num)
179
189
  end
180
190
  interval
181
191
  end
@@ -80,8 +80,8 @@ module Fluent
80
80
  raise ArgumentError, "BUG: block not specified which handles connection" unless block_given?
81
81
  raise ArgumentError, "BUG: block must have just one argument" unless block.arity == 1
82
82
 
83
- if proto == :tcp || proto == :tls # default linger_timeout only for server
84
- socket_options[:linger_timeout] ||= 0
83
+ if proto == :tcp || proto == :tls
84
+ socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0
85
85
  end
86
86
 
87
87
  socket_option_validate!(proto, **socket_options)
@@ -132,8 +132,8 @@ module Fluent
132
132
  raise ArgumentError, "BUG: block not specified which handles received data" unless block_given?
133
133
  raise ArgumentError, "BUG: block must have 1 or 2 arguments" unless callback.arity == 1 || callback.arity == 2
134
134
 
135
- if proto == :tcp || proto == :tls # default linger_timeout only for server
136
- socket_options[:linger_timeout] ||= 0
135
+ if proto == :tcp || proto == :tls
136
+ socket_options[:linger_timeout] ||= @transport_config&.linger_timeout || 0
137
137
  end
138
138
 
139
139
  unless socket
@@ -263,6 +263,25 @@ module Fluent
263
263
  include Fluent::Configurable
264
264
  config_section :transport, required: false, multi: false, init: true, param_name: :transport_config do
265
265
  config_argument :protocol, :enum, list: [:tcp, :tls], default: :tcp
266
+
267
+ ### Socket Params ###
268
+
269
+ # SO_LINGER 0 to send RST rather than FIN to avoid lots of connections sitting in TIME_WAIT at src.
270
+ # Set positive value if needing to send FIN on closing on non-Windows.
271
+ # (On Windows, Fluentd can send FIN with zero `linger_timeout` since Fluentd doesn't set 0 to SO_LINGER on Windows.
272
+ # See `socket_option.rb`.)
273
+ # NOTE:
274
+ # Socket-options can be specified from each plugin as needed, so most of them is not defined here for now.
275
+ # This is because there is no positive reason to do so.
276
+ # `linger_timeout` option in particular needs to be defined here
277
+ # although it can be specified from each plugin as well.
278
+ # This is because this helper fixes the default value to `0` for its own reason
279
+ # and it has a critical effect on the behavior.
280
+ desc 'The timeout time used to set linger option.'
281
+ config_param :linger_timeout, :integer, default: 0
282
+
283
+ ### TLS Params ###
284
+
266
285
  config_param :version, :enum, list: Fluent::TLS::SUPPORTED_VERSIONS, default: Fluent::TLS::DEFAULT_VERSION
267
286
  config_param :min_version, :enum, list: Fluent::TLS::SUPPORTED_VERSIONS, default: nil
268
287
  config_param :max_version, :enum, list: Fluent::TLS::SUPPORTED_VERSIONS, default: nil
@@ -526,6 +545,10 @@ module Fluent
526
545
  data = @sock.recv(@max_bytes, @flags)
527
546
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR, Errno::ECONNRESET, IOError, Errno::EBADF
528
547
  return
548
+ rescue Errno::EMSGSIZE
549
+ # Windows ONLY: This happens when the data size is larger than `@max_bytes`.
550
+ @log.info "A received data was ignored since it was too large."
551
+ return
529
552
  end
530
553
  @callback.call(data)
531
554
  rescue => e
@@ -539,6 +562,10 @@ module Fluent
539
562
  data, addr = @sock.recvfrom(@max_bytes)
540
563
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR, Errno::ECONNRESET, IOError, Errno::EBADF
541
564
  return
565
+ rescue Errno::EMSGSIZE
566
+ # Windows ONLY: This happens when the data size is larger than `@max_bytes`.
567
+ @log.info "A received data was ignored since it was too large."
568
+ return
542
569
  end
543
570
  @callback.call(data, UDPCallbackSocket.new(@sock, addr, close_socket: @close_socket))
544
571
  rescue => e
@@ -709,13 +736,15 @@ module Fluent
709
736
  return true
710
737
  end
711
738
  rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
739
+ peeraddr = (@_handler_socket.peeraddr rescue PEERADDR_FAILED)
712
740
  @log.trace "unexpected error before accepting TLS connection",
713
- host: @_handler_socket.peeraddr[3], port: @_handler_socket.peeraddr[1], error: e
741
+ addr: peeraddr[3], host: peeraddr[2], port: peeraddr[1], error: e
714
742
  close rescue nil
715
743
  rescue OpenSSL::SSL::SSLError => e
744
+ peeraddr = (@_handler_socket.peeraddr rescue PEERADDR_FAILED)
716
745
  # Use same log level as on_readable
717
746
  @log.warn "unexpected error before accepting TLS connection by OpenSSL",
718
- host: @_handler_socket.peeraddr[3], port: @_handler_socket.peeraddr[1], error: e
747
+ addr: peeraddr[3], host: peeraddr[2], port: peeraddr[1], error: e
719
748
  close rescue nil
720
749
  end
721
750
 
@@ -44,7 +44,7 @@ module Fluent
44
44
 
45
45
  @discovery_manager.start
46
46
  unless @discovery_manager.static_config?
47
- timer_execute(@_plugin_helper_service_discovery_title, @_plugin_helper_service_discovery_iterval) do
47
+ timer_execute(@_plugin_helper_service_discovery_title, @_plugin_helper_service_discovery_interval) do
48
48
  @discovery_manager.run_once
49
49
  end
50
50
  end
@@ -96,7 +96,7 @@ module Fluent
96
96
  # @param custom_build_method [Proc]
97
97
  def service_discovery_create_manager(title, configurations:, load_balancer: nil, custom_build_method: nil, interval: 3)
98
98
  @_plugin_helper_service_discovery_title = title
99
- @_plugin_helper_service_discovery_iterval = interval
99
+ @_plugin_helper_service_discovery_interval = interval
100
100
 
101
101
  @discovery_manager = Fluent::PluginHelper::ServiceDiscovery::Manager.new(
102
102
  log: log,
@@ -96,6 +96,7 @@ module Fluent
96
96
  enable_system_cert_store: true, allow_self_signed_cert: false, cert_paths: nil,
97
97
  cert_path: nil, private_key_path: nil, private_key_passphrase: nil,
98
98
  cert_thumbprint: nil, cert_logical_store_name: nil, cert_use_enterprise_store: true,
99
+ connect_timeout: nil,
99
100
  **kwargs, &block)
100
101
 
101
102
  host_is_ipaddress = IPAddr.new(host) rescue false
@@ -158,13 +159,23 @@ module Fluent
158
159
  end
159
160
  Fluent::TLS.set_version_to_context(context, version, min_version, max_version)
160
161
 
161
- tcpsock = socket_create_tcp(host, port, **kwargs)
162
+ tcpsock = socket_create_tcp(host, port, connect_timeout: connect_timeout, **kwargs)
162
163
  sock = WrappedSocket::TLS.new(tcpsock, context)
163
164
  sock.sync_close = true
164
165
  sock.hostname = fqdn if verify_fqdn && fqdn && sock.respond_to?(:hostname=)
165
166
 
166
167
  log.trace "entering TLS handshake"
167
- sock.connect
168
+ if connect_timeout
169
+ begin
170
+ Timeout.timeout(connect_timeout) { sock.connect }
171
+ rescue Timeout::Error
172
+ log.warn "timeout while connecting tls session", host: host
173
+ sock.close rescue nil
174
+ raise
175
+ end
176
+ else
177
+ sock.connect
178
+ end
168
179
 
169
180
  begin
170
181
  if verify_fqdn
@@ -101,16 +101,16 @@ module Fluent
101
101
  end
102
102
 
103
103
  def thread_exist?(title)
104
- @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.size > 0
104
+ @_threads.values.count{|thread| title == thread[:_fluentd_plugin_helper_thread_title] } > 0
105
105
  end
106
106
 
107
107
  def thread_started?(title)
108
- t = @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.first
108
+ t = @_threads.values.find{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }
109
109
  t && t[:_fluentd_plugin_helper_thread_started]
110
110
  end
111
111
 
112
112
  def thread_running?(title)
113
- t = @_threads.values.select{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }.first
113
+ t = @_threads.values.find{|thread| title == thread[:_fluentd_plugin_helper_thread_title] }
114
114
  t && t[:_fluentd_plugin_helper_thread_running]
115
115
  end
116
116
 
@@ -32,6 +32,7 @@ require 'fluent/plugin_helper/retry_state'
32
32
  require 'fluent/plugin_helper/record_accessor'
33
33
  require 'fluent/plugin_helper/compat_parameters'
34
34
  require 'fluent/plugin_helper/service_discovery'
35
+ require 'fluent/plugin_helper/metrics'
35
36
 
36
37
  module Fluent
37
38
  module PluginHelper
@@ -15,6 +15,7 @@
15
15
  #
16
16
 
17
17
  require 'set'
18
+ require 'fluent/env'
18
19
  require 'fluent/variable_store'
19
20
 
20
21
  module Fluent
@@ -48,7 +49,7 @@ module Fluent
48
49
  # Thread::Backtrace::Location#path returns base filename or absolute path.
49
50
  # #absolute_path returns absolute_path always.
50
51
  # https://bugs.ruby-lang.org/issues/12159
51
- if location.absolute_path =~ /\/test_[^\/]+\.rb$/ # location.path =~ /test_.+\.rb$/
52
+ if /\/test_[^\/]+\.rb$/.match?(location.absolute_path) # location.path =~ /test_.+\.rb$/
52
53
  return true
53
54
  end
54
55
  end
@@ -76,7 +77,7 @@ module Fluent
76
77
 
77
78
  # Fluent::Plugin::Base#fluentd_worker_id
78
79
  dir = File.join(system_config.root_dir, "worker#{fluentd_worker_id}", plugin_id)
79
- FileUtils.mkdir_p(dir, mode: system_config.dir_permission || 0755) unless Dir.exist?(dir)
80
+ FileUtils.mkdir_p(dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(dir)
80
81
  @_plugin_root_dir = dir.freeze
81
82
  dir
82
83
  end
@@ -45,7 +45,8 @@ module Fluent
45
45
  if value = @map[type]
46
46
  return value
47
47
  end
48
- raise ConfigError, "Unknown #{@kind} plugin '#{type}'. Run 'gem search -rd fluent-plugin' to find plugins" # TODO error class
48
+ raise NotFoundPluginError.new("Unknown #{@kind} plugin '#{type}'. Run 'gem search -rd fluent-plugin' to find plugins",
49
+ kind: @kind, type: type)
49
50
  end
50
51
 
51
52
  def reverse_lookup(value)
@@ -55,9 +55,11 @@ module Fluent
55
55
  @suppress_emit_error_log_interval = 0
56
56
  @next_emit_error_log_time = nil
57
57
  @without_source = false
58
+ @enable_input_metrics = false
58
59
 
59
60
  suppress_interval(system_config.emit_error_log_interval) unless system_config.emit_error_log_interval.nil?
60
61
  @without_source = system_config.without_source unless system_config.without_source.nil?
62
+ @enable_input_metrics = !!system_config.enable_input_metrics
61
63
  end
62
64
 
63
65
  attr_reader :inputs
@@ -131,6 +133,7 @@ module Fluent
131
133
  end
132
134
  name = e.arg
133
135
  raise ConfigError, "Missing symbol argument on <label> directive" if name.empty?
136
+ raise ConfigError, "@ROOT for <label> is not permitted, reserved for getting root router" if name == '@ROOT'
134
137
 
135
138
  if name == ERROR_LABEL
136
139
  error_label_config = e
@@ -315,6 +318,9 @@ module Fluent
315
318
  # See also 'fluentd/plugin/input.rb'
316
319
  input.context_router = @event_router
317
320
  input.configure(conf)
321
+ if @enable_input_metrics
322
+ @event_router.add_metric_callbacks(input.plugin_id, Proc.new {|es| input.metric_callback(es) })
323
+ end
318
324
  @inputs << input
319
325
 
320
326
  input
data/lib/fluent/rpc.rb CHANGED
@@ -20,9 +20,10 @@ module Fluent
20
20
  module RPC
21
21
  class Server
22
22
  def initialize(endpoint, log)
23
- bind, port = endpoint.split(':')
24
- @bind = bind
25
- @port = port
23
+ m = endpoint.match(/^\[?(?<host>[0-9a-zA-Z:\-\.]+)\]?:(?<port>[0-9]+)$/)
24
+ raise Fluent::ConfigError, "Invalid rpc_endpoint: #{endpoint}" unless m
25
+ @bind = m[:host]
26
+ @port = m[:port]
26
27
  @log = log
27
28
 
28
29
  @server = WEBrick::HTTPServer.new(