fluent-plugin-redis_list_poller 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5664df7a09d8c92d2eff417ca21e3e77c1469d96
4
+ data.tar.gz: f23f3179502d0104f0634e7acb5ad1bdc8abd430
5
+ SHA512:
6
+ metadata.gz: 60ecb470169580c8b2a27ae5d7892f55d547680433ce16e66eb58d0141c0fbabf6d8e4c71de6c100fd8bfead32edae64e94928ad75d63e71691cb09c29ed7f38
7
+ data.tar.gz: 5a15699078c53d68f47cdbe5543ddabff3be92676e9d670ccc67a3739e8a8b0e6725a21620509dd5c89a833681dc451b3589a84a780039aa25ab30afb32fd08e
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
@@ -0,0 +1,4 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-redis_poll_input.gemspec
4
+ gemspec
@@ -0,0 +1,11 @@
1
+ Licensed under the Apache License, Version 2.0 (the "License");
2
+ you may not use this file except in compliance with the License.
3
+ You may obtain a copy of the License at
4
+
5
+ http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
@@ -0,0 +1,71 @@
1
+ # Fluent::Plugin::RedisListPoller
2
+
3
+ This gem provides a few input plugins for Fluentd which are designed to more efficiently poll large volumes of messages than other existing redis input plugins.
4
+
5
+ * *redis_list_poller*: Input plugin designed to fetch large volumes of messages
6
+ * *redis_list_monitor*: Input plugin designed to fetch queue size metrics
7
+
8
+ In additional to the standard stuff, the `redis_list_poller` input plugin also looks for a lock key in Redis to see whether it has been administratively disabled. This lock key follows the naming convention of `redis:KEY_NAME:lock`.
9
+
10
+ ## Requirements
11
+
12
+ * Fluentd v0.14+
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ gem install fluent-plugin-redis_list_poller
18
+ ```
19
+
20
+ ## Configuration Options
21
+
22
+ ```
23
+ <source>
24
+ @type redis_list_poller
25
+ host 127.0.0.1
26
+ port 6379
27
+ path nil
28
+ password nil
29
+ db 0
30
+ timeout 5.0
31
+ driver ruby
32
+
33
+ key redis_list_item
34
+ command lpop
35
+ batch_size 100
36
+
37
+ tag redis.data
38
+ format json
39
+
40
+ poll_inteval 0.01
41
+ sleep_inteval 5
42
+ retry_interval 5
43
+ </source>
44
+ ```
45
+
46
+ ## Benchmarks
47
+
48
+ These very simple benchmarks which give a rough ideas of the sorts of message rates one can expect from this input plugin.
49
+
50
+ They were run within a Vagrant box, with a local Redis, running on my Macbook Pro 15'. Fluentd is running on a single CPU core and is using the examples/standalone.conf.
51
+
52
+ poll_interval|batch_size|messages/second|
53
+ -------------|----------|---------------|
54
+ 1 | 1 | 1
55
+ 0.5 | 1 | 2
56
+ 0.2 | 1 | 5
57
+ 0.01 | 1 | 100
58
+ 0.001 | 1 | 457
59
+ poll_interval|batch_size|messages/second|
60
+ 1 | 10 | 10
61
+ 0.5 | 10 | 20
62
+ 0.2 | 10 | 50
63
+ 0.01 | 10 | 1000
64
+ 0.001 | 10 | 1793
65
+ poll_interval|batch_size|messages/second|
66
+ 1 | 100 | 100
67
+ 0.5 | 100 | 200
68
+ 0.2 | 100 | 500
69
+ 0.01 | 100 | 7823
70
+ 0.001 | 100 | 7600
71
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "aargh"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ for x in `seq 1 10000`; do
4
+ echo "RPUSH test \"{ \\\"message\\\": \\\"${x}\\\" }\""
5
+ done | redis-cli --pipe
6
+
@@ -0,0 +1,25 @@
1
+ #<source>
2
+ # @type redis_list_monitor
3
+ # tag redis.metrics
4
+ # host 127.0.0.1
5
+ # key test
6
+ # poll_interval 1
7
+ #</source>
8
+
9
+ <source>
10
+ @type redis_list_poller
11
+ tag redis.content
12
+ host 127.0.0.1
13
+ key test
14
+ batch_size 1
15
+ poll_interval 1
16
+ </source>
17
+
18
+ <match redis.content>
19
+ @type flowcounter_simple
20
+ unit second
21
+ </match>
22
+
23
+ #<match redis.metrics>
24
+ # @type stdout
25
+ #</match>
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "fluent-plugin-redis_list_poller"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["Jonathan Serafini"]
7
+ spec.email = ["jonathan@serafini.ca"]
8
+
9
+ spec.summary = %q{A fluentd redis input plugin supporting batch operations}
10
+ spec.description = spec.summary
11
+ spec.homepage = "https://github.com/JonathanSerafini/fluent-plugin-redis_list_poller"
12
+ spec.license = "apache2"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.executables = []
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.add_development_dependency "bundler"
19
+ spec.add_development_dependency "rake"
20
+
21
+ spec.add_runtime_dependency "fluentd", [">= 0.12.0", "< 2"]
22
+ end
@@ -0,0 +1,174 @@
1
+ require "fluent/plugin/input"
2
+ require "fluent/plugin_mixin/redis"
3
+
4
+ module Fluent
5
+ module Plugin
6
+ # Input plugin which will monitor the size of a redis list and periodically
7
+ # output metrics to the login pipeline.
8
+ # @since 0.1.0
9
+ class RedisListMonitorInput < Input
10
+ include Fluent::PluginMixin::Redis
11
+
12
+ Plugin.register_input('redis_list_monitor', self)
13
+
14
+ # input plugin parameters
15
+ config_param :tag, :string, :default => nil
16
+
17
+ # Initialize new input plugin
18
+ # @since 0.1.0
19
+ # @return [NilClass]
20
+ def initialize
21
+ super
22
+ require 'cool.io'
23
+ end
24
+
25
+ # Initialize attributes and parameters
26
+ # @since 0.1.0
27
+ # @return [NilClass]
28
+ def configure(config)
29
+ super
30
+
31
+ configure_params(config)
32
+ configure_locking(config)
33
+
34
+ @queue_length = 0
35
+ @retry_at = nil
36
+ end
37
+
38
+ # Configure plugin parameters
39
+ # @since 0.1.0
40
+ # @return [NilClass]
41
+ def configure_params(config)
42
+ %w(host port key tag).each do |key|
43
+ next if instance_variable_get("@#{key}")
44
+ raise Fluent::ConfigError, "configuration key missing: #{key}"
45
+ end
46
+ end
47
+
48
+ # Configure locking
49
+ # @since 0.1.0
50
+ # @return [NilClass]
51
+ def configure_locking(config)
52
+ @storage = storage_create(type: 'local')
53
+ @lock_key = "redis:#{@key}:lock"
54
+ end
55
+
56
+ # Prepare the plugin event loop
57
+ #
58
+ # This method will initialize the Redis connection object, create any required Redis structures as well
59
+ # as define and begin the event pollers.
60
+ #
61
+ # @since 0.1.0
62
+ # @return [NilClass]
63
+ def start
64
+ super
65
+
66
+ @loop = Coolio::Loop.new
67
+
68
+ start_redis
69
+ start_poller
70
+
71
+ @thread = Thread.new(&method(:run))
72
+ end
73
+
74
+ def start_poller
75
+ @poller = TimerWatcher.new(
76
+ @poll_interval,
77
+ log,
78
+ &method(:action_poll)
79
+ )
80
+
81
+ @loop.attach(@poller)
82
+ end
83
+
84
+ # Begin the logging pipeline
85
+ # @since 0.1.0
86
+ # @return [NilClass]
87
+ def run
88
+ @loop.run
89
+ rescue => e
90
+ log.error "unexpected error", :error => e
91
+ log.error_backtrace
92
+ end
93
+
94
+ # Tear down the plugin
95
+ # @since 0.1.0
96
+ # @return [NilClass]
97
+ def shutdown
98
+ @loop.watchers.each { |w| w.detach }
99
+ @loop.stop
100
+ Thread.kill(@thread)
101
+ @thread.join
102
+ shutdown_redis
103
+ super
104
+ end
105
+
106
+ # Wether the poller has been temporarily disabled or should fetch messages
107
+ # been temporarily disabled
108
+ # @since 0.1.0
109
+ # @return [TrueClass, FalseClass]
110
+ def sleeping?
111
+ @retry_at and @retry_at >= Engine.now
112
+ end
113
+
114
+ # Set a sleep delay, ensuring that we will not attempt to fetch messages
115
+ # @since 0.1.0
116
+ # @param [Integer] delay, the amount of seconds to wait
117
+ # @return [Integer] timestamp when this expires
118
+ def sleep!(delay = @sleep_interval)
119
+ @retry_at = Engine.now + delay
120
+ end
121
+
122
+ # Action to execute when the monitor event watcher executes
123
+ #
124
+ # The monitor is simply responsible for outputting the queue length to
125
+ # the logs as well as detecting zero length lists.
126
+ #
127
+ # @since 0.1.0
128
+ # @return [NilClass]
129
+ def action_poll
130
+ now = Engine.now
131
+
132
+ if sleeping?
133
+ log.trace "redis worker is sleeping"
134
+ return
135
+ end
136
+
137
+ list_size = @redis.llen(@key)
138
+
139
+ event = {
140
+ "timestamp" => now,
141
+ "message" => "redis queue monitor",
142
+ "hostname" => @host,
143
+ "key" => @key,
144
+ "size" => list_size
145
+ }
146
+
147
+ router.emit @tag, now, event
148
+ rescue => e
149
+ log.error "error monitoring queue", :error => e
150
+ log.error_backtrace
151
+ sleep!(@retry_interval)
152
+ end
153
+
154
+ # Generic Cool.io timer which will execute a given callback on schedule.
155
+ # @since 0.1.0
156
+ class TimerWatcher < Coolio::TimerWatcher
157
+ attr_reader :log
158
+
159
+ def initialize(interval, log, &callback)
160
+ @callback = callback
161
+ @log = log
162
+ super(interval, true)
163
+ end
164
+
165
+ def on_timer
166
+ @callback.call
167
+ rescue => e
168
+ log.error "unexpected error", :error=>e
169
+ log.error_backtrace
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,263 @@
1
+ require "fluent/plugin/input"
2
+ require "fluent/plugin_mixin/redis"
3
+
4
+ module Fluent
5
+ module Plugin
6
+ class RedisListPollerInput < Input
7
+ include Fluent::PluginMixin::Redis
8
+
9
+ Plugin.register_input('redis_list_poller', self)
10
+
11
+ helpers :storage
12
+
13
+ # redis list details
14
+ # - command: redis command to execute when fetching messages
15
+ # - batch_size: if greater than 0, fetch messages in batches
16
+ config_param :command, :string, :default => "lpop"
17
+ config_param :batch_size, :integer, :default => 0
18
+
19
+ # input plugin parameters
20
+ config_param :tag, :string, :default => nil
21
+ config_param :format, :string, :default => "json"
22
+
23
+ # Initialize new input plugin
24
+ # @since 0.1.0
25
+ # @return [NilClass]
26
+ def initialize
27
+ super
28
+ require 'cool.io'
29
+ require 'msgpack'
30
+ end
31
+
32
+ # Initialize attributes and parameters
33
+ # @since 0.1.0
34
+ # @return [NilClass]
35
+ def configure(config)
36
+ super
37
+
38
+ configure_params(config)
39
+ configure_parser(config)
40
+ configure_locking(config)
41
+
42
+ @retry_at = nil
43
+ end
44
+
45
+ # Configure plugin parameters
46
+ # @since 0.1.0
47
+ # @return [NilClass]
48
+ def configure_params(config)
49
+ %w(host port key command format tag).each do |key|
50
+ next if instance_variable_get("@#{key}")
51
+ raise Fluent::ConfigError, "configuration key missing: #{key}"
52
+ end
53
+
54
+ unless %w(lpop rpop).include?(@command)
55
+ raise Fluent::ConfigError, "command must be either lpop or rpop"
56
+ end
57
+ end
58
+
59
+ # Configure record parser
60
+ # @since 0.1.0
61
+ # @return [NilClass]
62
+ def configure_parser(config)
63
+ @parser = Plugin.new_parser(@format)
64
+ @parser.configure(config)
65
+ end
66
+
67
+ # Configure locking
68
+ # @since 0.1.0
69
+ # @return [NilClass]
70
+ def configure_locking(config)
71
+ @storage = storage_create(type: 'local')
72
+ @lock_key = "fluentd:#{@key}:lock"
73
+ end
74
+
75
+ # Prepare the plugin event loop
76
+ #
77
+ # This method will initialize the Redis connection object, create any required Redis structures as well
78
+ # as define and begin the event pollers.
79
+ #
80
+ # @since 0.1.0
81
+ # @return [NilClass]
82
+ def start
83
+ super
84
+
85
+ @loop = Coolio::Loop.new
86
+ start_redis
87
+ start_poller
88
+ @thread = Thread.new(&method(:run))
89
+ end
90
+
91
+ # Prepare the Redis queue poller
92
+ #
93
+ # This timed event will routinely poll items from the Redis list and
94
+ # emit those through the pipeline.
95
+ #
96
+ # @since 0.1.0
97
+ # @return [NilClass]
98
+ def start_poller
99
+ @poller = TimerWatcher.new(
100
+ @poll_interval,
101
+ log,
102
+ &method(:action_poll)
103
+ )
104
+
105
+ @lock_monitor = TimerWatcher.new(
106
+ 1,
107
+ log,
108
+ &method(:action_locking_monitor)
109
+ )
110
+
111
+ @loop.attach(@poller)
112
+ @loop.attach(@lock_monitor)
113
+ end
114
+
115
+ # Begin the logging pipeline
116
+ # @since 0.1.0
117
+ # @return [NilClass]
118
+ def run
119
+ @loop.run
120
+ rescue => e
121
+ log.error "unexpected error", :error => e
122
+ log.error_backtrace
123
+ end
124
+
125
+ # Tear down the plugin
126
+ # @since 0.1.0
127
+ # @return [NilClass]
128
+ def shutdown
129
+ @loop.watchers.each { |w| w.detach }
130
+ @loop.stop
131
+ Thread.kill(@thread)
132
+ @thread.join
133
+ shutdown_redis
134
+ super
135
+ end
136
+
137
+ # Whether to fetch a single item or a multiple items in batch
138
+ # @since 0.1.0
139
+ # @return [TrueClass, FalseClass]
140
+ def batched?
141
+ @batch_size and @batch_size > 1
142
+ end
143
+
144
+ # Wether the poller has been temporarily disabled or should fetch messages
145
+ # been temporarily disabled
146
+ # @since 0.1.0
147
+ # @return [TrueClass, FalseClass]
148
+ def sleeping?
149
+ @retry_at and @retry_at >= Engine.now
150
+ end
151
+
152
+ # Whether the poller has been locked
153
+ # @since 0.1.0
154
+ # @return [TrueClass, FalseClass]
155
+ def locked?
156
+ @storage.get(@lock_key)
157
+ end
158
+
159
+ # Set a sleep delay, ensuring that we will not attempt to fetch messages
160
+ # @since 0.1.0
161
+ # @param [Integer] delay, the amount of seconds to wait
162
+ # @return [Integer] timestamp when this expires
163
+ def sleep!(delay = @sleep_interval)
164
+ @retry_at = Engine.now + delay
165
+ end
166
+
167
+ # Poll messages from the redis server in either single message or
168
+ # batch mode.
169
+ # @since 0.1.0
170
+ # @param [&block] the block to yield single messages to
171
+ # @return [NilClass]
172
+ def poll_messages
173
+ commands = []
174
+
175
+ if batched?
176
+ @redis.pipelined do
177
+ @batch_size.times do
178
+ commands << @redis.call(@command, @key)
179
+ end
180
+ end
181
+ else
182
+ commands << @redis.call(@command, @key)
183
+ end
184
+
185
+ commands.each do |command|
186
+ yield command.is_a?(Redis::Future) ? command.value : command
187
+ end
188
+ end
189
+
190
+ # Action to execute when polling for the lock key
191
+ # @since 0.1.0
192
+ # @return [NilClass]
193
+ def action_locking_monitor
194
+ lock_value = @redis.get(@lock_key)
195
+ @storage.put(@lock_key, lock_value)
196
+ end
197
+
198
+ # Action to execute when the poller event watcher executes
199
+ #
200
+ # Given that the watcher is pretty lightweight, we simply return if the
201
+ # worker has been set to sleep instead of actually sleeping. Doing
202
+ # otherwise seemed to cause locking.
203
+ #
204
+ # Otherwise we iterate through messages, parse and emit them.
205
+ #
206
+ # @since 0.1.0
207
+ # @return [NilClass]
208
+ def action_poll
209
+ now = Engine.now
210
+ messages = []
211
+
212
+ if sleeping?
213
+ log.trace "redis worker is sleeping"
214
+ return
215
+ end
216
+
217
+ if locked?
218
+ log.trace "redis queue is locked"
219
+ return
220
+ end
221
+
222
+ poll_messages do |message|
223
+ if message.nil?
224
+ log.debug "redis queue is empty"
225
+ sleep!(@sleep_interval)
226
+ break
227
+ end
228
+
229
+ @parser.parse(message) do |time, record|
230
+ if time && record
231
+ router.emit @tag || @key, time || Engine.now, record
232
+ else
233
+ log.warn "failed to parse message: #{message}"
234
+ end
235
+ end
236
+ end
237
+ rescue => e
238
+ log.error "error fetching record", :error => e
239
+ log.error_backtrace
240
+ sleep!(@retry_interval)
241
+ end
242
+
243
+ # Generic Cool.io timer which will execute a given callback on schedule.
244
+ # @since 0.1.0
245
+ class TimerWatcher < Coolio::TimerWatcher
246
+ attr_reader :log
247
+
248
+ def initialize(interval, log, &callback)
249
+ @callback = callback
250
+ @log = log
251
+ super(interval, true)
252
+ end
253
+
254
+ def on_timer
255
+ @callback.call
256
+ rescue => e
257
+ log.error "unexpected error", :error => e
258
+ log.error_backtrace
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module Fluent
3
+ module PluginMixin
4
+ module Redis
5
+ def self.included(base)
6
+ base.class_eval do
7
+ # redis connection details
8
+ config_param :host, :string, :default => '127.0.0.1'
9
+ config_param :port, :integer, :default => 6379
10
+ config_param :path, :string, :default => nil
11
+ config_param :password, :string, :default => nil
12
+ config_param :db, :integer, :default => 0
13
+ config_param :timeout, :float, :default => 5.0
14
+ config_param :driver, :string, :default => "ruby"
15
+
16
+ # redis list details
17
+ # - key: redis key of type `list` to fetch messages from
18
+ # - command: redis command to execute when fetching messages
19
+ # - batch_size: if greater than 0, fetch messages in batches
20
+ config_param :key, :string, :default => nil
21
+
22
+ # worker parameters
23
+ # - poll_inteval: interval between message polling actions
24
+ # *NOTE*: Apparently this must be greather than 0
25
+ # - sleep_interval: interval to wait after receiving 0 messages
26
+ # - retry_interval: interval to wait before retrying after an error
27
+ config_param :poll_interval, :float, :default => 1
28
+ config_param :sleep_interval, :float, :default => 5
29
+ config_param :retry_interval, :float, :default => 5
30
+
31
+ attr_reader :redis
32
+ end
33
+ end
34
+
35
+ # Initialize new input plugin
36
+ # @since 0.1.0
37
+ # @return [NilClass]
38
+ def initialize
39
+ require 'redis'
40
+ super
41
+ end
42
+
43
+ # Prepare the Redis conncection object
44
+ # @since 0.1.0
45
+ # @return [Redis]
46
+ def start_redis
47
+ @redis = ::Redis.new(
48
+ :host => @host,
49
+ :port => @port,
50
+ :driver => @driver,
51
+ :thread_safe => true
52
+ )
53
+ end
54
+
55
+ # Destroy the Redis connection object
56
+ # @since 0.1.0
57
+ # @return [NilClass]
58
+ def shutdown_redis
59
+ @redis.quit
60
+ end
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-redis_list_poller
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Serafini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.12.0
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '2'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.12.0
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2'
61
+ description: A fluentd redis input plugin supporting batch operations
62
+ email:
63
+ - jonathan@serafini.ca
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - ".gitignore"
69
+ - CHANGELOG.txt
70
+ - Gemfile
71
+ - LICENSE.txt
72
+ - README.md
73
+ - Rakefile
74
+ - bin/console
75
+ - bin/setup
76
+ - examples/data.sh
77
+ - examples/standalone.conf
78
+ - fluent-plugin-redis_list_poller.gemspec
79
+ - lib/fluent/plugin/in_redis_list_monitor.rb
80
+ - lib/fluent/plugin/in_redis_list_poller.rb
81
+ - lib/fluent/plugin_mixin/redis.rb
82
+ homepage: https://github.com/JonathanSerafini/fluent-plugin-redis_list_poller
83
+ licenses:
84
+ - apache2
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.5.2
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: A fluentd redis input plugin supporting batch operations
106
+ test_files: []
107
+ has_rdoc: