fluentd 0.12.40 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,60 @@
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 'singleton'
18
+
19
+ module Fluent
20
+ module Compat
21
+ # TODO: remove when old plugin API are removed
22
+ class NullOutputChain
23
+ include Singleton
24
+
25
+ def next
26
+ end
27
+ end
28
+
29
+ class OutputChain
30
+ def initialize(array, tag, es, chain=NullOutputChain.instance)
31
+ @array = array
32
+ @tag = tag
33
+ @es = es
34
+ @offset = 0
35
+ @chain = chain
36
+ end
37
+
38
+ def next
39
+ if @array.length <= @offset
40
+ return @chain.next
41
+ end
42
+ @offset += 1
43
+ @array[@offset-1].emit_events(@tag, @es)
44
+ self.next
45
+ end
46
+ end
47
+
48
+ class CopyOutputChain < OutputChain
49
+ def next
50
+ if @array.length <= @offset
51
+ return @chain.next
52
+ end
53
+ @offset += 1
54
+ es = @array.length > @offset ? @es.dup : @es
55
+ @array[@offset-1].emit_events(@tag, es)
56
+ self.next
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,163 @@
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'
18
+ require 'fluent/plugin/parser'
19
+ require 'fluent/mixin'
20
+
21
+ require 'fluent/plugin/parser_json'
22
+ require 'fluent/plugin/parser_tsv'
23
+ require 'fluent/plugin/parser_ltsv'
24
+ require 'fluent/plugin/parser_csv'
25
+ require 'fluent/plugin/parser_none'
26
+ require 'fluent/plugin/parser_apache2'
27
+ require 'fluent/plugin/parser_syslog'
28
+ require 'fluent/plugin/parser_multiline'
29
+
30
+ module Fluent
31
+ module Compat
32
+ class Parser < Fluent::Plugin::Parser
33
+ # TODO: warn when deprecated
34
+ end
35
+
36
+ class TextParser
37
+ # Keep backward compatibility for existing plugins
38
+ ParserError = Fluent::Plugin::Parser::ParserError
39
+ # TODO: will be removed at v1
40
+ TypeConverter = Fluent::TypeConverter
41
+
42
+ def initialize
43
+ # TODO: warn when deprecated
44
+ @parser = nil
45
+ @estimate_current_event = nil
46
+ end
47
+
48
+ attr_reader :parser
49
+
50
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
51
+ # 'configure()' may raise errors for unexpected configurations
52
+ attr_accessor :estimate_current_event
53
+
54
+ def configure(conf, required=true)
55
+ format = conf['format']
56
+
57
+ @parser = TextParser.lookup(format)
58
+ if ! @estimate_current_event.nil? && @parser.respond_to?(:'estimate_current_event=')
59
+ @parser.estimate_current_event = @estimate_current_event
60
+ end
61
+
62
+ if @parser.respond_to?(:configure)
63
+ @parser.configure(conf)
64
+ end
65
+
66
+ return true
67
+ end
68
+
69
+ def parse(text, &block)
70
+ if block
71
+ @parser.parse(text, &block)
72
+ else
73
+ @parser.parse(text) { |time, record|
74
+ return time, record
75
+ }
76
+ end
77
+ end
78
+
79
+ def self.register_template(type, template, time_format=nil)
80
+ # TODO: warn when deprecated to use Plugin.register_parser directly
81
+ if template.is_a?(Class) || template.respond_to?(:call)
82
+ Fluent::Plugin.register_parser(type, template)
83
+ elsif template.is_a?(Regexp)
84
+ Fluent::Plugin.register_parser(type, Proc.new { RegexpParser.new(template, {'time_format' => time_format}) })
85
+ else
86
+ raise ArgumentError, "Template for parser must be a Class, callable object or regular expression object"
87
+ end
88
+ end
89
+
90
+ def self.lookup(format)
91
+ # TODO: warn when deprecated to use Plugin.new_parser or RegexpParser.new directly
92
+ if format.nil?
93
+ raise ConfigError, "'format' parameter is required"
94
+ end
95
+
96
+ if format[0] == ?/ && format[format.length-1] == ?/
97
+ # regexp
98
+ begin
99
+ regexp = Regexp.new(format[1..-2])
100
+ if regexp.named_captures.empty?
101
+ raise "No named captures"
102
+ end
103
+ rescue
104
+ raise ConfigError, "Invalid regexp '#{format[1..-2]}': #{$!}"
105
+ end
106
+
107
+ RegexpParser.new(regexp)
108
+ else
109
+ # built-in template
110
+ begin
111
+ Fluent::Plugin.new_parser(format)
112
+ rescue ConfigError # keep same error message
113
+ raise ConfigError, "Unknown format template '#{format}'"
114
+ end
115
+ end
116
+ end
117
+
118
+ class TimeParser < Fluent::Plugin::Parser::TimeParser
119
+ # TODO: warn when deprecated
120
+ end
121
+
122
+ class RegexpParser < Fluent::Plugin::RegexpParser
123
+ # TODO: warn when deprecated
124
+ end
125
+
126
+ class ValuesParser < Fluent::Plugin::ValuesParser
127
+ # TODO: warn when deprecated
128
+ end
129
+
130
+ class JSONParser < Fluent::Plugin::JSONParser
131
+ # TODO: warn when deprecated
132
+ end
133
+
134
+ class TSVParser < Fluent::Plugin::TSVParser
135
+ # TODO: warn when deprecated
136
+ end
137
+
138
+ class LabeledTSVParser < Fluent::Plugin::LabeledTSVParser
139
+ # TODO: warn when deprecated
140
+ end
141
+
142
+ class CSVParser < Fluent::Plugin::CSVParser
143
+ # TODO: warn when deprecated
144
+ end
145
+
146
+ class NoneParser < Fluent::Plugin::NoneParser
147
+ # TODO: warn when deprecated
148
+ end
149
+
150
+ class ApacheParser < Fluent::Plugin::Apache2Parser
151
+ # TODO: warn when deprecated
152
+ end
153
+
154
+ class SyslogParser < Fluent::Plugin::SyslogParser
155
+ # TODO: warn when deprecated
156
+ end
157
+
158
+ class MultilineParser < Fluent::Plugin::MultilineParser
159
+ # TODO: warn when deprecated
160
+ end
161
+ end
162
+ end
163
+ end
@@ -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 'fluent/configurable'
18
+
19
+ module Fluent
20
+ module Compat
21
+ module PropagateDefault
22
+ # This mixin is to prepend to 3rd party plugins of v0.12 APIs.
23
+ # 3rd party plugins may override default values of some parameters, like `buffer_type`.
24
+ # But default values of such parameters will NOT used, but defaults of <buffer>@type</buffer>
25
+ # will be used in fact. It should bring troubles.
26
+ # This mixin defines Class method .config_param and .config_set_default (which should be used by extend)
27
+ # to propagate changes of default values to subsections.
28
+ def self.included(mod)
29
+ mod.extend(ClassMethods)
30
+ end
31
+
32
+ module ClassMethods
33
+ CONFIGURABLE_CLASS_METHODS = Fluent::Configurable::ClassMethods
34
+
35
+ def config_param(name, type = nil, **kwargs, &block)
36
+ CONFIGURABLE_CLASS_METHODS.instance_method(:config_param).bind(self).call(name, type, **kwargs, &block)
37
+ pparams = propagate_default_params
38
+ if kwargs.has_key?(:default) && pparams[name.to_s]
39
+ newer = pparams[name.to_s].to_sym
40
+ overridden_default_value = kwargs[:default]
41
+
42
+ CONFIGURABLE_CLASS_METHODS.instance_method(:config_section).bind(self).call(:buffer) do
43
+ config_set_default newer, overridden_default_value
44
+ end
45
+ end
46
+ end
47
+
48
+ def config_set_default(name, defval)
49
+ CONFIGURABLE_CLASS_METHODS.instance_method(:config_set_default).bind(self).call(name, defval)
50
+ pparams = propagate_default_params
51
+ if pparams[name.to_s]
52
+ newer = pparams[name.to_s].to_sym
53
+
54
+ CONFIGURABLE_CLASS_METHODS.instance_method(:config_section).bind(self).call(:buffer) do
55
+ self.config_set_default newer, defval
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -20,18 +20,32 @@ require 'fluent/configurable'
20
20
 
