fluentd 0.14.1 → 0.14.2

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.

Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +110 -1
  3. data/Rakefile +5 -1
  4. data/appveyor.yml +7 -1
  5. data/example/in_forward.conf +4 -0
  6. data/lib/fluent/compat/exec_util.rb +129 -0
  7. data/lib/fluent/compat/file_util.rb +54 -0
  8. data/lib/fluent/compat/filter.rb +21 -3
  9. data/lib/fluent/compat/formatter.rb +4 -2
  10. data/lib/fluent/compat/formatter_utils.rb +85 -0
  11. data/lib/fluent/compat/handle_tag_and_time_mixin.rb +60 -0
  12. data/lib/fluent/compat/input.rb +1 -3
  13. data/lib/fluent/compat/output.rb +95 -39
  14. data/lib/fluent/compat/parser.rb +17 -0
  15. data/lib/fluent/compat/parser_utils.rb +40 -0
  16. data/lib/fluent/compat/socket_util.rb +165 -0
  17. data/lib/fluent/compat/string_util.rb +34 -0
  18. data/lib/fluent/{test/driver/owner.rb → compat/structured_format_mixin.rb} +5 -11
  19. data/lib/fluent/config/element.rb +2 -2
  20. data/lib/fluent/configurable.rb +2 -1
  21. data/lib/fluent/event.rb +61 -7
  22. data/lib/fluent/event_router.rb +1 -1
  23. data/lib/fluent/plugin.rb +7 -7
  24. data/lib/fluent/plugin/buf_file.rb +5 -2
  25. data/lib/fluent/plugin/buffer.rb +194 -64
  26. data/lib/fluent/plugin/buffer/chunk.rb +28 -3
  27. data/lib/fluent/plugin/buffer/file_chunk.rb +5 -21
  28. data/lib/fluent/plugin/buffer/memory_chunk.rb +1 -11
  29. data/lib/fluent/plugin/exec_util.rb +2 -112
  30. data/lib/fluent/plugin/file_util.rb +3 -38
  31. data/lib/fluent/plugin/file_wrapper.rb +1 -1
  32. data/lib/fluent/plugin/filter_grep.rb +3 -7
  33. data/lib/fluent/plugin/filter_record_transformer.rb +5 -5
  34. data/lib/fluent/plugin/filter_stdout.rb +18 -11
  35. data/lib/fluent/plugin/formatter.rb +0 -48
  36. data/lib/fluent/plugin/formatter_csv.rb +7 -8
  37. data/lib/fluent/plugin/formatter_hash.rb +1 -4
  38. data/lib/fluent/plugin/formatter_json.rb +1 -4
  39. data/lib/fluent/plugin/formatter_ltsv.rb +5 -6
  40. data/lib/fluent/plugin/formatter_msgpack.rb +1 -4
  41. data/lib/fluent/plugin/formatter_out_file.rb +36 -3
  42. data/lib/fluent/plugin/formatter_stdout.rb +36 -1
  43. data/lib/fluent/plugin/in_dummy.rb +9 -2
  44. data/lib/fluent/plugin/in_exec.rb +20 -57
  45. data/lib/fluent/plugin/in_forward.rb +4 -3
  46. data/lib/fluent/plugin/in_object_space.rb +8 -44
  47. data/lib/fluent/plugin/in_syslog.rb +13 -24
  48. data/lib/fluent/plugin/in_tail.rb +3 -0
  49. data/lib/fluent/plugin/out_buffered_stdout.rb +14 -4
  50. data/lib/fluent/plugin/out_exec.rb +7 -5
  51. data/lib/fluent/plugin/out_exec_filter.rb +10 -10
  52. data/lib/fluent/plugin/out_file.rb +1 -3
  53. data/lib/fluent/plugin/out_forward.rb +38 -57
  54. data/lib/fluent/plugin/out_stdout.rb +14 -5
  55. data/lib/fluent/plugin/out_stream.rb +3 -0
  56. data/lib/fluent/plugin/output.rb +31 -14
  57. data/lib/fluent/plugin/parser.rb +0 -69
  58. data/lib/fluent/plugin/parser_apache.rb +10 -6
  59. data/lib/fluent/plugin/parser_apache_error.rb +8 -3
  60. data/lib/fluent/plugin/parser_csv.rb +3 -1
  61. data/lib/fluent/plugin/parser_json.rb +1 -1
  62. data/lib/fluent/plugin/parser_multiline.rb +5 -3
  63. data/lib/fluent/plugin/parser_nginx.rb +10 -6
  64. data/lib/fluent/plugin/parser_regexp.rb +73 -0
  65. data/lib/fluent/plugin/socket_util.rb +2 -148
  66. data/lib/fluent/plugin/storage_local.rb +1 -1
  67. data/lib/fluent/plugin/string_util.rb +3 -18
  68. data/lib/fluent/plugin_helper.rb +1 -0
  69. data/lib/fluent/plugin_helper/compat_parameters.rb +166 -41
  70. data/lib/fluent/plugin_helper/formatter.rb +30 -19
  71. data/lib/fluent/plugin_helper/inject.rb +25 -12
  72. data/lib/fluent/plugin_helper/parser.rb +22 -13
  73. data/lib/fluent/plugin_helper/storage.rb +22 -13
  74. data/lib/fluent/registry.rb +19 -6
  75. data/lib/fluent/supervisor.rb +27 -1
  76. data/lib/fluent/test/driver/base.rb +16 -92
  77. data/lib/fluent/test/driver/base_owned.rb +17 -53
  78. data/lib/fluent/test/driver/base_owner.rb +125 -0
  79. data/lib/fluent/test/driver/filter.rb +24 -2
  80. data/lib/fluent/test/driver/input.rb +2 -2
  81. data/lib/fluent/test/driver/multi_output.rb +2 -2
  82. data/lib/fluent/test/driver/output.rb +3 -5
  83. data/lib/fluent/test/helpers.rb +25 -0
  84. data/lib/fluent/test/input_test.rb +4 -4
  85. data/lib/fluent/test/output_test.rb +3 -3
  86. data/lib/fluent/version.rb +1 -1
  87. data/test/config/test_element.rb +135 -6
  88. data/test/plugin/test_buf_file.rb +71 -3
  89. data/test/plugin/test_buffer.rb +305 -86
  90. data/test/plugin/test_buffer_chunk.rb +60 -2
  91. data/test/plugin/test_buffer_file_chunk.rb +4 -3
  92. data/test/plugin/test_filter_grep.rb +25 -21
  93. data/test/plugin/test_filter_record_transformer.rb +75 -67
  94. data/test/plugin/test_filter_stdout.rb +171 -74
  95. data/test/plugin/test_formatter_csv.rb +94 -0
  96. data/test/plugin/test_formatter_json.rb +30 -0
  97. data/test/plugin/test_formatter_ltsv.rb +52 -0
  98. data/test/plugin/test_formatter_msgpack.rb +28 -0
  99. data/test/plugin/test_formatter_out_file.rb +95 -0
  100. data/test/plugin/test_formatter_single_value.rb +38 -0
  101. data/test/plugin/test_in_dummy.rb +95 -0
  102. data/test/plugin/test_in_exec.rb +27 -31
  103. data/test/plugin/test_in_forward.rb +24 -0
  104. data/test/plugin/test_in_gc_stat.rb +5 -5
  105. data/test/plugin/test_in_object_space.rb +4 -4
  106. data/test/plugin/test_in_syslog.rb +60 -35
  107. data/test/plugin/test_out_buffered_stdout.rb +17 -3
  108. data/test/plugin/test_out_forward.rb +93 -5
  109. data/test/plugin/test_out_stdout.rb +14 -3
  110. data/test/plugin/test_output_as_buffered_retries.rb +20 -0
  111. data/test/plugin/test_output_as_buffered_secondary.rb +16 -0
  112. data/test/plugin/test_output_as_standard.rb +22 -22
  113. data/test/plugin/test_parser_apache.rb +13 -9
  114. data/test/plugin/test_parser_apache_error.rb +11 -6
  115. data/test/plugin/test_parser_csv.rb +35 -25
  116. data/test/plugin/test_parser_nginx.rb +11 -5
  117. data/test/plugin/test_parser_regexp.rb +235 -68
  118. data/test/plugin/test_parser_tsv.rb +54 -58
  119. data/test/plugin_helper/test_compat_parameters.rb +111 -46
  120. data/test/plugin_helper/test_formatter.rb +40 -0
  121. data/test/plugin_helper/test_inject.rb +101 -2
  122. data/test/plugin_helper/test_parser.rb +40 -0
  123. data/test/plugin_helper/test_storage.rb +43 -0
  124. data/test/test_event.rb +93 -0
  125. data/test/test_event_router.rb +13 -4
  126. data/test/test_event_time.rb +0 -3
  127. data/test/test_formatter.rb +7 -164
  128. data/test/test_plugin_classes.rb +28 -1
  129. metadata +24 -3
