fluentd 0.12.40 → 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 (252) 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 +810 -237
  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 +51 -595
  101. data/lib/fluent/plugin/in_tcp.rb +8 -1
  102. data/lib/fluent/plugin/in_udp.rb +8 -14
  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 +19 -9
  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 +120 -114
  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 -234
  198. data/test/plugin/test_in_tcp.rb +14 -0
  199. data/test/plugin/test_in_udp.rb +21 -13
  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 +180 -54
  245. data/lib/fluent/buffer.rb +0 -365
  246. data/lib/fluent/plugin/filter_parser.rb +0 -107
  247. data/lib/fluent/plugin/in_status.rb +0 -76
  248. data/lib/fluent/test/helpers.rb +0 -86
  249. data/test/plugin/data/log/foo/bar2 +0 -0
  250. data/test/plugin/test_filter_parser.rb +0 -744
  251. data/test/plugin/test_in_status.rb +0 -38
  252. data/test/test_buffer.rb +0 -624
@@ -0,0 +1,62 @@
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 'msgpack'
18
+ require 'fluent/time'
19
+
20
+ module Fluent
21
+ module MessagePackFactory
22
+ @@engine_factory = nil
23
+
24
+ module Mixin
25
+ def msgpack_factory
26
+ MessagePackFactory.engine_factory
27
+ end
28
+
29
+ def msgpack_packer(*args)
30
+ msgpack_factory.packer(*args)
31
+ end
32
+
33
+ def msgpack_unpacker(*args)
34
+ msgpack_factory.unpacker(*args)
35
+ end
36
+ end
37
+
38
+ def self.engine_factory
39
+ @@engine_factory || factory
40
+ end
41
+
42
+ def self.factory
43
+ factory = MessagePack::Factory.new
44
+ factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
45
+ factory
46
+ end
47
+
48
+ def self.packer(*args)
49
+ factory.packer(*args)
50
+ end
51
+
52
+ def self.unpacker(*args)
53
+ factory.unpacker(*args)
54
+ end
55
+
56
+ def self.init
57
+ factory = MessagePack::Factory.new
58
+ factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
59
+ @@engine_factory = factory
60
+ end
61
+ end
62
+ end
@@ -14,618 +14,13 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'thread'
18
-
19
- require 'fluent/config'
20
- require 'fluent/configurable'
21
- require 'fluent/engine'
22
- require 'fluent/log'
23
- require 'fluent/plugin'
24
- require 'fluent/status'
25
- require 'fluent/timezone'
17
+ require 'fluent/compat/output'
18
+ require 'fluent/output_chain'
26
19
 
27
20
  module Fluent
