fluentd 0.12.43 → 0.14.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.

Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +6 -0
  3. data/.gitignore +2 -0
  4. data/.travis.yml +33 -21
  5. data/CONTRIBUTING.md +1 -0
  6. data/ChangeLog +1239 -0
  7. data/README.md +0 -25
  8. data/Rakefile +2 -1
  9. data/Vagrantfile +17 -0
  10. data/appveyor.yml +35 -0
  11. data/example/filter_stdout.conf +5 -5
  12. data/example/in_forward.conf +2 -2
  13. data/example/in_http.conf +2 -2
  14. data/example/in_out_forward.conf +17 -0
  15. data/example/in_syslog.conf +2 -2
  16. data/example/in_tail.conf +2 -2
  17. data/example/in_tcp.conf +2 -2
  18. data/example/in_udp.conf +2 -2
  19. data/example/out_copy.conf +4 -4
  20. data/example/out_file.conf +2 -2
  21. data/example/out_forward.conf +2 -2
  22. data/example/out_forward_buf_file.conf +23 -0
  23. data/example/v0_12_filter.conf +8 -8
  24. data/fluent.conf +29 -0
  25. data/fluentd.gemspec +18 -11
  26. data/lib/fluent/agent.rb +60 -58
  27. data/lib/fluent/command/cat.rb +1 -1
  28. data/lib/fluent/command/debug.rb +7 -5
  29. data/lib/fluent/command/fluentd.rb +97 -2
  30. data/lib/fluent/compat/call_super_mixin.rb +67 -0
  31. data/lib/fluent/compat/filter.rb +50 -0
  32. data/lib/fluent/compat/formatter.rb +109 -0
  33. data/lib/fluent/compat/input.rb +50 -0
  34. data/lib/fluent/compat/output.rb +617 -0
  35. data/lib/fluent/compat/output_chain.rb +60 -0
  36. data/lib/fluent/compat/parser.rb +163 -0
  37. data/lib/fluent/compat/propagate_default.rb +62 -0
  38. data/lib/fluent/config.rb +23 -20
  39. data/lib/fluent/config/configure_proxy.rb +119 -70
  40. data/lib/fluent/config/dsl.rb +5 -18
  41. data/lib/fluent/config/element.rb +72 -8
  42. data/lib/fluent/config/error.rb +0 -3
  43. data/lib/fluent/config/literal_parser.rb +0 -2
  44. data/lib/fluent/config/parser.rb +4 -4
  45. data/lib/fluent/config/section.rb +39 -28
  46. data/lib/fluent/config/types.rb +2 -13
  47. data/lib/fluent/config/v1_parser.rb +1 -3
  48. data/lib/fluent/configurable.rb +48 -16
  49. data/lib/fluent/daemon.rb +15 -0
  50. data/lib/fluent/engine.rb +26 -52
  51. data/lib/fluent/env.rb +6 -4
  52. data/lib/fluent/event.rb +58 -11
  53. data/lib/fluent/event_router.rb +5 -5
  54. data/lib/fluent/filter.rb +2 -50
  55. data/lib/fluent/formatter.rb +4 -293
  56. data/lib/fluent/input.rb +2 -32
  57. data/lib/fluent/label.rb +2 -2
  58. data/lib/fluent/load.rb +3 -2
  59. data/lib/fluent/log.rb +107 -38
  60. data/lib/fluent/match.rb +0 -36
  61. data/lib/fluent/mixin.rb +117 -7
  62. data/lib/fluent/msgpack_factory.rb +62 -0
  63. data/lib/fluent/output.rb +7 -612
  64. data/lib/fluent/output_chain.rb +23 -0
  65. data/lib/fluent/parser.rb +4 -800
  66. data/lib/fluent/plugin.rb +100 -121
  67. data/lib/fluent/plugin/bare_output.rb +63 -0
  68. data/lib/fluent/plugin/base.rb +121 -0
  69. data/lib/fluent/plugin/buf_file.rb +101 -182
  70. data/lib/fluent/plugin/buf_memory.rb +9 -92
  71. data/lib/fluent/plugin/buffer.rb +473 -0
  72. data/lib/fluent/plugin/buffer/chunk.rb +135 -0
  73. data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
  74. data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
  75. data/lib/fluent/plugin/exec_util.rb +80 -75
  76. data/lib/fluent/plugin/file_util.rb +33 -28
  77. data/lib/fluent/plugin/file_wrapper.rb +120 -0
  78. data/lib/fluent/plugin/filter.rb +51 -0
  79. data/lib/fluent/plugin/filter_grep.rb +13 -40
  80. data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
  81. data/lib/fluent/plugin/formatter.rb +93 -0
  82. data/lib/fluent/plugin/formatter_csv.rb +48 -0
  83. data/lib/fluent/plugin/formatter_hash.rb +32 -0
  84. data/lib/fluent/plugin/formatter_json.rb +47 -0
  85. data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
  86. data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
  87. data/lib/fluent/plugin/formatter_out_file.rb +45 -0
  88. data/lib/fluent/plugin/formatter_single_value.rb +34 -0
  89. data/lib/fluent/plugin/formatter_stdout.rb +39 -0
  90. data/lib/fluent/plugin/in_debug_agent.rb +4 -0
  91. data/lib/fluent/plugin/in_dummy.rb +22 -18
  92. data/lib/fluent/plugin/in_exec.rb +18 -8
  93. data/lib/fluent/plugin/in_forward.rb +36 -79
  94. data/lib/fluent/plugin/in_gc_stat.rb +4 -0
  95. data/lib/fluent/plugin/in_http.rb +21 -18
  96. data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
  97. data/lib/fluent/plugin/in_object_space.rb +6 -1
  98. data/lib/fluent/plugin/in_stream.rb +7 -3
  99. data/lib/fluent/plugin/in_syslog.rb +46 -95
  100. data/lib/fluent/plugin/in_tail.rb +58 -640
  101. data/lib/fluent/plugin/in_tcp.rb +8 -1
  102. data/lib/fluent/plugin/in_udp.rb +8 -18
  103. data/lib/fluent/plugin/input.rb +33 -0
  104. data/lib/fluent/plugin/multi_output.rb +95 -0
  105. data/lib/fluent/plugin/out_buffered_null.rb +59 -0
  106. data/lib/fluent/plugin/out_copy.rb +11 -7
  107. data/lib/fluent/plugin/out_exec.rb +15 -11
  108. data/lib/fluent/plugin/out_exec_filter.rb +18 -10
  109. data/lib/fluent/plugin/out_file.rb +34 -5
  110. data/lib/fluent/plugin/out_forward.rb +25 -19
  111. data/lib/fluent/plugin/out_null.rb +0 -14
  112. data/lib/fluent/plugin/out_roundrobin.rb +11 -7
  113. data/lib/fluent/plugin/out_stdout.rb +5 -7
  114. data/lib/fluent/plugin/out_stream.rb +3 -1
  115. data/lib/fluent/plugin/output.rb +979 -0
  116. data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
  117. data/lib/fluent/plugin/parser.rb +244 -0
  118. data/lib/fluent/plugin/parser_apache.rb +24 -0
  119. data/lib/fluent/plugin/parser_apache2.rb +84 -0
  120. data/lib/fluent/plugin/parser_apache_error.rb +21 -0
  121. data/lib/fluent/plugin/parser_csv.rb +31 -0
  122. data/lib/fluent/plugin/parser_json.rb +79 -0
  123. data/lib/fluent/plugin/parser_ltsv.rb +50 -0
  124. data/lib/fluent/plugin/parser_multiline.rb +102 -0
  125. data/lib/fluent/plugin/parser_nginx.rb +24 -0
  126. data/lib/fluent/plugin/parser_none.rb +36 -0
  127. data/lib/fluent/plugin/parser_syslog.rb +82 -0
  128. data/lib/fluent/plugin/parser_tsv.rb +37 -0
  129. data/lib/fluent/plugin/socket_util.rb +119 -117
  130. data/lib/fluent/plugin/storage.rb +84 -0
  131. data/lib/fluent/plugin/storage_local.rb +116 -0
  132. data/lib/fluent/plugin/string_util.rb +16 -13
  133. data/lib/fluent/plugin_helper.rb +39 -0
  134. data/lib/fluent/plugin_helper/child_process.rb +298 -0
  135. data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
  136. data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
  137. data/lib/fluent/plugin_helper/event_loop.rb +118 -0
  138. data/lib/fluent/plugin_helper/retry_state.rb +177 -0
  139. data/lib/fluent/plugin_helper/storage.rb +308 -0
  140. data/lib/fluent/plugin_helper/thread.rb +147 -0
  141. data/lib/fluent/plugin_helper/timer.rb +85 -0
  142. data/lib/fluent/plugin_id.rb +63 -0
  143. data/lib/fluent/process.rb +21 -30
  144. data/lib/fluent/registry.rb +21 -9
  145. data/lib/fluent/root_agent.rb +115 -40
  146. data/lib/fluent/supervisor.rb +330 -320
  147. data/lib/fluent/system_config.rb +42 -18
  148. data/lib/fluent/test.rb +6 -1
  149. data/lib/fluent/test/base.rb +23 -3
  150. data/lib/fluent/test/driver/base.rb +247 -0
  151. data/lib/fluent/test/driver/event_feeder.rb +98 -0
  152. data/lib/fluent/test/driver/filter.rb +35 -0
  153. data/lib/fluent/test/driver/input.rb +31 -0
  154. data/lib/fluent/test/driver/output.rb +78 -0
  155. data/lib/fluent/test/driver/test_event_router.rb +45 -0
  156. data/lib/fluent/test/filter_test.rb +0 -1
  157. data/lib/fluent/test/formatter_test.rb +2 -1
  158. data/lib/fluent/test/input_test.rb +23 -17
  159. data/lib/fluent/test/output_test.rb +28 -39
  160. data/lib/fluent/test/parser_test.rb +1 -1
  161. data/lib/fluent/time.rb +104 -1
  162. data/lib/fluent/{status.rb → unique_id.rb} +15 -24
  163. data/lib/fluent/version.rb +1 -1
  164. data/lib/fluent/winsvc.rb +72 -0
  165. data/test/compat/test_calls_super.rb +164 -0
  166. data/test/config/test_config_parser.rb +83 -0
  167. data/test/config/test_configurable.rb +547 -274
  168. data/test/config/test_configure_proxy.rb +146 -29
  169. data/test/config/test_dsl.rb +3 -181
  170. data/test/config/test_element.rb +274 -0
  171. data/test/config/test_literal_parser.rb +1 -1
  172. data/test/config/test_section.rb +79 -7
  173. data/test/config/test_system_config.rb +21 -0
  174. data/test/config/test_types.rb +3 -26
  175. data/test/helper.rb +78 -8
  176. data/test/plugin/test_bare_output.rb +118 -0
  177. data/test/plugin/test_base.rb +75 -0
  178. data/test/plugin/test_buf_file.rb +420 -521
  179. data/test/plugin/test_buf_memory.rb +32 -194
  180. data/test/plugin/test_buffer.rb +981 -0
  181. data/test/plugin/test_buffer_chunk.rb +110 -0
  182. data/test/plugin/test_buffer_file_chunk.rb +770 -0
  183. data/test/plugin/test_buffer_memory_chunk.rb +265 -0
  184. data/test/plugin/test_filter.rb +255 -0
  185. data/test/plugin/test_filter_grep.rb +2 -73
  186. data/test/plugin/test_filter_record_transformer.rb +24 -68
  187. data/test/plugin/test_filter_stdout.rb +6 -6
  188. data/test/plugin/test_in_debug_agent.rb +2 -0
  189. data/test/plugin/test_in_dummy.rb +11 -17
  190. data/test/plugin/test_in_exec.rb +6 -25
  191. data/test/plugin/test_in_forward.rb +112 -151
  192. data/test/plugin/test_in_gc_stat.rb +2 -0
  193. data/test/plugin/test_in_http.rb +106 -157
  194. data/test/plugin/test_in_object_space.rb +21 -5
  195. data/test/plugin/test_in_stream.rb +14 -13
  196. data/test/plugin/test_in_syslog.rb +30 -275
  197. data/test/plugin/test_in_tail.rb +95 -282
  198. data/test/plugin/test_in_tcp.rb +14 -0
  199. data/test/plugin/test_in_udp.rb +21 -67
  200. data/test/plugin/test_input.rb +122 -0
  201. data/test/plugin/test_multi_output.rb +180 -0
  202. data/test/plugin/test_out_buffered_null.rb +79 -0
  203. data/test/plugin/test_out_copy.rb +15 -2
  204. data/test/plugin/test_out_exec.rb +75 -25
  205. data/test/plugin/test_out_exec_filter.rb +74 -8
  206. data/test/plugin/test_out_file.rb +61 -7
  207. data/test/plugin/test_out_forward.rb +92 -15
  208. data/test/plugin/test_out_roundrobin.rb +1 -0
  209. data/test/plugin/test_out_stdout.rb +22 -13
  210. data/test/plugin/test_out_stream.rb +18 -0
  211. data/test/plugin/test_output.rb +515 -0
  212. data/test/plugin/test_output_as_buffered.rb +1540 -0
  213. data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
  214. data/test/plugin/test_output_as_buffered_retries.rb +808 -0
  215. data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
  216. data/test/plugin/test_output_as_standard.rb +362 -0
  217. data/test/plugin/test_owned_by.rb +35 -0
  218. data/test/plugin/test_storage.rb +167 -0
  219. data/test/plugin/test_storage_local.rb +8 -0
  220. data/test/plugin_helper/test_child_process.rb +599 -0
  221. data/test/plugin_helper/test_compat_parameters.rb +175 -0
  222. data/test/plugin_helper/test_event_emitter.rb +51 -0
  223. data/test/plugin_helper/test_event_loop.rb +52 -0
  224. data/test/plugin_helper/test_retry_state.rb +399 -0
  225. data/test/plugin_helper/test_storage.rb +411 -0
  226. data/test/plugin_helper/test_thread.rb +164 -0
  227. data/test/plugin_helper/test_timer.rb +100 -0
  228. data/test/scripts/exec_script.rb +0 -6
  229. data/test/scripts/fluent/plugin/out_test.rb +3 -0
  230. data/test/test_config.rb +13 -4
  231. data/test/test_event.rb +24 -13
  232. data/test/test_event_router.rb +8 -7
  233. data/test/test_event_time.rb +187 -0
  234. data/test/test_formatter.rb +13 -51
  235. data/test/test_input.rb +1 -1
  236. data/test/test_log.rb +239 -16
  237. data/test/test_mixin.rb +1 -1
  238. data/test/test_output.rb +53 -66
  239. data/test/test_parser.rb +105 -323
  240. data/test/test_plugin_helper.rb +81 -0
  241. data/test/test_root_agent.rb +4 -52
  242. data/test/test_supervisor.rb +272 -0
  243. data/test/test_unique_id.rb +47 -0
  244. metadata +181 -55
  245. data/CHANGELOG.md +0 -710
  246. data/lib/fluent/buffer.rb +0 -365
  247. data/lib/fluent/plugin/filter_parser.rb +0 -107
  248. data/lib/fluent/plugin/in_status.rb +0 -76
  249. data/lib/fluent/test/helpers.rb +0 -86
  250. data/test/plugin/data/log/foo/bar2 +0 -0
  251. data/test/plugin/test_filter_parser.rb +0 -744
  252. data/test/plugin/test_in_status.rb +0 -38
  253. data/test/test_buffer.rb +0 -624
