fluentd 0.10.50 → 0.10.51

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dcc68a7c0e54890fee8388d37e9801edac3fb77f
4
- data.tar.gz: 992e8adb5d7c043f91f58e095aaf1d6cb5c7b363
3
+ metadata.gz: c0d7335ca94183ce7a33d7578b88addeb64b1c8f
4
+ data.tar.gz: 77807fdc964ab88d09ecc41787339c0825dba08c
5
5
  SHA512:
6
- metadata.gz: 84b5ed1c244b405de5ed3d637fbad708cbb361a42a7efd13793c2992f7aad66c9c9d49256b105545e65e2627d5e3de64838e0df05d9e0d6bd82e6c47d7f56230
7
- data.tar.gz: ad3c062f06ec7b472f7efb72acc693c9b71e83fc4eaf1df4c6c23ca5820543cb72bfea59778f3f5cb42f1510927f1f52c9f674a8bee3debdb3f86c4cc75e5950
6
+ metadata.gz: d3d90bcc098a60fc5525960445b25e6e5aea09f4221be6cbb943b8d656a34bb89ffdbfdad89a645394c85d953fd9577f2ec359f37f90c66520e658cb5c4f8d6a
7
+ data.tar.gz: a5759301599ea3243f1cb0021910ad411145cb524312d9d653be7bf94aeba6866eab42515c9dc77cb7279743f73290652c312feba6682113e57720b1951eca40
@@ -5,7 +5,7 @@ rvm:
5
5
  - 2.0.0
6
6
  - 2.1
7
7
  - ruby-head
8
- - rbx
8
+ - rbx-2
9
9
 
10
10
  os:
11
11
  - linux
@@ -24,4 +24,4 @@ script: bundle exec rake
24
24
  matrix:
25
25
  allow_failures:
26
26
  - rvm: ruby-head
