fluentd 0.10.42 → 0.10.43

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.

data/ChangeLog CHANGED
@@ -1,3 +1,12 @@
1
+ Release 0.10.43 - 2013/02/03
2
+
3
+ * Input/Output: Add 'log_level' option to plugins
4
+ * parser/in_tail: Fix RegexpParser forget to call configure method
5
+ * parser/in_tail: Improve type conversion performance
6
+ * in_http: Add add_http_headers option to add HTTP headers to record
7
+ * Buffer: Improve submit_buffer throughput using round-robin writer selection
8
+ * add sigdump gem to dump useful information via SIGCONT
9
+
1
10
  Release 0.10.42 - 2013/12/25
2
11
 
3
12
  * parser/in_tail: Add 'types' and related parameters to convert record value type
@@ -1,6 +1,6 @@
1
1
  = Fluentd
2
2
 
3
- {<img src="https://travis-ci.org/fluent/fluentd.png" />}[https://travis-ci.org/fluent/fluentd]
3
+ {<img src="https://travis-ci.org/fluent/fluentd.png" />}[https://travis-ci.org/fluent/fluentd] {<img src="https://codeclimate.com/github/fluent/fluentd.png " />}[https://codeclimate.com/github/fluent/fluentd]
4
4
 
5
5
  Fluentd is an event collector system. It is a generalized version of syslogd, which handles JSON objects for its log messages.
6
6
 
@@ -64,3 +64,6 @@ License:: Apache License, Version 2.0
64
64
  == Contributors:
65
65
 
66
66
  Patches contributed by {those people}[https://github.com/fluent/fluentd/contributors].
67
+
68
+ {<img src="https://ga-beacon.appspot.com/UA-24890265-6/fluent/fluentd" />}[https://github.com/fluent/fluentd]
69
+
@@ -23,6 +23,7 @@ Gem::Specification.new do |gem|
23
23
  gem.add_runtime_dependency(%q<yajl-ruby>, ["~> 1.0"])
24
24
  gem.add_runtime_dependency(%q<cool.io>, ["~> 1.1.1"])
25
25
  gem.add_runtime_dependency(%q<http_parser.rb>, ["~> 0.5.1"])
26
+ gem.add_runtime_dependency(%q<sigdump>, ["~> 0.2.2"])
26
27
 
27
28
  gem.add_development_dependency(%q<rake>, [">= 0.9.2"])
28
29
  gem.add_development_dependency(%q<parallel_tests>, [">= 0.15.3"])
@@ -19,6 +19,7 @@ module Fluent
19
19
  class Input
20
20
  include Configurable
21
21
  include PluginId
22
+ include PluginLoggerMixin
22
23
 
23
24
  def initialize
24
25
  super
@@ -35,4 +36,3 @@ module Fluent
35
36
  end
36
37
  end
37
38
  end
38
-
@@ -9,6 +9,7 @@ require 'json'
9
9
  require 'yajl'
10
10
  require 'uri'
11
11
  require 'msgpack'
12
+ require 'sigdump/setup'
12
13
  # I hate global variable but we suffer pain now for the sake of future.
13
14
  # We will switch to MessagePack 0.5 and deprecate 0.4.
14
15
  $use_msgpack_5 = defined?(MessagePack::Packer) ? true : false
@@ -15,6 +15,9 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
+
19
+ require 'forwardable'
20
+
18
21
  module Fluent
19
22
  class Log
20
23
  module TTYColor
@@ -47,6 +50,7 @@ module Fluent
47
50
  @self_event = false
48
51
  @tag = 'fluent'
49
52
  @time_format = '%Y-%m-%d %H:%M:%S %z '
53
+ @depth_offset = 1
50
54
  enable_color out.tty?
51
55
  # TODO: This variable name is unclear so we should change to better name.
52
56
  @threads_exclude_events = []
@@ -71,6 +75,10 @@ module Fluent
71
75
  self
72
76
  end
73
77
 
78
+ def enable_color?
79
+ !@color_reset.empty?
80
+ end
81
+
74
82
  def enable_color(b=true)
75
83
  if b
76
84
  @color_trace = TTYColor::BLUE
@@ -107,7 +115,7 @@ module Fluent
107
115
  return if @level > LEVEL_TRACE
108
116
  args << block.call if block
109
117
  time, msg = event(:trace, args)
110
- puts [@color_trace, caller_line(time, 1, LEVEL_TRACE), msg, @color_reset].join
118
+ puts [@color_trace, caller_line(time, @depth_offset, LEVEL_TRACE), msg, @color_reset].join
111
119
  rescue
112
120
  # logger should not raise an exception. This rescue prevents unexpected behaviour.
113
121
  end
@@ -126,7 +134,7 @@ module Fluent
126
134
  return if @level > LEVEL_DEBUG
127
135
  args << block.call if block
128
136
  time, msg = event(:debug, args)
129
- puts [@color_debug, caller_line(time, 1, LEVEL_DEBUG), msg, @color_reset].join
137
+ puts [@color_debug, caller_line(time, @depth_offset, LEVEL_DEBUG), msg, @color_reset].join
130
138
  rescue
131
139
  end
132
140
  alias DEBUG debug
@@ -144,7 +152,7 @@ module Fluent
144
152
  return if @level > LEVEL_INFO
145
153
  args << block.call if block
146
154
  time, msg = event(:info, args)
147
- puts [@color_info, caller_line(time, 1, LEVEL_INFO), msg, @color_reset].join
155
+ puts [@color_info, caller_line(time, @depth_offset, LEVEL_INFO), msg, @color_reset].join
148
156
  rescue
149
157
  end
150
158
  alias INFO info
@@ -162,7 +170,7 @@ module Fluent
162
170
  return if @level > LEVEL_WARN
163
171
  args << block.call if block
164
172
  time, msg = event(:warn, args)
165
- puts [@color_warn, caller_line(time, 1, LEVEL_WARN), msg, @color_reset].join
173
+ puts [@color_warn, caller_line(time, @depth_offset, LEVEL_WARN), msg, @color_reset].join
166
174
  rescue
167
175
  end
168
176
  alias WARN warn
@@ -180,7 +188,7 @@ module Fluent
180
188
  return if @level > LEVEL_ERROR
181
189
  args << block.call if block
182
190
  time, msg = event(:error, args)
183
- puts [@color_error, caller_line(time, 1, LEVEL_ERROR), msg, @color_reset].join
191
+ puts [@color_error, caller_line(time, @depth_offset, LEVEL_ERROR), msg, @color_reset].join
184
192
  rescue
185
193
  end
186
194
  alias ERROR error
@@ -198,7 +206,7 @@ module Fluent
198
206
  return if @level > LEVEL_FATAL
199
207
  args << block.call if block
200
208
  time, msg = event(:fatal, args)
201
- puts [@color_fatal, caller_line(time, 1, LEVEL_FATAL), msg, @color_reset].join
209
+ puts [@color_fatal, caller_line(time, @depth_offset, LEVEL_FATAL), msg, @color_reset].join
202
210
  rescue
203
211
  end
204
212
  alias FATAL fatal
@@ -230,11 +238,12 @@ module Fluent
230
238
  return if @level > level
231
239
 
232
240
  time = Time.now
241
+ line = caller_line(time, 5, level)
233
242
  if @suppress_repeated_stacktrace && (Thread.current[:last_repeated_stacktrace] == backtrace)
234
- puts [" ", caller_line(time, 5, level), 'suppressed same stacktrace'].join
243
+ puts [" ", line, 'suppressed same stacktrace'].join
235
244
  else
236
245
  backtrace.each { |msg|
237
- puts [" ", caller_line(time, 5, level), msg].join
246
+ puts [" ", line, msg].join
238
247
  }
239
248
  Thread.current[:last_repeated_stacktrace] = backtrace if @suppress_repeated_stacktrace
240
249
  end
@@ -286,5 +295,71 @@ module Fluent
286
295
  return log_msg
287
296
  end
288
297
  end
289
- end
290
298
 
299
+
300
+ # PluginLogger has own log level separated from global $log object.
301
+ # This class enables log_level option in each plugin.
302
+ #
303
+ # PluginLogger has same functionality as Log but some methods are forwarded to internal logger
304
+ # for keeping logging action consistency in the process, e.g. color, tag, event, etc.
305
+ class PluginLogger < Log
306
+ def initialize(logger)
307
+ @logger = logger
308
+ @level = @logger.level
309
+ @depth_offset = 2
310
+ @suppress_repeated_stacktrace = logger.instance_variable_get(:@suppress_repeated_stacktrace)
311
+
312
+ enable_color @logger.enable_color?
313
+ end
314
+
315
+ def level=(log_level_str)
316
+ @level = case log_level_str.downcase
317
+ when "trace" then LEVEL_TRACE
318
+ when "debug" then LEVEL_DEBUG
319
+ when "info" then LEVEL_INFO
320
+ when "warn" then LEVEL_WARN
321
+ when "error" then LEVEL_ERROR
322
+ when "fatal" then LEVEL_FATAL
323
+ else raise "Unknown log level: level = #{log_level_str}"
324
+ end
325
+ end
326
+
327
+ alias orig_enable_color enable_color
328
+
329
+ def enable_color(b = true)
330
+ orig_enable_color b
331
+ @logger.enable_color b
332
+ end
333
+
334
+ extend Forwardable
335
+ def_delegators '@logger', :enable_color?, :enable_debug, :enable_event,
336
+ :disable_events, :tag, :tag=, :time_format, :time_format=,
337
+ :event, :caller_line, :puts, :write, :flush
338
+ end
339
+
340
+
341
+ module PluginLoggerMixin
342
+ def self.included(klass)
343
+ klass.instance_eval {
344
+ config_param :log_level, :string, :default => nil
345
+ }
346
+ end
347
+
348
+ def initialize
349
+ super
350
+
351
+ @log = $log # Use $log object directly by default
352
+ end
353
+
354
+ attr_accessor :log
355
+
356
+ def configure(conf)
357
+ super
358
+
359
+ if @log_level
360
+ @log = PluginLogger.new($log)
361
+ @log.level = @log_level
362
+ end
363
+ end
364
+ end
365
+ end
@@ -59,6 +59,7 @@ module Fluent
59
59
  class Output
60
60
  include Configurable
61
61
  include PluginId
62
+ include PluginLoggerMixin
62
63
 
63
64
  def initialize
64
65
  super
@@ -223,6 +224,8 @@ module Fluent
223
224
  @buffer.start
224
225
  @secondary.start if @secondary
225
226
  @writers.each {|writer| writer.start }
227
+ @writer_current_position = 0
228
+ @writers_size = @writers.size
226
229
  end
227
230
 
228
231
  def shutdown
@@ -240,8 +243,9 @@ module Fluent
240
243
  end
241
244
 
242
245
  def submit_flush
243
- # TODO roundrobin?
244
- @writers.first.submit_flush
246
+ # Without locks: it is rough but enough to select "next" writer selection
247
+ @writer_current_position = (@writer_current_position + 1) % @writers_size
248
+ @writers[@writer_current_position].submit_flush
245
249
  end
246
250
 
247
251
  def format_stream(tag, es)
@@ -137,10 +137,14 @@ module Fluent
137
137
  @mutex = Mutex.new
138
138
  end
139
139
 
140
+ def configure(conf)
141
+ super
142
+ @time_parser = TimeParser.new(@time_format)
143
+ end
144
+
140
145
  def call(text)
141
146
  m = @regexp.match(text)
142
147
  unless m
143
- $log.warn "pattern not match: #{text.inspect}"
144
148
  return nil, nil
145
149
  end
146
150
 
@@ -198,7 +202,6 @@ module Fluent
198
202
 
199
203
  return time, record
200
204
  rescue Yajl::ParseError
201
- $log.warn "pattern not match: #{text.inspect}: #{$!}"
202
205
  return nil, nil
203
206
  end
204
207
  end
@@ -246,8 +249,10 @@ module Fluent
246
249
  private
247
250
 
248
251
  def convert_field_type!(record)
249
- record.each { |key, value|
250
- record[key] = convert_type(key, value)
252
+ @type_converters.each_key { |key|
253
+ if value = record[key]
254
+ record[key] = convert_type(key, value)
255
+ end
251
256
  }
252
257
  end
253
258
  end
@@ -320,7 +325,6 @@ module Fluent
320
325
  def call(text)
321
326
  m = REGEXP.match(text)
322
327
  unless m
323
- $log.warn "pattern not match: #{text.inspect}"
324
328
  return nil, nil
325
329
  end
326
330
 
@@ -41,7 +41,7 @@ module Fluent
41
41
  else
42
42
  uri = "druby://#{@bind}:#{@port}"
43
43
  end
44
- $log.info "listening dRuby", :uri => uri, :object => @object
44
+ log.info "listening dRuby", :uri => uri, :object => @object
45
45
  obj = eval(@object)
46
46
  @server = DRb::DRbServer.new(uri, obj)
47
47
  end
@@ -124,8 +124,8 @@ module Fluent
124
124
  @parser.call(io)
125
125
  Process.waitpid(io.pid)
126
126
  rescue
127
- $log.error "exec failed to run or shutdown child process", :error => $!.to_s, :error_class => $!.class.to_s
128
- $log.warn_backtrace $!.backtrace
127
+ log.error "exec failed to run or shutdown child process", :error => $!.to_s, :error_class => $!.class.to_s
128
+ log.warn_backtrace $!.backtrace
129
129
  end
130
130
  end
131
131
  end
@@ -147,7 +147,7 @@ module Fluent
147
147
 
148
148
  Engine.emit(tag, time, record)
149
149
  rescue => e
150
- $log.error "exec failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
150
+ log.error "exec failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
151
151
  end
152
152
  end
153
153
  end
@@ -61,8 +61,8 @@ module Fluent
61
61
  end
62
62
 
63
63
  def listen
64
- $log.info "listening fluent socket on #{@bind}:#{@port}"
65
- s = Coolio::TCPServer.new(@bind, @port, Handler, method(:on_message))
64
+ log.info "listening fluent socket on #{@bind}:#{@port}"
65
+ s = Coolio::TCPServer.new(@bind, @port, Handler, log, method(:on_message))
66
66
  s.listen(@backlog) unless @backlog.nil?
67
67
  s
68
68
  end
@@ -73,15 +73,15 @@ module Fluent
73
73
  # File.unlink(@path)
74
74
  # end
75
75
  # FileUtils.mkdir_p File.dirname(@path)
76
- # $log.debug "listening fluent socket on #{@path}"
76
+ # log.debug "listening fluent socket on #{@path}"
77
77
  # Coolio::UNIXServer.new(@path, Handler, method(:on_message))
78
78
  #end
79
79
 
80
80
  def run
81
81
  @loop.run
82
82
  rescue => e
83
- $log.error "unexpected error", :error => e, :error_class => e.class
84
- $log.error_backtrace
83
+ log.error "unexpected error", :error => e, :error_class => e.class
84
+ log.error_backtrace
85
85
  end
86
86
 
87
87
  protected
@@ -143,14 +143,15 @@ module Fluent
143
143
  end
144
144
 
145
145
  class Handler < Coolio::Socket
146
- def initialize(io, on_message)
146
+ def initialize(io, log, on_message)
147
147
  super(io)
148
148
  if io.is_a?(TCPSocket)
149
149
  opt = [1, @timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
150
150
  io.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
151
151
  end
152
- $log.trace { "accepted fluent socket object_id=#{self.object_id}" }
153
152
  @on_message = on_message
153
+ @log = log
154
+ @log.trace { "accepted fluent socket object_id=#{self.object_id}" }
154
155
  end
155
156
 
156
157
  def on_connect
@@ -176,21 +177,21 @@ module Fluent
176
177
  def on_read_json(data)
177
178
  @y << data
178
179
  rescue => e
179
- $log.error "forward error", :error => e, :error_class => e.class
180
- $log.error_backtrace
180
+ @log.error "forward error", :error => e, :error_class => e.class
181
+ @log.error_backtrace
181
182
  close
182
183
  end
183
184
 
184
185
  def on_read_msgpack(data)
185
186
  @u.feed_each(data, &@on_message)
186
187
  rescue => e
187
- $log.error "forward error", :error => e, :error_class => e.class
188
- $log.error_backtrace
188
+ @log.error "forward error", :error => e, :error_class => e.class
189
+ @log.error_backtrace
189
190
  close
190
191
  end
191
192
 
192
193
  def on_close
193
- $log.trace { "closed fluent socket object_id=#{self.object_id}" }
194
+ @log.trace { "closed fluent socket object_id=#{self.object_id}" }
194
195
  end
195
196
  end
196
197
 
@@ -216,7 +217,7 @@ module Fluent
216
217
  end
217
218
 
218
219
  def on_heartbeat_request(host, port, msg)
219
- #$log.trace "heartbeat request from #{host}:#{port}"
220
+ #log.trace "heartbeat request from #{host}:#{port}"
220
221
  begin
221
222
  @usock.send "\0", 0, host, port
222
223
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::EINTR
@@ -27,8 +27,9 @@ module Fluent
27
27
  config_param :tag, :string
28
28
 
29
29
  class TimerWatcher < Coolio::TimerWatcher
30
- def initialize(interval, repeat, &callback)
30
+ def initialize(interval, repeat, log, &callback)
31
31
  @callback = callback
32
+ @log = log
32
33
  super(interval, repeat)
33
34
  end
34
35
 
@@ -36,8 +37,8 @@ module Fluent
36
37
  @callback.call
37
38
  rescue
38
39
  # TODO log?
39
- $log.error $!.to_s
40
- $log.error_backtrace
40
+ @log.error $!.to_s
41
+ @log.error_backtrace
41
42
  end
42
43
  end
43
44
 
@@ -47,7 +48,7 @@ module Fluent
47
48
 
48
49
  def start
49
50
  @loop = Coolio::Loop.new
50
- @timer = TimerWatcher.new(@emit_interval, true, &method(:on_timer))
51
+ @timer = TimerWatcher.new(@emit_interval, true, log, &method(:on_timer))
51
52
  @loop.attach(@timer)
52
53
  @thread = Thread.new(&method(:run))
53
54
  end
@@ -61,8 +62,8 @@ module Fluent
61
62
  def run
62
63
  @loop.run
63
64
  rescue
64
- $log.error "unexpected error", :error=>$!.to_s
65
- $log.error_backtrace
65
+ log.error "unexpected error", :error=>$!.to_s
66
+ log.error_backtrace
66
67
  end
67
68
 
68
69
  def on_timer