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,411 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin_helper/storage'
3
+ require 'fluent/plugin/base'
4
+
5
+ class ExampleStorage < Fluent::Plugin::Storage
6
+ Fluent::Plugin.register_storage('example', self)
7
+
8
+ attr_reader :data, :saved, :load_times, :save_times
9
+
10
+ def initialize
11
+ super
12
+ @data = {}
13
+ @saved = {}
14
+ @load_times = 0
15
+ @save_times = 0
16
+ end
17
+ def load
18
+ @data ||= {}
19
+ @load_times += 1
20
+ end
21
+ def save
22
+ @saved = @data.dup
23
+ @save_times += 1
24
+ end
25
+ def get(key)
26
+ @data[key]
27
+ end
28
+ def fetch(key, defval)
29
+ @data.fetch(key, defval)
30
+ end
31
+ def put(key, value)
32
+ @data[key] = value
33
+ end
34
+ def delete(key)
35
+ @data.delete(key)
36
+ end
37
+ def update(key, &block)
38
+ @data[key] = block.call(@data[key])
39
+ end
40
+ def close
41
+ @data = {}
42
+ super
43
+ end
44
+ def terminate
45
+ @saved = {}
46
+ @load_times = @save_times = 0
47
+ super
48
+ end
49
+ end
50
+
51
+ class Example2Storage < ExampleStorage
52
+ Fluent::Plugin.register_storage('ex2', self)
53
+ config_param :dummy_path, :string, default: 'dummy'
54
+ end
55
+ class Example3Storage < ExampleStorage
56
+ Fluent::Plugin.register_storage('ex3', self)
57
+ def synchronized?
58
+ true
59
+ end
60
+ end
61
+ class Example4Storage < ExampleStorage
62
+ Fluent::Plugin.register_storage('ex4', self)
63
+ def persistent_always?
64
+ true
65
+ end
66
+ def synchronized?
67
+ true
68
+ end
69
+ end
70
+
71
+ class StorageHelperTest < Test::Unit::TestCase
72
+ class Dummy < Fluent::Plugin::TestBase
73
+ helpers :storage
74
+ end
75
+
76
+ setup do
77
+ @d = nil
78
+ end
79
+
80
+ teardown do
81
+ if @d
82
+ @d.stop unless @d.stopped?
83
+ @d.shutdown unless @d.shutdown?
84
+ @d.close unless @d.closed?
85
+ @d.terminate unless @d.terminated?
86
+ end
87
+ end
88
+
89
+ test 'can be initialized without any storages at first' do
90
+ d = Dummy.new
91
+ assert_equal 0, d._storages.size
92
+ end
93
+
94
+ test 'can be configured without storage sections' do
95
+ d = Dummy.new
96
+ assert_nothing_raised do
97
+ d.configure(config_element())
98
+ end
99
+ assert_equal 0, d._storages.size
100
+ end
101
+
102
+ test 'can be configured with a storage section' do
103
+ d = Dummy.new
104
+ conf = config_element('ROOT', '', {}, [
105
+ config_element('storage', '', {'@type' => 'example'})
106
+ ])
107
+ assert_nothing_raised do
108
+ d.configure(conf)
109
+ end
110
+ assert_equal 1, d._storages.size
111
+ assert{ d._storages.values.all?{ |s| !s.running } }
112
+ end
113
+
114
+ test 'can be configured with 2 or more storage sections with different usages with each other' do
115
+ d = Dummy.new
116
+ conf = config_element('ROOT', '', {}, [
117
+ config_element('storage', 'default', {'@type' => 'example'}),
118
+ config_element('storage', 'extra', {'@type' => 'ex2', 'dummy_path' => 'v'}),
119
+ ])
120
+ assert_nothing_raised do
121
+ d.configure(conf)
122
+ end
123
+ assert_equal 2, d._storages.size
124
+ assert{ d._storages.values.all?{ |s| !s.running } }
125
+ end
126
+
127
+ test 'cannot be configured with 2 storage sections with same usage' do
128
+ d = Dummy.new
129
+ conf = config_element('ROOT', '', {}, [
130
+ config_element('storage', 'default', {'@type' => 'example'}),
131
+ config_element('storage', 'extra', {'@type' => 'ex2', 'dummy_path' => 'v'}),
132
+ config_element('storage', 'extra', {'@type' => 'ex2', 'dummy_path' => 'v2'}),
133
+ ])
134
+ assert_raises Fluent::ConfigError do
135
+ d.configure(conf)
136
+ end
137
+ end
138
+
139
+ test 'creates a storage plugin instance which is already configured without usage' do
140
+ @d = d = Dummy.new
141
+ conf = config_element('ROOT', '', {}, [
142
+ config_element('storage', '', {'@type' => 'example'})
143
+ ])
144
+ d.configure(conf)
145
+ d.start
146
+
147
+ s = d.storage_create
148
+ assert{ s.implementation.is_a? ExampleStorage }
149
+ end
150
+
151
+ test 'creates a storage plugin instance which is already configured with usage' do
152
+ @d = d = Dummy.new
153
+ conf = config_element('ROOT', '', {}, [
154
+ config_element('storage', 'mydata', {'@type' => 'example'})
155
+ ])
156
+ d.configure(conf)
157
+ d.start
158
+
159
+ s = d.storage_create(usage: 'mydata')
160
+ assert{ s.implementation.is_a? ExampleStorage }
161
+ end
162
+
163
+ test 'creates a storage plugin without configurations' do
164
+ @d = d = Dummy.new
165
+ d.configure(config_element())
166
+ d.start
167
+
168
+ s = d.storage_create(usage: 'mydata', type: 'example', conf: config_element('storage', 'mydata'))
169
+ assert{ s.implementation.is_a? ExampleStorage }
170
+ end
171
+
172
+ test 'raises exception for storage creation without explicit type specification' do
173
+ @d = d = Dummy.new
174
+ d.configure(config_element())
175
+ d.start
176
+
177
+ assert_raises ArgumentError do
178
+ d.storage_create(usage: 'mydata', conf: config_element('storage', 'mydata', {'@type' => 'example'}))
179
+ end
180
+ end
181
+
182
+ test 'creates 2 or more storage plugin instances' do
183
+ @d = d = Dummy.new
184
+ conf = config_element('ROOT', '', {}, [
185
+ config_element('storage', 'mydata', {'@type' => 'example'}),
186
+ config_element('storage', 'secret', {'@type' => 'ex2', 'dummy_path' => 'yay!'}),
187
+ ])
188
+ d.configure(conf)
189
+ d.start
190
+
191
+ s1 = d.storage_create(usage: 'mydata')
192
+ s2 = d.storage_create(usage: 'secret')
193
+ assert{ s1.implementation.is_a? ExampleStorage }
194
+ assert{ s2.implementation.is_a? Example2Storage }
195
+ assert_equal 'yay!', s2.implementation.dummy_path
196
+ end
197
+
198
+ test 'creates wrapped instances for non-synchronized plugin in default' do # and check operations
199
+ @d = d = Dummy.new
200
+ conf = config_element('ROOT', '', {}, [
201
+ config_element('storage', 'mydata', {'@type' => 'example'})
202
+ ])
203
+ d.configure(conf)
204
+ d.start
205
+
206
+ s = d.storage_create(usage: 'mydata')
207
+ assert !s.implementation.synchronized?
208
+ assert{ s.is_a? Fluent::PluginHelper::Storage::SynchronizeWrapper }
209
+ assert s.synchronized?
210
+ assert s.autosave
211
+ assert s.save_at_shutdown
212
+
213
+ assert_nil s.get('key')
214
+ assert_equal 'value', s.put('key', 'value')
215
+ assert_equal 'value', s.fetch('key', 'v1')
216
+ assert_equal 'v2', s.update('key'){|v| v[0] + '2' }
217
+ assert_equal 'v2', s.get('key')
218
+ assert_equal 'v2', s.delete('key')
219
+ end
220
+
221
+ test 'creates wrapped instances for non-persistent plugins when configured as persistent' do # and check operations
222
+ @d = d = Dummy.new
223
+ conf = config_element('ROOT', '', {}, [
224
+ config_element('storage', 'mydata', {'@type' => 'example', 'persistent' => 'true'})
225
+ ])
226
+ d.configure(conf)
227
+ d.start
228
+
229
+ s = d.storage_create(usage: 'mydata')
230
+ assert !s.implementation.persistent_always?
231
+ assert{ s.is_a? Fluent::PluginHelper::Storage::PersistentWrapper }
232
+ assert s.persistent
233
+ assert s.persistent_always?
234
+ assert s.synchronized?
235
+ assert !s.autosave
236
+ assert s.save_at_shutdown
237
+
238
+ assert_nil s.get('key')
239
+ assert_equal 'value', s.put('key', 'value')
240
+ assert_equal 'value', s.fetch('key', 'v1')
241
+ assert_equal 'v2', s.update('key'){|v| v[0] + '2' }
242
+ assert_equal 'v2', s.get('key')
243
+ assert_equal 'v2', s.delete('key')
244
+ end
245
+
246
+ test 'creates bare instances for synchronized plugin in default' do
247
+ @d = d = Dummy.new
248
+ conf = config_element('ROOT', '', {}, [
249
+ config_element('storage', 'mydata', {'@type' => 'ex3'})
250
+ ])
251
+ d.configure(conf)
252
+ d.start
253
+
254
+ s = d.storage_create(usage: 'mydata')
255
+ assert s.implementation.synchronized?
256
+ assert{ s.is_a? Example3Storage }
257
+ assert s.synchronized?
258
+ end
259
+
260
+ test 'creates bare instances for persistent-always plugin when configured as persistent' do
261
+ @d = d = Dummy.new
262
+ conf = config_element('ROOT', '', {}, [
263
+ config_element('storage', 'mydata', {'@type' => 'ex4', 'persistent' => 'true'})
264
+ ])
265
+ d.configure(conf)
266
+ d.start
267
+
268
+ s = d.storage_create(usage: 'mydata')
269
+ assert s.implementation.persistent_always?
270
+ assert{ s.is_a? Example4Storage }
271
+ assert s.persistent
272
+ assert s.persistent_always?
273
+ assert s.synchronized?
274
+ end
275
+
276
+ test 'does not execute timer if autosave is not specified' do
277
+ @d = d = Dummy.new
278
+ conf = config_element('ROOT', '', {}, [
279
+ config_element('storage', 'mydata', {'@type' => 'example', 'autosave' => 'false'})
280
+ ])
281
+ d.configure(conf)
282
+ d.start
283
+
284
+ d.storage_create(usage: 'mydata')
285
+ assert_equal 0, d._timers.size
286
+ end
287
+
288
+ test 'executes timer if autosave is specified and plugin is not persistent' do
289
+ @d = d = Dummy.new
290
+ conf = config_element('ROOT', '', {}, [
291
+ config_element('storage', 'mydata', {'@type' => 'example', 'autosave_interval' => '1s', 'persistent' => 'false'})
292
+ ])
293
+ d.configure(conf)
294
+ d.start
295
+
296
+ d.storage_create(usage: 'mydata')
297
+ assert_equal 1, d._timers.size
298
+ end
299
+
300
+ test 'executes timer for autosave, which calls #save periodically' do
301
+ @d = d = Dummy.new
302
+ conf = config_element('ROOT', '', {}, [
303
+ config_element('storage', 'mydata', {'@type' => 'example', 'autosave_interval' => '1s', 'persistent' => 'false'})
304
+ ])
305
+ d.configure(conf)
306
+ d.start
307
+
308
+ s = d.storage_create(usage: 'mydata')
309
+ assert_equal 1, d._timers.size
310
+ timeout = Time.now + 3
311
+ while Time.now < timeout
312
+ s.put('k', 'v')
313
+ sleep 0.2
314
+ end
315
+
316
+ d.stop
317
+ assert{ s.implementation.save_times > 0 }
318
+ end
319
+
320
+ test 'saves data for each operations if plugin storage is configured as persistent, and wrapped' do
321
+ @d = d = Dummy.new
322
+ conf = config_element('ROOT', '', {}, [
323
+ config_element('storage', 'mydata', {'@type' => 'example', 'persistent' => 'true'})
324
+ ])
325
+ d.configure(conf)
326
+ d.start
327
+ s = d.storage_create(usage: 'mydata')
328
+ assert_equal 1, s.implementation.load_times
329
+ assert_equal 0, s.implementation.save_times
330
+
331
+ s.get('k1')
332
+ assert_equal 2, s.implementation.load_times
333
+ assert_equal 0, s.implementation.save_times
334
+
335
+ s.put('k1', 'v1')
336
+ assert_equal 3, s.implementation.load_times
337
+ assert_equal 1, s.implementation.save_times
338
+
339
+ s.fetch('k2', 'v2')
340
+ assert_equal 4, s.implementation.load_times
341
+ assert_equal 1, s.implementation.save_times
342
+
343
+ s.delete('k1')
344
+ assert_equal 5, s.implementation.load_times
345
+ assert_equal 2, s.implementation.save_times
346
+ end
347
+
348
+ test 'stops timer for autosave by #stop, calls #save by #shutdown if save_at_shutdown is specified' do
349
+ @d = d = Dummy.new
350
+ conf = config_element('ROOT', '', {}, [
351
+ config_element('storage', 'mydata', {'@type' => 'example', 'save_at_shutdown' => 'true'})
352
+ ])
353
+ d.configure(conf)
354
+
355
+ assert !d.timer_running?
356
+
357
+ d.start
358
+
359
+ assert d.timer_running?
360
+
361
+ s = d.storage_create(usage: 'mydata')
362
+ assert s.autosave
363
+ assert_equal 1, d._timers.size
364
+
365
+ d.stop
366
+
367
+ assert !d.timer_running?
368
+
369
+ assert_equal 1, s.implementation.load_times
370
+ assert_equal 0, s.implementation.save_times
371
+
372
+ d.shutdown
373
+
374
+ assert_equal 1, s.implementation.load_times
375
+ assert_equal 1, s.implementation.save_times
376
+ end
377
+
378
+ test 'calls #close and #terminate for all plugin instances by #close/#shutdown' do
379
+ @d = d = Dummy.new
380
+ conf = config_element('ROOT', '', {}, [
381
+ config_element('storage', 'mydata', {'@type' => 'example', 'autosave' => 'false', 'save_at_shutdown' => 'true'})
382
+ ])
383
+ d.configure(conf)
384
+ d.start
385
+ s = d.storage_create(usage: 'mydata')
386
+
387
+ s.put('k1', 'v1')
388
+ s.put('k2', 2)
389
+ s.put('k3', true)
390
+
391
+ d.stop
392
+
393
+ assert_equal 3, s.implementation.data.size
394
+ assert_equal 0, s.implementation.saved.size
395
+
396
+ d.shutdown
397
+
398
+ assert_equal 3, s.implementation.data.size
399
+ assert_equal 3, s.implementation.saved.size
400
+
401
+ d.close
402
+
403
+ assert_equal 0, s.implementation.data.size
404
+ assert_equal 3, s.implementation.saved.size
405
+
406
+ d.shutdown
407
+
408
+ assert_equal 0, s.implementation.data.size
409
+ assert_equal 0, s.implementation.saved.size
410
+ end
411
+ end
@@ -0,0 +1,164 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin_helper/thread'
3
+ require 'fluent/plugin/base'
4
+ require 'timeout'
5
+
6
+ class ThreadTest < Test::Unit::TestCase
7
+ class Dummy < Fluent::Plugin::TestBase
8
+ helpers :thread
9
+ def configure(conf)
10
+ super
11
+ @_thread_wait_seconds = 0.1
12
+ self
13
+ end
14
+ end
15
+
16
+ test 'can be instantiated to be able to create threads' do
17
+ d1 = Dummy.new
18
+ assert d1.respond_to?(:thread_current_running?)
19
+ assert d1.respond_to?(:thread_create)
20
+ assert d1.respond_to?(:_threads)
21
+ assert !d1.thread_current_running?
22
+ assert d1._threads.empty?
23
+ end
24
+
25
+ test 'can be configured' do
26
+ d1 = Dummy.new
27
+ assert_nothing_raised do
28
+ d1.configure(config_element())
29
+ end
30
+ assert d1.plugin_id
31
+ assert d1.log
32
+ end
33
+
34
+ test 'can create thread after prepared' do
35
+ d1 = Dummy.new
36
+ d1.configure(config_element())
37
+ d1.start
38
+
39
+ m1 = Mutex.new
40
+ m2 = Mutex.new
41
+
42
+ m1.lock
43
+ thread_run = false
44
+
45
+ Timeout.timeout(10) do
46
+ t = d1.thread_create(:test1) do
47
+ m2.lock
48
+
49
+ assert !d1._threads.empty? # this must be true always
50
+ assert d1.thread_current_running?
51
+
52
+ thread_run = true
53
+ m2.unlock
54
+ m1.lock
55
+ end
56
+ Thread.pass until m2.locked? || thread_run
57
+
58
+ m2.lock; m2.unlock
59
+ assert_equal 1, d1._threads.size
60
+
61
+ assert_equal :test1, t[:_fluentd_plugin_helper_thread_title]
62
+ assert t[:_fluentd_plugin_helper_thread_running]
63
+ assert !d1._threads.empty?
64
+
65
+ m1.unlock
66
+
67
+ while t[:_fluentd_plugin_helper_thread_running]
68
+ Thread.pass
69
+ end
70
+ end
71
+
72
+ assert d1._threads.empty?
73
+
74
+ d1.stop; d1.shutdown; d1.close; d1.terminate
75
+ end
76
+
77
+ test 'can wait until all threads start' do
78
+ d1 = Dummy.new.configure(config_element()).start
79
+ ary = []
80
+ d1.thread_create(:t1) do
81
+ ary << 1
82
+ end
83
+ d1.thread_create(:t2) do
84
+ ary << 2
85
+ end
86
+ d1.thread_create(:t3) do
87
+ ary << 3
88
+ end
89
+ Timeout.timeout(10) do
90
+ d1.thread_wait_until_start
91
+ end
92
+ assert_equal [1,2,3], ary.sort
93
+
94
+ d1.stop; d1.shutdown; d1.close; d1.terminate
95
+ end
96
+
97
+ test 'can stop threads which is watching thread_current_running?, and then close it' do
98
+ d1 = Dummy.new.configure(config_element()).start
99
+
100
+ m1 = Mutex.new
101
+ thread_in_run = false
102
+ Timeout.timeout(10) do
103
+ t = d1.thread_create(:test2) do
104
+ thread_in_run = true
105
+ m1.lock
106
+ while d1.thread_current_running?
107
+ Thread.pass
108
+ end
109
+ thread_in_run = false
110
+ m1.unlock
111
+ end
112
+ Thread.pass until m1.locked?
113
+
114
+ assert thread_in_run
115
+ assert !d1._threads.empty?
116
+
117
+ d1.stop
118
+ Thread.pass while m1.locked?
119
+ assert !t[:_fluentd_plugin_helper_thread_running]
120
+ assert t.stop?
121
+ end
122
+
123
+ assert d1._threads.empty?
124
+
125
+ d1.stop; d1.shutdown; d1.close; d1.terminate
126
+ end
127
+
128
+ test 'can terminate threads forcedly which is running forever' do
129
+ d1 = Dummy.new.configure(config_element()).start
130
+
131
+ m1 = Mutex.new
132
+ thread_in_run = false
133
+ Timeout.timeout(10) do
134
+ t = d1.thread_create(:test2) do
135
+ thread_in_run = true
136
+ m1.lock
137
+ while true
138
+ Thread.pass
139
+ end
140
+ thread_in_run = false
141
+ end
142
+ Thread.pass until m1.locked?
143
+
144
+ assert thread_in_run
145
+ assert !d1._threads.empty?
146
+
147
+ d1.stop
148
+ assert !t[:_fluentd_plugin_helper_thread_running]
149
+ assert t.alive?
150
+
151
+ d1.shutdown
152
+ assert t.alive?
153
+ assert !d1._threads.empty?
154
+
155
+ d1.close
156
+ assert t.alive?
157
+ assert !d1._threads.empty?
158
+
159
+ d1.terminate
160
+ assert t.stop?
161
+ assert d1._threads.empty?
162
+ end
163
+ end
164
+ end