fluentd 0.12.40 → 0.14.0
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/.github/ISSUE_TEMPLATE.md +6 -0
- data/.gitignore +2 -0
- data/.travis.yml +33 -21
- data/CONTRIBUTING.md +1 -0
- data/ChangeLog +810 -237
- data/README.md +0 -25
- data/Rakefile +2 -1
- data/Vagrantfile +17 -0
- data/appveyor.yml +35 -0
- data/example/filter_stdout.conf +5 -5
- data/example/in_forward.conf +2 -2
- data/example/in_http.conf +2 -2
- data/example/in_out_forward.conf +17 -0
- data/example/in_syslog.conf +2 -2
- data/example/in_tail.conf +2 -2
- data/example/in_tcp.conf +2 -2
- data/example/in_udp.conf +2 -2
- data/example/out_copy.conf +4 -4
- data/example/out_file.conf +2 -2
- data/example/out_forward.conf +2 -2
- data/example/out_forward_buf_file.conf +23 -0
- data/example/v0_12_filter.conf +8 -8
- data/fluent.conf +29 -0
- data/fluentd.gemspec +18 -11
- data/lib/fluent/agent.rb +60 -58
- data/lib/fluent/command/cat.rb +1 -1
- data/lib/fluent/command/debug.rb +7 -5
- data/lib/fluent/command/fluentd.rb +97 -2
- data/lib/fluent/compat/call_super_mixin.rb +67 -0
- data/lib/fluent/compat/filter.rb +50 -0
- data/lib/fluent/compat/formatter.rb +109 -0
- data/lib/fluent/compat/input.rb +50 -0
- data/lib/fluent/compat/output.rb +617 -0
- data/lib/fluent/compat/output_chain.rb +60 -0
- data/lib/fluent/compat/parser.rb +163 -0
- data/lib/fluent/compat/propagate_default.rb +62 -0
- data/lib/fluent/config.rb +23 -20
- data/lib/fluent/config/configure_proxy.rb +119 -70
- data/lib/fluent/config/dsl.rb +5 -18
- data/lib/fluent/config/element.rb +72 -8
- data/lib/fluent/config/error.rb +0 -3
- data/lib/fluent/config/literal_parser.rb +0 -2
- data/lib/fluent/config/parser.rb +4 -4
- data/lib/fluent/config/section.rb +39 -28
- data/lib/fluent/config/types.rb +2 -13
- data/lib/fluent/config/v1_parser.rb +1 -3
- data/lib/fluent/configurable.rb +48 -16
- data/lib/fluent/daemon.rb +15 -0
- data/lib/fluent/engine.rb +26 -52
- data/lib/fluent/env.rb +6 -4
- data/lib/fluent/event.rb +58 -11
- data/lib/fluent/event_router.rb +5 -5
- data/lib/fluent/filter.rb +2 -50
- data/lib/fluent/formatter.rb +4 -293
- data/lib/fluent/input.rb +2 -32
- data/lib/fluent/label.rb +2 -2
- data/lib/fluent/load.rb +3 -2
- data/lib/fluent/log.rb +107 -38
- data/lib/fluent/match.rb +0 -36
- data/lib/fluent/mixin.rb +117 -7
- data/lib/fluent/msgpack_factory.rb +62 -0
- data/lib/fluent/output.rb +7 -612
- data/lib/fluent/output_chain.rb +23 -0
- data/lib/fluent/parser.rb +4 -800
- data/lib/fluent/plugin.rb +100 -121
- data/lib/fluent/plugin/bare_output.rb +63 -0
- data/lib/fluent/plugin/base.rb +121 -0
- data/lib/fluent/plugin/buf_file.rb +101 -182
- data/lib/fluent/plugin/buf_memory.rb +9 -92
- data/lib/fluent/plugin/buffer.rb +473 -0
- data/lib/fluent/plugin/buffer/chunk.rb +135 -0
- data/lib/fluent/plugin/buffer/file_chunk.rb +339 -0
- data/lib/fluent/plugin/buffer/memory_chunk.rb +100 -0
- data/lib/fluent/plugin/exec_util.rb +80 -75
- data/lib/fluent/plugin/file_util.rb +33 -28
- data/lib/fluent/plugin/file_wrapper.rb +120 -0
- data/lib/fluent/plugin/filter.rb +51 -0
- data/lib/fluent/plugin/filter_grep.rb +13 -40
- data/lib/fluent/plugin/filter_record_transformer.rb +22 -18
- data/lib/fluent/plugin/formatter.rb +93 -0
- data/lib/fluent/plugin/formatter_csv.rb +48 -0
- data/lib/fluent/plugin/formatter_hash.rb +32 -0
- data/lib/fluent/plugin/formatter_json.rb +47 -0
- data/lib/fluent/plugin/formatter_ltsv.rb +42 -0
- data/lib/fluent/plugin/formatter_msgpack.rb +32 -0
- data/lib/fluent/plugin/formatter_out_file.rb +45 -0
- data/lib/fluent/plugin/formatter_single_value.rb +34 -0
- data/lib/fluent/plugin/formatter_stdout.rb +39 -0
- data/lib/fluent/plugin/in_debug_agent.rb +4 -0
- data/lib/fluent/plugin/in_dummy.rb +22 -18
- data/lib/fluent/plugin/in_exec.rb +18 -8
- data/lib/fluent/plugin/in_forward.rb +36 -79
- data/lib/fluent/plugin/in_gc_stat.rb +4 -0
- data/lib/fluent/plugin/in_http.rb +21 -18
- data/lib/fluent/plugin/in_monitor_agent.rb +15 -48
- data/lib/fluent/plugin/in_object_space.rb +6 -1
- data/lib/fluent/plugin/in_stream.rb +7 -3
- data/lib/fluent/plugin/in_syslog.rb +46 -95
- data/lib/fluent/plugin/in_tail.rb +51 -595
- data/lib/fluent/plugin/in_tcp.rb +8 -1
- data/lib/fluent/plugin/in_udp.rb +8 -14
- data/lib/fluent/plugin/input.rb +33 -0
- data/lib/fluent/plugin/multi_output.rb +95 -0
- data/lib/fluent/plugin/out_buffered_null.rb +59 -0
- data/lib/fluent/plugin/out_copy.rb +11 -7
- data/lib/fluent/plugin/out_exec.rb +15 -11
- data/lib/fluent/plugin/out_exec_filter.rb +18 -10
- data/lib/fluent/plugin/out_file.rb +34 -5
- data/lib/fluent/plugin/out_forward.rb +19 -9
- data/lib/fluent/plugin/out_null.rb +0 -14
- data/lib/fluent/plugin/out_roundrobin.rb +11 -7
- data/lib/fluent/plugin/out_stdout.rb +5 -7
- data/lib/fluent/plugin/out_stream.rb +3 -1
- data/lib/fluent/plugin/output.rb +979 -0
- data/lib/fluent/plugin/owned_by_mixin.rb +42 -0
- data/lib/fluent/plugin/parser.rb +244 -0
- data/lib/fluent/plugin/parser_apache.rb +24 -0
- data/lib/fluent/plugin/parser_apache2.rb +84 -0
- data/lib/fluent/plugin/parser_apache_error.rb +21 -0
- data/lib/fluent/plugin/parser_csv.rb +31 -0
- data/lib/fluent/plugin/parser_json.rb +79 -0
- data/lib/fluent/plugin/parser_ltsv.rb +50 -0
- data/lib/fluent/plugin/parser_multiline.rb +102 -0
- data/lib/fluent/plugin/parser_nginx.rb +24 -0
- data/lib/fluent/plugin/parser_none.rb +36 -0
- data/lib/fluent/plugin/parser_syslog.rb +82 -0
- data/lib/fluent/plugin/parser_tsv.rb +37 -0
- data/lib/fluent/plugin/socket_util.rb +120 -114
- data/lib/fluent/plugin/storage.rb +84 -0
- data/lib/fluent/plugin/storage_local.rb +116 -0
- data/lib/fluent/plugin/string_util.rb +16 -13
- data/lib/fluent/plugin_helper.rb +39 -0
- data/lib/fluent/plugin_helper/child_process.rb +298 -0
- data/lib/fluent/plugin_helper/compat_parameters.rb +99 -0
- data/lib/fluent/plugin_helper/event_emitter.rb +80 -0
- data/lib/fluent/plugin_helper/event_loop.rb +118 -0
- data/lib/fluent/plugin_helper/retry_state.rb +177 -0
- data/lib/fluent/plugin_helper/storage.rb +308 -0
- data/lib/fluent/plugin_helper/thread.rb +147 -0
- data/lib/fluent/plugin_helper/timer.rb +85 -0
- data/lib/fluent/plugin_id.rb +63 -0
- data/lib/fluent/process.rb +21 -30
- data/lib/fluent/registry.rb +21 -9
- data/lib/fluent/root_agent.rb +115 -40
- data/lib/fluent/supervisor.rb +330 -320
- data/lib/fluent/system_config.rb +42 -18
- data/lib/fluent/test.rb +6 -1
- data/lib/fluent/test/base.rb +23 -3
- data/lib/fluent/test/driver/base.rb +247 -0
- data/lib/fluent/test/driver/event_feeder.rb +98 -0
- data/lib/fluent/test/driver/filter.rb +35 -0
- data/lib/fluent/test/driver/input.rb +31 -0
- data/lib/fluent/test/driver/output.rb +78 -0
- data/lib/fluent/test/driver/test_event_router.rb +45 -0
- data/lib/fluent/test/filter_test.rb +0 -1
- data/lib/fluent/test/formatter_test.rb +2 -1
- data/lib/fluent/test/input_test.rb +23 -17
- data/lib/fluent/test/output_test.rb +28 -39
- data/lib/fluent/test/parser_test.rb +1 -1
- data/lib/fluent/time.rb +104 -1
- data/lib/fluent/{status.rb → unique_id.rb} +15 -24
- data/lib/fluent/version.rb +1 -1
- data/lib/fluent/winsvc.rb +72 -0
- data/test/compat/test_calls_super.rb +164 -0
- data/test/config/test_config_parser.rb +83 -0
- data/test/config/test_configurable.rb +547 -274
- data/test/config/test_configure_proxy.rb +146 -29
- data/test/config/test_dsl.rb +3 -181
- data/test/config/test_element.rb +274 -0
- data/test/config/test_literal_parser.rb +1 -1
- data/test/config/test_section.rb +79 -7
- data/test/config/test_system_config.rb +21 -0
- data/test/config/test_types.rb +3 -26
- data/test/helper.rb +78 -8
- data/test/plugin/test_bare_output.rb +118 -0
- data/test/plugin/test_base.rb +75 -0
- data/test/plugin/test_buf_file.rb +420 -521
- data/test/plugin/test_buf_memory.rb +32 -194
- data/test/plugin/test_buffer.rb +981 -0
- data/test/plugin/test_buffer_chunk.rb +110 -0
- data/test/plugin/test_buffer_file_chunk.rb +770 -0
- data/test/plugin/test_buffer_memory_chunk.rb +265 -0
- data/test/plugin/test_filter.rb +255 -0
- data/test/plugin/test_filter_grep.rb +2 -73
- data/test/plugin/test_filter_record_transformer.rb +24 -68
- data/test/plugin/test_filter_stdout.rb +6 -6
- data/test/plugin/test_in_debug_agent.rb +2 -0
- data/test/plugin/test_in_dummy.rb +11 -17
- data/test/plugin/test_in_exec.rb +6 -25
- data/test/plugin/test_in_forward.rb +112 -151
- data/test/plugin/test_in_gc_stat.rb +2 -0
- data/test/plugin/test_in_http.rb +106 -157
- data/test/plugin/test_in_object_space.rb +21 -5
- data/test/plugin/test_in_stream.rb +14 -13
- data/test/plugin/test_in_syslog.rb +30 -275
- data/test/plugin/test_in_tail.rb +95 -234
- data/test/plugin/test_in_tcp.rb +14 -0
- data/test/plugin/test_in_udp.rb +21 -13
- data/test/plugin/test_input.rb +122 -0
- data/test/plugin/test_multi_output.rb +180 -0
- data/test/plugin/test_out_buffered_null.rb +79 -0
- data/test/plugin/test_out_copy.rb +15 -2
- data/test/plugin/test_out_exec.rb +75 -25
- data/test/plugin/test_out_exec_filter.rb +74 -8
- data/test/plugin/test_out_file.rb +61 -7
- data/test/plugin/test_out_forward.rb +92 -15
- data/test/plugin/test_out_roundrobin.rb +1 -0
- data/test/plugin/test_out_stdout.rb +22 -13
- data/test/plugin/test_out_stream.rb +18 -0
- data/test/plugin/test_output.rb +515 -0
- data/test/plugin/test_output_as_buffered.rb +1540 -0
- data/test/plugin/test_output_as_buffered_overflow.rb +247 -0
- data/test/plugin/test_output_as_buffered_retries.rb +808 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +776 -0
- data/test/plugin/test_output_as_standard.rb +362 -0
- data/test/plugin/test_owned_by.rb +35 -0
- data/test/plugin/test_storage.rb +167 -0
- data/test/plugin/test_storage_local.rb +8 -0
- data/test/plugin_helper/test_child_process.rb +599 -0
- data/test/plugin_helper/test_compat_parameters.rb +175 -0
- data/test/plugin_helper/test_event_emitter.rb +51 -0
- data/test/plugin_helper/test_event_loop.rb +52 -0
- data/test/plugin_helper/test_retry_state.rb +399 -0
- data/test/plugin_helper/test_storage.rb +411 -0
- data/test/plugin_helper/test_thread.rb +164 -0
- data/test/plugin_helper/test_timer.rb +100 -0
- data/test/scripts/exec_script.rb +0 -6
- data/test/scripts/fluent/plugin/out_test.rb +3 -0
- data/test/test_config.rb +13 -4
- data/test/test_event.rb +24 -13
- data/test/test_event_router.rb +8 -7
- data/test/test_event_time.rb +187 -0
- data/test/test_formatter.rb +13 -51
- data/test/test_input.rb +1 -1
- data/test/test_log.rb +239 -16
- data/test/test_mixin.rb +1 -1
- data/test/test_output.rb +53 -66
- data/test/test_parser.rb +105 -323
- data/test/test_plugin_helper.rb +81 -0
- data/test/test_root_agent.rb +4 -52
- data/test/test_supervisor.rb +272 -0
- data/test/test_unique_id.rb +47 -0
- metadata +180 -54
- data/lib/fluent/buffer.rb +0 -365
- data/lib/fluent/plugin/filter_parser.rb +0 -107
- data/lib/fluent/plugin/in_status.rb +0 -76
- data/lib/fluent/test/helpers.rb +0 -86
- data/test/plugin/data/log/foo/bar2 +0 -0
- data/test/plugin/test_filter_parser.rb +0 -744
- data/test/plugin/test_in_status.rb +0 -38
- data/test/test_buffer.rb +0 -624
@@ -0,0 +1,62 @@
|
|
1
|
+
#
|
2
|
+
# Fluentd
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'msgpack'
|
18
|
+
require 'fluent/time'
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module MessagePackFactory
|
22
|
+
@@engine_factory = nil
|
23
|
+
|
24
|
+
module Mixin
|
25
|
+
def msgpack_factory
|
26
|
+
MessagePackFactory.engine_factory
|
27
|
+
end
|
28
|
+
|
29
|
+
def msgpack_packer(*args)
|
30
|
+
msgpack_factory.packer(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def msgpack_unpacker(*args)
|
34
|
+
msgpack_factory.unpacker(*args)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.engine_factory
|
39
|
+
@@engine_factory || factory
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.factory
|
43
|
+
factory = MessagePack::Factory.new
|
44
|
+
factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
|
45
|
+
factory
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.packer(*args)
|
49
|
+
factory.packer(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.unpacker(*args)
|
53
|
+
factory.unpacker(*args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.init
|
57
|
+
factory = MessagePack::Factory.new
|
58
|
+
factory.register_type(Fluent::EventTime::TYPE, Fluent::EventTime)
|
59
|
+
@@engine_factory = factory
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/fluent/output.rb
CHANGED
@@ -14,618 +14,13 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
-
require '
|
18
|
-
|
19
|
-
require 'fluent/config'
|
20
|
-
require 'fluent/configurable'
|
21
|
-
require 'fluent/engine'
|
22
|
-
require 'fluent/log'
|
23
|
-
require 'fluent/plugin'
|
24
|
-
require 'fluent/status'
|
25
|
-
require 'fluent/timezone'
|
17
|
+
require 'fluent/compat/output'
|
18
|
+
require 'fluent/output_chain'
|
26
19
|
|
27
20
|
module Fluent
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
@offset = 0
|
34
|
-
@chain = chain
|
35
|
-
end
|
36
|
-
|
37
|
-
def next
|
38
|
-
if @array.length <= @offset
|
39
|
-
return @chain.next
|
40
|
-
end
|
41
|
-
@offset += 1
|
42
|
-
result = @array[@offset-1].emit(@tag, @es, self)
|
43
|
-
result
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class CopyOutputChain < OutputChain
|
48
|
-
def next
|
49
|
-
if @array.length <= @offset
|
50
|
-
return @chain.next
|
51
|
-
end
|
52
|
-
@offset += 1
|
53
|
-
es = @array.length > @offset ? @es.dup : @es
|
54
|
-
result = @array[@offset-1].emit(@tag, es, self)
|
55
|
-
result
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class NullOutputChain
|
60
|
-
require 'singleton'
|
61
|
-
include Singleton
|
62
|
-
|
63
|
-
def next
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
class Output
|
69
|
-
include Configurable
|
70
|
-
include PluginId
|
71
|
-
include PluginLoggerMixin
|
72
|
-
|
73
|
-
attr_accessor :router
|
74
|
-
|
75
|
-
def initialize
|
76
|
-
super
|
77
|
-
end
|
78
|
-
|
79
|
-
def configure(conf)
|
80
|
-
super
|
81
|
-
|
82
|
-
if label_name = conf['@label']
|
83
|
-
label = Engine.root_agent.find_label(label_name)
|
84
|
-
@router = label.event_router
|
85
|
-
elsif @router.nil?
|
86
|
-
@router = Engine.root_agent.event_router
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def start
|
91
|
-
end
|
92
|
-
|
93
|
-
def shutdown
|
94
|
-
end
|
95
|
-
|
96
|
-
#def emit(tag, es, chain)
|
97
|
-
#end
|
98
|
-
|
99
|
-
def secondary_init(primary)
|
100
|
-
if primary.class != self.class
|
101
|
-
$log.warn "type of secondary output should be same as primary output", primary: primary.class.to_s, secondary: self.class.to_s
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
class OutputThread
|
107
|
-
def initialize(output)
|
108
|
-
@output = output
|
109
|
-
@finish = false
|
110
|
-
@next_time = Time.now.to_f + 1.0
|
111
|
-
end
|
112
|
-
|
113
|
-
def configure(conf)
|
114
|
-
end
|
115
|
-
|
116
|
-
def start
|
117
|
-
@mutex = Mutex.new
|
118
|
-
@cond = ConditionVariable.new
|
119
|
-
@thread = Thread.new(&method(:run))
|
120
|
-
end
|
121
|
-
|
122
|
-
def shutdown
|
123
|
-
@finish = true
|
124
|
-
@mutex.synchronize {
|
125
|
-
@cond.signal
|
126
|
-
}
|
127
|
-
Thread.pass
|
128
|
-
@thread.join
|
129
|
-
end
|
130
|
-
|
131
|
-
def submit_flush
|
132
|
-
@mutex.synchronize {
|
133
|
-
@next_time = 0
|
134
|
-
@cond.signal
|
135
|
-
}
|
136
|
-
Thread.pass
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
def run
|
141
|
-
@mutex.lock
|
142
|
-
begin
|
143
|
-
until @finish
|
144
|
-
time = Time.now.to_f
|
145
|
-
|
146
|
-
if @next_time <= time
|
147
|
-
@mutex.unlock
|
148
|
-
begin
|
149
|
-
@next_time = @output.try_flush
|
150
|
-
ensure
|
151
|
-
@mutex.lock
|
152
|
-
end
|
153
|
-
next_wait = @next_time - Time.now.to_f
|
154
|
-
else
|
155
|
-
next_wait = @next_time - time
|
156
|
-
end
|
157
|
-
|
158
|
-
cond_wait(next_wait) if next_wait > 0
|
159
|
-
end
|
160
|
-
ensure
|
161
|
-
@mutex.unlock
|
162
|
-
end
|
163
|
-
rescue
|
164
|
-
$log.error "error on output thread", error: $!.to_s
|
165
|
-
$log.error_backtrace
|
166
|
-
raise
|
167
|
-
ensure
|
168
|
-
@mutex.synchronize {
|
169
|
-
@output.before_shutdown
|
170
|
-
}
|
171
|
-
end
|
172
|
-
|
173
|
-
def cond_wait(sec)
|
174
|
-
@cond.wait(@mutex, sec)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
class BufferedOutput < Output
|
180
|
-
def initialize
|
181
|
-
super
|
182
|
-
@next_flush_time = 0
|
183
|
-
@last_retry_time = 0
|
184
|
-
@next_retry_time = 0
|
185
|
-
@num_errors = 0
|
186
|
-
@num_errors_lock = Mutex.new
|
187
|
-
@secondary_limit = 8
|
188
|
-
@emit_count = 0
|
189
|
-
end
|
190
|
-
|
191
|
-
desc 'The buffer type (memory, file)'
|
192
|
-
config_param :buffer_type, :string, default: 'memory'
|
193
|
-
desc 'The interval between data flushes.'
|
194
|
-
config_param :flush_interval, :time, default: 60
|
195
|
-
config_param :try_flush_interval, :float, default: 1
|
196
|
-
desc 'If true, the value of `retry_value` is ignored and there is no limit'
|
197
|
-
config_param :disable_retry_limit, :bool, default: false
|
198
|
-
desc 'The limit on the number of retries before buffered data is discarded'
|
199
|
-
config_param :retry_limit, :integer, default: 17
|
200
|
-
desc 'The initial intervals between write retries.'
|
201
|
-
config_param :retry_wait, :time, default: 1.0
|
202
|
-
desc 'The maximum intervals between write retries.'
|
203
|
-
config_param :max_retry_wait, :time, default: nil
|
204
|
-
desc 'The number of threads to flush the buffer.'
|
205
|
-
config_param :num_threads, :integer, default: 1
|
206
|
-
desc 'The threshold to show slow flush logs'
|
207
|
-
config_param :slow_flush_log_threshold, :float, default: 20.0
|
208
|
-
desc 'The interval between data flushes for queued chunk.'
|
209
|
-
config_param :queued_chunk_flush_interval, :time, default: 1
|
210
|
-
|
211
|
-
def configure(conf)
|
212
|
-
super
|
213
|
-
|
214
|
-
@retry_wait = @retry_wait.to_f # converted to Float for calc_retry_wait
|
215
|
-
@buffer = Plugin.new_buffer(@buffer_type)
|
216
|
-
@buffer.configure(conf)
|
217
|
-
|
218
|
-
if @buffer.respond_to?(:enable_parallel)
|
219
|
-
if @num_threads == 1
|
220
|
-
@buffer.enable_parallel(false)
|
221
|
-
else
|
222
|
-
@buffer.enable_parallel(true)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
@writers = (1..@num_threads).map {
|
227
|
-
writer = OutputThread.new(self)
|
228
|
-
writer.configure(conf)
|
229
|
-
writer
|
230
|
-
}
|
231
|
-
|
232
|
-
if sconf = conf.elements.select {|e| e.name == 'secondary' }.first
|
233
|
-
type = sconf['@type'] || conf['@type'] || sconf['type'] || conf['type']
|
234
|
-
@secondary = Plugin.new_output(type)
|
235
|
-
@secondary.router = router
|
236
|
-
@secondary.configure(sconf)
|
237
|
-
|
238
|
-
if secondary_limit = conf['secondary_limit']
|
239
|
-
@secondary_limit = secondary_limit.to_i
|
240
|
-
if @secondary_limit < 0
|
241
|
-
raise ConfigError, "invalid parameter 'secondary_limit #{secondary_limit}'"
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
@secondary.secondary_init(self)
|
246
|
-
end
|
247
|
-
|
248
|
-
Status.register(self, "queue_size") { @buffer.queue_size }
|
249
|
-
Status.register(self, "emit_count") { @emit_count }
|
250
|
-
end
|
251
|
-
|
252
|
-
def start
|
253
|
-
@next_flush_time = Time.now.to_f + @flush_interval
|
254
|
-
@buffer.start
|
255
|
-
@secondary.start if @secondary
|
256
|
-
@writers.each {|writer| writer.start }
|
257
|
-
@writer_current_position = 0
|
258
|
-
@writers_size = @writers.size
|
259
|
-
end
|
260
|
-
|
261
|
-
def shutdown
|
262
|
-
@writers.each {|writer| writer.shutdown }
|
263
|
-
@secondary.shutdown if @secondary
|
264
|
-
@buffer.shutdown
|
265
|
-
end
|
266
|
-
|
267
|
-
def emit(tag, es, chain, key="")
|
268
|
-
@emit_count += 1
|
269
|
-
data = format_stream(tag, es)
|
270
|
-
if @buffer.emit(key, data, chain)
|
271
|
-
submit_flush
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def submit_flush
|
276
|
-
# Without locks: it is rough but enough to select "next" writer selection
|
277
|
-
@writer_current_position = (@writer_current_position + 1) % @writers_size
|
278
|
-
@writers[@writer_current_position].submit_flush
|
279
|
-
end
|
280
|
-
|
281
|
-
def format_stream(tag, es)
|
282
|
-
out = ''
|
283
|
-
es.each {|time,record|
|
284
|
-
out << format(tag, time, record)
|
285
|
-
}
|
286
|
-
out
|
287
|
-
end
|
288
|
-
|
289
|
-
#def format(tag, time, record)
|
290
|
-
#end
|
291
|
-
|
292
|
-
#def write(chunk)
|
293
|
-
#end
|
294
|
-
|
295
|
-
def enqueue_buffer(force = false)
|
296
|
-
@buffer.keys.each {|key|
|
297
|
-
@buffer.push(key)
|
298
|
-
}
|
299
|
-
end
|
300
|
-
|
301
|
-
def try_flush
|
302
|
-
time = Time.now.to_f
|
303
|
-
|
304
|
-
empty = @buffer.queue_size == 0
|
305
|
-
if empty && @next_flush_time < (now = Time.now.to_f)
|
306
|
-
@buffer.synchronize do
|
307
|
-
if @next_flush_time < now
|
308
|
-
enqueue_buffer
|
309
|
-
@next_flush_time = now + @flush_interval
|
310
|
-
empty = @buffer.queue_size == 0
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
if empty
|
315
|
-
return time + @try_flush_interval
|
316
|
-
end
|
317
|
-
|
318
|
-
begin
|
319
|
-
retrying = !@num_errors.zero?
|
320
|
-
|
321
|
-
if retrying
|
322
|
-
@num_errors_lock.synchronize do
|
323
|
-
if retrying = !@num_errors.zero? # re-check in synchronize
|
324
|
-
if @next_retry_time >= time
|
325
|
-
# allow retrying for only one thread
|
326
|
-
return time + @try_flush_interval
|
327
|
-
end
|
328
|
-
# assume next retry failes and
|
329
|
-
# clear them if when it succeeds
|
330
|
-
@last_retry_time = time
|
331
|
-
@num_errors += 1
|
332
|
-
@next_retry_time += calc_retry_wait
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
chunk_write_start = Time.now
|
338
|
-
|
339
|
-
if @secondary && !@disable_retry_limit && @num_errors > @retry_limit
|
340
|
-
has_next = flush_secondary(@secondary)
|
341
|
-
else
|
342
|
-
has_next = @buffer.pop(self)
|
343
|
-
end
|
344
|
-
|
345
|
-
elapsed_time = Time.now - chunk_write_start
|
346
|
-
if elapsed_time > @slow_flush_log_threshold
|
347
|
-
$log.warn "buffer flush took longer time than slow_flush_log_threshold:",
|
348
|
-
plugin_id: plugin_id, elapsed_time: elapsed_time, slow_flush_log_threshold: @slow_flush_log_threshold
|
349
|
-
end
|
350
|
-
|
351
|
-
# success
|
352
|
-
if retrying
|
353
|
-
@num_errors = 0
|
354
|
-
# Note: don't notify to other threads to prevent
|
355
|
-
# burst to recovered server
|
356
|
-
$log.warn "retry succeeded.", plugin_id: plugin_id
|
357
|
-
end
|
358
|
-
|
359
|
-
if has_next
|
360
|
-
return Time.now.to_f + @queued_chunk_flush_interval
|
361
|
-
else
|
362
|
-
return time + @try_flush_interval
|
363
|
-
end
|
364
|
-
|
365
|
-
rescue => e
|
366
|
-
if retrying
|
367
|
-
error_count = @num_errors
|
368
|
-
else
|
369
|
-
# first error
|
370
|
-
error_count = 0
|
371
|
-
@num_errors_lock.synchronize do
|
372
|
-
if @num_errors.zero?
|
373
|
-
@last_retry_time = time
|
374
|
-
@num_errors += 1
|
375
|
-
@next_retry_time = time + calc_retry_wait
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
if @disable_retry_limit || error_count < @retry_limit
|
381
|
-
$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, plugin_id: plugin_id
|
382
|
-
$log.warn_backtrace e.backtrace
|
383
|
-
|
384
|
-
elsif @secondary
|
385
|
-
if error_count == @retry_limit
|
386
|
-
$log.warn "failed to flush the buffer.", error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
|
387
|
-
$log.warn "retry count exceededs limit. falling back to secondary output."
|
388
|
-
$log.warn_backtrace e.backtrace
|
389
|
-
retry # retry immediately
|
390
|
-
elsif error_count <= @retry_limit + @secondary_limit
|
391
|
-
$log.warn "failed to flush the buffer, next retry will be with secondary output.", next_retry: Time.at(@next_retry_time), error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
|
392
|
-
$log.warn_backtrace e.backtrace
|
393
|
-
else
|
394
|
-
$log.warn "failed to flush the buffer.", error_class: e.class, error: e.to_s, plugin_id: plugin_id
|
395
|
-
$log.warn "secondary retry count exceededs limit."
|
396
|
-
$log.warn_backtrace e.backtrace
|
397
|
-
write_abort
|
398
|
-
@num_errors = 0
|
399
|
-
end
|
400
|
-
|
401
|
-
else
|
402
|
-
$log.warn "failed to flush the buffer.", error_class: e.class.to_s, error: e.to_s, plugin_id: plugin_id
|
403
|
-
$log.warn "retry count exceededs limit."
|
404
|
-
$log.warn_backtrace e.backtrace
|
405
|
-
write_abort
|
406
|
-
@num_errors = 0
|
407
|
-
end
|
408
|
-
|
409
|
-
return @next_retry_time
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
def force_flush
|
414
|
-
@num_errors_lock.synchronize do
|
415
|
-
@next_retry_time = Time.now.to_f - 1
|
416
|
-
end
|
417
|
-
enqueue_buffer(true)
|
418
|
-
submit_flush
|
419
|
-
end
|
420
|
-
|
421
|
-
def before_shutdown
|
422
|
-
begin
|
423
|
-
@buffer.before_shutdown(self)
|
424
|
-
rescue
|
425
|
-
$log.warn "before_shutdown failed", error: $!.to_s
|
426
|
-
$log.warn_backtrace
|
427
|
-
end
|
428
|
-
end
|
429
|
-
|
430
|
-
def calc_retry_wait
|
431
|
-
# TODO retry pattern
|
432
|
-
wait = if @disable_retry_limit || @num_errors <= @retry_limit
|
433
|
-
@retry_wait * (2 ** (@num_errors - 1))
|
434
|
-
else
|
435
|
-
# secondary retry
|
436
|
-
@retry_wait * (2 ** (@num_errors - 2 - @retry_limit))
|
437
|
-
end
|
438
|
-
retry_wait = wait.finite? ? wait + (rand * (wait / 4.0) - (wait / 8.0)) : wait
|
439
|
-
@max_retry_wait ? [retry_wait, @max_retry_wait].min : retry_wait
|
440
|
-
end
|
441
|
-
|
442
|
-
def write_abort
|
443
|
-
$log.error "throwing away old logs."
|
444
|
-
begin
|
445
|
-
@buffer.clear!
|
446
|
-
rescue
|
447
|
-
$log.error "unexpected error while aborting", error: $!.to_s
|
448
|
-
$log.error_backtrace
|
449
|
-
end
|
450
|
-
end
|
451
|
-
|
452
|
-
def flush_secondary(secondary)
|
453
|
-
@buffer.pop(secondary)
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
|
458
|
-
class ObjectBufferedOutput < BufferedOutput
|
459
|
-
def initialize
|
460
|
-
super
|
461
|
-
end
|
462
|
-
|
463
|
-
def emit(tag, es, chain)
|
464
|
-
@emit_count += 1
|
465
|
-
data = es.to_msgpack_stream
|
466
|
-
key = tag
|
467
|
-
if @buffer.emit(key, data, chain)
|
468
|
-
submit_flush
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
module BufferedEventStreamMixin
|
473
|
-
include Enumerable
|
474
|
-
|
475
|
-
def repeatable?
|
476
|
-
true
|
477
|
-
end
|
478
|
-
|
479
|
-
def each(&block)
|
480
|
-
msgpack_each(&block)
|
481
|
-
end
|
482
|
-
|
483
|
-
def to_msgpack_stream
|
484
|
-
read
|
485
|
-
end
|
486
|
-
end
|
487
|
-
|
488
|
-
def write(chunk)
|
489
|
-
chunk.extend(BufferedEventStreamMixin)
|
490
|
-
write_objects(chunk.key, chunk)
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
|
495
|
-
class TimeSlicedOutput < BufferedOutput
|
496
|
-
require 'fluent/timezone'
|
497
|
-
|
498
|
-
def initialize
|
499
|
-
super
|
500
|
-
@localtime = true
|
501
|
-
#@ignore_old = false # TODO
|
502
|
-
end
|
503
|
-
|
504
|
-
desc 'The time format used as part of the file name.'
|
505
|
-
config_param :time_slice_format, :string, default: '%Y%m%d'
|
506
|
-
desc 'The amount of time Fluentd will wait for old logs to arrive.'
|
507
|
-
config_param :time_slice_wait, :time, default: 10*60
|
508
|
-
desc 'Parse the time value in the specified timezone'
|
509
|
-
config_param :timezone, :string, default: nil
|
510
|
-
config_set_default :buffer_type, 'file' # overwrite default buffer_type
|
511
|
-
config_set_default :buffer_chunk_limit, 256*1024*1024 # overwrite default buffer_chunk_limit
|
512
|
-
config_set_default :flush_interval, nil
|
513
|
-
config_set_default :slow_flush_log_threshold, 40.0
|
514
|
-
|
515
|
-
attr_accessor :localtime
|
516
|
-
attr_reader :time_slicer # for test
|
517
|
-
|
518
|
-
def configure(conf)
|
519
|
-
super
|
520
|
-
|
521
|
-
if conf['utc']
|
522
|
-
@localtime = false
|
523
|
-
elsif conf['localtime']
|
524
|
-
@localtime = true
|
525
|
-
end
|
526
|
-
|
527
|
-
if conf['timezone']
|
528
|
-
@timezone = conf['timezone']
|
529
|
-
Fluent::Timezone.validate!(@timezone)
|
530
|
-
end
|
531
|
-
|
532
|
-
if @timezone
|
533
|
-
@time_slicer = Timezone.formatter(@timezone, @time_slice_format)
|
534
|
-
elsif @localtime
|
535
|
-
@time_slicer = Proc.new {|time|
|
536
|
-
Time.at(time).strftime(@time_slice_format)
|
537
|
-
}
|
538
|
-
else
|
539
|
-
@time_slicer = Proc.new {|time|
|
540
|
-
Time.at(time).utc.strftime(@time_slice_format)
|
541
|
-
}
|
542
|
-
end
|
543
|
-
|
544
|
-
@time_slice_cache_interval = time_slice_cache_interval
|
545
|
-
@before_tc = nil
|
546
|
-
@before_key = nil
|
547
|
-
|
548
|
-
if @flush_interval
|
549
|
-
if conf['time_slice_wait']
|
550
|
-
$log.warn "time_slice_wait is ignored if flush_interval is specified: #{conf}"
|
551
|
-
end
|
552
|
-
@enqueue_buffer_proc = Proc.new do
|
553
|
-
@buffer.keys.each {|key|
|
554
|
-
@buffer.push(key)
|
555
|
-
}
|
556
|
-
end
|
557
|
-
|
558
|
-
else
|
559
|
-
@flush_interval = [60, @time_slice_cache_interval].min
|
560
|
-
@enqueue_buffer_proc = Proc.new do
|
561
|
-
nowslice = @time_slicer.call(Engine.now - @time_slice_wait)
|
562
|
-
@buffer.keys.each {|key|
|
563
|
-
if key < nowslice
|
564
|
-
@buffer.push(key)
|
565
|
-
end
|
566
|
-
}
|
567
|
-
end
|
568
|
-
end
|
569
|
-
end
|
570
|
-
|
571
|
-
def emit(tag, es, chain)
|
572
|
-
@emit_count += 1
|
573
|
-
formatted_data = {}
|
574
|
-
es.each {|time,record|
|
575
|
-
begin
|
576
|
-
tc = time / @time_slice_cache_interval
|
577
|
-
if @before_tc == tc
|
578
|
-
key = @before_key
|
579
|
-
else
|
580
|
-
@before_tc = tc
|
581
|
-
key = @time_slicer.call(time)
|
582
|
-
@before_key = key
|
583
|
-
end
|
584
|
-
rescue => e
|
585
|
-
@router.emit_error_event(tag, Engine.now, {'time' => time, 'record' => record}, e)
|
586
|
-
next
|
587
|
-
end
|
588
|
-
|
589
|
-
formatted_data[key] ||= ''
|
590
|
-
formatted_data[key] << format(tag, time, record)
|
591
|
-
}
|
592
|
-
formatted_data.each { |key, data|
|
593
|
-
if @buffer.emit(key, data, chain)
|
594
|
-
submit_flush
|
595
|
-
end
|
596
|
-
}
|
597
|
-
end
|
598
|
-
|
599
|
-
def enqueue_buffer(force = false)
|
600
|
-
if force
|
601
|
-
@buffer.keys.each {|key|
|
602
|
-
@buffer.push(key)
|
603
|
-
}
|
604
|
-
else
|
605
|
-
@enqueue_buffer_proc.call
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
#def format(tag, event)
|
610
|
-
#end
|
611
|
-
|
612
|
-
private
|
613
|
-
def time_slice_cache_interval
|
614
|
-
if @time_slicer.call(0) != @time_slicer.call(60-1)
|
615
|
-
return 1
|
616
|
-
elsif @time_slicer.call(0) != @time_slicer.call(60*60-1)
|
617
|
-
return 30
|
618
|
-
elsif @time_slicer.call(0) != @time_slicer.call(24*60*60-1)
|
619
|
-
return 60*30
|
620
|
-
else
|
621
|
-
return 24*60*30
|
622
|
-
end
|
623
|
-
end
|
624
|
-
end
|
625
|
-
|
626
|
-
|
627
|
-
class MultiOutput < Output
|
628
|
-
#def outputs
|
629
|
-
#end
|
630
|
-
end
|
21
|
+
Output = Fluent::Compat::Output
|
22
|
+
BufferedOutput = Fluent::Compat::BufferedOutput
|
23
|
+
ObjectBufferedOutput = Fluent::Compat::ObjectBufferedOutput
|
24
|
+
TimeSlicedOutput = Fluent::Compat::TimeSlicedOutput
|
25
|
+
MultiOutput = Fluent::Compat::MultiOutput
|
631
26
|
end
|