fluentd 0.10.36 → 0.10.37

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.

@@ -0,0 +1,74 @@
1
+ require 'fluent/config'
2
+
3
+ module Fluent
4
+ module Config
5
+ module DSL
6
+ module DSLParser
7
+ def self.read(path)
8
+ path = File.expand_path(path)
9
+ data = File.read(path)
10
+ parse(data, path)
11
+ end
12
+
13
+ def self.parse(source, source_path="config.rb")
14
+ DSLElement.new('ROOT', nil).__eval(source, source_path).__to_config_element
15
+ end
16
+ end
17
+
18
+ class DSLElement < BasicObject
19
+ def initialize(name, arg)
20
+ @name = name
21
+ @arg = arg || ''
22
+ @attrs = {}
23
+ @elements = []
24
+ end
25
+
26
+ def __eval(source, source_path)
27
+ instance_eval(source, source_path)
28
+ self
29
+ end
30
+
31
+ def __to_config_element
32
+ Config::Element.new(@name, @arg, @attrs, @elements)
33
+ end
34
+
35
+ def method_missing(name, *args, &block)
36
+ raise ArgumentError, "Configuration DSL Syntax Error: only one argument allowed" if args.size > 1
37
+ value = args.first
38
+ if block
39
+ element = DSLElement.new(name.to_s, value)
40
+ element.instance_exec(&block)
41
+ @elements.push(element.__to_config_element)
42
+ else
43
+ # @attrs[name.to_s] = value.is_a?(::Symbol) ? value.to_s : value
44
+ @attrs[name.to_s] = value.to_s
45
+ end
46
+ self
47
+ end
48
+
49
+ def source(&block)
50
+ __element('source', nil, block)
51
+ end
52
+
53
+ def match(*args, &block)
54
+ __need_arg('match', args); __element('match', args.first, block)
55
+ end
56
+
57
+ private
58
+
59
+ def __element(name, arg, block)
60
+ raise ArgumentError, "#{name} block must be specified" if block.nil?
61
+ element = DSLElement.new(name.to_s, arg)
62
+ element.instance_exec(&block)
63
+ @elements.push(element.__to_config_element)
64
+ self
65
+ end
66
+
67
+ def __need_arg(name, args)
68
+ raise ArgumentError, "#{name} block requires arguments for match pattern" if args.nil? || args.size != 1
69
+ true
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -16,318 +16,321 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  module Fluent
19
+ class EngineClass
20
+ def initialize
21
+ @matches = []
22
+ @sources = []
23
+ @match_cache = {}
24
+ @match_cache_keys = []
25
+ @started = []
26
+ @default_loop = nil
19
27
 
28
+ @log_emit_thread = nil
29
+ @log_event_loop_stop = false
30
+ @log_event_queue = []
20
31
 
21
- class EngineClass
22
- def initialize
23
- @matches = []
24
- @sources = []
25
- @match_cache = {}
26
- @match_cache_keys = []
27
- @started = []
28
- @default_loop = nil
29
-
30
- @log_emit_thread = nil
31
- @log_event_loop_stop = false
32
- @log_event_queue = []
33
-
34
- @suppress_emit_error_log_interval = 0
35
- @next_emit_error_log_time = nil
36
- end
32
+ @suppress_emit_error_log_interval = 0
33
+ @next_emit_error_log_time = nil
34
+ end
37
35
 
38
- MATCH_CACHE_SIZE = 1024
36
+ MATCH_CACHE_SIZE = 1024
39
37
 
40
- LOG_EMIT_INTERVAL = 0.1
38
+ LOG_EMIT_INTERVAL = 0.1
41
39
 
42
- attr_reader :matches, :sources
40
+ attr_reader :matches, :sources
43
41
 
44
- def init
45
- BasicSocket.do_not_reverse_lookup = true
46
- Plugin.load_plugins
47
- if defined?(Encoding)
48
- Encoding.default_internal = 'ASCII-8BIT' if Encoding.respond_to?(:default_internal)
49
- Encoding.default_external = 'ASCII-8BIT' if Encoding.respond_to?(:default_external)
42
+ def init
43
+ BasicSocket.do_not_reverse_lookup = true
44
+ Plugin.load_plugins
45
+ if defined?(Encoding)
46
+ Encoding.default_internal = 'ASCII-8BIT' if Encoding.respond_to?(:default_internal)
47
+ Encoding.default_external = 'ASCII-8BIT' if Encoding.respond_to?(:default_external)
48
+ end
49
+ self
50
50
  end
