fluentd 0.14.0 → 0.14.1

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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/example/copy_roundrobin.conf +39 -0
  3. data/example/filter_stdout.conf +5 -5
  4. data/example/in_forward.conf +2 -2
  5. data/example/in_http.conf +2 -2
  6. data/example/in_syslog.conf +2 -2
  7. data/example/in_tail.conf +2 -2
  8. data/example/in_tcp.conf +2 -2
  9. data/example/in_udp.conf +2 -2
  10. data/example/out_buffered_null.conf +32 -0
  11. data/example/out_copy.conf +4 -4
  12. data/example/out_file.conf +2 -2
  13. data/example/out_forward.conf +2 -2
  14. data/example/v0_12_filter.conf +8 -8
  15. data/fluentd.gemspec +1 -1
  16. data/lib/fluent/command/fluentd.rb +6 -1
  17. data/lib/fluent/compat/handle_tag_name_mixin.rb +53 -0
  18. data/lib/fluent/compat/input.rb +1 -0
  19. data/lib/fluent/compat/output.rb +1 -0
  20. data/lib/fluent/compat/record_filter_mixin.rb +34 -0
  21. data/lib/fluent/compat/set_tag_key_mixin.rb +50 -0
  22. data/lib/fluent/compat/set_time_key_mixin.rb +69 -0
  23. data/lib/fluent/compat/type_converter.rb +90 -0
  24. data/lib/fluent/config/configure_proxy.rb +24 -4
  25. data/lib/fluent/config/dsl.rb +18 -1
  26. data/lib/fluent/config/v1_parser.rb +3 -2
  27. data/lib/fluent/configurable.rb +1 -1
  28. data/lib/fluent/event.rb +37 -9
  29. data/lib/fluent/mixin.rb +12 -286
  30. data/lib/fluent/plugin/buffer.rb +2 -2
  31. data/lib/fluent/plugin/in_dummy.rb +5 -1
  32. data/lib/fluent/plugin/in_gc_stat.rb +7 -37
  33. data/lib/fluent/plugin/in_http.rb +2 -0
  34. data/lib/fluent/plugin/{in_stream.rb → in_unix.rb} +0 -0
  35. data/lib/fluent/plugin/out_buffered_stdout.rb +60 -0
  36. data/lib/fluent/plugin/out_copy.rb +8 -51
  37. data/lib/fluent/plugin/out_null.rb +5 -5
  38. data/lib/fluent/plugin/out_relabel.rb +5 -5
  39. data/lib/fluent/plugin/out_roundrobin.rb +13 -40
  40. data/lib/fluent/plugin/output.rb +9 -0
  41. data/lib/fluent/plugin_helper.rb +2 -0
  42. data/lib/fluent/plugin_helper/formatter.rb +138 -0
  43. data/lib/fluent/plugin_helper/inject.rb +112 -0
  44. data/lib/fluent/plugin_helper/parser.rb +138 -0
  45. data/lib/fluent/plugin_helper/storage.rb +64 -50
  46. data/lib/fluent/process.rb +6 -1
  47. data/lib/fluent/registry.rb +1 -1
  48. data/lib/fluent/supervisor.rb +20 -2
  49. data/lib/fluent/test.rb +30 -5
  50. data/lib/fluent/test/base.rb +2 -66
  51. data/lib/fluent/test/driver/base.rb +3 -0
  52. data/lib/fluent/test/driver/base_owned.rb +106 -0
  53. data/lib/fluent/test/driver/formatter.rb +30 -0
  54. data/lib/fluent/test/driver/multi_output.rb +52 -0
  55. data/lib/fluent/test/driver/owner.rb +32 -0
  56. data/lib/fluent/test/driver/parser.rb +30 -0
  57. data/lib/fluent/test/helpers.rb +54 -0
  58. data/lib/fluent/test/log.rb +73 -0
  59. data/lib/fluent/time.rb +71 -0
  60. data/lib/fluent/version.rb +1 -1
  61. data/test/compat/test_parser.rb +82 -0
  62. data/test/config/test_configure_proxy.rb +15 -0
  63. data/test/config/test_dsl.rb +180 -2
  64. data/test/helper.rb +2 -24
  65. data/test/plugin/test_in_gc_stat.rb +6 -6
  66. data/test/plugin/test_in_http.rb +49 -32
  67. data/test/plugin/{test_in_stream.rb → test_in_unix.rb} +1 -1
  68. data/test/plugin/test_out_buffered_stdout.rb +108 -0
  69. data/test/plugin/test_out_copy.rb +88 -127
  70. data/test/plugin/test_out_null.rb +29 -0
  71. data/test/plugin/test_out_relabel.rb +28 -0
  72. data/test/plugin/test_out_roundrobin.rb +35 -29
  73. data/test/plugin/test_out_stdout.rb +4 -4
  74. data/test/plugin/test_output_as_buffered.rb +51 -0
  75. data/test/plugin/test_output_as_buffered_secondary.rb +13 -0
  76. data/test/plugin/test_parser_apache.rb +38 -0
  77. data/test/plugin/test_parser_apache2.rb +38 -0
  78. data/test/plugin/test_parser_apache_error.rb +40 -0
  79. data/test/plugin/test_parser_base.rb +32 -0
  80. data/test/plugin/test_parser_csv.rb +94 -0
  81. data/test/plugin/test_parser_json.rb +107 -0
  82. data/test/plugin/test_parser_labeled_tsv.rb +129 -0
  83. data/test/plugin/test_parser_multiline.rb +100 -0
  84. data/test/plugin/test_parser_nginx.rb +42 -0
  85. data/test/plugin/test_parser_none.rb +53 -0
  86. data/test/plugin/test_parser_regexp.rb +110 -0
  87. data/test/plugin/test_parser_syslog.rb +66 -0
  88. data/test/plugin/test_parser_time.rb +46 -0
  89. data/test/plugin/test_parser_tsv.rb +125 -0
  90. data/test/plugin_helper/test_child_process.rb +11 -2
  91. data/test/plugin_helper/test_formatter.rb +212 -0
  92. data/test/plugin_helper/test_inject.rb +388 -0
  93. data/test/plugin_helper/test_parser.rb +223 -0
  94. data/test/plugin_helper/test_retry_state.rb +40 -40
  95. data/test/plugin_helper/test_storage.rb +77 -10
  96. data/test/scripts/fluent/plugin/out_test.rb +22 -17
  97. data/test/scripts/fluent/plugin/out_test2.rb +80 -0
  98. data/test/test_event.rb +57 -0
  99. data/test/test_formatter.rb +0 -178
  100. data/test/test_output.rb +2 -152
  101. data/test/test_root_agent.rb +3 -2
  102. data/test/test_supervisor.rb +93 -26
  103. data/test/test_time_formatter.rb +186 -0
  104. metadata +69 -7
  105. data/test/test_parser.rb +0 -1087