@@ -0,0 +1,85 @@
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 'fluent/plugin_helper/event_loop'
18
+
19
+ module Fluent
20
+ module PluginHelper
21
+ module Timer
22
+ include Fluent::PluginHelper::EventLoop
23
+
24
+ # stop : turn checker into false (callbacks not called anymore)
25
+ # shutdown : [-]
26
+ # close : [-]
27
+ # terminate: [-]
28
+
29
+ attr_reader :_timers # for tests
30
+
31
+ # interval: integer/float, repeat: true/false
32
+ def timer_execute(title, interval, repeat: true, &block)
33
+ raise ArgumentError, "BUG: title must be a symbol" unless title.is_a? Symbol
34
+ raise ArgumentError, "BUG: block not specified for callback" unless block_given?
35
+ checker = ->(){ @_timer_running }
36
+ timer = TimerWatcher.new(title, interval, repeat, log, checker, &block)
37
+ @_timers << title
38
+ event_loop_attach(timer)
39
+ end
40
+
41
+ def timer_running?
42
+ defined?(@_timer_running) && @_timer_running
43
+ end
44
+
45
+ def initialize
46
+ super
47
+ @_timers = []
48
+ end
49
+
50
+ def start
51
+ super
52
+ @_timer_running = true
53
+ end
54
+
55
+ def stop
56
+ super
57
+ @_timer_running = false
58
+ end
59
+
60
+ def terminate
61
+ super
62
+ @_timers = []
63
+ end
64
+
65
+ class TimerWatcher < Coolio::TimerWatcher
66
+ def initialize(title, interval, repeat, log, checker, &callback)
67
+ @title = title
68
+ @callback = callback
69
+ @log = log
70
+ @checker = checker
71
+ super(interval, repeat)
72
+ end
73
+
74
+ def on_timer
75
+ @callback.call if @checker.call
76
+ rescue => e
77
+ @log.error "Unexpected error raised. Stopping the timer.", title: @title, error: e
78
+ @log.error_backtrace
79
+ self.detach
80
+ @log.error "Timer detached.", title: @title
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # Fluent
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 'set'
18
+
19
+ module Fluent
20
+ module PluginId
21
+ @@configured_ids = Set.new
22
+
23
+ def configure(conf)
24
+ @id = conf['@id']
25
+ @_id_configured = !!@id # plugin id is explicitly configured by users (or not)
26
+ if @id
27
+ @id = @id.to_s
28
+ if @@configured_ids.include?(@id) && !plugin_id_for_test?
29
+ raise Fluent::ConfigError, "Duplicated plugin id `#{@id}`. Check whole configuration and fix it."
30
+ end
31
+ @@configured_ids.add(@id)
32
+ end
33
+
34
+ super
35
+ end
36
+
37
+ def plugin_id_for_test?
38
+ caller_locations.each do |location|
39
+ # Thread::Backtrace::Location#path returns base filename or absolute path.
40
+ # #absolute_path returns absolute_path always.
41
+ # https://bugs.ruby-lang.org/issues/12159
42
+ if location.absolute_path =~ /\/test_[^\/]+\.rb$/ # location.path =~ /test_.+\.rb$/
43
+ return true
44
+ end
45
+ end
46
+ false
47
+ end
48
+
49
+ def plugin_id_configured?
50
+ if instance_variable_defined?("@_id_configured")
51
+ @_id_configured
52
+ end
53
+ end
54
+
55
+ def plugin_id
56
+ if instance_variable_defined?("@id")
57
+ @id || "object:#{object_id.to_s(16)}"
58
+ else
59
+ "object:#{object_id.to_s(16)}"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -40,23 +40,23 @@ module Fluent
40
40
  @parent_uri = DRb.uri