@@ -51,8 +51,8 @@ module Fluent
51
51
  @unique_id = generate_unique_id
52
52
  @metadata = metadata
53
53
 
54
- # state: staged/queued/closed
55
- @state = :staged
54
+ # state: unstaged/staged/queued/closed
55
+ @state = :unstaged
56
56
 
57
57
  @size = 0
58
58
  @created_at = Time.now
@@ -63,7 +63,11 @@ module Fluent
63
63
 
64
64
  # data is array of formatted record string
65
65
  def append(data)
66
- raise NotImplementedError, "Implement this method in child class"
66
+ adding = ''.b
67
+ data.each do |d|
68
+ adding << d.b
69
+ end
70
+ concat(adding, data.size)
67
71
  end
68
72
 
69
73
  # for event streams which is packed or zipped (and we want not to unpack/uncompress)
@@ -92,6 +96,14 @@ module Fluent
92
96
  size == 0
93
97
  end
94
98
 
99
+ def writable?
100
+ @state == :staged || @state == :unstaged
101
+ end
102
+
103
+ def unstaged?
104
+ @state == :unstaged
105
+ end
106
+
95
107
  def staged?
96
108
  @state == :staged
97
109
  end
@@ -104,16 +116,29 @@ module Fluent
104
116
  @state == :closed