@@ -0,0 +1,112 @@
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/event'
18
+ require 'time'
19
+
20
+ module Fluent
21
+ module PluginHelper
22
+ module Inject
23
+ def inject_values_to_record(tag, time, record)
24
+ return record unless @_inject_enabled
25
+
26
+ r = record.dup
27
+ if @_inject_hostname_key
28
+ r[@_inject_hostname_key] = @_inject_hostname
29
+ end
30
+ if @_inject_tag_key
31
+ r[@_inject_tag_key] = tag
32
+ end
33
+ if @_inject_time_key
34
+ r[@_inject_time_key] = @_inject_time_formatter.call(time)
35
+ end
36
+
37
+ r
38
+ end
39
+
40
+ def inject_values_to_event_stream(tag, es)
41
+ return es unless @_inject_enabled
42
+
43
+ new_es = Fluent::MultiEventStream.new
44
+ es.each do |time, record|
45
+ r = record.dup
46
+ if @_inject_hostname_key
47
+ r[@_inject_hostname_key] = @_inject_hostname
48
+ end
49
+ if @_inject_tag_key
50
+ r[@_inject_tag_key] = tag
51
+ end
52
+ if @_inject_time_key
53
+ r[@_inject_time_key] = @_inject_time_formatter.call(time)
54
+ end
55
+ new_es.add(time, r)
56
+ end
57
+
58
+ new_es
59
+ end
60
+
61
+ def self.included(mod)
62
+ mod.instance_eval do
63
+ config_section :inject, required: false, multi: false, param_name: :inject_config do
64
+ config_param :hostname_key, :string, default: nil
65
+ config_param :hostname, :string, default: nil
66
+ config_param :tag_key, :string, default: nil
67
+ config_param :time_key, :string, default: nil
68
+ config_param :time_type, :enum, list: [:float, :unixtime, :string], default: :float
69
+ config_param :time_format, :string, default: nil
70
+ config_param :timezone, :string, default: "#{Time.now.strftime('%z')}" # localtime
71
+ end
72
+ end
73
+ end
74
+
75
+ def initialize
76
+ super
77
+ @_inject_hostname_key = nil
78
+ @_inject_hostname = nil
79
+ @_inject_tag_key = nil
80
+ @_inject_time_key = nil
81
+ @_inject_time_formatter = nil
82
+ end
83
+
84
+ def configure(conf)
85
+ super
86
+
87
+ if @inject_config
88
+ @_inject_hostname_key = @inject_config.hostname_key
89
+ if @_inject_hostname_key
90
+ @_inject_hostname = @inject_config.hostname
91
+ unless @_inject_hostname
92
+ @_inject_hostname = Socket.gethostname
93
+ log.info "using hostname for specified field", host_key: @_inject_hostname_key, host_name: @_inject_hostname
94
+ end
95
+ end
96
+ @_inject_tag_key = @inject_config.tag_key
97
+ @_inject_time_key = @inject_config.time_key
98
+ if @_inject_time_key
99
+ @_inject_time_formatter = case @inject_config.time_type
100
+ when :float then ->(time){ time.to_r.truncate(+6).to_f } # microsecond floating point value
101
+ when :unixtime then ->(time){ time.to_i }
102
+ else
103
+ Fluent::TimeFormatter.new(@inject_config.time_format, false, @inject_config.timezone)
104
+ end
105
+ end
106
+
107
+ @_inject_enabled = @_inject_hostname_key || @_inject_tag_key || @_inject_time_key
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,138 @@
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/config/element'
20
+
21
+ module Fluent
22
+ module PluginHelper
23
+ module Parser
24
+ def parser_create(usage: '', type: nil, conf: nil)
25
+ parser = @_parsers[usage]
26
+ return parser if parser
27
+
28
+ if !type
29
+ raise ArgumentError, "BUG: both type and conf are not specified" unless conf
30
+ raise Fluent::ConfigError, "@type is required in <parse>" unless conf['@type']
31
+ type = conf['@type']
32
+ end
33
+ parser = Fluent::Plugin.new_parser(type, parent: self)
34
+ config = case conf
35
+ when Fluent::Config::Element
36
+ conf
37
+ when Hash
38
+ # in code, programmer may use symbols as keys, but Element needs strings
39
+ conf = Hash[conf.map{|k,v| [k.to_s, v]}]
40
+ Fluent::Config::Element.new('parse', usage, conf, [])
41
+ when nil
42
+ Fluent::Config::Element.new('parse', usage, {}, [])
43
+ else
44
+ raise ArgumentError, "BUG: conf must be a Element, Hash (or unspecified), but '#{conf.class}'"
45
+ end
46
+ parser.configure(config)
47
+ if @_parsers_started
48
+ parser.start
49
+ end
50
+
51
+ @_parsers[usage] = parser
52
+ parser
53
+ end
54
+
55
+ def self.included(mod)
56
+ mod.instance_eval do
57
+ # minimum section definition to instantiate parser plugin instances
58
+ config_section :parse, required: false, multi: true, param_name: :parser_configs do
59
+ config_argument :usage, :string, default: ''
60
+ config_param :@type, :string
61
+ end
62
+ end
63
+ end
64
+
65
+ attr_reader :_parsers # for tests
66
+
67
+ def initialize
68
+ super
69
+ @_parsers_started = false
70
+ @_parsers = {} # usage => parser
71
+ end
72
+
73
+ def configure(conf)
74
+ super
75
+
76
+ @parser_configs.each do |section|
77
+ if @_parsers[section.usage]
78
+ raise Fluent::ConfigError, "duplicated parsers configured: #{section.usage}"
79
+ end
80
+ parser = Plugin.new_parser(section[:@type], parent: self)
81
+ parser.configure(section.corresponding_config_element)
82
+ @_parsers[section.usage] = parser
83
+ end
84
+ end
85
+
86
+ def start
87
+ super
88
+ @_parsers_started = true
89
+ @_parsers.each_pair do |usage, parser|
90
+ parser.start
91
+ end
92
+ end
93
+
94
+ def parser_operate(method_name, &block)
95
+ @_parsers.each_pair do |usage, parser|
96
+ begin
97
+ parser.send(method_name)
98
+ block.call(parser) if block_given?
99
+ rescue => e
100
+ log.error "unexpected error while #{method_name}", usage: usage, parser: parser, error: e
101
+ end
102
+ end
103
+ end
104
+
105
+ def stop
106
+ super
107
+ parser_operate(:stop)
108
+ end
109
+
110
+ def before_shutdown
111
+ parser_operate(:before_shutdown)
112
+ super
113
+ end
114
+
115
+ def shutdown
116
+ parser_operate(:shutdown)
117
+ super
118
+ end
119
+
120
+ def after_shutdown
121
+ parser_operate(:after_shutdown)
122
+ super
123
+ end
124
+
125
+ def close
126
+ parser_operate(:close)
127
+ super
128
+ end
129
+
130
+ def terminate
131
+ parser_operate(:terminate)
132
+ @_parsers_started = false
133
+ @_parsers = {}
134
+ super
135
+ end
136
+ end
137
+ end
138
+ end
@@ -14,19 +14,16 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'monitor'
18
17
  require 'forwardable'