41
41
  end
42
42
 
43
- def fork(forward_interval, delegate_object)
43
+ def fork(delegate_object)
44
44
  ipr, ipw = IO.pipe # child Engine.emit_stream -> parent Engine.emit_stream
45
- opr, opw = IO.pipe # parent target.emit -> child target.emit
45
+ opr, opw = IO.pipe # parent target.emit_events -> child target.emit_events
46
46
 
47
47
  pid = Process.fork
48
48
  if pid
49
49
  # parent process
50
50
  ipw.close
51
51
  opr.close
52
- forward_thread = process_parent(ipr, opw, pid, forward_interval, delegate_object)
52
+ forward_thread = process_parent(ipr, opw, pid, delegate_object)
53
53
  return pid, forward_thread
54
54
  end
55
55
 
56
56
  # child process
57
57
  ipr.close
58
58
  opw.close
59
- forward_thread = process_child(ipw, opr, forward_interval, delegate_object)
59
+ forward_thread = process_child(ipw, opr, delegate_object)
60
60
  return nil, forward_thread
61
61
  end
62
62
 
@@ -77,14 +77,14 @@ module Fluent
77
77
  end
78
78
 
79
79
  private
80
- def process_child(ipw, opr, forward_interval, delegate_object)
80
+ def process_child(ipw, opr, delegate_object)
81
81
  DRb.start_service(create_drb_uri, delegate_object)
