fluentd 0.14.17-x64-mingw32 → 1.3.1-x64-mingw32
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/.travis.yml +16 -5
- data/ADOPTERS.md +5 -0
- data/{ChangeLog → CHANGELOG.md} +495 -6
- data/CONTRIBUTING.md +5 -2
- data/GOVERNANCE.md +55 -0
- data/LICENSE +202 -0
- data/MAINTAINERS.md +7 -5
- data/README.md +17 -10
- data/bin/fluent-ca-generate +6 -0
- data/example/counter.conf +18 -0
- data/example/secondary_file.conf +3 -2
- data/fluentd.gemspec +3 -3
- data/lib/fluent/agent.rb +1 -1
- data/lib/fluent/command/binlog_reader.rb +11 -2
- data/lib/fluent/command/ca_generate.rb +181 -0
- data/lib/fluent/command/cat.rb +28 -15
- data/lib/fluent/command/debug.rb +4 -4
- data/lib/fluent/command/fluentd.rb +2 -2
- data/lib/fluent/command/plugin_config_formatter.rb +24 -2
- data/lib/fluent/command/plugin_generator.rb +26 -8
- data/lib/fluent/config/configure_proxy.rb +7 -1
- data/lib/fluent/config/dsl.rb +8 -5
- data/lib/fluent/config/element.rb +5 -0
- data/lib/fluent/config/literal_parser.rb +7 -1
- data/lib/fluent/config/types.rb +28 -2
- data/lib/fluent/config/v1_parser.rb +1 -2
- data/lib/fluent/configurable.rb +1 -0
- data/lib/fluent/counter.rb +23 -0
- data/lib/fluent/counter/base_socket.rb +46 -0
- data/lib/fluent/counter/client.rb +297 -0
- data/lib/fluent/counter/error.rb +86 -0
- data/lib/fluent/counter/mutex_hash.rb +163 -0
- data/lib/fluent/counter/server.rb +273 -0
- data/lib/fluent/counter/store.rb +205 -0
- data/lib/fluent/counter/validator.rb +145 -0
- data/lib/fluent/env.rb +1 -0
- data/lib/fluent/event_router.rb +1 -1
- data/lib/fluent/log.rb +119 -29
- data/lib/fluent/plugin/base.rb +12 -0
- data/lib/fluent/plugin/buf_file.rb +20 -16
- data/lib/fluent/plugin/buffer.rb +130 -32
- data/lib/fluent/plugin/buffer/file_chunk.rb +23 -4
- data/lib/fluent/plugin/compressable.rb +1 -1
- data/lib/fluent/plugin/filter_grep.rb +135 -21
- data/lib/fluent/plugin/filter_parser.rb +13 -2
- data/lib/fluent/plugin/filter_record_transformer.rb +16 -14
- data/lib/fluent/plugin/formatter_stdout.rb +3 -2
- data/lib/fluent/plugin/formatter_tsv.rb +5 -1
- data/lib/fluent/plugin/in_debug_agent.rb +8 -1
- data/lib/fluent/plugin/in_forward.rb +1 -1
- data/lib/fluent/plugin/in_http.rb +84 -3
- data/lib/fluent/plugin/in_monitor_agent.rb +7 -1
- data/lib/fluent/plugin/in_syslog.rb +31 -10
- data/lib/fluent/plugin/in_tail.rb +142 -53
- data/lib/fluent/plugin/in_tcp.rb +5 -6
- data/lib/fluent/plugin/in_udp.rb +6 -2
- data/lib/fluent/plugin/in_unix.rb +1 -1
- data/lib/fluent/plugin/multi_output.rb +1 -0
- data/lib/fluent/plugin/out_copy.rb +25 -2
- data/lib/fluent/plugin/out_file.rb +26 -7
- data/lib/fluent/plugin/out_forward.rb +81 -42
- data/lib/fluent/plugin/out_secondary_file.rb +2 -2
- data/lib/fluent/plugin/out_stdout.rb +0 -1
- data/lib/fluent/plugin/out_stream.rb +1 -1
- data/lib/fluent/plugin/output.rb +221 -57
- data/lib/fluent/plugin/parser_apache.rb +1 -1
- data/lib/fluent/plugin/parser_apache2.rb +5 -1
- data/lib/fluent/plugin/parser_apache_error.rb +1 -1
- data/lib/fluent/plugin/parser_json.rb +10 -3
- data/lib/fluent/plugin/parser_ltsv.rb +7 -0
- data/lib/fluent/plugin/parser_multiline.rb +2 -1
- data/lib/fluent/plugin/parser_nginx.rb +1 -1
- data/lib/fluent/plugin/parser_none.rb +1 -0
- data/lib/fluent/plugin/parser_regexp.rb +15 -14
- data/lib/fluent/plugin/parser_syslog.rb +9 -5
- data/lib/fluent/plugin_helper.rb +2 -0
- data/lib/fluent/plugin_helper/cert_option.rb +28 -9
- data/lib/fluent/plugin_helper/compat_parameters.rb +3 -1
- data/lib/fluent/plugin_helper/counter.rb +51 -0
- data/lib/fluent/plugin_helper/event_loop.rb +9 -0
- data/lib/fluent/plugin_helper/record_accessor.rb +210 -0
- data/lib/fluent/plugin_helper/retry_state.rb +15 -7
- data/lib/fluent/plugin_helper/server.rb +87 -25
- data/lib/fluent/plugin_helper/socket_option.rb +5 -2
- data/lib/fluent/plugin_helper/timer.rb +8 -7
- data/lib/fluent/root_agent.rb +18 -9
- data/lib/fluent/supervisor.rb +63 -23
- data/lib/fluent/system_config.rb +30 -2
- data/lib/fluent/test/helpers.rb +1 -1
- data/lib/fluent/time.rb +15 -7
- data/lib/fluent/timezone.rb +26 -2
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/README.md.erb +2 -2
- data/templates/new_gem/lib/fluent/plugin/filter.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/input.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/output.rb.erb +1 -1
- data/templates/new_gem/lib/fluent/plugin/parser.rb.erb +4 -4
- data/test/command/test_ca_generate.rb +70 -0
- data/test/command/test_fluentd.rb +2 -2
- data/test/command/test_plugin_config_formatter.rb +8 -7
- data/test/command/test_plugin_generator.rb +65 -39
- data/test/config/test_config_parser.rb +7 -2
- data/test/config/test_configurable.rb +7 -2
- data/test/config/test_configure_proxy.rb +41 -3
- data/test/config/test_dsl.rb +10 -10
- data/test/config/test_element.rb +10 -0
- data/test/config/test_literal_parser.rb +8 -0
- data/test/config/test_plugin_configuration.rb +56 -0
- data/test/config/test_system_config.rb +19 -1
- data/test/config/test_types.rb +37 -0
- data/test/counter/test_client.rb +559 -0
- data/test/counter/test_error.rb +44 -0
- data/test/counter/test_mutex_hash.rb +179 -0
- data/test/counter/test_server.rb +589 -0
- data/test/counter/test_store.rb +258 -0
- data/test/counter/test_validator.rb +137 -0
- data/test/plugin/test_buf_file.rb +124 -0
- data/test/plugin/test_buffer.rb +3 -2
- data/test/plugin/test_filter_grep.rb +580 -2
- data/test/plugin/test_filter_parser.rb +33 -2
- data/test/plugin/test_filter_record_transformer.rb +22 -1
- data/test/plugin/test_formatter_ltsv.rb +3 -0
- data/test/plugin/test_formatter_tsv.rb +68 -0
- data/test/plugin/test_in_debug_agent.rb +21 -0
- data/test/plugin/test_in_exec.rb +3 -5
- data/test/plugin/test_in_http.rb +178 -0
- data/test/plugin/test_in_monitor_agent.rb +1 -1
- data/test/plugin/test_in_syslog.rb +64 -0
- data/test/plugin/test_in_tail.rb +116 -6
- data/test/plugin/test_in_tcp.rb +21 -0
- data/test/plugin/test_in_udp.rb +78 -0
- data/test/plugin/test_metadata.rb +89 -0
- data/test/plugin/test_out_copy.rb +31 -0
- data/test/plugin/test_out_file.rb +108 -2
- data/test/plugin/test_out_forward.rb +195 -2
- data/test/plugin/test_out_secondary_file.rb +14 -0
- data/test/plugin/test_output.rb +159 -45
- data/test/plugin/test_output_as_buffered.rb +19 -0
- data/test/plugin/test_output_as_buffered_backup.rb +307 -0
- data/test/plugin/test_output_as_buffered_retries.rb +70 -0
- data/test/plugin/test_output_as_buffered_secondary.rb +1 -1
- data/test/plugin/test_parser_apache2.rb +1 -0
- data/test/plugin/test_parser_labeled_tsv.rb +17 -0
- data/test/plugin/test_parser_nginx.rb +40 -0
- data/test/plugin/test_parser_regexp.rb +6 -7
- data/test/plugin/test_parser_syslog.rb +155 -5
- data/test/plugin_helper/test_child_process.rb +4 -4
- data/test/plugin_helper/test_compat_parameters.rb +22 -0
- data/test/plugin_helper/test_record_accessor.rb +197 -0
- data/test/plugin_helper/test_retry_state.rb +20 -0
- data/test/plugin_helper/test_server.rb +30 -2
- data/test/test_config.rb +3 -3
- data/test/test_configdsl.rb +2 -2
- data/test/test_log.rb +51 -1
- data/test/test_root_agent.rb +33 -0
- data/test/test_supervisor.rb +105 -0
- metadata +68 -8
- data/COPYING +0 -14
@@ -370,6 +370,12 @@ module Fluent
|
|
370
370
|
|
371
371
|
def dump_config_definition
|
372
372
|
dumped_config = {}
|
373
|
+
if @argument
|
374
|
+
argument_name, _block, options = @argument
|
375
|
+
options[:required] = !@defaults.key?(argument_name)
|
376
|
+
options[:argument] = true
|
377
|
+
dumped_config[argument_name] = options
|
378
|
+
end
|
373
379
|
@params.each do |name, config|
|
374
380
|
dumped_config[name] = config[1]
|
375
381
|
dumped_config[name][:required] = !@defaults.key?(name)
|
@@ -378,7 +384,7 @@ module Fluent
|
|
378
384
|
end
|
379
385
|
# Overwrite by config_set_default
|
380
386
|
@defaults.each do |name, value|
|
381
|
-
if @params.key?(name)
|
387
|
+
if @params.key?(name) || (@argument && @argument.first == name)
|
382
388
|
dumped_config[name][:default] = value
|
383
389
|
else
|
384
390
|
dumped_config[name] = { default: value }
|
data/lib/fluent/config/dsl.rb
CHANGED
@@ -22,6 +22,8 @@ require 'fluent/config/element'
|
|
22
22
|
module Fluent
|
23
23
|
module Config
|
24
24
|
module DSL
|
25
|
+
RESERVED_PARAMETERS = [:type, :id, :log_level, :label] # Need '@' prefix for reserved parameters
|
26
|
+
|
25
27
|
module Parser
|
26
28
|
def self.read(path)
|
27
29
|
path = File.expand_path(path)
|
@@ -95,11 +97,12 @@ module Fluent
|
|
95
97
|
proxy.element.instance_exec(&block)
|
96
98
|
@elements.push(proxy.to_config_element)
|
97
99
|
else
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
param_name = RESERVED_PARAMETERS.include?(name) ? "@#{name}" : name.to_s
|
101
|
+
@attrs[param_name] = if value.is_a?(Array) || value.is_a?(Hash)
|
102
|
+
JSON.dump(value)
|
103
|
+
else
|
104
|
+
value.to_s
|
105
|
+
end
|
103
106
|
end
|
104
107
|
|
105
108
|
self
|
@@ -76,6 +76,11 @@ module Fluent
|
|
76
76
|
"name:#{@name}, arg:#{@arg}, " + attrs + ", " + @elements.inspect
|
77
77
|
end
|
78
78
|
|
79
|
+
# Used by PP and Pry
|
80
|
+
def pretty_print(q)
|
81
|
+
q.text(inspect)
|
82
|
+
end
|
83
|
+
|
79
84
|
# This method assumes _o_ is an Element object. Should return false for nil or other object
|
80
85
|
def ==(o)
|
81
86
|
self.name == o.name && self.arg == o.arg &&
|
@@ -18,6 +18,7 @@ require 'stringio'
|
|
18
18
|
|
19
19
|
require 'json'
|
20
20
|
require 'yajl'
|
21
|
+
require 'socket'
|
21
22
|
require 'irb/ruby-lex' # RubyLex
|
22
23
|
|
23
24
|
require 'fluent/config/basic_parser'
|
@@ -162,6 +163,11 @@ module Fluent
|
|
162
163
|
if @eval_context.nil?
|
163
164
|
parse_error! "embedded code is not allowed in this file"
|
164
165
|
end
|
166
|
+
# Add hostname and worker_id to code for preventing unused warnings
|
167
|
+
code = <<EOM + code
|
168
|
+
hostname = Socket.gethostname
|
169
|
+
worker_id = ENV['SERVERENGINE_WORKER_ID'] || ''
|
170
|
+
EOM
|
165
171
|
@eval_context.instance_eval(code)
|
166
172
|
end
|
167
173
|
|
@@ -192,7 +198,7 @@ module Fluent
|
|
192
198
|
|
193
199
|
def scan_json(is_array)
|
194
200
|
result = nil
|
195
|
-
# Yajl does not raise ParseError for
|
201
|
+
# Yajl does not raise ParseError for incomplete json string, like '[1', '{"h"', '{"h":' or '{"h1":1'
|
196
202
|
# This is the reason to use JSON module.
|
197
203
|
|
198
204
|
buffer = (is_array ? "[" : "{")
|
data/lib/fluent/config/types.rb
CHANGED
@@ -60,11 +60,35 @@ module Fluent
|
|
60
60
|
when ''
|
61
61
|
true
|
62
62
|
else
|
63
|
-
|
63
|
+
# Current parser passes comment without actual values, e.g. "param #foo".
|
64
|
+
# parser should pass empty string in this case but changing behaviour may break existing environment so keep parser behaviour. Just ignore comment value in boolean handling for now.
|
65
|
+
if str.respond_to?('start_with?') && str.start_with?('#')
|
66
|
+
true
|
67
|
+
else
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.regexp_value(str)
|
74
|
+
return nil unless str
|
75
|
+
return Regexp.compile(str) unless str.start_with?("/")
|
76
|
+
right_slash_position = str.rindex("/")
|
77
|
+
if right_slash_position < str.size - 3
|
78
|
+
raise Fluent::ConfigError, "invalid regexp: missing right slash: #{str}"
|
64
79
|
end
|
80
|
+
options = str[(right_slash_position + 1)..-1]
|
81
|
+
option = 0
|
82
|
+
option |= Regexp::IGNORECASE if options.include?("i")
|
83
|
+
option |= Regexp::MULTILINE if options.include?("m")
|
84
|
+
Regexp.compile(str[1...right_slash_position], option)
|
65
85
|
end
|
66
86
|
|
67
|
-
STRING_TYPE = Proc.new { |val, opts|
|
87
|
+
STRING_TYPE = Proc.new { |val, opts|
|
88
|
+
v = val.to_s
|
89
|
+
v = v.frozen? ? v.dup : v # config_param can't assume incoming string is mutable
|
90
|
+
v.force_encoding(Encoding::UTF_8)
|
91
|
+
}
|
68
92
|
ENUM_TYPE = Proc.new { |val, opts|
|
69
93
|
s = val.to_sym
|
70
94
|
list = opts[:list]
|
@@ -79,6 +103,7 @@ module Fluent
|
|
79
103
|
SIZE_TYPE = Proc.new { |val, opts| Config.size_value(val) }
|
80
104
|
BOOL_TYPE = Proc.new { |val, opts| Config.bool_value(val) }
|
81
105
|
TIME_TYPE = Proc.new { |val, opts| Config.time_value(val) }
|
106
|
+
REGEXP_TYPE = Proc.new { |val, opts| Config.regexp_value(val) }
|
82
107
|
|
83
108
|
REFORMAT_VALUE = ->(type, value) {
|
84
109
|
if value.nil?
|
@@ -91,6 +116,7 @@ module Fluent
|
|
91
116
|
when :size then Config.size_value(value)
|
92
117
|
when :bool then Config.bool_value(value)
|
93
118
|
when :time then Config.time_value(value)
|
119
|
+
when :regexp then Config.regexp_value(value)
|
94
120
|
else
|
95
121
|
raise "unknown type in REFORMAT: #{type}"
|
96
122
|
end
|
@@ -174,9 +174,8 @@ module Fluent
|
|
174
174
|
ss = StringScanner.new(data)
|
175
175
|
V1Parser.new(ss, basepath, fname, @eval_context).parse_element(true, nil, attrs, elems)
|
176
176
|
end
|
177
|
-
|
178
177
|
rescue SystemCallError => e
|
179
|
-
cpe = ConfigParseError.new("include error #{uri}")
|
178
|
+
cpe = ConfigParseError.new("include error #{uri} - #{e}")
|
180
179
|
cpe.set_backtrace(e.backtrace)
|
181
180
|
raise cpe
|
182
181
|
end
|
data/lib/fluent/configurable.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
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 'fluent/counter/client'
|
18
|
+
require 'fluent/counter/server'
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Counter
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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 'cool.io'
|
18
|
+
require 'fluent/msgpack_factory'
|
19
|
+
|
20
|
+
module Fluent
|
21
|
+
module Counter
|
22
|
+
class BaseSocket < Coolio::TCPSocket
|
23
|
+
include Fluent::MessagePackFactory::Mixin
|
24
|
+
|
25
|
+
def packed_write(data)
|
26
|
+
write pack(data)
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_read(data)
|
30
|
+
msgpack_unpacker.feed_each(data) do |d|
|
31
|
+
on_message d
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_message(data)
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def pack(data)
|
42
|
+
msgpack_packer.pack(data)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,297 @@
|
|
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 'cool.io'
|
18
|
+
require 'fluent/counter/base_socket'
|
19
|
+
require 'fluent/counter/error'
|
20
|
+
require 'timeout'
|
21
|
+
|
22
|
+
module Fluent
|
23
|
+
module Counter
|
24
|
+
class Client
|
25
|
+
DEFAULT_PORT = 24321
|
26
|
+
DEFAULT_ADDR = '127.0.0.1'
|
27
|
+
DEFAULT_TIMEOUT = 5
|
28
|
+
ID_LIMIT_COUNT = 1 << 31
|
29
|
+
|
30
|
+
def initialize(loop = nil, opt = {})
|
31
|
+
@loop = loop || Coolio::Loop.new
|
32
|
+
@port = opt[:port] || DEFAULT_PORT
|
33
|
+
@host = opt[:host] || DEFAULT_ADDR
|
34
|
+
@log = opt[:log] || $log
|
35
|
+
@timeout = opt[:timeout] || DEFAULT_TIMEOUT
|
36
|
+
@conn = Connection.connect(@host, @port, method(:on_message))
|
37
|
+
@responses = {}
|
38
|
+
@id = 0
|
39
|
+
@id_mutex = Mutex.new
|
40
|
+
@loop_mutex = Mutex.new
|
41
|
+
end
|
42
|
+
|
43
|
+
def start
|
44
|
+
@loop.attach(@conn)
|
45
|
+
@log.debug("starting counter client: #{@host}:#{@port}")
|
46
|
+
self
|
47
|
+
rescue => e
|
48
|
+
if @log
|
49
|
+
@log.error e
|
50
|
+
else
|
51
|
+
STDERR.puts e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def stop
|
56
|
+
@conn.close
|
57
|
+
@log.debug("calling stop in counter client: #{@host}:#{@port}")
|
58
|
+
end
|
59
|
+
|
60
|
+
def establish(scope)
|
61
|
+
scope = Timeout.timeout(@timeout) {
|
62
|
+
response = send_request('establish', nil, [scope])
|
63
|
+
Fluent::Counter.raise_error(response.errors.first) if response.errors?
|
64
|
+
data = response.data
|
65
|
+
data.first
|
66
|
+
}
|
67
|
+
@scope = scope
|
68
|
+
rescue Timeout::Error
|
69
|
+
raise "Can't establish the connection to counter server due to timeout"
|
70
|
+
end
|
71
|
+
|
72
|
+
# === Example
|
73
|
+
# `init` receives various arguments.
|
74
|
+
#
|
75
|
+
# 1. init(name: 'name')
|
76
|
+
# 2. init({ name: 'name',reset_interval: 20 }, options: {})
|
77
|
+
# 3. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }])
|
78
|
+
# 4. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }], options: {})
|
79
|
+
# 5. init([{ name: 'name1',reset_interval: 20 }, { name: 'name2',reset_interval: 20 }]) { |res| ... }
|
80
|
+
def init(params, options: {})
|
81
|
+
exist_scope!
|
82
|
+
params = [params] unless params.is_a?(Array)
|
83
|
+
res = send_request('init', @scope, params, options)
|
84
|
+
|
85
|
+
# if `async` is false or missing, block at this method and return a Future::Result object.
|
86
|
+
if block_given?
|
87
|
+
Thread.start do
|
88
|
+
yield res.get
|
89
|
+
end
|
90
|
+
else
|
91
|
+
res
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete(*params, options: {})
|
96
|
+
exist_scope!
|
97
|
+
res = send_request('delete', @scope, params, options)
|
98
|
+
|
99
|
+
if block_given?
|
100
|
+
Thread.start do
|
101
|
+
yield res.get
|
102
|
+
end
|
103
|
+
else
|
104
|
+
res
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# === Example
|
109
|
+
# `inc` receives various arguments.
|
110
|
+
#
|
111
|
+
# 1. inc(name: 'name')
|
112
|
+
# 2. inc({ name: 'name',value: 20 }, options: {})
|
113
|
+
# 3. inc([{ name: 'name1',value: 20 }, { name: 'name2',value: 20 }])
|
114
|
+
# 4. inc([{ name: 'name1',value: 20 }, { name: 'name2',value: 20 }], options: {})
|
115
|
+
def inc(params, options: {})
|
116
|
+
exist_scope!
|
117
|
+
params = [params] unless params.is_a?(Array)
|
118
|
+
res = send_request('inc', @scope, params, options)
|
119
|
+
|
120
|
+
if block_given?
|
121
|
+
Thread.start do
|
122
|
+
yield res.get
|
123
|
+
end
|
124
|
+
else
|
125
|
+
res
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def get(*params, options: {})
|
130
|
+
exist_scope!
|
131
|
+
res = send_request('get', @scope, params, options)
|
132
|
+
|
133
|
+
if block_given?
|
134
|
+
Thread.start do
|
135
|
+
yield res.get
|
136
|
+
end
|
137
|
+
else
|
138
|
+
res
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def reset(*params, options: {})
|
143
|
+
exist_scope!
|
144
|
+
res = send_request('reset', @scope, params, options)
|
145
|
+
|
146
|
+
if block_given?
|
147
|
+
Thread.start do
|
148
|
+
yield res.get
|
149
|
+
end
|
150
|
+
else
|
151
|
+
res
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def exist_scope!
|
158
|
+
raise 'Call `establish` method to get a `scope` before calling this method' unless @scope
|
159
|
+
end
|
160
|
+
|
161
|
+
def on_message(data)
|
162
|
+
if response = @responses.delete(data['id'])
|
163
|
+
response.set(data)
|
164
|
+
else
|
165
|
+
@log.warn("Receiving missing id data: #{data}")
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def send_request(method, scope, params, opt = {})
|
170
|
+
id = generate_id
|
171
|
+
res = Future.new(@loop, @loop_mutex)
|
172
|
+
@responses[id] = res # set a response value to this future object at `on_message`
|
173
|
+
request = build_request(method, id, scope, params, opt)
|
174
|
+
@log.debug(request)
|
175
|
+
@conn.send_data request
|
176
|
+
res
|
177
|
+
end
|
178
|
+
|
179
|
+
def build_request(method, id, scope = nil, params = nil, options = nil)
|
180
|
+
r = { id: id, method: method }
|
181
|
+
r[:scope] = scope if scope
|
182
|
+
r[:params] = params if params
|
183
|
+
r[:options] = options if options
|
184
|
+
r
|
185
|
+
end
|
186
|
+
|
187
|
+
def generate_id
|
188
|
+
id = 0
|
189
|
+
@id_mutex.synchronize do
|
190
|
+
id = @id
|
191
|
+
@id += 1
|
192
|
+
@id = 0 if ID_LIMIT_COUNT < @id
|
193
|
+
end
|
194
|
+
id
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class Connection < Fluent::Counter::BaseSocket
|
199
|
+
def initialize(io, on_message)
|
200
|
+
super(io)
|
201
|
+
@connection = false
|
202
|
+
@buffer = ''
|
203
|
+
@on_message = on_message
|
204
|
+
end
|
205
|
+
|
206
|
+
def send_data(data)
|
207
|
+
if @connection
|
208
|
+
packed_write data
|
209
|
+
else
|
210
|
+
@buffer += pack(data)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def on_connect
|
215
|
+
@connection = true
|
216
|
+
write @buffer
|
217
|
+
@buffer = ''
|
218
|
+
end
|
219
|
+
|
220
|
+
def on_close
|
221
|
+
@connection = false
|
222
|
+
end
|
223
|
+
|
224
|
+
def on_message(data)
|
225
|
+
@on_message.call(data)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
class Future
|
230
|
+
class Result
|
231
|
+
attr_reader :data, :errors
|
232
|
+
|
233
|
+
def initialize(result)
|
234
|
+
@errors = result['errors']
|
235
|
+
@data = result['data']
|
236
|
+
end
|
237
|
+
|
238
|
+
def success?
|
239
|
+
@errors.nil? || @errors.empty?
|
240
|
+
end
|
241
|
+
|
242
|
+
def error?
|
243
|
+
!success?
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def initialize(loop, mutex)
|
248
|
+
@set = false
|
249
|
+
@result = nil
|
250
|
+
@mutex = mutex
|
251
|
+
@loop = loop
|
252
|
+
end
|
253
|
+
|
254
|
+
def set(v)
|
255
|
+
@result = Result.new(v)
|
256
|
+
@set = true
|
257
|
+
end
|
258
|
+
|
259
|
+
def errors
|
260
|
+
get.errors
|
261
|
+
end
|
262
|
+
|
263
|
+
def errors?
|
264
|
+
es = errors
|
265
|
+
es && !es.empty?
|
266
|
+
end
|
267
|
+
|
268
|
+
def data
|
269
|
+
get.data
|
270
|
+
end
|
271
|
+
|
272
|
+
def get
|
273
|
+
# Block until `set` method is called and @result is set
|
274
|
+
join if @result.nil?
|
275
|
+
@result
|
276
|
+
end
|
277
|
+
|
278
|
+
def wait
|
279
|
+
res = get
|
280
|
+
if res.error?
|
281
|
+
Fluent::Counter.raise_error(res.errors.first)
|
282
|
+
end
|
283
|
+
res
|
284
|
+
end
|
285
|
+
|
286
|
+
private
|
287
|
+
|
288
|
+
def join
|
289
|
+
until @set
|
290
|
+
@mutex.synchronize do
|
291
|
+
@loop.run_once(0.0001) # retun a lock as soon as possible
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|