51
- self
52
- end
53
51
 
54
- def suppress_interval(interval_time)
55
- @suppress_emit_error_log_interval = interval_time
56
- @next_emit_error_log_time = Time.now.to_i
57
- end
52
+ def suppress_interval(interval_time)
53
+ @suppress_emit_error_log_interval = interval_time
54
+ @next_emit_error_log_time = Time.now.to_i
55
+ end
58
56
 
59
- def read_config(path)
60
- $log.info "reading config file", :path=>path
61
- File.open(path) {|io|
62
- parse_config(io, File.basename(path), File.dirname(path))
63
- }
64
- end
57
+ def read_config(path)
58
+ $log.info "reading config file", :path=>path
59
+ File.open(path) {|io|
60
+ parse_config(io, File.basename(path), File.dirname(path))
61
+ }
62
+ end
65
63
 
66
- def parse_config(io, fname, basepath=Dir.pwd)
67
- conf = Config.parse(io, fname, basepath)
68
- configure(conf)
69
- conf.check_not_fetched {|key,e|
70
- $log.warn "parameter '#{key}' in #{e.to_s.strip} is not used."
71
- }
72
- end
64
+ def parse_config(io, fname, basepath=Dir.pwd)
65
+ conf = if fname =~ /\.rb$/
66
+ Config::DSL::DSLParser.parse(io, fname)
67
+ else
68
+ Config.parse(io, fname, basepath)
69
+ end
70
+ configure(conf)
71
+ conf.check_not_fetched {|key,e|
72
+ $log.warn "parameter '#{key}' in #{e.to_s.strip} is not used."
73
+ }
74
+ end
73
75
 
74
- def configure(conf)
75
- $log.info "using configuration file: #{conf.to_s.rstrip}"
76
+ def configure(conf)
77
+ $log.info "using configuration file: #{conf.to_s.rstrip}"
76
78
 
77
- conf.elements.select {|e|
78
- e.name == 'source'
79
- }.each {|e|
80
- type = e['type']
81
- unless type
82
- raise ConfigError, "Missing 'type' parameter on <source> directive"
83
- end
84
- $log.info "adding source type=#{type.dump}"
79
+ conf.elements.select {|e|
80
+ e.name == 'source'
81
+ }.each {|e|
82
+ type = e['type']
83
+ unless type
84
+ raise ConfigError, "Missing 'type' parameter on <source> directive"
85
+ end
86
+ $log.info "adding source type=#{type.dump}"
85
87
 
86
- input = Plugin.new_input(type)
87
- input.configure(e)
88
+ input = Plugin.new_input(type)
89
+ input.configure(e)
88
90
 
89
- @sources << input
90
- }
91
+ @sources << input
92
+ }
91
93
 
92
- conf.elements.select {|e|
93
- e.name == 'match'
94
- }.each {|e|
95
- type = e['type']
96
- pattern = e.arg
97
- unless type
98
- raise ConfigError, "Missing 'type' parameter on <match #{e.arg}> directive"
99
- end
100
- $log.info "adding match", :pattern=>pattern, :type=>type
94
+ conf.elements.select {|e|
95
+ e.name == 'match'
96
+ }.each {|e|
97
+ type = e['type']
98
+ pattern = e.arg
99
+ unless type
100
+ raise ConfigError, "Missing 'type' parameter on <match #{e.arg}> directive"
101
+ end
102
+ $log.info "adding match", :pattern=>pattern, :type=>type
101
103
 
102
- output = Plugin.new_output(type)
103
- output.configure(e)
104
+ output = Plugin.new_output(type)
105
+ output.configure(e)
104
106
 
105
- match = Match.new(pattern, output)
106
- @matches << match
107
- }
108
- end
107
+ match = Match.new(pattern, output)
108
+ @matches << match
109
+ }
110
+ end
109
111
 