82
82
  child_uri = DRb.uri
83
83
 
84
84
  send_header(ipw, child_uri)
85
85
 
86
86
  # override target.emit_stream to write event stream to the pipe
87
- fwd = new_forwarder(ipw, forward_interval)
87
+ fwd = new_forwarder(ipw, 0.5) # TODO interval
88
88
  Engine.define_singleton_method(:emit_stream) do |tag,es|
89
89
  fwd.emit(tag, es)
90
90
  end
@@ -115,8 +115,8 @@ module Fluent
115
115
  ]
116
116
  end
117
117
 
118
- def process_parent(ipr, opw, pid, forward_interval, delegate_object)
119
- child_uri = read_header(ipr)
118
+ def process_parent(ipr, opw, pid, delegate_object)
119
+ # child_uri = read_header(ipr)
120
120
 
121
121
  # read event stream from the pipe and forward to Engine.emit_stream
122
122
  forward_thread = Thread.new(ipr, pid, &method(:input_forward_main))
@@ -127,7 +127,7 @@ module Fluent
127
127
 
128
128
  # return forwarder for DetachProcessMixin to
129
129
  # override target.emit and write event stream to the pipe
130
- fwd = new_forwarder(opw, forward_interval)
130
+ fwd = new_forwarder(opw, 0.5) # TODO interval
131
131
  # note: override emit method on DetachProcessMixin