105
117
  end
106
118
 
119
+ def staged!
120
+ @state = :staged
121
+ self
122
+ end
123
+
124
+ def unstaged!
125
+ @state = :unstaged
126
+ self
127
+ end
128
+
107
129
  def enqueued!
108
130
  @state = :queued
131
+ self
109
132
  end
110
133
 
111
134
  def close
112
135
  @state = :closed
136
+ self
113
137
  end
114
138
 
115
139
  def purge
116
140
  @state = :closed
141
+ self
117
142
  end
118
143
 
119
144
  def read
@@ -55,26 +55,8 @@ module Fluent
55
55
  end
56
56
  end
57
57
 
58
- def append(data)
59
- raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
60
-
61
- bytes = 0
62
- adding = ''.force_encoding(Encoding::ASCII_8BIT)
63
- data.each do |d|
64
- x = d.force_encoding(Encoding::ASCII_8BIT)
65
- bytes += x.bytesize
66
- adding << x
67
- end
68
- @chunk.write adding
69
-
70
- @adding_bytes += bytes
71
- @adding_size += data.size
72
-
73
- true
74
- end
75
-
76
58
  def concat(bulk, bulk_size)
77
- raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
59
+ raise "BUG: concatenating to unwritable chunk, now '#{self.state}'" unless self.writable?
78
60
 
79
61
  bulk.force_encoding(Encoding::ASCII_8BIT)
80
62
  @chunk.write bulk
@@ -167,7 +149,9 @@ module Fluent
167
149
  if /\.(b|q)([0-9a-f]+)\.[^\/]*\Z/n =~ path # //n switch means explicit 'ASCII-8BIT' pattern
168
150
  $1 == 'b' ? :staged : :queued
169
151
  else