19
18
 
20
19
  require 'fluent/plugin'
21
20
  require 'fluent/plugin/storage'
22
- require 'fluent/plugin_helper/thread'
23
21
  require 'fluent/plugin_helper/timer'
24
22
  require 'fluent/config/element'
25
23
 
26
24
  module Fluent
27
25
  module PluginHelper
28
26
  module Storage
29
- include Fluent::PluginHelper::Thread
30
27
  include Fluent::PluginHelper::Timer
31
28
 
32
29
  StorageState = Struct.new(:storage, :running)
@@ -35,38 +32,34 @@ module Fluent
35
32
  s = @_storages[usage]
36
33
  if s && s.running
37
34
  return s.storage
38
- elsif !s
39
- unless type
40
- raise ArgumentError, "BUG: type not specified without configuration"
35
+ elsif s
36
+ # storage is already created, but not loaded / started
37
+ else # !s
38
+ if !type
39
+ raise ArgumentError, "BUG: both type and conf are not specified" unless conf
40
+ raise Fluent::ConfigError, "@type is not specified for <storage>" unless conf['@type']
41
+ type = conf['@type']
41
42
  end
42
43
  storage = Plugin.new_storage(type, parent: self)
43
44
  config = case conf
44
45
  when Fluent::Config::Element
45
46
  conf