110
- def load_plugin_dir(dir)
111
- Plugin.load_plugin_dir(dir)
112
- end
112
+ def load_plugin_dir(dir)
113
+ Plugin.load_plugin_dir(dir)
114
+ end
113
115
 
114
- def emit(tag, time, record)
115
- emit_stream tag, OneEventStream.new(time, record)
116
- end
116
+ def emit(tag, time, record)
117
+ unless record.nil?
118
+ emit_stream tag, OneEventStream.new(time, record)
119
+ end
120
+ end
117
121
 
118
- def emit_array(tag, array)
119
- emit_stream tag, ArrayEventStream.new(array)
120
- end
122
+ def emit_array(tag, array)
123
+ emit_stream tag, ArrayEventStream.new(array)
124
+ end
121
125
 
122
- def emit_stream(tag, es)
123
- target = @match_cache[tag]
124
- unless target
125
- target = match(tag) || NoMatchMatch.new
126
- # this is not thread-safe but inconsistency doesn't
127
- # cause serious problems while locking causes.
128
- if @match_cache_keys.size >= MATCH_CACHE_SIZE
129
- @match_cache_keys.delete @match_cache_keys.shift
126
+ def emit_stream(tag, es)
127
+ target = @match_cache[tag]
128
+ unless target
129
+ target = match(tag) || NoMatchMatch.new
130
+ # this is not thread-safe but inconsistency doesn't
131
+ # cause serious problems while locking causes.
132
+ if @match_cache_keys.size >= MATCH_CACHE_SIZE
133
+ @match_cache_keys.delete @match_cache_keys.shift
134
+ end
135
+ @match_cache[tag] = target
136
+ @match_cache_keys << tag
130
137
  end
131
- @match_cache[tag] = target
132
- @match_cache_keys << tag
138
+ target.emit(tag, es)
139
+ rescue => e
140
+ if @suppress_emit_error_log_interval == 0 || now > @next_emit_error_log_time
141
+ $log.warn "emit transaction failed ", :error_class=>e.class, :error=>e
142
+ $log.warn_backtrace
143
+ # $log.debug "current next_emit_error_log_time: #{Time.at(@next_emit_error_log_time)}"
144
+ @next_emit_error_log_time = Time.now.to_i + @suppress_emit_error_log_interval
145
+ # $log.debug "next emit failure log suppressed"
146
+ # $log.debug "next logged time is #{Time.at(@next_emit_error_log_time)}"
147
+ end
148
+ raise
133
149
  end
134
- target.emit(tag, es)
135
- rescue => e
136
- if @suppress_emit_error_log_interval == 0 || now > @next_emit_error_log_time
137
- $log.warn "emit transaction failed ", :error_class=>e.class, :error=>e
138
- $log.warn_backtrace
139
- # $log.debug "current next_emit_error_log_time: #{Time.at(@next_emit_error_log_time)}"
140
- @next_emit_error_log_time = Time.now.to_i + @suppress_emit_error_log_interval
141
- # $log.debug "next emit failure log suppressed"
142
- # $log.debug "next logged time is #{Time.at(@next_emit_error_log_time)}"
150
+
151
+ def match(tag)
152
+ @matches.find {|m| m.match(tag) }
143
153
  end
144
- raise
145
- end
146
154
 
147
- def match(tag)
148
- @matches.find {|m| m.match(tag) }
149
- end
155
+ def match?(tag)
156
+ !!match(tag)
157
+ end
150
158
 
151
- def match?(tag)
152
- !!match(tag)
153
- end
159
+ def flush!
160
+ flush_recursive(@matches)
161
+ end
154
162
 
155
- def flush!
156
- flush_recursive(@matches)
157
- end
163
+ def now
164
+ # TODO thread update
165
+ Time.now.to_i
166
+ end
158
167
 
159
- def now
160
- # TODO thread update
161
- Time.now.to_i
162
- end
168
+ def log_event_loop
169
+ $log.disable_events(Thread.current)
170
+
171
+ while sleep(LOG_EMIT_INTERVAL)
172
+ break if @log_event_loop_stop
173
+ next if @log_event_queue.empty?
163
174
 
164
- def log_event_loop
165
- $log.disable_events(Thread.current)
175
+ # NOTE: thead-safe of slice! depends on GVL
176
+ events = @log_event_queue.slice!(0..-1)
177
+ next if events.empty?
166
178
 