21
21
  module Fluent
22
22
  module Config
23
- def self.parse(str, fname, basepath = Dir.pwd, v1_config = false)
24
- if fname =~ /\.rb$/
23
+ def self.parse(str, fname, basepath = Dir.pwd, v1_config = nil, syntax: :v1)
24
+ parser = if fname =~ /\.rb$/ || syntax == :ruby
25
+ :ruby
26
+ elsif v1_config.nil?
27
+ case syntax
28
+ when :v1 then :v1
29
+ when :v0 then :v0
30
+ else
31
+ raise ArgumentError, "Unknown Fluentd configuration syntax: '#{syntax}'"
32
+ end
33
+ elsif v1_config then :v1
34
+ else :v0
35
+ end
36
+ case parser
37
+ when :v1
38
+ require 'fluent/config/v1_parser'
39
+ V1Parser.parse(str, fname, basepath, Kernel.binding)
40
+ when :v0
41
+ # TODO: show deprecated message in v1
42
+ require 'fluent/config/parser'
43
+ Parser.parse(str, fname, basepath)
44
+ when :ruby
25
45
  require 'fluent/config/dsl'
26
46
  Config::DSL::Parser.parse(str, File.join(basepath, fname))
27
47
  else
28
- if v1_config
29
- require 'fluent/config/v1_parser'
30
- V1Parser.parse(str, fname, basepath, Kernel.binding)
31
- else
32
- require 'fluent/config/parser'
33
- Parser.parse(str, fname, basepath)
34
- end
48
+ raise "[BUG] unknown configuration parser specification:'#{parser}'"
35
49
  end