170
- :queued
152
+ # files which matches to glob of buffer file pattern
153
+ # it includes files which are created by out_file
154
+ :unknown
171
155
  end
172
156
  end
173
157
 
@@ -267,7 +251,7 @@ module Fluent
267
251
  @meta.sync = true
268
252
  @meta.binmode
269
253
 
270
- @state = :staged
254
+ @state = :unstaged
271
255
  @bytesize = 0
272
256
  @commit_position = @chunk.pos # must be 0
273
257
  @adding_bytes = 0
@@ -28,18 +28,8 @@ module Fluent
28
28
  @adding_size = 0
29
29
  end
30
30
 
31
- def append(data)
32
- raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
33
-
34
- adding = data.join.force_encoding(Encoding::ASCII_8BIT)
35
- @chunk << adding
36
- @adding_bytes += adding.bytesize
37
- @adding_size += data.size
38
- true
39
- end
40
-
41
31
  def concat(bulk, bulk_size)
42
- raise "BUG: appending to non-staged chunk, now '#{self.state}'" unless self.staged?
32
+ raise "BUG: concatenating to unwritable chunk, now '#{self.state}'" unless self.writable?
43
33
 
44
34
  bulk.force_encoding(Encoding::ASCII_8BIT)
45
35
  @chunk << bulk
@@ -14,119 +14,9 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'msgpack'
18
- require 'yajl'
19
-
20
- require 'fluent/engine'
21
- require 'fluent/plugin'
22
- require 'fluent/parser'
17
+ require 'fluent/compat/exec_util'
23
18
 
24
19
  module Fluent
25
- module Plugin
26
- module ExecUtil
27
- SUPPORTED_FORMAT = {
28
- 'tsv' => :tsv,
29
- 'json' => :json,
30
- 'msgpack' => :msgpack,
31
- }
32
-
33
- class Parser
34
- def initialize(on_message)
35
- @on_message = on_message
36
- end
37
- end
38
-
39
- class TextParserWrapperParser < Parser
40
- def initialize(conf, on_message)
41
- @parser = Plugin.new_parser(conf['format'])
42
- @parser.configure(conf)
43
- super(on_message)
44
- end
45
-
46
- def call(io)
47
- io.each_line(&method(:each_line))
48
- end
49
-
50
- def each_line(line)
51
- line.chomp!
52
- @parser.parse(line) { |time, record|
53
- @on_message.call(record, time)
54
- }
55
- end
56
- end
57
-
58
- class TSVParser < Parser
59
- def initialize(keys, on_message)
60
- @keys = keys
61
- super(on_message)
62
- end
63
-
64
- def call(io)
65
- io.each_line(&method(:each_line))
66
- end
67
-
68
- def each_line(line)
69
- line.chomp!
70
- vals = line.split("\t")
71
-
72
- record = Hash[@keys.zip(vals)]
73
-
74
- @on_message.call(record)
75
- end
76
- end
77
-
78
- class JSONParser < Parser
79
- def call(io)
80
- y = Yajl::Parser.new
81
- y.on_parse_complete = @on_message
82
- y.parse(io)
83
- end
84
- end
85
-
86
- class MessagePackParser < Parser
87
- def call(io)
88
- @u = Fluent::Engine.msgpack_factory.unpacker(io)
89
- begin
90
- @u.each(&@on_message)
91
- rescue EOFError
92
- end
93
- end
94
- end
95
-
96
- class Formatter
97
- end
98
-
99
- class TSVFormatter < Formatter
100
- def initialize(in_keys)
101
- @in_keys = in_keys
102
- super()
103
- end
104
-
105
- def call(record, out)
106
- last = @in_keys.length-1
107
- for i in 0..last
108
- key = @in_keys[i]
109
- out << record[key].to_s
110
- out << "\t" if i != last
111
- end
112
- out << "\n"
113
- end
114
- end
115
-
116
- class JSONFormatter < Formatter
117
- def call(record, out)
118
- out << Yajl.dump(record) << "\n"
119
- end
120
- end
121
-
122
- class MessagePackFormatter < Formatter
123
- def call(record, out)
124
- record.to_msgpack(out)
125
- end
126
- end
127
- end
128
- end
129
-
130
20
  # obsolete