132
132
  forward_thread.define_singleton_method(:forwarder) do
133
133
  fwd
@@ -153,7 +153,7 @@ module Fluent
153
153
  read_event_stream(opr) {|tag,es|
154
154
  # FIXME error handling
155
155
  begin
156
- target.emit(tag, es, NullOutputChain.instance)
156
+ target.emit_events(tag, es)
157
157
  rescue
158
158
  $log.warn "failed to emit", error: $!.to_s, pid: Process.pid
159
159
  $log.warn_backtrace
@@ -300,11 +300,11 @@ module Fluent
300
300
 
301
301
  private
302
302
 
303
- def detach_process_impl(num, forward_interval, &block)
303
+ def detach_process_impl(num, &block)
304
304
  children = []
305
305
 
306
306
  num.times do |i|
307
- pid, forward_thread = DetachProcessManager.instance.fork(forward_interval, self)
307
+ pid, forward_thread = DetachProcessManager.instance.fork(self)
308
308
 
309
309
  if pid
310
310
  # parent process
@@ -365,7 +365,7 @@ module Fluent
365
365
  }
366
366
  end
367
367
 
368
- # override target.emit and write event stream to the pipe
368
+ # override target.emit_events and write event stream to the pipe
369
369
  forwarders = children.map {|pair| pair[1].forwarder }
370
370
  if forwarders.length > 1
371
371
  # use roundrobin
@@ -373,9 +373,8 @@ module Fluent
373
373
  else
374
374
  fwd = forwarders[0]
375
375
  end
376
- define_singleton_method(:emit) do |tag,es,chain|
377
- chain.next
378
- fwd.emit(tag, es)
376
+ define_singleton_method(:emit_events) do |tag,es|
377
+ fwd.emit_events(tag, es)
379
378
  end
380
379
  end
381
380
 
@@ -418,6 +417,8 @@ module Fluent
418
417
  def configure(conf)
419
418
  super