27
- - rvm: rbx
27
+ - rvm: rbx-2
@@ -0,0 +1,34 @@
1
+ # Contributing to Fluentd
2
+
3
+ We'd love your contribution. Here are the guidelines!
4
+
5
+ ## Got a question or problem?
6
+
7
+ RESOURCES of [Official site](http://www.fluentd.org/) and [Fluentd documentation](http://docs.fluentd.org/) may help you.
8
+
9
+ If you have further questions about Fluentd and plugins, please direct these to [Mailing List](https://groups.google.com/forum/#!forum/fluentd).
10
+
11
+ Don't use Github issue for asking questions.
12
+ Github issue is mainly for submitting a bug report or feature request. See below.
13
+
14
+ ## Found a bug?
15
+
16
+ If you find a bug of Fluentd or a mistake in the documentation, you can help us by
17
+ submitting an issue to Fluentd. Even better you can submit a Pull Request with a fix.
18
+
19
+ * **Fluentd**: Use [fluentd](https://github.com/fluent/fluentd) repository.
20
+ * **Documentation**: Use [fluentd-docs](https://github.com/fluent/fluentd-docs) repository.
21
+
22
+ If you find a bug of 3rd party plugins, please submit an issue to each plugin repository.
23
+
24
+ ## Patch Guidelines
25
+
26
+ Here are some things that would increase a chance that your patch is accepted:
27
+
28
+ * Write tests.
29
+ * Run tests before send Pull Request by `bundle exec rake test`
30
+ * Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
31
+
32
+ There are some patches which are hard to write tests, e.g. process handling, concurrency issue or etc.
33
+ In such case, please don't hesitate to submit a Pull Request.
34
+ We can discuss how to manage a patch on Pull Request :)
data/ChangeLog CHANGED
@@ -1,3 +1,14 @@
1
+ Release 0.10.51 - 2014/07/04
2
+
3
+ * in_tail: Fix rotation handling when new file not found
4
+ * in_syslog: Change debug log level to warn at pattern mismatch
5
+ * formatter: Use localtime by default
6
+ * parser: Add SyslogParser
7
+ * parser: Add "estimate_current_event" attribute to TextParsers not to set current time into parse result
8
+ * config: Add <system> section to set core parameters via configuration file
9
+ * test: Support v1 configuration in TestDriver
10
+ * Add udp and tcp input plugins
11
+
1
12
  Release 0.10.50 - 2014/06/17
2
13
 
3
14
  * in_tail: Fix race condition at shutdown
data/README.md CHANGED
@@ -22,11 +22,11 @@ An event consists of *tag*, *time* and *record*. Tag is a string separated with
22
22
 
23
23
  ## More Information
24
24
 
25
- - Web site: http://fluentd.org/
26
- - Documents: http://docs.fluentd.org/
25
+ - Website: http://fluentd.org/
26
+ - Documentation: http://docs.fluentd.org/
27
27
  - Source repository: http://github.com/fluent
28
28
  - Discussion: http://groups.google.com/group/fluentd
29
- - News Letters: http://go.treasuredata.com/Fluentd_education
29
+ - Newsletters: http://get.treasuredata.com/Fluentd_education
30
30
  - Author: Sadayuki Furuhashi
31
31
  - Copyright: (c) 2011 FURUHASHI Sadayuki
32
32
  - License: Apache License, Version 2.0
data/Rakefile CHANGED
@@ -11,6 +11,9 @@ task :test => [:base_test, :spec]
11
11
 
12
12
  desc 'Run test_unit based test'
13
13
  Rake::TestTask.new(:base_test) do |t|
14
+ # To run test for only one file (or file path pattern)
15
+ # $ bundle exec rake base_test TEST=test/test_specified_path.rb
16
+ # $ bundle exec rake base_test TEST=test/test_*.rb
14
17
  t.libs << "test"
15
18
  t.test_files = (Dir["test/test_*.rb"] + Dir["test/plugin/test_*.rb"] - ["helper.rb"]).sort
16
19
  t.verbose = true
@@ -38,6 +38,7 @@
38
38
  # Listen DRb for debug
39
39
  <source>
40
40
  type debug_agent
41
+ bind 127.0.0.1
41
42
  port 24230
42
43
  </source>
43
44
 
@@ -20,23 +20,18 @@ module Fluent
20
20
  require 'fluent/config/element'
21
21
 
22
22
  module Config
23
- def self.read(path, v1_config = false)
24
- if v1_config
25
- require 'fluent/config/v1_parser'
26
- V1Parser.read(path)
27
- else
28
- require 'fluent/config/parser'
29
- Parser.read(path)
30
- end
31
- end
32
-
33
23
  def self.parse(str, fname, basepath = Dir.pwd, v1_config = false)
34
- if v1_config
35
- require 'fluent/config/v1_parser'
36
- V1Parser.parse(str, fname, basepath, Kernel.binding)
24
+ if fname =~ /\.rb$/
25
+ require 'fluent/config/dsl'
26
+ Config::DSL::Parser.parse(str, File.join(basepath, fname))
37
27
  else
38
- require 'fluent/config/parser'
39
- Parser.parse(str, fname, basepath)
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
40
35
  end
41
36
  end
42
37
 
@@ -4,13 +4,6 @@ module Fluent
4
4
  require 'fluent/config/element'
5
5
 
6
6
  class Parser
7
- def self.read(path)
8
- path = File.expand_path(path)
9
- File.open(path) { |io|
10
- parse(io, File.basename(path), File.dirname(path))
11
- }
12
- end
13
-
14
7
  def self.parse(io, fname, basepath = Dir.pwd)
15
8
  attrs, elems = Parser.new(basepath, io.each_line, fname).parse!(true)
16
9
  Element.new('ROOT', '', attrs, elems)
@@ -24,12 +24,6 @@ module Fluent
24
24
  class V1Parser < LiteralParser
25
25
  ELEMENT_NAME = /[a-zA-Z0-9_]+/
26
26
 
27
- def self.read(path, eval_context = nil)
28
- path = File.expand_path(path)
29
- data = File.read(path)
30
- parse(data, File.basename(path), File.dirname(path), eval_context)
31
- end
32
-
33
27
  def self.parse(data, fname, basepath = Dir.pwd, eval_context = nil)
34
28
  ss = StringScanner.new(data)
35
29
  ps = V1Parser.new(ss, basepath, fname, eval_context)
@@ -62,23 +62,19 @@ module Fluent
62
62
  @suppress_config_dump = flag
63
63
  end
64
64
 
65
- def read_config(path)
66
- $log.info "reading config file", :path=>path
67
- File.open(path) {|io|
68
- parse_config(io, File.basename(path), File.dirname(path))
69
- }
65
+ def parse_config(io, fname, basepath = Dir.pwd, v1_config = false)
66
+ if fname =~ /\.rb$/
67
+ require 'fluent/config/dsl'
68
+ Config::DSL::Parser.parse(io, File.join(basepath, fname))
69
+ else
70
+ Config.parse(io, fname, basepath, v1_config)
71
+ end
70
72
  end
71
73
 
72
- def parse_config(io, fname, basepath = Dir.pwd, v1_config = false)
73
- conf = if fname =~ /\.rb$/
74
- require 'fluent/config/dsl'
75
- Config::DSL::Parser.parse(io, File.join(basepath, fname))
76
- else
77
- Config.parse(io, fname, basepath, v1_config)
78
- end
74
+ def run_configure(conf)
79
75
  configure(conf)
80
- conf.check_not_fetched {|key,e|
81
- $log.warn "parameter '#{key}' in #{e.to_s.strip} is not used."
76
+ conf.check_not_fetched { |key, e|
77
+ $log.warn "parameter '#{key}' in #{e.to_s.strip} is not used." unless e.name == 'system'
82
78
  }
83
79
  end
84
80
 
@@ -27,6 +27,7 @@ module Fluent
27
27
  config_param :time_format, :string, :default => nil
28
28
  config_param :include_tag_key, :bool, :default => false
29
29
  config_param :tag_key, :string, :default => 'tag'
30
+ config_param :localtime, :bool, :default => true
30
31
  }
31
32
  end
32
33
 
@@ -35,8 +36,6 @@ module Fluent
35
36
 
36
37
  if conf['utc']
37
38
  @localtime = false
38
- elsif conf['localtime']
39
- @localtime = true
40
39
  end
41
40
  @timef = TimeFormatter.new(@time_format, @localtime)
42
41
  end
@@ -43,6 +43,18 @@ module Fluent
43
43
 
44
44
  LEVEL_TEXT = %w(trace debug info warn error fatal)
45
45
 
46
+ def self.str_to_level(log_level_str)
47
+ case log_level_str.downcase
48
+ when "trace" then LEVEL_TRACE
49
+ when "debug" then LEVEL_DEBUG
50
+ when "info" then LEVEL_INFO
51
+ when "warn" then LEVEL_WARN
52
+ when "error" then LEVEL_ERROR
53
+ when "fatal" then LEVEL_FATAL
54
+ else raise "Unknown log level: level = #{log_level_str}"
55
+ end
56
+ end
57
+
46
58
  def initialize(out=STDERR, level=LEVEL_TRACE, opts={})
47
59
  @out = out
48
60
  @level = level
@@ -313,15 +325,7 @@ module Fluent
313
325
  end
314
326
 
315
327
  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
328
+ @level = Log.str_to_level(log_level_str)
325
329
  end
326
330
 
327
331
  alias orig_enable_color enable_color
@@ -128,6 +128,10 @@ module Fluent
128
128
 
129
129
  config_param :time_format, :string, :default => nil
130
130
 
131
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
132
+ # 'configure()' may raise errors for unexpected configurations
133
+ attr_accessor :estimate_current_event
134
+
131
135
  def initialize(regexp, conf={})
132
136
  super()
133
137
  @regexp = regexp
@@ -136,6 +140,7 @@ module Fluent
136
140
  end
137
141
 
138
142
  @time_parser = TimeParser.new(@time_format)
143
+ @estimate_current_event = true
139
144
  @mutex = Mutex.new
140
145
  end
141
146
 
@@ -144,6 +149,10 @@ module Fluent
144
149
  @time_parser = TimeParser.new(@time_format)
145
150
  end
146
151
 
152
+ def patterns
153
+ {'format' => @regexp, 'time_format' => @time_format}
154
+ end
155
+
147
156
  def call(text)
148
157
  m = @regexp.match(text)
149
158
  unless m
@@ -173,7 +182,9 @@ module Fluent
173
182
  end
174
183
  }
175
184
 
176
- time ||= Engine.now
185
+ if @estimate_current_event
186
+ time ||= Engine.now
187
+ end
177
188
 
178
189
  if block_given?
179
190
  yield time, record
@@ -189,6 +200,15 @@ module Fluent
189
200
  config_param :time_key, :string, :default => 'time'
190
201
  config_param :time_format, :string, :default => nil
191
202
 
203
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
204
+ # 'configure()' may raise errors for unexpected configurations
205
+ attr_accessor :estimate_current_event
206
+
207
+ def initialize
208
+ super
209
+ @estimate_current_event = true
210
+ end
211
+
192
212
  def configure(conf)
193
213
  super
194
214
 
@@ -208,7 +228,11 @@ module Fluent
208
228
  time = value.to_i
209
229
  end
210
230
  else
211
- time = Engine.now
231
+ if @estimate_current_event
232
+ time = Engine.now
233
+ else
234
+ time = nil
235
+ end
212
236
  end
213
237
 
214
238
  if block_given?
@@ -233,12 +257,21 @@ module Fluent
233
257
  config_param :time_key, :string, :default => nil
234
258
  config_param :time_format, :string, :default => nil
235
259
 
260
+ # SET false BEFORE CONFIGURE, to return nil when time not parsed
261
+ # 'configure()' may raise errors for unexpected configurations
262
+ attr_accessor :estimate_current_event
263
+
264
+ def initialize
265
+ super
266
+ @estimate_current_event = true
267
+ end
268
+
236
269
  def configure(conf)
237
270
  super
238
271
 
239
272
  @keys = @keys.split(",")
240
273
 
241
- if @time_key && !@keys.include?(@time_key)
274
+ if @time_key && !@keys.include?(@time_key) && @estimate_current_event
242
275
  raise ConfigError, "time_key (#{@time_key.inspect}) is not included in keys (#{@keys.inspect})"
243
276
  end
244
277
 
@@ -256,12 +289,18 @@ module Fluent
256
289
  if @time_key
257
290
  value = record.delete(@time_key)
258
291
  time = if value.nil?
259
- Engine.now
292
+ if @estimate_current_event
293
+ Engine.now
294
+ else
295
+ nil
296
+ end
260
297
  else
261
298
  @mutex.synchronize { @time_parser.parse(value) }
262
299
  end
263
- else
300
+ elsif @estimate_current_event
264
301
  time = Engine.now
302
+ else
303
+ time = nil
265
304
  end
266
305
 
267
306
  convert_field_type!(record) if @type_converters
@@ -340,13 +379,21 @@ module Fluent
340
379
 
341
380
  config_param :message_key, :string, :default => 'message'
342
381
 
382
+ attr_accessor :estimate_current_event
383
+
384
+ def initialize
385
+ super
386
+ @estimate_current_event = true
387
+ end
388
+
343
389
  def call(text)
344
390
  record = {}
345
391
  record[@message_key] = text
392
+ time = @estimate_current_event ? Engine.now : nil
346
393
  if block_given?
347
- yield Engine.now, record
394
+ yield time, record
348
395
  else
349
- return Engine.now, record
396
+ return time, record
350
397
  end
351
398
  end
352
399
  end
@@ -355,12 +402,17 @@ module Fluent
355
402
  include Configurable
356
403
 
357
404
  REGEXP = /^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/
405
+ TIME_FORMAT = "%d/%b/%Y:%H:%M:%S %z"
358
406
 
359
407
  def initialize
360
- @time_parser = TimeParser.new("%d/%b/%Y:%H:%M:%S %z")
408
+ @time_parser = TimeParser.new(TIME_FORMAT)
361
409
  @mutex = Mutex.new
362
410
  end
363
411
 
412
+ def patterns
413
+ {'format' => REGEXP, 'time_format' => TIME_FORMAT}
414
+ end
415
+
364
416
  def call(text)
365
417
  m = REGEXP.match(text)
366
418
  unless m
@@ -415,6 +467,75 @@ module Fluent
415
467
  end
416
468
  end
417
469
 
470
+ class SyslogParser
471
+ include Configurable
472
+
473
+ # From existence TextParser pattern
474
+ REGEXP = /^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/
475
+ # From in_syslog default pattern
476
+ REGEXP_WITH_PRI = /^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/
477
+ TIME_FORMAT = "%b %d %H:%M:%S"
478
+
479
+ config_param :with_priority, :bool, :default => false
480
+
481
+ attr_accessor :estimate_current_event
482
+
483
+ def initialize
484
+ super
485
+ @estimate_current_event = true
486
+ @time_parser = TextParser::TimeParser.new(TIME_FORMAT)
487
+ @mutex = Mutex.new
488
+ end
489
+
490
+ def configure(conf)
491
+ super
492
+
493
+ @regexp = @with_priority ? REGEXP_WITH_PRI : REGEXP
494
+ end
495
+
496
+ def patterns
497
+ {'format' => @regexp, 'time_format' => TIME_FORMAT}
498
+ end
499
+
500
+ def call(text)
501
+ m = @regexp.match(text)
502
+ unless m
503
+ if block_given?
504
+ yield nil, nil
505
+ return
506
+ else
507
+ return nil, nil
508
+ end
509
+ end
510
+
511
+ time = nil
512
+ record = {}
513
+
514
+ m.names.each { |name|
515
+ if value = m[name]
516
+ case name
517
+ when "pri"
518
+ record['pri'] = value.to_i
519
+ when "time"
520
+ time = @mutex.synchronize { @time_parser.parse(value.gsub(/ +/, ' ')) }
521
+ else
522
+ record[name] = value
523
+ end
524
+ end
525
+ }
526
+
527
+ if @estimate_current_event
528
+ time ||= Engine.now
529
+ end
530
+
531
+ if block_given?
532
+ yield time, record
533
+ else
534
+ return time, record
535
+ end
536
+ end
537
+ end
538
+
418
539
  class MultilineParser
419
540
  include Configurable
420
541
 
@@ -504,7 +625,7 @@ module Fluent
504
625
  {
505
626
  'apache' => Proc.new { RegexpParser.new(/^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$/, {'time_format'=>"%d/%b/%Y:%H:%M:%S %z"}) },
506
627
  'apache2' => Proc.new { ApacheParser.new },
507
- 'syslog' => Proc.new { RegexpParser.new(/^(?<time>[^ ]*\s*[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?[^\:]*\: *(?<message>.*)$/, {'time_format'=>"%b %d %H:%M:%S"}) },
628
+ 'syslog' => Proc.new { SyslogParser.new },
508
629
  'json' => Proc.new { JSONParser.new },
509
630
  'tsv' => Proc.new { TSVParser.new },
510
631
  'ltsv' => Proc.new { LabeledTSVParser.new },