131
- ExecUtil = Fluent::Plugin::ExecUtil
21
+ ExecUtil = Fluent::Compat::ExecUtil
132
22
  end
@@ -14,44 +14,9 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- module Fluent
18
- module Plugin
19
- module FileUtil
20
- # Check file is writable if file exists
21
- # Check directory is writable if file does not exist
22
- #
23
- # @param [String] path File path
24
- # @return [Boolean] file is writable or not
25
- def writable?(path)
26
- return false if File.directory?(path)
27
- return File.writable?(path) if File.exist?(path)
28
-
29
- dirname = File.dirname(path)
30
- return false if !File.directory?(dirname)
31
- File.writable?(dirname)
32
- end
33
- module_function :writable?
34
-
35
- # Check file is writable in conjunction wtih mkdir_p(dirname(path))
36
- #
37
- # @param [String] path File path
38
- # @return [Boolean] file writable or not
39
- def writable_p?(path)
40
- return false if File.directory?(path)
41
- return File.writable?(path) if File.exist?(path)
42
-
43
- dirname = File.dirname(path)
44
- until File.exist?(dirname)
45
- dirname = File.dirname(dirname)
46
- end
47
-
48
- return false if !File.directory?(dirname)
49
- File.writable?(dirname)
50
- end
51
- module_function :writable_p?
52
- end
53
- end
17
+ require 'fluent/compat/file_util'
54
18
 
19
+ module Fluent
55
20
  # obsolete
56
- FileUtil = Fluent::Plugin::FileUtil
21
+ FileUtil = Fluent::Compat::FileUtil
57
22
  end
@@ -78,7 +78,7 @@ module Fluent
78
78
  0, creationdisposition, FILE_ATTRIBUTE_NORMAL, 0)
79
79
  if @file_handle == INVALID_HANDLE_VALUE
80
80
  err = GetLastError.call
81
- if err == ERROR_FILE_NOT_FOUND || err == ERROR_ACCESS_DENIED
81
+ if err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND || err == ERROR_ACCESS_DENIED
82
82
  raise SystemCallError.new(2)
83
83
  end
84
84
  raise SystemCallError.new(err)
@@ -14,18 +14,14 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/filter'
17
+ require 'fluent/plugin/filter'
18
18
  require 'fluent/config/error'
19
+ require 'fluent/plugin/string_util'
19
20
 
20
- module Fluent
21
+ module Fluent::Plugin
21
22
  class GrepFilter < Filter
22
23
  Fluent::Plugin.register_filter('grep', self)
23
24
 
24
- def initialize
25
- super
26
- require 'fluent/plugin/string_util'
27
- end
28
-
29
25
  REGEXP_MAX_NUM = 20
30
26
 
31
27
  (1..REGEXP_MAX_NUM).each {|i| config_param :"regexp#{i}", :string, default: nil }
@@ -18,13 +18,13 @@ require 'socket'
18
18
  require 'json'
19
19
  require 'ostruct'
20
20
 
21
- require 'fluent/filter'
21
+ require 'fluent/plugin/filter'
22
22
  require 'fluent/config/error'
23
23
  require 'fluent/event'
24
24
  require 'fluent/time'
25
25
 
26
- module Fluent
27
- class RecordTransformerFilter < Filter
26
+ module Fluent::Plugin
27
+ class RecordTransformerFilter < Fluent::Plugin::Filter
28
28
  Fluent::Plugin.register_filter('record_transformer', self)
29
29
 
30
30
  desc 'A comma-delimited list of keys to delete.'
@@ -81,7 +81,7 @@ module Fluent
81
81
  end
82
82
 
83
83
  def filter_stream(tag, es)
84
- new_es = MultiEventStream.new
84
+ new_es = Fluent::MultiEventStream.new
85
85
  tag_parts = tag.split('.')
86
86
  tag_prefix = tag_prefix(tag_parts)
87
87
  tag_suffix = tag_suffix(tag_parts)