36
50
  end
37
51
 
@@ -39,15 +53,4 @@ module Fluent
39
53
  Element.new(name, '', {}, [])
40
54
  end
41
55
  end
42
-
43
- module PluginId
44
- def configure(conf)
45
- @id = conf['@id'] || conf['id']
46
- super
47
- end
48
-
49
- def plugin_id
50
- @id ? @id : "object:#{object_id.to_s(16)}"
51
- end
52
- end
53
56
  end
@@ -14,12 +14,11 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/configurable'
18
-
19
17
  module Fluent
20
18
  module Config
21
19
  class ConfigureProxy
22
- attr_accessor :name, :final, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :descriptions, :sections
20
+ attr_accessor :name, :final, :param_name, :init, :required, :multi, :alias, :configured_in_section
21
+ attr_accessor :argument, :params, :defaults, :descriptions, :sections
23
22
  # config_param :desc, :string, :default => '....'
24
23
  # config_set_default :buffer_type, :memory
25
24
  #
@@ -38,20 +37,38 @@ module Fluent
38
37
  # end
39
38
  # end
40
39
 
41
- def initialize(name, opts = {})
40
+ def initialize(name, param_name: nil, final: nil, init: nil, required: nil, multi: nil, alias: nil, type_lookup:)
42
41
  @name = name.to_sym
43
- @final = opts.fetch(:final, false)
42
+ @final = final
43
+
44
+ @param_name = param_name && param_name.to_sym
45
+ @init = init
46
+ @required = required
47
+ @multi = multi
48
+ @alias = binding.local_variable_get(:alias)
49
+ @type_lookup = type_lookup
50
+
51
+ raise "init and required are exclusive" if @init && @required
44
52
 
45
- @param_name = (opts[:param_name] || @name).to_sym
46
- @required = opts[:required]
47
- @multi = opts[:multi]
48
- @alias = opts[:alias]
53
+ # specify section name for viewpoint of owner(parent) plugin
54
+ # for buffer plugins: all params are in <buffer> section of owner
55
+ # others: <storage>, <format> (formatter/parser), ...
56
+ @configured_in_section = nil
49
57
 
50
58
  @argument = nil # nil: ignore argument
51
59
  @params = {}
52
60
  @defaults = {}
53
61
  @descriptions = {}
54
62
  @sections = {}
63
+ @current_description = nil
64
+ end
65
+
66
+ def variable_name
67
+ @param_name || @name
68
+ end
69
+
70
+ def init?
71
+ @init.nil? ? false : @init
55
72
  end
56
73
 
57
74
  def required?
@@ -63,21 +80,38 @@ module Fluent
63
80
  end
64
81
 
65
82
  def final?
66
- @final
83
+ !!@final
67
84
  end
68
85
 
69
86
  def merge(other) # self is base class, other is subclass
70
87
  return merge_for_finalized(other) if self.final?
71
88
 
72
- options = {
73
- param_name: other.param_name,
74
- required: (other.required.nil? ? self.required : other.required),
75
- multi: (other.multi.nil? ? self.multi : other.multi)
76
- }
77
- merged = self.class.new(other.name, options)
89
+ [:param_name, :required, :multi, :alias, :configured_in_section].each do |prohibited_name|
90
+ if overwrite?(other, prohibited_name)
91
+ raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: #{prohibited_name}"
92
+ end
93
+ end
94
+
95
+ options = {}
96
+ # param_name affects instance variable name, which is just "internal" of each plugins.
97
+ # so it must not be changed. base class's name (or param_name) is always used.
98
+ options[:param_name] = @param_name
99
+
100
+ # subclass cannot overwrite base class's definition
101
+ options[:init] = @init.nil? ? other.init : self.init
102
+ options[:required] = @required.nil? ? other.required : self.required
103
+ options[:multi] = @multi.nil? ? other.multi : self.multi
104
+ options[:alias] = @alias.nil? ? other.alias : self.alias
105
+ options[:final] = @final || other.final
106
+ options[:type_lookup] = @type_lookup
107
+
108
+ merged = self.class.new(@name, options)
109
+
110
+ # configured_in MUST be kept
111
+ merged.configured_in_section = self.configured_in_section
78
112
 