420
419
 
420
+ @detach_process = nil
421
+
421
422
  if detach_process = conf['detach_process']
422
423
  b3v = Config.bool_value(detach_process)
423
424
  case b3v
@@ -438,17 +439,11 @@ module Fluent
438
439
  @detach_process = false
439
440
  end
440
441
  end
441
-
442
- if forward_interval = conf['detach_process_forward_interval']
443
- @forward_interval = Config.time_value(forward_interval)
444
- else
445
- @forward_interval = 0.5
446
- end
447
442
  end
448
443
 
449
444
  def detach_process(&block)
450
445
  if @detach_process
451
- detach_process_impl(1, @forward_interval, &block)
446
+ detach_process_impl(1, &block)
452
447
  else
453
448
  block.call
454
449
  end
@@ -467,6 +462,8 @@ module Fluent
467
462
  def configure(conf)
468
463
  super
469
464
 
465
+ @detach_process = nil
466
+
470
467
  if detach_process = conf['detach_process']
471
468
  b3v = Config.bool_value(detach_process)
472
469
  case b3v
@@ -486,19 +483,13 @@ module Fluent
486
483
  @detach_process = false
487
484
  end
488
485
  end
489
-
490
- if forward_interval = conf['detach_process_forward_interval']
491
- @forward_interval = Config.time_value(forward_interval)
492
- else
493
- @forward_interval = 0.5
494
- end
495
486
  end
496
487
 
497
488
  private
498
489
 
499
490
  def detach_multi_process(&block)
500
491
  if @detach_process
501
- detach_process_impl(@detach_process_num, @forward_interval, &block)
492
+ detach_process_impl(@detach_process_num, &block)
502
493
  else
503
494
  block.call
504
495
  end
@@ -18,13 +18,16 @@ require 'fluent/config/error'
18
18
 
19
19
  module Fluent
20
20
  class Registry
21
+ DEFAULT_PLUGIN_PATH = File.expand_path('plugin', __FILE__)
22
+
21
23
  def initialize(kind, search_prefix)
22
24
  @kind = kind
23
25
  @search_prefix = search_prefix
24
26
  @map = {}
27
+ @paths = [DEFAULT_PLUGIN_PATH]
25
28
  end
26
29
 
27
- attr_reader :kind
30
+ attr_reader :kind, :paths
28
31
 
29
32
  def register(type, value)
30
33
  type = type.to_sym
@@ -43,18 +46,27 @@ module Fluent
43
46
  raise ConfigError, "Unknown #{@kind} plugin '#{type}'. Run 'gem search -rd fluent-plugin' to find plugins" # TODO error class
44
47
  end
45
48
 
49
+ def reverse_lookup(value)
50
+ @map.each do |k, v|
51
+ return k if v == value
52
+ end
53
+ nil
54
+ end
55
+
46
56
  def search(type)
47
57
  path = "#{@search_prefix}#{type}"
48
58
 
49
59
  # prefer LOAD_PATH than gems
50
- files = $LOAD_PATH.map { |lp|
51
- lpath = File.expand_path(File.join(lp, "#{path}.rb"))
52
- File.exist?(lpath) ? lpath : nil
53
- }.compact
54
- unless files.empty?
55
- # prefer newer version
56
- require files.sort.last
57
- return
60
+ [@paths, $LOAD_PATH].each do |paths|
61
+ files = paths.map { |lp|
62
+ lpath = File.expand_path(File.join(lp, "#{path}.rb"))
63
+ File.exist?(lpath) ? lpath : nil
64
+ }.compact
65
+ unless files.empty?
66
+ # prefer newer version
67
+ require files.sort.last
68
+ return
69
+ end
58
70
  end
59
71
 