@@ -101,7 +101,7 @@ module Fluent
101
101
  })
102
102
  new_record = reform(record, placeholder_values)
103
103
  if @renew_time_key && new_record.has_key?(@renew_time_key)
104
- time = EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
104
+ time = Fluent::EventTime.from_time(Time.at(new_record[@renew_time_key].to_f))
105
105
  end
106
106
  new_es.add(time, new_record)
107
107
  end
@@ -14,31 +14,38 @@
14
14
  # limitations under the License.
15
15
  #
16
16
 
17
- require 'fluent/filter'
18
- require 'fluent/plugin'
17
+ require 'fluent/plugin/filter'
19
18
 
20
- module Fluent
19
+ module Fluent::Plugin
21
20
  class StdoutFilter < Filter
22
- Plugin.register_filter('stdout', self)
21
+ Fluent::Plugin.register_filter('stdout', self)
22
+
23
+ helpers :formatter, :compat_parameters, :inject
24
+
25
+ DEFAULT_FORMAT_TYPE = 'stdout'
26
+
27
+ config_section :format do
28
+ config_set_default :@type, DEFAULT_FORMAT_TYPE
29
+ end
23
30
 
24
31
  # for tests
25
32
  attr_reader :formatter
26
33
 
27
- desc 'The format of the output.'
28
- config_param :format, :string, default: 'stdout'
29
- # config_param :output_type, :string, :default => 'json' (StdoutFormatter defines this)
30
-
31
34
  def configure(conf)
35
+ compat_parameters_convert(conf, :inject, :formatter)
32
36
  super
37
+ end
33
38
 
34
- @formatter = Plugin.new_formatter(@format)
35
- @formatter.configure(conf)
39
+ def start
40
+ @formatter = formatter_create(conf: @config.elements('format').first, default_type: DEFAULT_FORMAT_TYPE)
41
+ super
36
42
  end
37
43
 
38
44
  def filter_stream(tag, es)
39
45
  es.each { |time, record|
40
46
  begin
41
- log.write @formatter.format(tag, time, record)
47
+ r = inject_values_to_record(tag, time, record)
48
+ log.write @formatter.format(tag, time, r)
42
49
  rescue => e
43
50
  router.emit_error_event(tag, time, record, e)
44
51
  end
@@ -29,54 +29,6 @@ module Fluent
29
29
  def format(tag, time, record)
30
30
  raise NotImplementedError, "Implement this method in child class"
31
31
  end
32
-
33
- # Mixins for formatter plugins
34
- module HandleTagAndTimeMixin
35
- def self.included(klass)
36
- klass.instance_eval {
37
- config_param :include_time_key, :bool, default: false
38
- config_param :time_key, :string, default: 'time'
39
- config_param :time_format, :string, default: nil
40
- config_param :time_as_epoch, :bool, default: false
41
- config_param :include_tag_key, :bool, default: false
42
- config_param :tag_key, :string, default: 'tag'
43
- config_param :localtime, :bool, default: true
44
- config_param :timezone, :string, default: nil
45
- }
46
- end
47
-
48
- def configure(conf)
49
- super
50
-
51
- if conf['utc']
52
- @localtime = false
53
- end
54
- @timef = Fluent::TimeFormatter.new(@time_format, @localtime, @timezone)
55
- if @time_as_epoch && !@include_time_key
56
- log.warn "time_as_epoch will be ignored because include_time_key is false"
57
- end
58
- end
59
-
60
- def filter_record(tag, time, record)
61
- if @include_tag_key
62
- record[@tag_key] = tag
63
- end
64
- if @include_time_key
65
- if @time_as_epoch
66
- record[@time_key] = time.to_i
67
- else
68
- record[@time_key] = @timef.format(time)
69
- end
70
- end
71
- end
72
- end
73
-
74
- module StructuredFormatMixin
75
- def format(tag, time, record)
76
- filter_record(tag, time, record)
77
- format_record(record)
78
- end
79
- end
80
32
  end
81
33
 
82
34
  class ProcWrappedFormatter < Formatter