79
113
  merged.argument = other.argument || self.argument
80
- merged.params = self.params.merge(other.params)
114
+ merged.params = other.params.merge(self.params)
81
115
  merged.defaults = self.defaults.merge(other.defaults)
82
116
  merged.sections = {}
83
117
  (self.sections.keys + other.sections.keys).uniq.each do |section_key|
@@ -98,20 +132,36 @@ module Fluent
98
132
 
99
133
  def merge_for_finalized(other)
100
134
  # list what subclass can do for finalized section
101
- # * overwrite param_name to escape duplicated name of instance variable
102
135
  # * append params/defaults/sections which are missing in superclass
136
+ # * change default values of superclass
137
+ # * overwrite init to make it enable to instantiate section objects with added default values
138
+
139
+ if other.final == false && overwrite?(other, :final)
140
+ raise ConfigError, "BUG: subclass cannot overwrite finalized base class's config_section"
141
+ end
142
+
143
+ [:param_name, :required, :multi, :alias, :configured_in_section].each do |prohibited_name|
144
+ if overwrite?(other, prohibited_name)
145
+ raise ConfigError, "BUG: subclass cannot overwrite base class's config_section: #{prohibited_name}"
146
+ end
147
+ end
148
+
149
+ options = {}
150
+ options[:param_name] = @param_name
151
+ options[:init] = @init || other.init
152
+ options[:required] = @required.nil? ? other.required : self.required
153
+ options[:multi] = @multi.nil? ? other.multi : self.multi
154
+ options[:alias] = @alias.nil? ? other.alias : self.alias
155
+ options[:final] = true
156
+ options[:type_lookup] = @type_lookup
157
+
158
+ merged = self.class.new(@name, options)
103
159
 
104
- options = {
105
- param_name: other.param_name,
106
- required: (self.required.nil? ? other.required : self.required),
107
- multi: (self.multi.nil? ? other.multi : self.multi),
108
- final: true,
109
- }
110
- merged = self.class.new(other.name, options)
160
+ merged.configured_in_section = self.configured_in_section
111
161
 
112
162
  merged.argument = self.argument || other.argument
113
163
  merged.params = other.params.merge(self.params)
114
- merged.defaults = other.defaults.merge(self.defaults)
164
+ merged.defaults = self.defaults.merge(other.defaults)
115
165
  merged.sections = {}
116
166
  (self.sections.keys + other.sections.keys).uniq.each do |section_key|
117
167
  self_section = self.sections[section_key]
@@ -129,49 +179,33 @@ module Fluent
129
179
  merged
130
180
  end
131
181
 
132
- def option_value_type!(name, opts, key, klass)
133
- if opts.has_key?(key) && !opts[key].is_a?(klass)
134
- raise ArgumentError, "#{name}: #{key} must be a #{klass}, but #{opts[key].class}"
182
+ def overwrite_defaults(other) # other is owner plugin's corresponding proxy
183
+ self.defaults = self.defaults.merge(other.defaults)
184
+ self.sections.keys.each do |section_key|
185
+ if other.sections.has_key?(section_key)
186
+ self.sections[section_key].overwrite_defaults(other.sections[section_key])
187
+ end
135
188
  end
136
189
  end
137
190
 
138
- def parameter_configuration(name, *args, &block)
191
+ def parameter_configuration(name, type = nil, **kwargs, &block)
139
192
  name = name.to_sym
140
193
 
141
194
  opts = {}
142
- args.each { |a|
143
- if a.is_a?(Symbol)
144
- opts[:type] = a
145
- elsif a.is_a?(Hash)
146
- opts.merge!(a)
147
- else
148
- raise ArgumentError, "#{self.name}: wrong number of arguments (#{1 + args.length} for #{block ? 2 : 3})"
149
- end
150
- }
195
+ opts[:type] = type
196
+ opts.merge!(kwargs)
151
197
 
152
- type = opts[:type]
153
198
  if block && type
154
- raise ArgumentError, "#{name}: both of block and type cannot be specified"
199
+ raise ArgumentError, "#{self.name}: both of block and type cannot be specified"
155
200
  end
156
201
 
157
202
  begin