60
72
  specs = Gem::Specification.find_all { |spec|
@@ -18,10 +18,10 @@ require 'delegate'
18
18
 
19
19
  require 'fluent/config/error'
20
20
  require 'fluent/agent'
21
- require 'fluent/engine'
22
21
  require 'fluent/label'
23
22
  require 'fluent/plugin'
24
23
  require 'fluent/system_config'
24
+ require 'fluent/time'
25
25
 
26
26
  module Fluent
27
27
  #
@@ -47,14 +47,14 @@ module Fluent
47
47
  class RootAgent < Agent
48
48
  ERROR_LABEL = "@ERROR".freeze # @ERROR is built-in error label
49
49
 
50
- def initialize(system_config = SystemConfig.new)
51
- super
50
+ def initialize(log:, system_config: SystemConfig.new)
51
+ super(log: log)
52
52
 
53
53
  @labels = {}
54
54
  @inputs = []
55
- @started_inputs = []
56
55
  @suppress_emit_error_log_interval = 0
57
56
  @next_emit_error_log_time = nil
57
+ @without_source = false
58
58
 
59
59
  suppress_interval(system_config.emit_error_log_interval) unless system_config.emit_error_log_interval.nil?
60
60
  @without_source = system_config.without_source unless system_config.without_source.nil?
@@ -68,7 +68,7 @@ module Fluent
68
68
 
69
69
  # initialize <label> elements before configuring all plugins to avoid 'label not found' in input, filter and output.
70
70
  label_configs = {}
71
- conf.elements.select { |e| e.name == 'label' }.each { |e|
71
+ conf.elements(name: 'label').each { |e|
72
72
  name = e.arg
73
73
  raise ConfigError, "Missing symbol argument on <label> directive" if name.empty?
74
74
 
@@ -89,9 +89,9 @@ module Fluent
89
89
  if @without_source
90
90
  log.info "'--without-source' is applied. Ignore <source> sections"
91
91
  else
92
- conf.elements.select { |e| e.name == 'source' }.each { |e|
93
- type = e['@type'] || e['type']
94
- raise ConfigError, "Missing '@type' parameter on <source> directive" unless type
92
+ conf.elements(name: 'source').each { |e|
93
+ type = e['@type']
94
+ raise ConfigError, "Missing 'type' parameter on <source> directive" unless type
95
95
  add_source(type, e)
96
96
  }
97
97
  end
@@ -104,43 +104,118 @@ module Fluent
104
104
  @error_collector = error_label.event_router
105
105
  end
106
106
 
107
- def start
108
- super
107
+ def lifecycle(desc: false, kind_callback: nil)
108
+ kind_or_label_list = if desc
109
+ [:output, :filter, @labels.values.reverse, :output_with_router, :input].flatten
110
+ else
111
+ [:input, :output_with_router, @labels.values, :filter, :output].flatten
112
+ end
113
+ kind_or_label_list.each do |kind|
114
+ if kind.respond_to?(:lifecycle)
115
+ label = kind
116
+ label.lifecycle(desc: desc) do |plugin, display_kind|
117
+ yield plugin, display_kind
118
+ end
119
+ else
120
+ list = if desc
121
+ lifecycle_control_list[kind].reverse
122
+ else
123
+ lifecycle_control_list[kind]
124
+ end
125
+ display_kind = (kind == :output_with_router ? :output : kind)
126
+ list.each do |instance|
127
+ yield instance, display_kind
128
+ end
129
+ end
130
+ if kind_callback
131
+ kind_callback.call
132
+ end
133
+ end
134
+ end
109
135
 
110
- @labels.each { |n, l|
111
- l.start
112
- }
136
+ def start
137
+ lifecycle(desc: true) do |i| # instance
138
+ i.start unless i.started?
139
+ end
140
+ end
113
141
 
114
- @inputs.each { |i|
115
- i.start
116
- @started_inputs << i
117
- }
142
+ def flush!
143
+ log.info "flushing all buffer forcedly"
144
+ flushing_threads = []
145
+ lifecycle(desc: true) do |instance|
146
+ if instance.respond_to?(:force_flush)
147
+ t = Thread.new do
148
+ Thread.current.abort_on_exception = true
149
+ begin
150
+ instance.force_flush
151
+ rescue => e
152
+ log.warn "unexpected error while flushing buffer", plugin: instance.class, plugin_id: instance.plugin_id, error: e
153
+ log.warn_backtrace
154
+ end
155
+ end
156
+ flushing_threads << t
157
+ end
158
+ end
159
+ flushing_threads.each{|t| t.join }
118
160
  end
119
161
 
120
- def shutdown
121
- # Shutdown Input plugin first to prevent emitting to terminated Output plugin
122
- @started_inputs.map { |i|
123
- Thread.new do
162
+ def shutdown # Fluentd's shutdown sequence is stop, before_shutdown, shutdown, after_shutdown, close, terminate for plugins
163
+ # Thesee method callers does `rescue Exception` to call methods of shutdown sequence as far as possible
164
+ # if plugin methods does something like infinite recursive call, `exit`, unregistering signal handlers or others.
165
+ # Plugins should be separated and be in sandbox to protect data in each plugins/buffers.
166
+
167
+ lifecycle_safe_sequence = ->(method, checker) {
168
+ lifecycle do |instance, kind|
124
169
  begin
125
- log.info "shutting down input", type: Plugin.lookup_name_from_class(i.class), plugin_id: i.plugin_id
126
- i.shutdown
127
- rescue => e
128
- log.warn "unexpected error while shutting down input plugin", plugin: i.class, plugin_id: i.plugin_id, error_class: e.class, error: e
170
+ log.debug "calling #{method} on #{kind} plugin", type: Plugin.lookup_type_from_class(instance.class), plugin_id: instance.plugin_id
171
+ instance.send(method) unless instance.send(checker)
172
+ rescue Exception => e
173
+ log.warn "unexpected error while calling #{method} on #{kind} plugin", pluguin: instance.class, plugin_id: instance.plugin_id, error: e
129
174
  log.warn_backtrace
130
175
  end
131
176
  end
132
- }.each { |t| t.join }
177
+ }
133
178
 
134
- @labels.each { |n, l|
135
- l.shutdown
179
+ lifecycle_unsafe_sequence = ->(method, checker) {
180
+ operation = case method
181
+ when :before_shutdown then "preparing shutdown"
182
+ when :shutdown then "shutting down"
183
+ when :close then "closing"
184
+ else
185
+ raise "BUG: unknown method name '#{method}'"
186
+ end
187
+ operation_threads = []
188
+ callback = ->(){
189
+ operation_threads.each{|t| t.join }
190
+ operation_threads.clear
191
+ }
192
+ lifecycle(kind_callback: callback) do |instance, kind|
193
+ t = Thread.new do
194
+ Thread.current.abort_on_exception = true
195
+ begin
196
+ log.info "#{operation} #{kind} plugin", type: Plugin.lookup_type_from_class(instance.class), plugin_id: instance.plugin_id
197
+ instance.send(method) unless instance.send(checker)
198
+ rescue Exception => e
199
+ log.warn "unexpected error while #{operation} on #{kind} plugin", plugin: instance.class, plugin_id: instance.plugin_id, error: e
200
+ log.warn_backtrace
201
+ end
202
+ end
203
+ operation_threads << t
204
+ end
136
205
  }
137
206
 
138
- super
139
- end
207
+ lifecycle_safe_sequence.call(:stop, :stopped?)
140
208
 
141
- def flush!
142
- super
143
- @labels.each{ |name, label| label.flush! }
209
+ # before_shutdown does force_flush for output plugins: it should block, so it's unsafe operation
210
+ lifecycle_unsafe_sequence.call(:before_shutdown, :before_shutdown?)
211
+
212
+ lifecycle_unsafe_sequence.call(:shutdown, :shutdown?)
213
+
214
+ lifecycle_safe_sequence.call(:after_shutdown, :after_shutdown?)
215
+
216
+ lifecycle_unsafe_sequence.call(:close, :closed?)
217
+
218
+ lifecycle_safe_sequence.call(:terminate, :terminated?)
144
219
  end
145
220
 
146
221
  def suppress_interval(interval_time)
@@ -163,7 +238,7 @@ module Fluent
163
238
  end
164
239
 
165
240
  def add_label(name)
166
- label = Label.new(name)
241
+ label = Label.new(name, log: log)
167
242
  label.root_agent = self
168
243
  @labels[name] = label
169
244
  end
@@ -177,7 +252,7 @@ module Fluent
177
252
  end
178
253
 
179
254
  def emit_error_event(tag, time, record, error)
180
- error_info = {error_class: error.class, error: error.to_s, location: (error.backtrace ? error.backtrace.first : nil), tag: tag, time: time}
255
+ error_info = {error: error, tag: tag, time: time}
181
256
  if @error_collector
182
257
  # A record is not included in the logs because <@ERROR> handles it. This warn is for the notification
183
258
  log.warn "send an error event to @ERROR:", error_info
@@ -189,12 +264,12 @@ module Fluent
189
264
  end
190
265
 
191
266
  def handle_emits_error(tag, es, error)
192
- error_info = {error_class: error.class, error: error.to_s, location: (error.backtrace ? error.backtrace.first : nil), tag: tag}
267
+ error_info = {error: error, tag: tag}
193
268
  if @error_collector
194
269
  log.warn "send an error event stream to @ERROR:", error_info
195
270
  @error_collector.emit_stream(tag, es)
196
271
  else
197
- now = Engine.now
272
+ now = Time.now
198
273
  if @suppress_emit_error_log_interval.zero? || now > @next_emit_error_log_time
199
274
  log.warn "emit transaction failed:", error_info
200
275
  log.warn_backtrace
@@ -218,14 +293,14 @@ module Fluent
218
293
  end
219
294
 
220
295
  def emit_error_event(tag, time, record, error)
221
- error_info = {error_class: error.class, error: error.to_s, location: (error.backtrace ? error.backtrace.first : nil), tag: tag, time: time, record: record}
296
+ error_info = {error: error, tag: tag, time: time, record: record}
222
297
  log.warn "dump an error event in @ERROR:", error_info
223
298
  end
224
299
 
225
300
  def handle_emits_error(tag, es, e)
226
- now = Engine.now
301
+ now = EventTime.now
227
302
  if @suppress_emit_error_log_interval.zero? || now > @next_emit_error_log_time
228
- log.warn "emit transaction failed in @ERROR:", error_class: e.class, error: e, tag: tag
303
+ log.warn "emit transaction failed in @ERROR:", error: e, tag: tag
229
304
  log.warn_backtrace
230
305
  @next_emit_error_log_time = now + @suppress_emit_error_log_interval
231
306
  end