46
47
  when Hash
48
+ # in code, programmer may use symbols as keys, but Element needs strings
47
49
  conf = Hash[conf.map{|k,v| [k.to_s, v]}]
48
- Fluent::Config::Element.new('storage', '', conf, [])
50
+ Fluent::Config::Element.new('storage', usage, conf, [])
49
51
  when nil
50
- Fluent::Config::Element.new('storage', '', {}, [])
52
+ Fluent::Config::Element.new('storage', usage, {}, [])
51
53
  else
52
54
  raise ArgumentError, "BUG: conf must be a Element, Hash (or unspecified), but '#{conf.class}'"
53
55
  end
54
56
  storage.configure(config)
57
+ if @_storages_started
58
+ storage.start
59
+ end
55
60
  s = @_storages[usage] = StorageState.new(wrap_instance(storage), false)
56
61
  end
57
62
 
58
- s.storage.load
59
-
60
- if s.storage.autosave && !s.storage.persistent
61
- timer_execute(:storage_autosave, s.storage.autosave_interval, repeat: true) do
62
- begin
63
- s.storage.save
64
- rescue => e
65
- log.error "plugin storage failed to save its data", usage: usage, type: type, error: e
66
- end
67
- end
68
- end
69
- s.running = true
70
63
  s.storage
71
64
  end
72
65
 
@@ -84,8 +77,8 @@ module Fluent
84
77
 
85
78
  def initialize
86
79
  super
80
+ @_storages_started = false
87
81
  @_storages = {} # usage => storage_state
88
- @_storages_mutex = Mutex.new
89
82
  end
90
83
 
91
84
  def configure(conf)
@@ -95,56 +88,75 @@ module Fluent
95
88
  if @_storages[section.usage]
96
89
  raise Fluent::ConfigError, "duplicated storages configured: #{section.usage}"
97
90
  end
