fluentd 0.10.52 → 0.10.53
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 +4 -4
- data/AUTHORS +1 -0
- data/ChangeLog +14 -0
- data/README.md +6 -2
- data/lib/fluent/config/configure_proxy.rb +3 -2
- data/lib/fluent/config/element.rb +17 -3
- data/lib/fluent/config/literal_parser.rb +23 -0
- data/lib/fluent/config/section.rb +7 -2
- data/lib/fluent/config/types.rb +2 -2
- data/lib/fluent/config/v1_parser.rb +4 -1
- data/lib/fluent/event.rb +17 -30
- data/lib/fluent/mixin.rb +21 -46
- data/lib/fluent/output.rb +19 -18
- data/lib/fluent/parser.rb +10 -2
- data/lib/fluent/plugin/in_debug_agent.rb +1 -1
- data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
- data/lib/fluent/plugin/in_syslog.rb +4 -0
- data/lib/fluent/plugin/in_tail.rb +2 -0
- data/lib/fluent/supervisor.rb +4 -1
- data/lib/fluent/test/input_test.rb +22 -8
- data/lib/fluent/version.rb +1 -1
- data/spec/config/config_parser_spec.rb +12 -1
- data/spec/config/configurable_spec.rb +152 -1
- data/spec/config/system_config_spec.rb +49 -0
- data/test/plugin/test_in_forward.rb +0 -5
- data/test/plugin/test_in_object_space.rb +6 -6
- data/test/plugin/test_in_stream.rb +0 -5
- data/test/plugin/test_in_syslog.rb +20 -1
- data/test/test_output.rb +12 -2
- data/test/test_parser.rb +55 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b76b903de67ead21383835723d9b289f437de46e
|
4
|
+
data.tar.gz: b1b787a0cc37983a878136b9731d5ad83eea40cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05b4ab5c735e1d6d01c059dde695faa7513180f1520b56f7078eedf9b1491fb00b9fd29aaec0f87f28784750a5c5aa210c5aaff2f5c9fe7740fad857c92b30ee
|
7
|
+
data.tar.gz: 075c930dd72a40427330313e11bf4e3fe5d4399ea91a44df072cbe6fb2605b584549b9075ae55234a999fd737ff805b24f0285969574cca485f360a9b9b6ffa8
|
data/AUTHORS
CHANGED
data/ChangeLog
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
Release 0.10.53 - 2014/08/21
|
2
|
+
|
3
|
+
* in_tail: Fix forget to detach Closer timer object
|
4
|
+
* in_debug_agent: Fix config_param type of unix_path
|
5
|
+
* in_syslog: Add include_source_host and source_host_Key options
|
6
|
+
* config: Dump V1 escaped parameter correctly at start phase
|
7
|
+
* config: Fix bug for config_param of bool value without defaults
|
8
|
+
* config: Add 'alias' option to config_section and config_param
|
9
|
+
* buffer: Add 'disable_retry_limit' option
|
10
|
+
* engine: Reduce memory usage when retry_limit is large
|
11
|
+
* parser: Add apache_error format
|
12
|
+
* supervisor: Dump Fluentd version at dry run mode
|
13
|
+
* test: InputTestDriver wait 'run' until input plugin emits all test data
|
14
|
+
|
1
15
|
Release 0.10.52 - 2014/07/15
|
2
16
|
|
3
17
|
* in_tail: Fix typo of warning argument. lb to line
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Fluentd: Open-Source Data Collector
|
2
2
|
===================================
|
3
3
|
|
4
|
-
[<img src="https://travis-ci.org/fluent/fluentd.
|
4
|
+
[<img src="https://travis-ci.org/fluent/fluentd.svg" />](https://travis-ci.org/fluent/fluentd) [![Code Climate](https://codeclimate.com/github/fluent/fluentd/badges/gpa.svg)](https://codeclimate.com/github/fluent/fluentd)
|
5
5
|
|
6
6
|
|
7
|
-
[Fluentd](http://fluentd.org/) collects events from various data sources and writes them to files,
|
7
|
+
[Fluentd](http://fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](http://www.fluentd.org/blog/unified-logging-layer)).
|
8
8
|
|
9
9
|
<p align="center">
|
10
10
|
<img src="http://docs.fluentd.org/images/fluentd-architecture.png" width="500px"/>
|
@@ -20,6 +20,10 @@ An event consists of *tag*, *time* and *record*. Tag is a string separated with
|
|
20
20
|
$ fluentd -c conf/fluent.conf &
|
21
21
|
$ echo '{"json":"message"}' | fluent-cat debug.test
|
22
22
|
|
23
|
+
## Fluentd UI: Admin GUI
|
24
|
+
|
25
|
+
[Fluentd UI](https://github.com/fluent/fluentd-ui) is a graphical user interface to start/stop/configure Fluentd.
|
26
|
+
|
23
27
|
## More Information
|
24
28
|
|
25
29
|
- Website: http://fluentd.org/
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Fluent
|
2
2
|
module Config
|
3
3
|
class ConfigureProxy
|
4
|
-
attr_accessor :name, :param_name, :required, :multi, :argument, :params, :defaults, :sections
|
4
|
+
attr_accessor :name, :param_name, :required, :multi, :alias, :argument, :params, :defaults, :sections
|
5
5
|
# config_param :desc, :string, :default => '....'
|
6
6
|
# config_set_default :buffer_type, :memory
|
7
7
|
#
|
@@ -12,7 +12,7 @@ module Fluent
|
|
12
12
|
# config_param :power, :integer
|
13
13
|
# end
|
14
14
|
#
|
15
|
-
# config_section :child, param_name: 'children', required: false, multi: true do
|
15
|
+
# config_section :child, param_name: 'children', required: false, multi: true, alias: 'node' do
|
16
16
|
# config_param :name, :string
|
17
17
|
# config_param :power, :integer, default: nil
|
18
18
|
# config_section :item do
|
@@ -26,6 +26,7 @@ module Fluent
|
|
26
26
|
@param_name = (opts[:param_name] || @name).to_sym
|
27
27
|
@required = opts[:required]
|
28
28
|
@multi = opts[:multi]
|
29
|
+
@alias = opts[:alias]
|
29
30
|
|
30
31
|
@argument = nil # nil: ignore argument
|
31
32
|
@params = {}
|
@@ -12,12 +12,14 @@ module Fluent
|
|
12
12
|
self[k] = v
|
13
13
|
}
|
14
14
|
@unused = unused || attrs.keys
|
15
|
+
@v1_config = false
|
15
16
|
end
|
16
17
|
|
17
|
-
attr_accessor :name, :arg, :elements, :unused
|
18
|
+
attr_accessor :name, :arg, :elements, :unused, :v1_config
|
18
19
|
|
19
20
|
def add_element(name, arg='')
|
20
21
|
e = Element.new(name, arg, {}, [])
|
22
|
+
e.v1_config = @v1_config
|
21
23
|
@elements << e
|
22
24
|
e
|
23
25
|
end
|
@@ -36,7 +38,9 @@ module Fluent
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def +(o)
|
39
|
-
Element.new(@name.dup, @arg.dup, o.merge(self), @elements + o.elements, (@unused + o.unused).uniq)
|
41
|
+
e = Element.new(@name.dup, @arg.dup, o.merge(self), @elements + o.elements, (@unused + o.unused).uniq)
|
42
|
+
e.v1_config = @v1_config
|
43
|
+
e
|
40
44
|
end
|
41
45
|
|
42
46
|
def each_element(*names, &block)
|
@@ -82,7 +86,11 @@ module Fluent
|
|
82
86
|
out << "#{indent}<#{@name} #{@arg}>\n"
|
83
87
|
end
|
84
88
|
each_pair { |k, v|
|
85
|
-
|
89
|
+
if @v1_config
|
90
|
+
out << "#{nindent}#{k} #{Element.unescape_parameter(v)}\n"
|
91
|
+
else
|
92
|
+
out << "#{nindent}#{k} #{v}\n"
|
93
|
+
end
|
86
94
|
}
|
87
95
|
@elements.each { |e|
|
88
96
|
out << e.to_s(nest + 1)
|
@@ -90,6 +98,12 @@ module Fluent
|
|
90
98
|
out << "#{indent}</#{@name}>\n"
|
91
99
|
out
|
92
100
|
end
|
101
|
+
|
102
|
+
def self.unescape_parameter(v)
|
103
|
+
result = ''
|
104
|
+
v.each_char { |c| result << LiteralParser.unescape_char(c) }
|
105
|
+
result
|
106
|
+
end
|
93
107
|
end
|
94
108
|
end
|
95
109
|
end
|
@@ -21,6 +21,29 @@ module Fluent
|
|
21
21
|
require 'irb/ruby-lex' # RubyLex
|
22
22
|
|
23
23
|
class LiteralParser < BasicParser
|
24
|
+
def self.unescape_char(c)
|
25
|
+
case c
|
26
|
+
when '"'
|
27
|
+
'\"'
|
28
|
+
when "'"
|
29
|
+
"\\'"
|
30
|
+
when '\\'
|
31
|
+
'\\\\'
|
32
|
+
when "\r"
|
33
|
+
'\r'
|
34
|
+
when "\n"
|
35
|
+
'\n'
|
36
|
+
when "\t"
|
37
|
+
'\t'
|
38
|
+
when "\f"
|
39
|
+
'\f'
|
40
|
+
when "\b"
|
41
|
+
'\b'
|
42
|
+
else
|
43
|
+
c
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
24
47
|
def initialize(strscan, eval_context)
|
25
48
|
super(strscan)
|
26
49
|
@eval_context = eval_context
|
@@ -86,7 +86,12 @@ module Fluent
|
|
86
86
|
proxy.params.each_pair do |name, defval|
|
87
87
|
varname = name.to_sym
|
88
88
|
block, opts = defval
|
89
|
-
if
|
89
|
+
if conf.has_key?(name.to_s) || opts[:alias] && conf.has_key?(opts[:alias].to_s)
|
90
|
+
val = if conf.has_key?(name.to_s)
|
91
|
+
conf[name.to_s]
|
92
|
+
else
|
93
|
+
conf[opts[:alias].to_s]
|
94
|
+
end
|
90
95
|
section_params[varname] = self.instance_exec(val, opts, name, &block)
|
91
96
|
end
|
92
97
|
unless section_params.has_key?(varname)
|
@@ -97,7 +102,7 @@ module Fluent
|
|
97
102
|
|
98
103
|
proxy.sections.each do |name, subproxy|
|
99
104
|
varname = subproxy.param_name.to_sym
|
100
|
-
elements = (conf.respond_to?(:elements) ? conf.elements : []).select{ |e| e.name == subproxy.name.to_s }
|
105
|
+
elements = (conf.respond_to?(:elements) ? conf.elements : []).select{ |e| e.name == subproxy.name.to_s || e.name == subproxy.alias.to_s }
|
101
106
|
|
102
107
|
if subproxy.required? && elements.size < 1
|
103
108
|
logger.error "config error in:\n#{conf}"
|
data/lib/fluent/config/types.rb
CHANGED
@@ -71,7 +71,7 @@ module Fluent
|
|
71
71
|
})
|
72
72
|
|
73
73
|
Configurable.register_type(:hash, Proc.new { |val, opts|
|
74
|
-
param = JSON.load(val)
|
74
|
+
param = val.is_a?(String) ? JSON.load(val) : val
|
75
75
|
if param.class != Hash
|
76
76
|
raise ConfigError, "hash required but got #{val.inspect}"
|
77
77
|
end
|
@@ -79,7 +79,7 @@ module Fluent
|
|
79
79
|
})
|
80
80
|
|
81
81
|
Configurable.register_type(:array, Proc.new { |val, opts|
|
82
|
-
param = JSON.load(val)
|
82
|
+
param = val.is_a?(String) ? JSON.load(val) : val
|
83
83
|
if param.class != Array
|
84
84
|
raise ConfigError, "array required but got #{val.inspect}"
|
85
85
|
end
|
@@ -39,6 +39,7 @@ module Fluent
|
|
39
39
|
def parse!
|
40
40
|
attrs, elems = parse_element(true, nil)
|
41
41
|
root = Element.new('ROOT', '', attrs, elems)
|
42
|
+
root.v1_config = true
|
42
43
|
|
43
44
|
spacing
|
44
45
|
unless eof?
|
@@ -86,7 +87,9 @@ module Fluent
|
|
86
87
|
e_arg ||= ''
|
87
88
|
# call parse_element recursively
|
88
89
|
e_attrs, e_elems = parse_element(false, e_name)
|
89
|
-
|
90
|
+
new_e = Element.new(e_name, e_arg, e_attrs, e_elems)
|
91
|
+
new_e.v1_config = true
|
92
|
+
elems << new_e
|
90
93
|
|
91
94
|
elsif root_element && skip(/(\@include|include)#{SPACING}/)
|
92
95
|
if !prev_match.start_with?('@')
|
data/lib/fluent/event.rb
CHANGED
@@ -23,8 +23,9 @@ module Fluent
|
|
23
23
|
false
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
def each(&block)
|
27
|
+
raise NotImplementedError, "DO NOT USE THIS CLASS directly."
|
28
|
+
end
|
28
29
|
|
29
30
|
def to_msgpack_stream
|
30
31
|
out = ''
|
@@ -56,7 +57,10 @@ module Fluent
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
|
60
|
+
# EventStream from entries: Array of [time, record]
|
61
|
+
#
|
62
|
+
# Use this class for many events data with a tag
|
63
|
+
# and its representation is [ [time, record], [time, record], .. ]
|
60
64
|
class ArrayEventStream < EventStream
|
61
65
|
def initialize(entries)
|
62
66
|
@entries = entries
|
@@ -79,15 +83,18 @@ module Fluent
|
|
79
83
|
@entries.each(&block)
|
80
84
|
nil
|
81
85
|
end
|
82
|
-
|
83
|
-
#attr_reader :entries
|
84
|
-
#
|
85
|
-
#def to_a
|
86
|
-
# @entries
|
87
|
-
#end
|
88
86
|
end
|
89
87
|
|
90
|
-
|
88
|
+
# EventStream from entries: numbers of pairs of time and record.
|
89
|
+
#
|
90
|
+
# This class can handle many events more efficiently than ArrayEventStream
|
91
|
+
# because this class generate less objects than ArrayEventStream.
|
92
|
+
#
|
93
|
+
# Use this class as below, in loop of data-enumeration:
|
94
|
+
# 1. initialize blank stream:
|
95
|
+
# streams[tag] ||= MultiEventStream
|
96
|
+
# 2. add events
|
97
|
+
# stream[tag].add(time, record)
|
91
98
|
class MultiEventStream < EventStream
|
92
99
|
def initialize
|
93
100
|
@time_array = []
|
@@ -173,25 +180,5 @@ module Fluent
|
|
173
180
|
end
|
174
181
|
|
175
182
|
end
|
176
|
-
|
177
|
-
#class IoEventStream < EventStream
|
178
|
-
# def initialize(io, num)
|
179
|
-
# @io = io
|
180
|
-
# @num = num
|
181
|
-
# @u = MessagePack::Unpacker.new(@io)
|
182
|
-
# end
|
183
|
-
#
|
184
|
-
# def repeatable?
|
185
|
-
# false
|
186
|
-
# end
|
187
|
-
#
|
188
|
-
# def each(&block)
|
189
|
-
# return nil if @num == 0
|
190
|
-
# @u.each {|obj|
|
191
|
-
# block.call(obj[0], obj[1])
|
192
|
-
# break if @array.size >= @num
|
193
|
-
# }
|
194
|
-
# end
|
195
|
-
#end
|
196
183
|
end
|
197
184
|
|
data/lib/fluent/mixin.rb
CHANGED
@@ -120,46 +120,33 @@ module Fluent
|
|
120
120
|
def configure(conf)
|
121
121
|
super
|
122
122
|
|
123
|
+
@include_time_key = false
|
124
|
+
|
123
125
|
if s = conf['include_time_key']
|
124
|
-
|
125
|
-
if
|
126
|
-
|
127
|
-
|
128
|
-
raise ConfigError, "Invalid boolean expression '#{s}' for include_time_key parameter"
|
129
|
-
end
|
130
|
-
@include_time_key = b
|
126
|
+
include_time_key = Config.bool_value(s)
|
127
|
+
raise ConfigError, "Invalid boolean expression '#{s}' for include_time_key parameter" if include_time_key.nil?
|
128
|
+
|
129
|
+
@include_time_key = include_time_key
|
131
130
|
end
|
132
131
|
|
133
132
|
if @include_time_key
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
unless @time_key
|
138
|
-
@time_key = 'time'
|
139
|
-
end
|
133
|
+
@time_key = conf['time_key'] || 'time'
|
134
|
+
@time_format = conf['time_format']
|
140
135
|
|
141
|
-
if
|
142
|
-
@time_format = time_format
|
143
|
-
end
|
144
|
-
|
145
|
-
if localtime = conf['localtime']
|
136
|
+
if conf['localtime']
|
146
137
|
@localtime = true
|
147
|
-
elsif
|
138
|
+
elsif conf['utc']
|
148
139
|
@localtime = false
|
149
140
|
end
|
150
141
|
|
151
142
|
@timef = TimeFormatter.new(@time_format, @localtime)
|
152
|
-
|
153
|
-
else
|
154
|
-
@include_time_key = false
|
155
143
|
end
|
156
144
|
end
|
157
145
|
|
158
146
|
def filter_record(tag, time, record)
|
159
147
|
super
|
160
|
-
|
161
|
-
|
162
|
-
end
|
148
|
+
|
149
|
+
record[@time_key] = @timef.format(time) if @include_time_key
|
163
150
|
end
|
164
151
|
end
|
165
152
|
|
@@ -171,34 +158,22 @@ module Fluent
|
|
171
158
|
def configure(conf)
|
172
159
|
super
|
173
160
|
|
174
|
-
|
175
|
-
b = Config.bool_value(s)
|
176
|
-
if s.empty?
|
177
|
-
b = true
|
178
|
-
elsif b == nil
|
179
|
-
raise ConfigError, "Invalid boolean expression '#{s}' for include_tag_key parameter"
|
180
|
-
end
|
181
|
-
@include_tag_key = b
|
182
|
-
end
|
161
|
+
@include_tag_key = false
|
183
162
|
|
184
|
-
if
|
185
|
-
|
186
|
-
|
187
|
-
end
|
188
|
-
unless @tag_key
|
189
|
-
@tag_key = 'tag'
|
190
|
-
end
|
163
|
+
if s = conf['include_tag_key']
|
164
|
+
include_tag_key = Config.bool_value(s)
|
165
|
+
raise ConfigError, "Invalid boolean expression '#{s}' for include_tag_key parameter" if include_tag_key.nil?
|
191
166
|
|
192
|
-
|
193
|
-
@include_tag_key = false
|
167
|
+
@include_tag_key = include_tag_key
|
194
168
|
end
|
169
|
+
|
170
|
+
@tag_key = conf['tag_key'] || 'tag' if @include_tag_key
|
195
171
|
end
|
196
172
|
|
197
173
|
def filter_record(tag, time, record)
|
198
174
|
super
|
199
|
-
|
200
|
-
|
201
|
-
end
|
175
|
+
|
176
|
+
record[@tag_key] = tag if @include_tag_key
|
202
177
|
end
|
203
178
|
end
|
204
179
|
end
|
data/lib/fluent/output.rb
CHANGED
@@ -165,8 +165,8 @@ module Fluent
|
|
165
165
|
@next_flush_time = 0
|
166
166
|
@last_retry_time = 0
|
167
167
|
@next_retry_time = 0
|
168
|
-
@
|
169
|
-
@
|
168
|
+
@num_errors = 0
|
169
|
+
@num_errors_lock = Mutex.new
|
170
170
|
@secondary_limit = 8
|
171
171
|
@emit_count = 0
|
172
172
|
end
|
@@ -174,6 +174,7 @@ module Fluent
|
|
174
174
|
config_param :buffer_type, :string, :default => 'memory'
|
175
175
|
config_param :flush_interval, :time, :default => 60
|
176
176
|
config_param :try_flush_interval, :float, :default => 1
|
177
|
+
config_param :disable_retry_limit, :bool, :default => false
|
177
178
|
config_param :retry_limit, :integer, :default => 17
|
178
179
|
config_param :retry_wait, :time, :default => 1.0
|
179
180
|
config_param :max_retry_wait, :time, :default => nil
|
@@ -286,11 +287,11 @@ module Fluent
|
|
286
287
|
end
|
287
288
|
|
288
289
|
begin
|
289
|
-
retrying = !@
|
290
|
+
retrying = !@num_errors.zero?
|
290
291
|
|
291
292
|
if retrying
|
292
|
-
@
|
293
|
-
if retrying = !@
|
293
|
+
@num_errors_lock.synchronize do
|
294
|
+
if retrying = !@num_errors.zero? # re-check in synchronize
|
294
295
|
if @next_retry_time >= time
|
295
296
|
# allow retrying for only one thread
|
296
297
|
return time + @try_flush_interval
|
@@ -298,13 +299,13 @@ module Fluent
|
|
298
299
|
# assume next retry failes and
|
299
300
|
# clear them if when it succeeds
|
300
301
|
@last_retry_time = time
|
301
|
-
@
|
302
|
+
@num_errors += 1
|
302
303
|
@next_retry_time += calc_retry_wait
|
303
304
|
end
|
304
305
|
end
|
305
306
|
end
|
306
307
|
|
307
|
-
if @secondary && @
|
308
|
+
if @secondary && !@disable_retry_limit && @num_errors > @retry_limit
|
308
309
|
has_next = flush_secondary(@secondary)
|
309
310
|
else
|
310
311
|
has_next = @buffer.pop(self)
|
@@ -312,7 +313,7 @@ module Fluent
|
|
312
313
|
|
313
314
|
# success
|
314
315
|
if retrying
|
315
|
-
@
|
316
|
+
@num_errors = 0
|
316
317
|
# Note: don't notify to other threads to prevent
|
317
318
|
# burst to recovered server
|
318
319
|
$log.warn "retry succeeded.", :instance=>object_id
|
@@ -326,20 +327,20 @@ module Fluent
|
|
326
327
|
|
327
328
|
rescue => e
|
328
329
|
if retrying
|
329
|
-
error_count = @
|
330
|
+
error_count = @num_errors
|
330
331
|
else
|
331
332
|
# first error
|
332
333
|
error_count = 0
|
333
|
-
@
|
334
|
-
if @
|
334
|
+
@num_errors_lock.synchronize do
|
335
|
+
if @num_errors.zero?
|
335
336
|
@last_retry_time = time
|
336
|
-
@
|
337
|
+
@num_errors += 1
|
337
338
|
@next_retry_time = time + calc_retry_wait
|
338
339
|
end
|
339
340
|
end
|
340
341
|
end
|
341
342
|
|
342
|
-
if error_count < @retry_limit
|
343
|
+
if @disable_retry_limit || error_count < @retry_limit
|
343
344
|
$log.warn "temporarily failed to flush the buffer.", :next_retry=>Time.at(@next_retry_time), :error_class=>e.class.to_s, :error=>e.to_s, :instance=>object_id
|
344
345
|
$log.warn_backtrace e.backtrace
|
345
346
|
|
@@ -357,7 +358,7 @@ module Fluent
|
|
357
358
|
$log.warn "secondary retry count exceededs limit."
|
358
359
|
$log.warn_backtrace e.backtrace
|
359
360
|
write_abort
|
360
|
-
@
|
361
|
+
@num_errors = 0
|
361
362
|
end
|
362
363
|
|
363
364
|
else
|
@@ -365,7 +366,7 @@ module Fluent
|
|
365
366
|
$log.warn "retry count exceededs limit."
|
366
367
|
$log.warn_backtrace e.backtrace
|
367
368
|
write_abort
|
368
|
-
@
|
369
|
+
@num_errors = 0
|
369
370
|
end
|
370
371
|
|
371
372
|
return @next_retry_time
|
@@ -388,11 +389,11 @@ module Fluent
|
|
388
389
|
|
389
390
|
def calc_retry_wait
|
390
391
|
# TODO retry pattern
|
391
|
-
wait = if @
|
392
|
-
@retry_wait * (2 ** (@
|
392
|
+
wait = if @disable_retry_limit || @num_errors <= @retry_limit
|
393
|
+
@retry_wait * (2 ** (@num_errors - 1))
|
393
394
|
else
|
394
395
|
# secondary retry
|
395
|
-
@retry_wait * (2 ** (@
|
396
|
+
@retry_wait * (2 ** (@num_errors - 2 - @retry_limit))
|
396
397
|
end
|
397
398
|
retry_wait = wait + (rand * (wait / 4.0) - (wait / 8.0))
|
398
399
|
@max_retry_wait ? [retry_wait, @max_retry_wait].min : retry_wait
|
data/lib/fluent/parser.rb
CHANGED
@@ -257,8 +257,6 @@ module Fluent
|
|
257
257
|
config_param :time_key, :string, :default => nil
|
258
258
|
config_param :time_format, :string, :default => nil
|
259
259
|
|
260
|
-
# SET false BEFORE CONFIGURE, to return nil when time not parsed
|
261
|
-
# 'configure()' may raise errors for unexpected configurations
|
262
260
|
attr_accessor :estimate_current_event
|
263
261
|
|
264
262
|
def initialize
|
@@ -624,6 +622,7 @@ module Fluent
|
|
624
622
|
TEMPLATE_REGISTRY = Registry.new(:config_type, 'fluent/plugin/parser_')
|
625
623
|
{
|
626
624
|
'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"}) },
|
625
|
+
'apache_error' => Proc.new { RegexpParser.new(/^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$/) },
|
627
626
|
'apache2' => Proc.new { ApacheParser.new },
|
628
627
|
'syslog' => Proc.new { SyslogParser.new },
|
629
628
|
'json' => Proc.new { JSONParser.new },
|
@@ -650,10 +649,15 @@ module Fluent
|
|
650
649
|
|
651
650
|
def initialize
|
652
651
|
@parser = nil
|
652
|
+
@estimate_current_event = nil
|
653
653
|
end
|
654
654
|
|
655
655
|
attr_reader :parser
|
656
656
|
|
657
|
+
# SET false BEFORE CONFIGURE, to return nil when time not parsed
|
658
|
+
# 'configure()' may raise errors for unexpected configurations
|
659
|
+
attr_accessor :estimate_current_event
|
660
|
+
|
657
661
|
def configure(conf, required=true)
|
658
662
|
format = conf['format']
|
659
663
|
|
@@ -687,6 +691,10 @@ module Fluent
|
|
687
691
|
@parser = factory.call
|
688
692
|
end
|
689
693
|
|
694
|
+
if ! @estimate_current_event.nil? && @parser.respond_to?(:'estimate_current_event=')
|
695
|
+
@parser.estimate_current_event = @estimate_current_event
|
696
|
+
end
|
697
|
+
|
690
698
|
if @parser.respond_to?(:configure)
|
691
699
|
@parser.configure(conf)
|
692
700
|
end
|
@@ -26,7 +26,7 @@ module Fluent
|
|
26
26
|
|
27
27
|
config_param :bind, :string, :default => '0.0.0.0'
|
28
28
|
config_param :port, :integer, :default => 24230
|
29
|
-
config_param :unix_path, :
|
29
|
+
config_param :unix_path, :string, :default => nil
|
30
30
|
#config_param :unix_mode # TODO
|
31
31
|
config_param :object, :string, :default => 'Engine'
|
32
32
|
|
@@ -217,7 +217,7 @@ module Fluent
|
|
217
217
|
'output_plugin' => 'is_a?(::Fluent::Output)',
|
218
218
|
'buffer_queue_length' => '@buffer.queue_size',
|
219
219
|
'buffer_total_queued_size' => '@buffer.total_queued_chunk_size',
|
220
|
-
'retry_count' => '@
|
220
|
+
'retry_count' => '@num_errors',
|
221
221
|
'config' => 'config',
|
222
222
|
}
|
223
223
|
|
@@ -78,6 +78,8 @@ module Fluent
|
|
78
78
|
raise ConfigError, "syslog input protocol type should be 'tcp' or 'udp'"
|
79
79
|
end
|
80
80
|
end
|
81
|
+
config_param :include_source_host, :bool, :default => false
|
82
|
+
config_param :source_host_key, :string, :default => 'source_host'.freeze
|
81
83
|
|
82
84
|
def configure(conf)
|
83
85
|
super
|
@@ -137,6 +139,7 @@ module Fluent
|
|
137
139
|
return
|
138
140
|
end
|
139
141
|
|
142
|
+
record[@source_host_key] = addr[2] if @include_source_host
|
140
143
|
emit(pri, time, record)
|
141
144
|
}
|
142
145
|
rescue => e
|
@@ -152,6 +155,7 @@ module Fluent
|
|
152
155
|
end
|
153
156
|
|
154
157
|
pri = record.delete('pri')
|
158
|
+
record[@source_host_key] = addr[2] if @include_source_host
|
155
159
|
emit(pri, time, record)
|
156
160
|
}
|
157
161
|
rescue => e
|
data/lib/fluent/supervisor.rb
CHANGED
@@ -151,6 +151,8 @@ module Fluent
|
|
151
151
|
private
|
152
152
|
|
153
153
|
def dry_run
|
154
|
+
$log.info "starting fluentd-#{Fluent::VERSION} as dry run mode"
|
155
|
+
|
154
156
|
read_config
|
155
157
|
change_privilege
|
156
158
|
init_engine
|
@@ -158,7 +160,7 @@ module Fluent
|
|
158
160
|
run_configure
|
159
161
|
exit 0
|
160
162
|
rescue => e
|
161
|
-
$log.error "
|
163
|
+
$log.error "dry run failed: #{e}"
|
162
164
|
exit 1
|
163
165
|
end
|
164
166
|
|
@@ -358,6 +360,7 @@ module Fluent
|
|
358
360
|
end
|
359
361
|
end
|
360
362
|
|
363
|
+
# TODO: this method should be moved to SystemConfig class method
|
361
364
|
def apply_system_config(opt)
|
362
365
|
# Create NULL file to avoid $log uninitialized problem before call @log.init
|
363
366
|
file = File.open(File::NULL)
|
@@ -29,6 +29,9 @@ module Fluent
|
|
29
29
|
super(klass, &block)
|
30
30
|
@emit_streams = []
|
31
31
|
@expects = nil
|
32
|
+
# for checking only the number of emitted records during run
|
33
|
+
@expected_emits_length = nil
|
34
|
+
@run_timeout = 5
|
32
35
|
end
|
33
36
|
|
34
37
|
def expect_emit(tag, time, record)
|
@@ -40,6 +43,8 @@ module Fluent
|
|
40
43
|
@expects ||= []
|
41
44
|
end
|
42
45
|
|
46
|
+
attr_accessor :expected_emits_length
|
47
|
+
attr_accessor :run_timeout
|
43
48
|
attr_reader :emit_streams
|
44
49
|
|
45
50
|
def emits
|
@@ -78,15 +83,24 @@ module Fluent
|
|
78
83
|
super {
|
79
84
|
block.call if block
|
80
85
|
|
81
|
-
if @expects
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
+
if @expected_emits_length || @expects
|
87
|
+
max_length = @expected_emits_length || @expects.length
|
88
|
+
started_at = Time.now
|
89
|
+
i, j = 0, 0
|
90
|
+
while i < max_length && Time.now <= started_at + @run_timeout
|
91
|
+
if j >= @emit_streams.length
|
92
|
+
sleep 0.01
|
93
|
+
next
|
94
|
+
end
|
95
|
+
|
96
|
+
tag, events = @emit_streams[j]
|
97
|
+
events.each do |time, record|
|
98
|
+
assert_equal(@expects[i], [tag, time, record]) if @expects
|
86
99
|
i += 1
|
87
|
-
|
88
|
-
|
89
|
-
|
100
|
+
end
|
101
|
+
j += 1
|
102
|
+
end
|
103
|
+
assert_equal(@expects.length, i) if @expects
|
90
104
|
end
|
91
105
|
}
|
92
106
|
self
|
data/lib/fluent/version.rb
CHANGED
@@ -299,5 +299,16 @@ describe Fluent::Config::V1Parser do
|
|
299
299
|
|
300
300
|
# TODO: Add uri based include spec
|
301
301
|
end
|
302
|
-
end
|
303
302
|
|
303
|
+
describe 'unescape parameter' do
|
304
|
+
it 'parses dumpped configuration' do
|
305
|
+
original = %q!a\\\\\n\r\f\b\\'\\"z!
|
306
|
+
expected = %!a\\\n\r\f\b'"z!
|
307
|
+
|
308
|
+
conf = parse_text(%[k1 #{original}])
|
309
|
+
expect(conf['k1']).to eq(expected) # escape check
|
310
|
+
conf2 = parse_text(conf.to_s) # use dumpped configuration to check unescape
|
311
|
+
expect(conf2.elements.first['k1']).to eq(expected)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
@@ -80,6 +80,33 @@ module ConfigurableSpec
|
|
80
80
|
ary + [@nodes, @description1, @description2, @description3]
|
81
81
|
end
|
82
82
|
end
|
83
|
+
|
84
|
+
class Example0
|
85
|
+
include Fluent::Configurable
|
86
|
+
|
87
|
+
config_param :stringvalue, :string
|
88
|
+
config_param :boolvalue, :bool
|
89
|
+
config_param :integervalue, :integer
|
90
|
+
config_param :sizevalue, :size
|
91
|
+
config_param :timevalue, :time
|
92
|
+
config_param :floatvalue, :float
|
93
|
+
config_param :hashvalue, :hash
|
94
|
+
config_param :arrayvalue, :array
|
95
|
+
end
|
96
|
+
|
97
|
+
class Example1
|
98
|
+
include Fluent::Configurable
|
99
|
+
|
100
|
+
config_param :name, :string, alias: :fullname
|
101
|
+
config_param :bool, :bool, alias: :flag
|
102
|
+
config_section :detail, required: true, multi: false, alias: "information" do
|
103
|
+
config_param :address, :string
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_all
|
107
|
+
[@name, @detail]
|
108
|
+
end
|
109
|
+
end
|
83
110
|
end
|
84
111
|
|
85
112
|
describe Fluent::Configurable do
|
@@ -111,6 +138,11 @@ describe Fluent::Configurable do
|
|
111
138
|
end
|
112
139
|
|
113
140
|
describe '#configure' do
|
141
|
+
it 'returns configurable object itself' do
|
142
|
+
b2 = ConfigurableSpec::Base2.new
|
143
|
+
expect(b2.configure({"name1" => "t1", "name5" => "t5"})).to be_a(ConfigurableSpec::Base2)
|
144
|
+
end
|
145
|
+
|
114
146
|
it 'raise errors without any specifications for param without defaults' do
|
115
147
|
b2 = ConfigurableSpec::Base2.new
|
116
148
|
expect{ b2.configure({}) }.to raise_error(Fluent::ConfigError)
|
@@ -128,7 +160,7 @@ describe Fluent::Configurable do
|
|
128
160
|
expect(b2a.flag2).to eq(true)
|
129
161
|
|
130
162
|
b2b = ConfigurableSpec::Base2.new
|
131
|
-
expect{ b2b.configure({"flag1" =>
|
163
|
+
expect{ b2b.configure({"flag1" => false, "flag2" => "no", "name1" => "t1", "name5" => "t5"}) }.not_to raise_error()
|
132
164
|
expect(b2b.flag1).to eq(false)
|
133
165
|
expect(b2b.flag2).to eq(false)
|
134
166
|
end
|
@@ -368,6 +400,125 @@ describe Fluent::Configurable do
|
|
368
400
|
expect(b4.description3[2].note).to eql('desc3: d-3a')
|
369
401
|
expect(b4.description3[2].text).to eql('dddd3-3')
|
370
402
|
end
|
403
|
+
|
404
|
+
it 'checks missing of specifications' do
|
405
|
+
conf0 = e('ROOT', '', {}, [])
|
406
|
+
ex01 = ConfigurableSpec::Example0.new
|
407
|
+
expect { ex01.configure(conf0) }.to raise_error(Fluent::ConfigError)
|
408
|
+
|
409
|
+
complete = {
|
410
|
+
"stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
|
411
|
+
"sizevalue" => "10m", "timevalue" => "100s", "floatvalue" => "1.001",
|
412
|
+
"hashvalue" => '{"foo":1, "bar":2}',
|
413
|
+
"arrayvalue" => '[1,"ichi"]',
|
414
|
+
}
|
415
|
+
|
416
|
+
checker = lambda {|conf| ConfigurableSpec::Example0.new.configure(conf) }
|
417
|
+
|
418
|
+
expect { checker.call(complete) }.not_to raise_error()
|
419
|
+
expect { checker.call(complete.reject{|k,v| k == "stringvalue" }) }.to raise_error(Fluent::ConfigError)
|
420
|
+
expect { checker.call(complete.reject{|k,v| k == "boolvalue" }) }.to raise_error(Fluent::ConfigError)
|
421
|
+
expect { checker.call(complete.reject{|k,v| k == "integervalue"}) }.to raise_error(Fluent::ConfigError)
|
422
|
+
expect { checker.call(complete.reject{|k,v| k == "sizevalue" }) }.to raise_error(Fluent::ConfigError)
|
423
|
+
expect { checker.call(complete.reject{|k,v| k == "timevalue" }) }.to raise_error(Fluent::ConfigError)
|
424
|
+
expect { checker.call(complete.reject{|k,v| k == "floatvalue" }) }.to raise_error(Fluent::ConfigError)
|
425
|
+
expect { checker.call(complete.reject{|k,v| k == "hashvalue" }) }.to raise_error(Fluent::ConfigError)
|
426
|
+
expect { checker.call(complete.reject{|k,v| k == "arrayvalue" }) }.to raise_error(Fluent::ConfigError)
|
427
|
+
end
|
428
|
+
|
429
|
+
it 'accepts configuration values as string representation' do
|
430
|
+
conf = {
|
431
|
+
"stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
|
432
|
+
"sizevalue" => "10m", "timevalue" => "10m", "floatvalue" => "1.001",
|
433
|
+
"hashvalue" => '{"foo":1, "bar":2}',
|
434
|
+
"arrayvalue" => '[1,"ichi"]',
|
435
|
+
}
|
436
|
+
ex = ConfigurableSpec::Example0.new.configure(conf)
|
437
|
+
expect(ex.stringvalue).to eq("s1")
|
438
|
+
expect(ex.boolvalue).to equal(true)
|
439
|
+
expect(ex.integervalue).to eq(10)
|
440
|
+
expect(ex.sizevalue).to eq(10 * 1024 * 1024)
|
441
|
+
expect(ex.timevalue).to eq(10 * 60)
|
442
|
+
expect(ex.floatvalue).to eq(1.001)
|
443
|
+
expect(ex.hashvalue).to eq({"foo" => 1, "bar" => 2})
|
444
|
+
expect(ex.arrayvalue).to eq([1, "ichi"])
|
445
|
+
end
|
446
|
+
|
447
|
+
it 'accepts configuration values as ruby value representation (especially for DSL)' do
|
448
|
+
conf = {
|
449
|
+
"stringvalue" => "s1", "boolvalue" => true, "integervalue" => 10,
|
450
|
+
"sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
|
451
|
+
"hashvalue" => {"foo" => 1, "bar" => 2},
|
452
|
+
"arrayvalue" => [1,"ichi"],
|
453
|
+
}
|
454
|
+
ex = ConfigurableSpec::Example0.new.configure(conf)
|
455
|
+
expect(ex.stringvalue).to eq("s1")
|
456
|
+
expect(ex.boolvalue).to equal(true)
|
457
|
+
expect(ex.integervalue).to eq(10)
|
458
|
+
expect(ex.sizevalue).to eq(10 * 1024 * 1024)
|
459
|
+
expect(ex.timevalue).to eq(10 * 60)
|
460
|
+
expect(ex.floatvalue).to eq(1.001)
|
461
|
+
expect(ex.hashvalue).to eq({"foo" => 1, "bar" => 2})
|
462
|
+
expect(ex.arrayvalue).to eq([1, "ichi"])
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'gets both of true(yes) and false(no) for bool value parameter' do
|
466
|
+
conf = {
|
467
|
+
"stringvalue" => "s1", "integervalue" => 10,
|
468
|
+
"sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
|
469
|
+
"hashvalue" => {"foo" => 1, "bar" => 2},
|
470
|
+
"arrayvalue" => [1,"ichi"],
|
471
|
+
}
|
472
|
+
ex0 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "true"}))
|
473
|
+
expect(ex0.boolvalue).to equal(true)
|
474
|
+
|
475
|
+
ex1 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "yes"}))
|
476
|
+
expect(ex1.boolvalue).to equal(true)
|
477
|
+
|
478
|
+
ex2 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => true}))
|
479
|
+
expect(ex2.boolvalue).to equal(true)
|
480
|
+
|
481
|
+
ex3 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "false"}))
|
482
|
+
expect(ex3.boolvalue).to equal(false)
|
483
|
+
|
484
|
+
ex4 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "no"}))
|
485
|
+
expect(ex4.boolvalue).to equal(false)
|
486
|
+
|
487
|
+
ex5 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => false}))
|
488
|
+
expect(ex5.boolvalue).to equal(false)
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
context 'class defined with config_param/config_section having :alias' do
|
494
|
+
describe '#initialize' do
|
495
|
+
it 'does not create methods for alias' do
|
496
|
+
ex1 = ConfigurableSpec::Example1.new
|
497
|
+
expect { ex1.name }.not_to raise_error()
|
498
|
+
expect { ex1.fullname }.to raise_error(NoMethodError)
|
499
|
+
expect { ex1.bool }.not_to raise_error()
|
500
|
+
expect { ex1.flag }.to raise_error(NoMethodError)
|
501
|
+
expect { ex1.detail }.not_to raise_error()
|
502
|
+
expect { ex1.information}.to raise_error(NoMethodError)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
describe '#configure' do
|
507
|
+
def e(name, arg = '', attrs = {}, elements = [])
|
508
|
+
attrs_str_keys = {}
|
509
|
+
attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
|
510
|
+
Fluent::Config::Element.new(name, arg, attrs_str_keys, elements)
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'provides accessible data for alias attribute keys' do
|
514
|
+
ex1 = ConfigurableSpec::Example1.new
|
515
|
+
ex1.configure(e('ROOT', '', {"fullname" => "foo bar", "bool" => false}, [e('information', '', {"address" => "Mountain View 0"})]))
|
516
|
+
expect(ex1.name).to eql("foo bar")
|
517
|
+
expect(ex1.bool).not_to be_nil
|
518
|
+
expect(ex1.bool).to be_falsy
|
519
|
+
expect(ex1.detail).not_to be_nil
|
520
|
+
expect(ex1.detail.address).to eql("Mountain View 0")
|
521
|
+
end
|
371
522
|
end
|
372
523
|
end
|
373
524
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'fluent/configurable'
|
2
|
+
require 'fluent/config/element'
|
3
|
+
require 'fluent/config/section'
|
4
|
+
require 'fluent/supervisor'
|
5
|
+
|
6
|
+
describe Fluent::Supervisor::SystemConfig do
|
7
|
+
def parse_text(text)
|
8
|
+
basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
|
9
|
+
Fluent::Config.parse(text, '(test)', basepath, true).elements.find { |e| e.name == 'system' }
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should not override default configurations when no parameters' do
|
13
|
+
conf = parse_text(<<EOS)
|
14
|
+
<system>
|
15
|
+
</system>
|
16
|
+
EOS
|
17
|
+
sc = Fluent::Supervisor::SystemConfig.new(conf)
|
18
|
+
expect(sc.log_level).to be_nil
|
19
|
+
expect(sc.suppress_repeated_stacktrace).to be_nil
|
20
|
+
expect(sc.emit_error_log_interval).to be_nil
|
21
|
+
expect(sc.suppress_config_dump).to be_nil
|
22
|
+
expect(sc.without_source).to be_nil
|
23
|
+
expect(sc.to_opt).to eql({})
|
24
|
+
end
|
25
|
+
|
26
|
+
{'log_level' => 'error', 'suppress_repeated_stacktrace' => true, 'emit_error_log_interval' => 60, 'suppress_config_dump' => true, 'without_source' => true}.each { |k, v|
|
27
|
+
it "accepts #{k} parameter" do
|
28
|
+
conf = parse_text(<<EOS)
|
29
|
+
<system>
|
30
|
+
#{k} #{v}
|
31
|
+
</system>
|
32
|
+
EOS
|
33
|
+
sc = Fluent::Supervisor::SystemConfig.new(conf)
|
34
|
+
expect(sc.instance_variable_get("@#{k}")).not_to be_nil
|
35
|
+
if k == 'emit_error_log_interval'
|
36
|
+
expect(sc.to_opt).to include(:suppress_interval)
|
37
|
+
else
|
38
|
+
expect(sc.to_opt).to include(k.to_sym)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
}
|
42
|
+
|
43
|
+
{'foo' => 'bar', 'hoge' => 'fuga'}.each { |k, v|
|
44
|
+
it "should not affect settable parameters with unknown #{k} parameter" do
|
45
|
+
sc = Fluent::Supervisor::SystemConfig.new({k => v})
|
46
|
+
expect(sc.to_opt).to be_empty
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
@@ -44,7 +44,6 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
44
44
|
d.expected_emits.each {|tag,time,record|
|
45
45
|
send_data [tag, 0, record].to_msgpack
|
46
46
|
}
|
47
|
-
sleep 0.5
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
@@ -60,7 +59,6 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
60
59
|
d.expected_emits.each {|tag,time,record|
|
61
60
|
send_data [tag, time, record].to_msgpack
|
62
61
|
}
|
63
|
-
sleep 0.5
|
64
62
|
end
|
65
63
|
end
|
66
64
|
|
@@ -78,7 +76,6 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
78
76
|
entries << [time, record]
|
79
77
|
}
|
80
78
|
send_data ["tag1", entries].to_msgpack
|
81
|
-
sleep 0.5
|
82
79
|
end
|
83
80
|
end
|
84
81
|
|
@@ -96,7 +93,6 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
96
93
|
[time, record].to_msgpack(entries)
|
97
94
|
}
|
98
95
|
send_data ["tag1", entries].to_msgpack
|
99
|
-
sleep 0.5
|
100
96
|
end
|
101
97
|
end
|
102
98
|
|
@@ -112,7 +108,6 @@ class ForwardInputTest < Test::Unit::TestCase
|
|
112
108
|
d.expected_emits.each {|tag,time,record|
|
113
109
|
send_data [tag, time, record].to_json
|
114
110
|
}
|
115
|
-
sleep 0.5
|
116
111
|
end
|
117
112
|
end
|
118
113
|
|
@@ -33,15 +33,15 @@ class ObjectSpaceInputTest < Test::Unit::TestCase
|
|
33
33
|
|
34
34
|
time = Time.parse("2011-01-02 13:14:15").to_i
|
35
35
|
|
36
|
-
d.
|
37
|
-
|
38
|
-
end
|
36
|
+
d.expected_emits_length = 2
|
37
|
+
d.run
|
39
38
|
|
40
39
|
emits = d.emits
|
41
40
|
assert_equal true, emits.length > 0
|
42
41
|
|
43
|
-
tag, time, record
|
44
|
-
|
42
|
+
emits.each { |tag, time, record|
|
43
|
+
assert_equal d.instance.tag, tag
|
44
|
+
assert_equal d.instance.top, record.keys.size
|
45
|
+
}
|
45
46
|
end
|
46
47
|
end
|
47
|
-
|
@@ -19,7 +19,6 @@ module StreamInputTest
|
|
19
19
|
d.expected_emits.each {|tag,time,record|
|
20
20
|
send_data [tag, 0, record].to_msgpack
|
21
21
|
}
|
22
|
-
sleep 0.5
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
@@ -35,7 +34,6 @@ module StreamInputTest
|
|
35
34
|
d.expected_emits.each {|tag,time,record|
|
36
35
|
send_data [tag, time, record].to_msgpack
|
37
36
|
}
|
38
|
-
sleep 0.5
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
@@ -53,7 +51,6 @@ module StreamInputTest
|
|
53
51
|
entries << [time, record]
|
54
52
|
}
|
55
53
|
send_data ["tag1", entries].to_msgpack
|
56
|
-
sleep 0.5
|
57
54
|
end
|
58
55
|
end
|
59
56
|
|
@@ -71,7 +68,6 @@ module StreamInputTest
|
|
71
68
|
[time, record].to_msgpack(entries)
|
72
69
|
}
|
73
70
|
send_data ["tag1", entries].to_msgpack
|
74
|
-
sleep 0.5
|
75
71
|
end
|
76
72
|
end
|
77
73
|
|
@@ -87,7 +83,6 @@ module StreamInputTest
|
|
87
83
|
d.expected_emits.each {|tag,time,record|
|
88
84
|
send_data [tag, time, record].to_json
|
89
85
|
}
|
90
|
-
sleep 0.5
|
91
86
|
end
|
92
87
|
end
|
93
88
|
|
@@ -131,6 +131,24 @@ class SyslogInputTest < Test::Unit::TestCase
|
|
131
131
|
compare_test_result(d.emits, tests)
|
132
132
|
end
|
133
133
|
|
134
|
+
def test_msg_size_with_include_source_host
|
135
|
+
d = create_driver([CONFIG, 'include_source_host'].join("\n"))
|
136
|
+
tests = create_test_case
|
137
|
+
|
138
|
+
host = nil
|
139
|
+
d.run do
|
140
|
+
u = UDPSocket.new
|
141
|
+
u.connect('127.0.0.1', PORT)
|
142
|
+
host = u.peeraddr[2]
|
143
|
+
tests.each {|test|
|
144
|
+
u.send(test['msg'], 0)
|
145
|
+
}
|
146
|
+
sleep 1
|
147
|
+
end
|
148
|
+
|
149
|
+
compare_test_result(d.emits, tests, host)
|
150
|
+
end
|
151
|
+
|
134
152
|
def create_test_case
|
135
153
|
# actual syslog message has "\n"
|
136
154
|
[
|
@@ -139,10 +157,11 @@ class SyslogInputTest < Test::Unit::TestCase
|
|
139
157
|
]
|
140
158
|
end
|
141
159
|
|
142
|
-
def compare_test_result(emits, tests)
|
160
|
+
def compare_test_result(emits, tests, host = nil)
|
143
161
|
emits.each_index { |i|
|
144
162
|
assert_equal('syslog.kern.info', emits[0][0]) # <6> means kern.info
|
145
163
|
assert_equal(tests[i]['expected'], emits[i][2]['message'])
|
164
|
+
assert_equal(host, emits[i][2]['source_host']) if host
|
146
165
|
}
|
147
166
|
end
|
148
167
|
end
|
data/test/test_output.rb
CHANGED
@@ -27,6 +27,7 @@ module FluentOutputTest
|
|
27
27
|
d = create_driver
|
28
28
|
assert_equal 'memory', d.instance.buffer_type
|
29
29
|
assert_equal 60, d.instance.flush_interval
|
30
|
+
assert_equal false, d.instance.disable_retry_limit
|
30
31
|
assert_equal 17, d.instance.retry_limit
|
31
32
|
assert_equal 1.0, d.instance.retry_wait
|
32
33
|
assert_equal nil, d.instance.max_retry_wait
|
@@ -37,18 +38,27 @@ module FluentOutputTest
|
|
37
38
|
# max_retry_wait
|
38
39
|
d = create_driver(CONFIG + %[max_retry_wait 4])
|
39
40
|
assert_equal 4, d.instance.max_retry_wait
|
41
|
+
|
42
|
+
# disable_retry_limit
|
43
|
+
d = create_driver(CONFIG + %[disable_retry_limit true])
|
44
|
+
assert_equal true, d.instance.disable_retry_limit
|
40
45
|
end
|
41
46
|
|
42
47
|
def test_calc_retry_wait
|
43
48
|
# default
|
44
49
|
d = create_driver
|
45
|
-
d.instance.retry_limit.times {
|
50
|
+
d.instance.retry_limit.times {
|
51
|
+
# "d.instance.instance_variable_get(:@num_errors) += 1" causes SyntaxError
|
52
|
+
d.instance.instance_eval { @num_errors += 1 }
|
53
|
+
}
|
46
54
|
wait = d.instance.retry_wait * (2 ** (d.instance.retry_limit - 1))
|
47
55
|
assert( d.instance.calc_retry_wait > wait - wait / 8.0 )
|
48
56
|
|
49
57
|
# max_retry_wait
|
50
58
|
d = create_driver(CONFIG + %[max_retry_wait 4])
|
51
|
-
d.instance.retry_limit.times {
|
59
|
+
d.instance.retry_limit.times {
|
60
|
+
d.instance.instance_eval { @num_errors += 1 }
|
61
|
+
}
|
52
62
|
assert_equal 4, d.instance.calc_retry_wait
|
53
63
|
end
|
54
64
|
|
data/test/test_parser.rb
CHANGED
@@ -130,6 +130,43 @@ module ParserTest
|
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
|
+
class ApacheErrorParserTest < ::Test::Unit::TestCase
|
134
|
+
include ParserTest
|
135
|
+
|
136
|
+
def setup
|
137
|
+
@parser = TextParser::TEMPLATE_REGISTRY.lookup('apache_error').call
|
138
|
+
@expected = {
|
139
|
+
'level' => 'error',
|
140
|
+
'client' => '127.0.0.1',
|
141
|
+
'message' => 'client denied by server configuration'
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_call
|
146
|
+
@parser.call('[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration') { |time, record|
|
147
|
+
assert_equal(str2time('Wed Oct 11 14:32:52 2000'), time)
|
148
|
+
assert_equal(@expected, record)
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_call_with_pid
|
153
|
+
@parser.call('[Wed Oct 11 14:32:52 2000] [error] [pid 1000] [client 127.0.0.1] client denied by server configuration') { |time, record|
|
154
|
+
assert_equal(str2time('Wed Oct 11 14:32:52 2000'), time)
|
155
|
+
assert_equal(@expected.merge('pid' => '1000'), record)
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_call_without_client
|
160
|
+
@parser.call('[Wed Oct 11 14:32:52 2000] [notice] Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations') { |time, record|
|
161
|
+
assert_equal(str2time('Wed Oct 11 14:32:52 2000'), time)
|
162
|
+
assert_equal({
|
163
|
+
'level' => 'notice',
|
164
|
+
'message' => 'Apache/2.2.15 (Unix) DAV/2 configured -- resuming normal operations'
|
165
|
+
}, record)
|
166
|
+
}
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
133
170
|
class Apache2ParserTest < ::Test::Unit::TestCase
|
134
171
|
include ParserTest
|
135
172
|
|
@@ -656,5 +693,23 @@ EOS
|
|
656
693
|
i += 1
|
657
694
|
}
|
658
695
|
end
|
696
|
+
|
697
|
+
def test_setting_estimate_current_event_value
|
698
|
+
p1 = TextParser.new
|
699
|
+
assert_nil p1.estimate_current_event
|
700
|
+
assert_nil p1.parser
|
701
|
+
|
702
|
+
p1.configure('format' => 'none')
|
703
|
+
assert_equal true, p1.parser.estimate_current_event
|
704
|
+
|
705
|
+
p2 = TextParser.new
|
706
|
+
assert_nil p2.estimate_current_event
|
707
|
+
assert_nil p2.parser
|
708
|
+
|
709
|
+
p2.estimate_current_event = false
|
710
|
+
|
711
|
+
p2.configure('format' => 'none')
|
712
|
+
assert_equal false, p2.parser.estimate_current_event
|
713
|
+
end
|
659
714
|
end
|
660
715
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluentd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.53
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -341,6 +341,7 @@ files:
|
|
341
341
|
- spec/config/helper.rb
|
342
342
|
- spec/config/literal_parser_spec.rb
|
343
343
|
- spec/config/section_spec.rb
|
344
|
+
- spec/config/system_config_spec.rb
|
344
345
|
- spec/spec_helper.rb
|
345
346
|
- test/helper.rb
|
346
347
|
- test/plugin/data/2010/01/20100102-030405.log
|
@@ -409,6 +410,7 @@ test_files:
|
|
409
410
|
- spec/config/helper.rb
|
410
411
|
- spec/config/literal_parser_spec.rb
|
411
412
|
- spec/config/section_spec.rb
|
413
|
+
- spec/config/system_config_spec.rb
|
412
414
|
- spec/spec_helper.rb
|
413
415
|
- test/helper.rb
|
414
416
|
- test/plugin/data/2010/01/20100102-030405.log
|