28
- class OutputChain
29
- def initialize(array, tag, es, chain=NullOutputChain.instance)
30
- @array = array
31
- @tag = tag
32
- @es = es
33
- @offset = 0
34
- @chain = chain
35
- end
36
-
37
- def next
38
- if @array.length <= @offset
39
- return @chain.next
40
- end
41
- @offset += 1
42
- result = @array[@offset-1].emit(@tag, @es, self)
43
- result
44
- end
45
- end
46
-
47
- class CopyOutputChain < OutputChain
48
- def next
49
- if @array.length <= @offset
50
- return @chain.next
51
- end
52
- @offset += 1
53
- es = @array.length > @offset ? @es.dup : @es
54
- result = @array[@offset-1].emit(@tag, es, self)
55
- result
56
- end
57
- end
58
-
59
- class NullOutputChain
60
- require 'singleton'
61
- include Singleton
62
-
63
- def next
64
- end
65
- end
66
-
67
-
68
- class Output
69
- include Configurable
70
- include PluginId
71
- include PluginLoggerMixin
72
-
73
- attr_accessor :router
74
-
75
- def initialize
76
- super
77
- end
78
-
79
- def configure(conf)
80
- super
81
-
82
- if label_name = conf['@label']
83
- label = Engine.root_agent.find_label(label_name)
84
- @router = label.event_router
85
- elsif @router.nil?
86
- @router = Engine.root_agent.event_router
87
- end
88
- end
89
-
90
- def start
91
- end
92
-
93
- def shutdown
94
- end
95
-
96
- #def emit(tag, es, chain)
97
- #end
98
-
99
- def secondary_init(primary)
100
- if primary.class != self.class
101
- $log.warn "type of secondary output should be same as primary output", primary: primary.class.to_s, secondary: self.class.to_s
102
- end
103
- end
104
- end
105
-
106
- class OutputThread
107
- def initialize(output)
108
- @output = output
109
- @finish = false
110
- @next_time = Time.now.to_f + 1.0
111
- end
112
-
113
- def configure(conf)
114
- end
115
-
116
- def start
117
- @mutex = Mutex.new
118
- @cond = ConditionVariable.new
119
- @thread = Thread.new(&method(:run))
120
- end
121
-
122
- def shutdown
123
- @finish = true
124
- @mutex.synchronize {
125
- @cond.signal
126
- }
127
- Thread.pass
128
- @thread.join
129
- end
130
-
131
- def submit_flush
132
- @mutex.synchronize {
133
- @next_time = 0
134
- @cond.signal
135
- }
136
- Thread.pass
137
- end
138
-
139
- private
140
- def run
141
- @mutex.lock
142
- begin
143
- until @finish
144
- time = Time.now.to_f
145
-
146
- if @next_time <= time
147
- @mutex.unlock
148
- begin
149
- @next_time = @output.try_flush
150
- ensure
151
- @mutex.lock
152
- end
153
- next_wait = @next_time - Time.now.to_f
154
- else
155
- next_wait = @next_time - time
156
- end
157
-
158
- cond_wait(next_wait) if next_wait > 0
159
- end
160
- ensure
161
- @mutex.unlock
162
- end
163
- rescue
164
- $log.error "error on output thread", error: $!.to_s
165
- $log.error_backtrace
166
- raise
167
- ensure
168
- @mutex.synchronize {
169
- @output.before_shutdown
170
- }
171
- end
172
-
173
- def cond_wait(sec)
174
- @cond.wait(@mutex, sec)
175
- end
176
- end
177
-
178
-
179
- class BufferedOutput < Output
180
- def initialize
181
- super
182
- @next_flush_time = 0
183
- @last_retry_time = 0
184
- @next_retry_time = 0
185
- @num_errors = 0
186
- @num_errors_lock = Mutex.new
187
- @secondary_limit = 8
188
- @emit_count = 0
189
- end
190
-
191
- desc 'The buffer type (memory, file)'
192
- config_param :buffer_type, :string, default: 'memory'
193
- desc 'The interval between data flushes.'
194
- config_param :flush_interval, :time, default: 60
195
- config_param :try_flush_interval, :float, default: 1
196
- desc 'If true, the value of `retry_value` is ignored and there is no limit'
197
- config_param :disable_retry_limit, :bool, default: false
198
- desc 'The limit on the number of retries before buffered data is discarded'
199
- config_param :retry_limit, :integer, default: 17
200
- desc 'The initial intervals between write retries.'
201
- config_param :retry_wait, :time, default: 1.0
202
- desc 'The maximum intervals between write retries.'
203
- config_param :max_retry_wait, :time, default: nil
204
- desc 'The number of threads to flush the buffer.'
205
- config_param :num_threads, :integer, default: 1
206
- desc 'The threshold to show slow flush logs'
207
- config_param :slow_flush_log_threshold, :float, default: 20.0
208
- desc 'The interval between data flushes for queued chunk.'
209
- config_param :queued_chunk_flush_interval, :time, default: 1
210
-
211
- def configure(conf)
212
- super
213
-
214
- @retry_wait = @retry_wait.to_f # converted to Float for calc_retry_wait
215
- @buffer = Plugin.new_buffer(@buffer_type)
216
- @buffer.configure(conf)
217
-
218
- if @buffer.respond_to?(:enable_parallel)
219
- if @num_threads == 1
220
- @buffer.enable_parallel(false)
221
- else
222
- @buffer.enable_parallel(true)
223
- end
224
- end
225
-
226
- @writers = (1..@num_threads).map {
227
- writer = OutputThread.new(self)
228
- writer.configure(conf)
229
- writer
230
- }
231
-
232
- if sconf = conf.elements.select {|e| e.name == 'secondary' }.first
233
- type = sconf['@type'] || conf['@type'] || sconf['type'] || conf['type']
234
- @secondary = Plugin.new_output(type)
235
- @secondary.router = router
236
- @secondary.configure(sconf)
237
-
238
- if secondary_limit = conf['secondary_limit']
239
- @secondary_limit = secondary_limit.to_i
240
- if @secondary_limit < 0
241
- raise ConfigError, "invalid parameter 'secondary_limit #{secondary_limit}'"
242
- end
243
- end
244
-
245
- @secondary.secondary_init(self)
246
- end
247
-
248
- Status.register(self, "queue_size") { @buffer.queue_size }
249
- Status.register(self, "emit_count") { @emit_count }
250
- end
251
-
252
- def start
253
- @next_flush_time = Time.now.to_f + @flush_interval
254
- @buffer.start
255
- @secondary.start if @secondary
256
- @writers.each {|writer| writer.start }
257
- @writer_current_position = 0
258
- @writers_size = @writers.size
259
- end
260
-
261
- def shutdown
262
- @writers.each {|writer| writer.shutdown }
263
- @secondary.shutdown if @secondary
264
- @buffer.shutdown
265
- end
266
-
267
- def emit(tag, es, chain, key="")
268
- @emit_count += 1
269
- data = format_stream(tag, es)
270
- if @buffer.emit(key, data, chain)
271
- submit_flush
272
- end
273
- end
274
-
275
- def submit_flush
276
- # Without locks: it is rough but enough to select "next" writer selection
277
- @writer_current_position = (@writer_current_position + 1) % @writers_size
278
- @writers[@writer_current_position].submit_flush
279
- end
280
-
281
- def format_stream(tag, es)
282
- out = ''
283
- es.each {|time,record|
284
- out << format(tag, time, record)
285
- }
286
- out
287
- end
288
-
289
- #def format(tag, time, record)
290
- #end
291
-
292
- #def write(chunk)
293
- #end
294
-
295
- def enqueue_buffer(force = false)
296
- @buffer.keys.each {|key|
297
- @buffer.push(key)
298
- }
299
- end
300
-
301
- def try_flush
302
- time = Time.now.to_f
303
-
304
- empty = @buffer.queue_size == 0
305
- if empty && @next_flush_time < (now = Time.now.to_f)
306
- @buffer.synchronize do
307
- if @next_flush_time < now
308
- enqueue_buffer
309
- @next_flush_time = now + @flush_interval
310
- empty = @buffer.queue_size == 0
311
- end
312
- end
313
- end
314
- if empty
315
- return time + @try_flush_interval
316
- end
317
-
318
- begin
319
- retrying = !@num_errors.zero?
320
-
321
- if retrying
322
- @num_errors_lock.synchronize do
323
- if retrying = !@num_errors.zero? # re-check in synchronize
324
- if @next_retry_time >= time
325
- # allow retrying for only one thread
326
- return time + @try_flush_interval
327
- end
328
- # assume next retry failes and
329
- # clear them if when it succeeds
330
- @last_retry_time = time
331
- @num_errors += 1
332
- @next_retry_time += calc_retry_wait
333
- end
334
- end
335
- end
336
-
337
- chunk_write_start = Time.now
338
-
339
- if @secondary && !@disable_retry_limit && @num_errors > @retry_limit
340
- has_next = flush_secondary(@secondary)
341
- else
342
- has_next = @buffer.pop(self)
343
- end
344
-
345
- elapsed_time = Time.now - chunk_write_start
346
- if elapsed_time > @slow_flush_log_threshold
347
- $log.warn "buffer flush took longer time than slow_flush_log_threshold:",
348
- plugin_id: plugin_id, elapsed_time: elapsed_time, slow_flush_log_threshold: @slow_flush_log_threshold
349
- end
350
-
351
- # success
352
- if retrying
353
- @num_errors = 0
354
- # Note: don't notify to other threads to prevent
355
- # burst to recovered server
356
- $log.warn "retry succeeded.", plugin_id: plugin_id
357
- end
358
-
359
- if has_next
360
- return Time.now.to_f + @queued_chunk_flush_interval
361
- else
362
- return time + @try_flush_interval
363
- end
364
-
365
- rescue => e
366
- if retrying
367
- error_count = @num_errors
368
- else
369
- # first error
370
- error_count = 0
371
- @num_errors_lock.synchronize do
372
- if @num_errors.zero?
373
- @last_retry_time = time
374
- @num_errors += 1
375
- @next_retry_time = time + calc_retry_wait
376
- end
377
- end
378
- end
379
-
380
- if @disable_retry_limit || error_count < @retry_limit
381
- $log.warn "temporarily failed to flush the buffer.", next_retry: Time.at(@next_retry_time), error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
382
- $log.warn_backtrace e.backtrace
383
-
384
- elsif @secondary
385
- if error_count == @retry_limit
386
- $log.warn "failed to flush the buffer.", error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
387
- $log.warn "retry count exceededs limit. falling back to secondary output."
388
- $log.warn_backtrace e.backtrace
389
- retry # retry immediately
390
- elsif error_count <= @retry_limit + @secondary_limit
391
- $log.warn "failed to flush the buffer, next retry will be with secondary output.", next_retry: Time.at(@next_retry_time), error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
392
- $log.warn_backtrace e.backtrace
393
- else
394
- $log.warn "failed to flush the buffer.", error_class: e.class, error: e.to_s, plugin_id: plugin_id
395
- $log.warn "secondary retry count exceededs limit."
396
- $log.warn_backtrace e.backtrace
397
- write_abort
398
- @num_errors = 0
399
- end
400
-
401
- else
402
- $log.warn "failed to flush the buffer.", error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
403
- $log.warn "retry count exceededs limit."
404
- $log.warn_backtrace e.backtrace
405
- write_abort
406
- @num_errors = 0
407
- end
408
-
409
- return @next_retry_time
410
- end
411
- end
412
-
413
- def force_flush
414
- @num_errors_lock.synchronize do
415
- @next_retry_time = Time.now.to_f - 1
416
- end
417
- enqueue_buffer(true)
418
- submit_flush
419
- end
420
-
421
- def before_shutdown
422
- begin
423
- @buffer.before_shutdown(self)
424
- rescue
425
- $log.warn "before_shutdown failed", error: $!.to_s
426
- $log.warn_backtrace
427
- end
428
- end
429
-
430
- def calc_retry_wait
431
- # TODO retry pattern
432
- wait = if @disable_retry_limit || @num_errors <= @retry_limit
433
- @retry_wait * (2 ** (@num_errors - 1))
434
- else
435
- # secondary retry
436
- @retry_wait * (2 ** (@num_errors - 2 - @retry_limit))
437
- end
438
- retry_wait = wait.finite? ? wait + (rand * (wait / 4.0) - (wait / 8.0)) : wait
439
- @max_retry_wait ? [retry_wait, @max_retry_wait].min : retry_wait
440
- end
441
-
442
- def write_abort
443
- $log.error "throwing away old logs."
444
- begin
445
- @buffer.clear!
446
- rescue
447
- $log.error "unexpected error while aborting", error: $!.to_s
448
- $log.error_backtrace
449
- end
450
- end
451
-
452
- def flush_secondary(secondary)
453
- @buffer.pop(secondary)
454
- end
455
- end
456
-
457
-
458
- class ObjectBufferedOutput < BufferedOutput
459
- def initialize
460
- super
461
- end
462
-
463
- def emit(tag, es, chain)
464
- @emit_count += 1
465
- data = es.to_msgpack_stream
466
- key = tag
467
- if @buffer.emit(key, data, chain)
468
- submit_flush
469
- end
470
- end
471
-
472
- module BufferedEventStreamMixin
473
- include Enumerable
474
-
475
- def repeatable?
476
- true
477
- end
478
-
479
- def each(&block)
480
- msgpack_each(&block)
481
- end
482
-
483
- def to_msgpack_stream
484
- read
485
- end
486
- end
487
-
488
- def write(chunk)
489
- chunk.extend(BufferedEventStreamMixin)
490
- write_objects(chunk.key, chunk)
491
- end
492
- end
493
-
494
-
495
- class TimeSlicedOutput < BufferedOutput
496
- require 'fluent/timezone'
497
-
498
- def initialize
499
- super
500
- @localtime = true
501
- #@ignore_old = false # TODO
502
- end
503
-
504
- desc 'The time format used as part of the file name.'
505
- config_param :time_slice_format, :string, default: '%Y%m%d'
506
- desc 'The amount of time Fluentd will wait for old logs to arrive.'
507
- config_param :time_slice_wait, :time, default: 10*60
508
- desc 'Parse the time value in the specified timezone'
509
- config_param :timezone, :string, default: nil
510
- config_set_default :buffer_type, 'file' # overwrite default buffer_type
511
- config_set_default :buffer_chunk_limit, 256*1024*1024 # overwrite default buffer_chunk_limit
512
- config_set_default :flush_interval, nil
513
- config_set_default :slow_flush_log_threshold, 40.0
514
-
515
- attr_accessor :localtime
516
- attr_reader :time_slicer # for test
517
-
518
- def configure(conf)
519
- super
520
-
521
- if conf['utc']
522
- @localtime = false
523
- elsif conf['localtime']
524
- @localtime = true
525
- end
526
-
527
- if conf['timezone']
528
- @timezone = conf['timezone']
529
- Fluent::Timezone.validate!(@timezone)
530
- end
531
-
532
- if @timezone
533
- @time_slicer = Timezone.formatter(@timezone, @time_slice_format)
534
- elsif @localtime
535
- @time_slicer = Proc.new {|time|
536
- Time.at(time).strftime(@time_slice_format)
537
- }
538
- else
539
- @time_slicer = Proc.new {|time|
540
- Time.at(time).utc.strftime(@time_slice_format)
541
- }
542
- end
543
-
544
- @time_slice_cache_interval = time_slice_cache_interval
545
- @before_tc = nil
546
- @before_key = nil
547
-
548
- if @flush_interval
549
- if conf['time_slice_wait']
550
- $log.warn "time_slice_wait is ignored if flush_interval is specified: #{conf}"
551
- end
552
- @enqueue_buffer_proc = Proc.new do
553
- @buffer.keys.each {|key|
554
- @buffer.push(key)
555
- }
556
- end
557
-
558
- else
559
- @flush_interval = [60, @time_slice_cache_interval].min
560
- @enqueue_buffer_proc = Proc.new do
561
- nowslice = @time_slicer.call(Engine.now - @time_slice_wait)
562
- @buffer.keys.each {|key|
563
- if key < nowslice
564
- @buffer.push(key)
565
- end
566
- }
567
- end
568
- end
569
- end
570
-
571
- def emit(tag, es, chain)
572
- @emit_count += 1
573
- formatted_data = {}
574
- es.each {|time,record|
575
- begin
576
- tc = time / @time_slice_cache_interval
577
- if @before_tc == tc
578
- key = @before_key
579
- else
580
- @before_tc = tc
581
- key = @time_slicer.call(time)
582
- @before_key = key
583
- end
584
- rescue => e
585
- @router.emit_error_event(tag, Engine.now, {'time' => time, 'record' => record}, e)
586
- next
587
- end
588
-
589
- formatted_data[key] ||= ''
590
- formatted_data[key] << format(tag, time, record)
591
- }
592
- formatted_data.each { |key, data|
593
- if @buffer.emit(key, data, chain)
594
- submit_flush
595
- end
596
- }
597
- end
598
-
599
- def enqueue_buffer(force = false)
600
- if force
601
- @buffer.keys.each {|key|
602
- @buffer.push(key)
603
- }
604
- else
605
- @enqueue_buffer_proc.call
606
- end
607
- end
608
-
609
- #def format(tag, event)
610
- #end
611
-
612
- private
613
- def time_slice_cache_interval
614
- if @time_slicer.call(0) != @time_slicer.call(60-1)
615
- return 1
616
- elsif @time_slicer.call(0) != @time_slicer.call(60*60-1)
617
- return 30
618
- elsif @time_slicer.call(0) != @time_slicer.call(24*60*60-1)
619
- return 60*30
620
- else
621
- return 24*60*30
622
- end
623
- end
624
- end
625
-
626
-
627
- class MultiOutput < Output
628
- #def outputs
629
- #end
630
- end
21
+ Output = Fluent::Compat::Output
22
+ BufferedOutput = Fluent::Compat::BufferedOutput
23
+ ObjectBufferedOutput = Fluent::Compat::ObjectBufferedOutput
24
+ TimeSlicedOutput = Fluent::Compat::TimeSlicedOutput
25
+ MultiOutput = Fluent::Compat::MultiOutput
631
26
  end