158
203
  type = :string if type.nil?
159
- block ||= Configurable.lookup_type(type)
204
+ block ||= @type_lookup.call(type)
160
205
  rescue ConfigError
161
206
  # override error message
162
- raise ArgumentError, "#{name}: unknown config_argument type `#{type}'"
163
- end
164
-
165
- option_value_type!(name, opts, :desc, String)
166
- option_value_type!(name, opts, :alias, Symbol)
167
- option_value_type!(name, opts, :deprecated, String)
168
- option_value_type!(name, opts, :obsoleted, String)
169
- if type == :enum
170
- if !opts.has_key?(:list) || !opts[:list].all?{|v| v.is_a?(Symbol) }
171
- raise ArgumentError, "#{name}: enum parameter requires :list of Symbols"
172
- end
207
+ raise ArgumentError, "#{self.name}: unknown config_argument type `#{type}'"
173
208
  end
174
- option_value_type!(name, opts, :value_type, Symbol) # hash, array
175
209
 
176
210
  if opts.has_key?(:default)
177
211
  config_set_default(name, opts[:default])
@@ -181,25 +215,28 @@ module Fluent
181
215
  config_set_desc(name, opts[:desc])
182
216
  end
183
217
 
184
- if opts[:deprecated] && opts[:obsoleted]
185
- raise ArgumentError, "#{name}: both of deprecated and obsoleted cannot be specified at once"
186
- end
187
-
188
218
  [name, block, opts]
189
219
  end
190
220
 
191
- def config_argument(name, *args, &block)
221
+ def configured_in(section_name)
222
+ if @configured_in_section
223
+ raise ArgumentError, "#{self.name}: configured_in called twice"
224
+ end
225
+ @configured_in_section = section_name.to_sym
226
+ end
227
+
228
+ def config_argument(name, type = nil, **kwargs, &block)
192
229
  if @argument
193
230
  raise ArgumentError, "#{self.name}: config_argument called twice"
194
231
  end
195
- name, block, opts = parameter_configuration(name, *args, &block)
232
+ name, block, opts = parameter_configuration(name, type, **kwargs, &block)
196
233
 
197
234
  @argument = [name, block, opts]
198
235
  name
199
236
  end
200
237
 
201
- def config_param(name, *args, &block)
202
- name, block, opts = parameter_configuration(name, *args, &block)
238
+ def config_param(name, type = nil, **kwargs, &block)
239
+ name, block, opts = parameter_configuration(name, type, **kwargs, &block)
203
240
 
204
241
  if @current_description
205
242
  config_set_desc(name, @current_description)
@@ -237,20 +274,24 @@ module Fluent
237
274
  @current_description = description
238
275
  end
239
276
 
240
- def config_section(name, *args, &block)
277
+ def config_section(name, **kwargs, &block)
241
278
  unless block_given?
242
- raise ArgumentError, "#{name}: config_section requires block parameter"
279
+ raise ArgumentError, "#{self.name}: config_section requires block parameter"
243
280
  end
244
281
  name = name.to_sym
245
282
 
246
- opts = {}
247
- unless args.empty? || args.size == 1 && args.first.is_a?(Hash)
248
- raise ArgumentError, "#{self.name}: unknown config_section arguments: #{args.inspect}"
249
- end
250
-
251
- sub_proxy = ConfigureProxy.new(name, *args)
283
+ sub_proxy = ConfigureProxy.new(name, type_lookup: @type_lookup, **kwargs)
252
284
  sub_proxy.instance_exec(&block)
253
285
 
286
+ if sub_proxy.init?
287
+ if sub_proxy.argument && !sub_proxy.defaults.has_key?(sub_proxy.argument.first)
288
+ raise ArgumentError, "#{self.name}: init is specified, but default value of argument is missing"
289
+ end
290
+ if sub_proxy.params.keys.any?{|param_name| !sub_proxy.defaults.has_key?(param_name)}
291
+ raise ArgumentError, "#{self.name}: init is specified, but there're parameters without default values"
292
+ end
293
+ end
294
+
254
295
  @params.delete(name)
255
296
  @sections[name] = sub_proxy
256
297
 
@@ -270,6 +311,14 @@ module Fluent
270
311
  end
271
312
  dumped_config
272
313
  end
314
+
315
+ private
316
+
317
+ def overwrite?(other, attribute_name)
318
+ value = instance_variable_get("@#{attribute_name}")
319
+ other_value = other.__send__(attribute_name)
320
+ !value.nil? && !other_value.nil? && value != other_value
321
+ end
273
322
  end
274
323
  end
275
324
  end