98
- config = conf.elements(name: 'storage', arg: section.usage).first
99
- raise "storage section with argument '#{section.usage}' not found. it may be a bug." unless config
100
-
101
- storage = Plugin.new_storage(section[:@type])
102
- storage.owner = self
103
- storage.configure(config)
91
+ storage = Plugin.new_storage(section[:@type], parent: self)
92
+ storage.configure(section.corresponding_config_element)
104
93
  @_storages[section.usage] = StorageState.new(wrap_instance(storage), false)
105
94
  end
106
95
  end
107
96
 
108
- def stop
97
+ def start
109
98
  super
110
- # timer stops automatically
99
+
100
+ @_storages_started = true
101
+ @_storages.each_pair do |usage, s|
102
+ s.storage.start
103
+ s.storage.load
104
+
105
+ if s.storage.autosave && !s.storage.persistent
106
+ timer_execute(:storage_autosave, s.storage.autosave_interval, repeat: true) do
107
+ begin
108
+ s.storage.save
109
+ rescue => e
110
+ log.error "plugin storage failed to save its data", usage: usage, type: type, error: e
111
+ end
112
+ end
113
+ end
114
+ s.running = true
115
+ end
111
116
  end
112
117
 
113
- def shutdown
118
+ def storage_operate(method_name, &block)
114
119
  @_storages.each_pair do |usage, s|
115
120
  begin
116
- s.storage.save if s.storage.save_at_shutdown
121
+ block.call(s) if block_given?
122
+ s.storage.send(method_name)
117
123
  rescue => e
118
- log.error "unexpected error while saving data of plugin storages", usage: usage, storage: s.storage, error: e
124
+ log.error "unexpected error while #{method_name}", usage: usage, storage: s.storage, error: e
119
125
  end
120
126
  end
127
+ end
121
128
 
129
+ def stop
122
130
  super
131
+ # timer stops automatically in super
132
+ storage_operate(:stop)
123
133
  end
124
134
 
125
- def close
126
- @_storages.each_pair do |usage, s|
127
- begin
128
- s.storage.close
129
- rescue => e
130
- log.error "unexpected error while closing plugin storages", usage: usage, storage: s.storage, error: e
131
- end
132
- s.running = false
135
+ def before_shutdown
136
+ storage_operate(:before_shutdown)
137
+ super
138
+ end
139
+
140
+ def shutdown
141
+ storage_operate(:shutdown) do |s|
142
+ s.storage.save if s.storage.save_at_shutdown
133
143
  end
144
+ super
145
+ end
146
+
147
+ def after_shutdown
148
+ storage_operate(:after_shutdown)
149
+ super
150
+ end
134
151
 
152
+ def close
153
+ storage_operate(:close){|s| s.running = false }
135
154
  super
136
155
  end
137
156
 
138
157
  def terminate
139
- @_storages.each_pair do |usage, s|
140
- begin
141
- s.storage.terminate
142
- rescue => e
143
- log.error "unexpected error while terminating plugin storages", usage: usage, storage: s.storage, error: e
144
- end
145
- end
158
+ storage_operate(:terminate)
146
159
  @_storages = {}
147
-
148
160
  super
149
161
  end
150
162
 
@@ -170,7 +182,8 @@ module Fluent
170
182
  end
171
183
 
172
184
  def_delegators :@storage, :autosave_interval, :save_at_shutdown
173
- def_delegators :@storage, :close, :terminate
185
+ def_delegators :@storage, :start, :stop, :before_shutdown, :shutdown, :after_shutdown, :close, :terminate
186
+ def_delegators :@storage, :started?, :stopped?, :before_shutdown?, :shutdown?, :after_shutdown?, :closed?, :terminated?
174
187
 
175
188
  def persistent_always?
176
189
  true
@@ -257,7 +270,8 @@ module Fluent
257
270
 
258
271
  def_delegators :@storage, :persistent, :autosave, :autosave_interval, :save_at_shutdown
259
272
  def_delegators :@storage, :persistent_always?
260
- def_delegators :@storage, :close, :terminate
273
+ def_delegators :@storage, :start, :stop, :before_shutdown, :shutdown, :after_shutdown, :close, :terminate
274
+ def_delegators :@storage, :started?, :stopped?, :before_shutdown?, :shutdown?, :after_shutdown?, :closed?, :terminated?
261
275
 
262
276
  def synchronized?
263
277
  true