167
- while sleep(LOG_EMIT_INTERVAL)
168
- break if @log_event_loop_stop
169
- next if @log_event_queue.empty?
179
+ events.each {|tag,time,record|
180
+ begin
181
+ Engine.emit(tag, time, record)
182
+ rescue => e
183
+ $log.error "failed to emit fluentd's log event", :tag => tag, :event => record, :error_class => e.class, :error => e
184
+ end
185
+ }
186
+ end
187
+ end
170
188
 
171
- # NOTE: thead-safe of slice! depends on GVL
172
- events = @log_event_queue.slice!(0..-1)
173
- next if events.empty?
189
+ def run
190
+ begin
191
+ start
174
192
 
175
- events.each {|tag,time,record|
176
- begin
177
- Engine.emit(tag, time, record)
178
- rescue => e
179
- $log.error "failed to emit fluentd's log event", :tag => tag, :event => record, :error_class => e.class, :error => e
193
+ if match?($log.tag)
194
+ $log.enable_event
195
+ @log_emit_thread = Thread.new(&method(:log_event_loop))
180
196
  end
181
- }
182
- end
183
- end
184
197
 
185
- def run
186
- begin
187
- start
198
+ # for empty loop
199
+ @default_loop = Coolio::Loop.default
200
+ @default_loop.attach Coolio::TimerWatcher.new(1, true)
201
+ # TODO attach async watch for thread pool
202
+ @default_loop.run
188
203
 
189
- if match?($log.tag)
190
- $log.enable_event
191
- @log_emit_thread = Thread.new(&method(:log_event_loop))
204
+ rescue => e
205
+ $log.error "unexpected error", :error_class=>e.class, :error=>e
206
+ $log.error_backtrace
207
+ ensure
208
+ $log.info "shutting down fluentd"
209
+ shutdown
210
+ if @log_emit_thread
211
+ @log_event_loop_stop = true
212
+ @log_emit_thread.join
213
+ end
192
214
  end
215
+ end
193
216
 
194
- # for empty loop
195
- @default_loop = Coolio::Loop.default
196
- @default_loop.attach Coolio::TimerWatcher.new(1, true)
197
- # TODO attach async watch for thread pool
198
- @default_loop.run
199
-
200
- rescue => e
201
- $log.error "unexpected error", :error_class=>e.class, :error=>e
202
- $log.error_backtrace
203
- ensure
204
- $log.info "shutting down fluentd"
205
- shutdown
206
- if @log_emit_thread
207
- @log_event_loop_stop = true
208
- @log_emit_thread.join
217
+ def stop
218
+ if @default_loop
219
+ @default_loop.stop
220
+ @default_loop = nil
209
221
  end
222
+ nil
210
223
  end
211
- end
212
224
 
213
- def stop
214
- if @default_loop
215
- @default_loop.stop
216
- @default_loop = nil
225
+ def push_log_event(tag, time, record)
226
+ return if @log_emit_thread.nil?
227
+ @log_event_queue.push([tag, time, record])
217
228
  end
218
- nil
219
- end
220
229
 
221
- def push_log_event(tag, time, record)
222
- return if @log_emit_thread.nil?
223
- @log_event_queue.push([tag, time, record])
224
- end
230
+ private
231
+ def start
232
+ @matches.each {|m|
233
+ m.start
234
+ @started << m
235
+ }
236
+ @sources.each {|s|
237
+ s.start
238
+ @started << s
239
+ }
240
+ end
225
241
 
226
- private
227
- def start
228
- @matches.each {|m|
229
- m.start
230
- @started << m
231
- }
232
- @sources.each {|s|
233
- s.start
234
- @started << s
235
- }
236
- end
242
+ def shutdown
243
+ @started.map {|s|
244
+ Thread.new do
245
+ begin
246
+ s.shutdown
247
+ rescue => e
248
+ $log.warn "unexpected error while shutting down", :error_class=>e.class, :error=>e
249
+ $log.warn_backtrace
250
+ end
251
+ end
252
+ }.each {|t|
253
+ t.join
254
+ }
255
+ end
237
256
 
