fluent-plugin-hash-forward 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +9 -0
- data/fluent-plugin-hash-forward.gemspec +3 -3
- data/lib/fluent/plugin/out_hash_forward.rb +123 -3
- data/spec/out_hash_forward_spec.rb +4 -4
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0afb6cf6c53fa7e63173685f40958889da2f770
|
4
|
+
data.tar.gz: e6a1bc25cc85e1d075cb4bc48579a77dc4a71958
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0075b38f21756454e85d18632e7d57d3994c14491b119494560142e379c6bd6e4b968ee42b147bd118d4cd53ace4cc65888f2a19e40b25418ecc59ba439fecc6
|
7
|
+
data.tar.gz: c8b4a6b1361a1c17a78aaf022729c37e8ea09be612fc870c062559b154182422c0e5f740646825e215a62cd31a96a7cab0037ae392e22c686f64576e3781af04
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -31,6 +31,15 @@ Basically same with out\_forward plugin. See [http://docs.fluentd.org/articles/o
|
|
31
31
|
|
32
32
|
Following parameters are additionally available:
|
33
33
|
|
34
|
+
|
35
|
+
* keepalive (bool)
|
36
|
+
|
37
|
+
Keepalive connection. Default is `false`.
|
38
|
+
|
39
|
+
* keepalive_time (time)
|
40
|
+
|
41
|
+
Keepalive expired time. Default is nil (which means to keep connection as long as possible).
|
42
|
+
|
34
43
|
* hash\_key\_slice *min*..*max*
|
35
44
|
|
36
45
|
Use sliced `tag` as a hash key to determine a forwarding node. Default: use entire `tag`.
|
@@ -3,10 +3,10 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "fluent-plugin-hash-forward"
|
6
|
-
s.version = "0.
|
7
|
-
s.authors = ["Ryosuke IWANAGA", "Naotoshi
|
6
|
+
s.version = "0.3.1"
|
7
|
+
s.authors = ["Ryosuke IWANAGA", "Naotoshi Seo"]
|
8
8
|
s.email = ["riywo.jp@gmail.com", "sonots@gmail.com"]
|
9
|
-
s.homepage = "https://github.com/
|
9
|
+
s.homepage = "https://github.com/sonots/fluent-plugin-hash-forward"
|
10
10
|
s.summary = %q{Fluentd plugin to keep forwarding messsages of a specific tag pattern to a specific node}
|
11
11
|
s.description = s.summary
|
12
12
|
s.licenses = ["MIT"]
|
@@ -4,6 +4,8 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
|
|
4
4
|
Fluent::Plugin.register_output('hash_forward', self)
|
5
5
|
|
6
6
|
config_param :hash_key_slice, :string, :default => nil
|
7
|
+
config_param :keepalive, :bool, :default => false
|
8
|
+
config_param :keepalive_time, :time, :default => nil # infinite
|
7
9
|
|
8
10
|
def configure(conf)
|
9
11
|
super
|
@@ -22,6 +24,10 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
|
|
22
24
|
@standby_weight_array = build_weight_array(@standby_nodes)
|
23
25
|
|
24
26
|
@cache_nodes = {}
|
27
|
+
@sock = {}
|
28
|
+
@sock_expired_at = {}
|
29
|
+
@mutex = {}
|
30
|
+
@watcher_interval = 1
|
25
31
|
end
|
26
32
|
|
27
33
|
# for test
|
@@ -31,13 +37,35 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
|
|
31
37
|
attr_reader :standby_weight_array
|
32
38
|
attr_accessor :hash_key_slice_lindex
|
33
39
|
attr_accessor :hash_key_slice_rindex
|
40
|
+
attr_accessor :watcher_interval
|
41
|
+
|
42
|
+
def start
|
43
|
+
super
|
44
|
+
start_watcher
|
45
|
+
end
|
46
|
+
|
47
|
+
def shutdown
|
48
|
+
super
|
49
|
+
stop_watcher
|
50
|
+
end
|
51
|
+
|
52
|
+
def start_watcher
|
53
|
+
if @keepalive and @keepalive_time
|
54
|
+
@watcher = Thread.new(&method(:watch_keepalive_time))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def stop_watcher
|
59
|
+
if @watcher
|
60
|
+
@watcher.terminate
|
61
|
+
@watcher.join
|
62
|
+
end
|
63
|
+
end
|
34
64
|
|
35
65
|
# Override
|
36
66
|
def write_objects(tag, chunk)
|
37
67
|
return if chunk.empty?
|
38
|
-
|
39
68
|
error = nil
|
40
|
-
|
41
69
|
nodes = nodes(tag)
|
42
70
|
|
43
71
|
# below is just copy from out_forward
|
@@ -64,8 +92,8 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
|
|
64
92
|
def rebuild_weight_array
|
65
93
|
end
|
66
94
|
|
95
|
+
# This is just a partial copy from ForwardOuput#rebuild_weight_array
|
67
96
|
def build_weight_array(nodes)
|
68
|
-
# below is just a partial copy from out_forward#rebuild_weight_array
|
69
97
|
weight_array = []
|
70
98
|
gcd = nodes.map {|n| n.weight }.inject(0) {|r,w| r.gcd(w) }
|
71
99
|
nodes.each {|n|
|
@@ -104,4 +132,96 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
|
|
104
132
|
sliced = tags[@hash_key_slice_lindex..@hash_key_slice_rindex]
|
105
133
|
return sliced.nil? ? "" : sliced.join('.')
|
106
134
|
end
|
135
|
+
|
136
|
+
# Override for keepalive
|
137
|
+
def send_data(node, tag, chunk)
|
138
|
+
get_mutex(node).synchronize do
|
139
|
+
sock = get_sock[node]
|
140
|
+
unless sock
|
141
|
+
sock = reconnect(node)
|
142
|
+
end
|
143
|
+
|
144
|
+
begin
|
145
|
+
sock_write(sock, tag, chunk)
|
146
|
+
node.heartbeat(false)
|
147
|
+
rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED, Errno::ETIMEDOUT => e
|
148
|
+
$log.warn "out_hash_forward: #{e.class} #{e.message}"
|
149
|
+
sock = reconnect(node)
|
150
|
+
retry
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def reconnect(node)
|
156
|
+
sock = connect(node)
|
157
|
+
opt = [1, @send_timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
|
158
|
+
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
|
159
|
+
|
160
|
+
opt = [@send_timeout.to_i, 0].pack('L!L!') # struct timeval
|
161
|
+
sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, opt)
|
162
|
+
|
163
|
+
if @keepalive
|
164
|
+
get_sock[node] = sock
|
165
|
+
get_sock_expired_at[node] = Time.now + @keepalive_time if @keepalive_time
|
166
|
+
end
|
167
|
+
|
168
|
+
sock
|
169
|
+
end
|
170
|
+
|
171
|
+
def sock_write(sock, tag, chunk)
|
172
|
+
# beginArray(2)
|
173
|
+
sock.write FORWARD_HEADER
|
174
|
+
|
175
|
+
# writeRaw(tag)
|
176
|
+
sock.write tag.to_msgpack # tag
|
177
|
+
|
178
|
+
# beginRaw(size)
|
179
|
+
sz = chunk.size
|
180
|
+
#if sz < 32
|
181
|
+
# # FixRaw
|
182
|
+
# sock.write [0xa0 | sz].pack('C')
|
183
|
+
#elsif sz < 65536
|
184
|
+
# # raw 16
|
185
|
+
# sock.write [0xda, sz].pack('Cn')
|
186
|
+
#else
|
187
|
+
# raw 32
|
188
|
+
sock.write [0xdb, sz].pack('CN')
|
189
|
+
#end
|
190
|
+
|
191
|
+
# writeRawBody(packed_es)
|
192
|
+
chunk.write_to(sock)
|
193
|
+
end
|
194
|
+
|
195
|
+
# watcher thread callback
|
196
|
+
def watch_keepalive_time
|
197
|
+
while true
|
198
|
+
sleep @watcher_interval
|
199
|
+
thread_ids = @sock.keys
|
200
|
+
thread_ids.each do |thread_id|
|
201
|
+
@sock[thread_id].each do |node, sock|
|
202
|
+
@mutex[thread_id][node].synchronize do
|
203
|
+
next unless sock_expired_at = @sock_expired_at[thread_id][node]
|
204
|
+
next unless Time.now >= sock_expired_at
|
205
|
+
sock.close rescue IOError if sock
|
206
|
+
@sock[thread_id][node] = nil
|
207
|
+
@sock_expired_at[thread_id][node] = nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def get_mutex(node)
|
215
|
+
thread_id = Thread.current.object_id
|
216
|
+
@mutex[thread_id] ||= {}
|
217
|
+
@mutex[thread_id][node] ||= Mutex.new
|
218
|
+
end
|
219
|
+
|
220
|
+
def get_sock
|
221
|
+
@sock[Thread.current.object_id] ||= {}
|
222
|
+
end
|
223
|
+
|
224
|
+
def get_sock_expired_at
|
225
|
+
@sock_expired_at[Thread.current.object_id] ||= {}
|
226
|
+
end
|
107
227
|
end
|
@@ -117,7 +117,7 @@ describe Fluent::HashForwardOutput do
|
|
117
117
|
<server>
|
118
118
|
host 192.168.1.3
|
119
119
|
port 24224
|
120
|
-
weight
|
120
|
+
weight 100
|
121
121
|
</server>
|
122
122
|
<server>
|
123
123
|
host 192.168.1.4
|
@@ -189,10 +189,10 @@ describe Fluent::HashForwardOutput do
|
|
189
189
|
let(:tag2) { 'test.tag2' }
|
190
190
|
let(:config) { CONFIG + %[hash_key_slice 0..-2] }
|
191
191
|
before do
|
192
|
-
@
|
192
|
+
@node = driver.nodes(tag1).first
|
193
193
|
end
|
194
|
-
it 'should forward to the
|
195
|
-
expect(driver.nodes(tag2).first).to eq(@
|
194
|
+
it 'should forward to the same node' do
|
195
|
+
expect(driver.nodes(tag2).first).to eq(@node)
|
196
196
|
end
|
197
197
|
end
|
198
198
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-hash-forward
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryosuke IWANAGA
|
8
|
-
- Naotoshi
|
8
|
+
- Naotoshi Seo
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|
@@ -99,7 +99,7 @@ files:
|
|
99
99
|
- lib/fluent/plugin/out_hash_forward.rb
|
100
100
|
- spec/out_hash_forward_spec.rb
|
101
101
|
- spec/spec_helper.rb
|
102
|
-
homepage: https://github.com/
|
102
|
+
homepage: https://github.com/sonots/fluent-plugin-hash-forward
|
103
103
|
licenses:
|
104
104
|
- MIT
|
105
105
|
metadata: {}
|