1
1
# encoding: utf-8
2
+ require_relative '../plugin_mixins/redis_connection'
2
3
require "logstash/namespace"
3
4
require "logstash/inputs/base"
4
5
require "logstash/inputs/threadable"
19
20
# newer. Anything older does not support the operations used by batching.
20
21
#
21
22
module LogStash module Inputs class Redis < LogStash ::Inputs ::Threadable
23
+
24
+ include ::LogStash ::PluginMixins ::RedisConnection
25
+
22
26
BATCH_EMPTY_SLEEP = 0.25
23
27
24
28
config_name "redis"
25
29
26
30
default :codec , "json"
27
31
28
- # The hostname of your Redis server.
29
- config :host , :validate => :string , :default => "127.0.0.1"
30
-
31
- # The port to connect on.
32
- config :port , :validate => :number , :default => 6379
33
-
34
- # SSL
35
- config :ssl , :validate => :boolean , :default => false
36
-
37
- # The unix socket path to connect on. Will override host and port if defined.
38
- # There is no unix socket path by default.
39
- config :path , :validate => :string
40
-
41
- # The Redis database number.
42
- config :db , :validate => :number , :default => 0
43
-
44
- # Initial connection timeout in seconds.
45
- config :timeout , :validate => :number , :default => 5
46
-
47
- # Password to authenticate with. There is no authentication by default.
48
- config :password , :validate => :password
49
-
50
32
# The name of a Redis list or channel.
51
33
config :key , :validate => :string , :required => true
52
34
@@ -60,9 +42,6 @@ module LogStash module Inputs class Redis < LogStash::Inputs::Threadable
60
42
# The number of events to return from Redis using EVAL.
61
43
config :batch_count , :validate => :number , :default => 125
62
44
63
- # Redefined Redis commands to be passed to the Redis client.
64
- config :command_map , :validate => :hash , :default => { }
65
-
66
45
# Maximum number of worker threads to spawn when using `data_type` `pattern_list`.
67
46
config :pattern_list_threads , :validate => :number , :default => 20
68
47
@@ -76,23 +55,6 @@ module LogStash module Inputs class Redis < LogStash::Inputs::Threadable
76
55
config :pattern_list_threadpool_sleep , :validate => :number , :default => 0.2
77
56
78
57
public
79
- # public API
80
- # use to store a proc that can provide a Redis instance or mock
81
- def add_external_redis_builder ( builder ) #callable
82
- @redis_builder = builder
83
- self
84
- end
85
-
86
- # use to apply an instance directly and bypass the builder
87
- def use_redis ( instance )
88
- @redis = instance
89
- self
90
- end
91
-
92
- def new_redis_instance
93
- @redis_builder . call
94
- end
95
-
96
58
def init_threadpool
97
59
@threadpool ||= Concurrent ::ThreadPoolExecutor . new (
98
60
min_threads : @pattern_list_threads ,
@@ -122,6 +84,8 @@ def register
122
84
@stop_method = method ( :subscribe_stop )
123
85
end
124
86
87
+ @batched = is_list_type? && batched?
88
+
125
89
@identity = "#{ @redis_url } #{ @data_type } :#{ @key } "
126
90
@logger . info ( "Registering Redis" , :identity => @identity )
127
91
end # def register
@@ -148,63 +112,6 @@ def is_list_type?
148
112
@data_type == 'list' || @data_type == 'pattern_list'
149
113
end
150
114
151
- # private
152
- def redis_params
153
- if @path . nil?
154
- connectionParams = {
155
- :host => @host ,
156
- :port => @port
157
- }
158
- else
159
- @logger . warn ( "Parameter 'path' is set, ignoring parameters: 'host' and 'port'" )
160
- connectionParams = {
161
- :path => @path
162
- }
163
- end
164
-
165
- baseParams = {
166
- :timeout => @timeout ,
167
- :db => @db ,
168
- :password => @password . nil? ? nil : @password . value ,
169
- :ssl => @ssl
170
- }
171
-
172
- return connectionParams . merge ( baseParams )
173
- end
174
-
175
- # private
176
- def internal_redis_builder
177
- ::Redis . new ( redis_params )
178
- end
179
-
180
- # private
181
- def connect
182
- redis = new_redis_instance
183
-
184
- # register any renamed Redis commands
185
- if @command_map . any?
186
- client_command_map = redis . client . command_map
187
- @command_map . each do |name , renamed |
188
- client_command_map [ name . to_sym ] = renamed . to_sym
189
- end
190
- end
191
-
192
- load_batch_script ( redis ) if batched? && is_list_type?
193
- redis
194
- end # def connect
195
-
196
- # private
197
- def load_batch_script ( redis )
198
- #A Redis Lua EVAL script to fetch a count of keys
199
- redis_script = <<EOF
200
- local batchsize = tonumber(ARGV[1])
201
- local result = redis.call(\' #{ @command_map . fetch ( 'lrange' , 'lrange' ) } \' , KEYS[1], 0, batchsize)
202
- redis.call(\' #{ @command_map . fetch ( 'ltrim' , 'ltrim' ) } \' , KEYS[1], batchsize + 1, -1)
203
- return result
204
- EOF
205
- @redis_script_sha = redis . script ( :load , redis_script )
206
- end
207
-
208
115
# private
209
116
def queue_event ( msg , output_queue , channel = nil )
210
117
begin
@@ -218,33 +125,16 @@ def queue_event(msg, output_queue, channel=nil)
218
125
end
219
126
end
220
127
221
- # private
222
- def reset_redis
223
- return if @redis . nil? || !@redis . connected?
224
-
225
- @redis . quit rescue nil
226
- @redis = nil
227
- end
228
-
229
- # private
230
128
def list_stop
231
129
reset_redis
232
130
end
233
131
234
132
# private
235
133
def list_runner ( output_queue )
236
- @list_method = batched? ? method ( :list_batch_listener ) : method ( :list_single_listener )
134
+ @list_method = @ batched ? method ( :list_batch_listener ) : method ( :list_single_listener )
237
135
while !stop?
238
- begin
239
- @redis ||= connect
136
+ redis_runner ( @batched ) do
240
137
@list_method . call ( @redis , output_queue )
241
- rescue ::Redis ::BaseError => e
242
- @logger . warn ( "Redis connection problem" , :exception => e )
243
- # Reset the redis variable to trigger reconnect
244
- @redis = nil
245
- # this sleep does not need to be stoppable as its
246
- # in a while !stop? loop
247
- sleep 1
248
138
end
249
139
end
250
140
end
@@ -298,7 +188,7 @@ def pattern_list_batch_processor(redis, output_queue, key)
298
188
# private
299
189
def pattern_list_worker_consume ( output_queue , key )
300
190
begin
301
- redis ||= connect
191
+ redis ||= connect ( @batched )
302
192
@pattern_list_processor . call ( redis , output_queue , key )
303
193
rescue ::Redis ::BaseError => e
304
194
@logger . warn ( "Redis connection problem in thread for key #{ key } . Sleeping a while before exiting thread." , :exception => e )
@@ -329,7 +219,7 @@ def pattern_list_launch_worker(output_queue, key)
329
219
# private
330
220
def pattern_list_ensure_workers ( output_queue )
331
221
return unless threadpool_capacity?
332
- redis_runner do
222
+ redis_runner ( @batched ) do
333
223
@redis . keys ( @key ) . shuffle . each do |key |
334
224
next if @current_workers . include? ( key )
335
225
pattern_list_launch_worker ( output_queue , key )
@@ -340,7 +230,7 @@ def pattern_list_ensure_workers(output_queue)
340
230
341
231
# private
342
232
def pattern_list_runner ( output_queue )
343
- @pattern_list_processor = batched? ? method ( :pattern_list_batch_processor ) : method ( :pattern_list_single_processor )
233
+ @pattern_list_processor = @ batched ? method ( :pattern_list_batch_processor ) : method ( :pattern_list_single_processor )
344
234
while !stop?
345
235
init_threadpool if @threadpool . nil?
346
236
pattern_list_ensure_workers ( output_queue )
@@ -375,7 +265,7 @@ def process_batch(redis, output_queue, key, batch_size, sleep_time)
375
265
# which should further improve the efficiency of the script
376
266
rescue ::Redis ::CommandError => e
377
267
if e . to_s =~ /NOSCRIPT/ then
378
- @logger . warn ( "Redis may have been restarted, reloading Redis batch EVAL script" , :exception => e ) ;
268
+ @logger . warn ( "Redis may have been restarted, reloading Redis batch EVAL script" , :exception => e )
379
269
load_batch_script ( redis )
380
270
retry
381
271
else
@@ -414,20 +304,6 @@ def subscribe_stop
414
304
@redis = nil
415
305
end
416
306
417
- # private
418
- def redis_runner
419
- begin
420
- @redis ||= connect
421
- yield
422
- rescue ::Redis ::BaseError => e
423
- @logger . warn ( "Redis connection problem" , :exception => e )
424
- # Reset the redis variable to trigger reconnect
425
- @redis = nil
426
- Stud . stoppable_sleep ( 1 ) { stop? }
427
- retry if !stop?
428
- end
429
- end
430
-
431
307
# private
432
308
def channel_runner ( output_queue )
433
309
redis_runner do
0 commit comments