238
- def shutdown
239
- @started.map {|s|
240
- Thread.new do
257
+ def flush_recursive(array)
258
+ array.each {|m|
241
259
  begin
242
- s.shutdown
260
+ if m.is_a?(Match)
261
+ m = m.output
262
+ end
263
+ if m.is_a?(BufferedOutput)
264
+ m.force_flush
265
+ elsif m.is_a?(MultiOutput)
266
+ flush_recursive(m.outputs)
267
+ end
243
268
  rescue => e
244
- $log.warn "unexpected error while shutting down", :error_class=>e.class, :error=>e
245
- $log.warn_backtrace
269
+ $log.debug "error while force flushing", :error_class=>e.class, :error=>e
270
+ $log.debug_backtrace
246
271
  end
247
- end
248
- }.each {|t|
249
- t.join
250
- }
251
- end
272
+ }
273
+ end
252
274
 
253
- def flush_recursive(array)
254
- array.each {|m|
255
- begin
256
- if m.is_a?(Match)
257
- m = m.output
258
- end
259
- if m.is_a?(BufferedOutput)
260
- m.force_flush
261
- elsif m.is_a?(MultiOutput)
262
- flush_recursive(m.outputs)
263
- end
264
- rescue => e
265
- $log.debug "error while force flushing", :error_class=>e.class, :error=>e
266
- $log.debug_backtrace
275
+ class NoMatchMatch
276
+ def initialize
277
+ @count = 0
267
278
  end
268
- }
269
- end
270
-
271
- class NoMatchMatch
272
- def initialize
273
- @count = 0
274
- end
275
279
 
276
- def emit(tag, es)
277
- # TODO use time instead of num of records
278
- c = (@count += 1)
279
- if c < 512
280
- if Math.log(c) / Math.log(2) % 1.0 == 0
281
- $log.warn "no patterns matched", :tag=>tag
282
- return
283
- end
284
- else
285
- if c % 512 == 0
286
- $log.warn "no patterns matched", :tag=>tag
287
- return
280
+ def emit(tag, es)
281
+ # TODO use time instead of num of records
282
+ c = (@count += 1)
283
+ if c < 512
284
+ if Math.log(c) / Math.log(2) % 1.0 == 0
285
+ $log.warn "no patterns matched", :tag=>tag
286
+ return
287
+ end
288
+ else
289
+ if c % 512 == 0
290
+ $log.warn "no patterns matched", :tag=>tag
291
+ return
292
+ end
288
293
  end
294
+ $log.on_trace { $log.trace "no patterns matched", :tag=>tag }
289
295
  end
290
- $log.on_trace { $log.trace "no patterns matched", :tag=>tag }
291
- end
292
296
 
293
- def start
294
- end
297
+ def start
298
+ end
295
299
 
296
- def shutdown
297
- end
300
+ def shutdown
301
+ end
298
302
 
299
- def match(tag)
300
- false
303
+ def match(tag)
304
+ false
305
+ end
301
306
  end
302
307
  end
303
- end
304
308
 
305
- Engine = EngineClass.new
309
+ Engine = EngineClass.new
306
310
 
307
311
 
308
- module Test
309
- @@test = false
312
+ module Test
313
+ @@test = false
310
314
 
311
- def test?
312
- @@test
313
- end
315
+ def test?
316
+ @@test
317
+ end
314
318
 
315
- def self.setup
316
- @@test = true
319
+ def self.setup
320
+ @@test = true
317
321
 
318
- Fluent.__send__(:remove_const, :Engine)
319
- engine = Fluent.const_set(:Engine, EngineClass.new).init
322
+ Fluent.__send__(:remove_const, :Engine)
323
+ engine = Fluent.const_set(:Engine, EngineClass.new).init
320
324
 
321
- engine.define_singleton_method(:now=) {|n|
322
- @now = n.to_i
323
- }
324
- engine.define_singleton_method(:now) {
325
- @now || super()
326
- }
325
+ engine.define_singleton_method(:now=) {|n|
326
+ @now = n.to_i
327
+ }
328
+ engine.define_singleton_method(:now) {
329
+ @now || super()
330
+ }
327
331
 
328
- nil
332
+ nil
333
+ end
329
334
  end
330
335
  end
331
336
 
332
- end
333
-