fluent-plugin-redis-sentinel 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e9eeef66cfcaa597cbe7addcdbfabe5bb9041edcd2143adef3b17d45a4405cb5
4
+ data.tar.gz: ad3711ea5d9d8ae62890c793255d3459e290090de0bb8a3ecaaa83cb2f7d4b84
5
+ SHA512:
6
+ metadata.gz: dd4c45130e3df49784149d3bbb4156486e1f9411ced78f7743089c0b513d84c9f0310561fbcebc9f1e57ff3cd15b91a79b42e3e8e30f8ee31c60796e562d5e6b
7
+ data.tar.gz: a3766502770a415c7579e3cbcc1871e5f751133093a7a2caaa882bacf1ec28a240881bd67413aa775391a05bd38666f72581b3aabba2aff5625a266661b62571
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/AUTHORS ADDED
@@ -0,0 +1,2 @@
1
+ moaikids
2
+ HANAI Tohru aka pokehanai
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,183 @@
1
+ Redis Output Plugin For fluentd
2
+ ===============================
3
+ [Fluentd][] output plugin to upload/publish event data to [Redis][] storage.
4
+
5
+ [Fluentd]: http://fluentd.org/
6
+ [Redis]: http://redis.io/
7
+
8
+ Requirements
9
+ ------------
10
+
11
+ | fluent-plugin-redis-store | fluentd | ruby |
12
+ |------------------------|---------|------|
13
+ | >= 0.2.0 | >= v0.14.15 | >= 2.1 |
14
+ | < 0.2.0 | >= v0.12.0 | >= 1.9 |
15
+
16
+ Background
17
+ ----------
18
+
19
+ This is folked project from [fluent-plugin-redisstore][].
20
+
21
+ [fluent-plugin-redisstore]: https://github.com/moaikids/fluent-plugin-redisstore
22
+
23
+ Features
24
+ --------
25
+
26
+ #### Supported Redis commands
27
+
28
+ Currently the plugin supports following Redis commands:
29
+
30
+ - **set** by `string` type (of the plugin)
31
+ - **lpush**/**rpush** by `list` type
32
+ - **sadd** by `set` type
33
+ - **zadd** by `zset` type
34
+ - **publish** by `publish` type
35
+
36
+ #### Supported _value_ format
37
+
38
+ - plain(as is)
39
+ - JSON
40
+ - [MessagePack](http://msgpack.org/)
41
+
42
+ #### _key_ string for Redis storage
43
+
44
+ Redis commands require _key_ and _value_.
45
+ For _key_, the plugin supports either way;
46
+
47
+ 1. Specify a fixed key.
48
+ You can do this simply using `key` option in td-agent configuration file.
49
+
50
+ ```apache
51
+ type redis_store
52
+ key userdata
53
+ ```
54
+
55
+ 2. Lookup a key string in every event data by a lookup path.
56
+ If event data have structured data like
57
+
58
+ ```javascript
59
+ { "user": { "name": "Kei" } }
60
+ ```
61
+
62
+ and you want to use each name of user, you can use `key_path` option.
63
+
64
+ ```apache
65
+ type redis_store
66
+ key_path user.name
67
+ ```
68
+
69
+ With the above data, `Kei` will be a _key_.
70
+
71
+ In addition, `key_prefix` and `key_suffix` are useful in some cases. Both are available either `key` and `key_path`
72
+
73
+ ```apache
74
+ type redis_store
75
+ key_path user.name
76
+ key_prefix ouruser.
77
+ key_suffix .accesslog
78
+ ```
79
+
80
+ With the previous data, _key_ will be `outuser.Kei.accesslog`.
81
+
82
+ #### _value_ data for Redis storage
83
+
84
+ To determine what _value_ in every event data to be srtored, you have two options;
85
+
86
+ 1. Store extracted data in event data, by a lookup path with `value_path` option.
87
+ It works like `key_path`.
88
+ 2. Store whole data.
89
+ This is default behavior. To do it, simply omit `value_path` option.
90
+
91
+ Installation
92
+ ------------
93
+
94
+ ```bash
95
+ fluent-gem install fluent-plugin-redis-store
96
+
97
+ # or if you are using td-agent:
98
+ td-agent-gem install fluent-plugin-redis-store
99
+ ```
100
+
101
+ Configuration
102
+ -------------
103
+
104
+ ### Redis connection
105
+
106
+ | Key | Type | Required? | Default | Description |
107
+ | :---- | :----- | :---------- | :----------------------- | :------------ |
108
+ | `host` | string | Optional | 127.0.0.1 | host name of Redis server |
109
+ | `port` | int | Optional | 6379 | port number of Redis server |
110
+ | `password` | string | Optional | | password for Redis connection |
111
+ | `path` | string | Optional | | To connect via Unix socket, try '/tmp/redis.sock' |
112
+ | `db` | int | Optional | 0 | DB number of Redis |
113
+ | `timeout` | float | Optional | 5.0 | connection timeout in seconds |
114
+
115
+ ### common options for storages
116
+
117
+ | Key | Type | Default | Description |
118
+ | :---- | :----- | :----------------------- | :------------ |
119
+ | `key` | string | | Fixed _key_ used to store(publish) in Redis |
120
+ | `key_path` | string | | path to lookup for _key_ in the event data |
121
+ | `key_prefix` | string | | prefix of _key_ |
122
+ | `key_suffix` | string | | suffix of _key_ |
123
+ | `value_path` | string | (whole event data) | path to lookup for _value_ in the event data |
124
+ | `store_type` | string | zset | `string`/`list`/`set`/`zset`/`publish` |
125
+ | `format_type` | string | plain | format type for _value_ (`plain`/`json`/`msgpack`) |
126
+ | `key_expire` | int | -1 | If set, the key will be expired in specified seconds |
127
+ | `flush_interval` | time | 1 | Time interval which events will be flushed to Redis |
128
+
129
+ Note: either `key` or `key_path` is required.
130
+
131
+ ### `string` storage specific options
132
+
133
+ | Key | Type | Default | Description |
134
+ | :---- | :----- | :----------------------- | :------------ |
135
+ | `type` | string | | Fixed _key_ used to store(publish) in Redis |
136
+ No more options than common options.
137
+
138
+ ### `list` storage specific options
139
+
140
+ | Key | Type | Default | Description |
141
+ | :---- | :----- | :----------------------- | :------------ |
142
+ | `order` | string | asc | `asc`: **rpush**, `desc`: **lpush** |
143
+
144
+ ### `set` storage specific options
145
+
146
+ No more options than common options.
147
+
148
+ ### `zset` storage specific options
149
+
150
+ | Key | Type | Default | Description |
151
+ | :---- | :----- | :----------------------- | :------------ |
152
+ | `score_path` | string | (_time_ of log event) | path to lookup for _score_ in the event data |
153
+ | `collision_policy` | string | (nil) | Only update elements that already exist (XX) or add a new element (NX) |
154
+ | `value_expire` | int | | value expiration in seconds |
155
+
156
+ If `value_expire` is set, the plugin assumes that the _score_ in the **SortedSet** is
157
+ based on *timestamp* and it deletes expired _members_ every after new event data arrives.
158
+
159
+ ### `publish` storage specific options
160
+
161
+ No more options than common options.
162
+
163
+
164
+ Contributors
165
+ ------------
166
+
167
+ moaikids
168
+ HANAI tohru
169
+ Mohit Khanna
170
+ yamada-shinji
171
+ Heitor de Souza
172
+ Hiroshi Hatake
173
+ Gabriel Bordeaux
174
+
175
+ Copyright
176
+ ---------
177
+
178
+ Copyright (c) 2013 moaikids
179
+ Copyright (c) 2014 HANAI Tohru
180
+
181
+ License
182
+ -------
183
+ Apache License, Version 2.0
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |gem|
3
+ gem.name = "fluent-plugin-redis-sentinel"
4
+ gem.email = "gp@path.com"
5
+ gem.version = "0.2.0"
6
+ gem.authors = ["A360"]
7
+ gem.licenses = ["Apache License Version 2.0"]
8
+ gem.summary = %q{Redis(zset/set/list/string/publish) output plugin for Fluentd}
9
+ gem.description = %q{Redis(zset/set/list/string/publish) output plugin for Fluentd...}
10
+ gem.homepage = "https://github.com/pokehanai/fluent-plugin-redis-store"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ["lib"]
16
+
17
+ gem.add_development_dependency "rake"
18
+ gem.add_development_dependency "test-unit"
19
+ gem.add_runtime_dependency "fluentd", [">= 0.14.15", "< 2"]
20
+ gem.add_runtime_dependency "redis", "= 5.0.7"
21
+ end
@@ -0,0 +1,285 @@
1
+ require 'fluent/plugin/output'
2
+
3
+ module Fluent::Plugin
4
+ class RedisStoreOutput < Output
5
+ Fluent::Plugin.register_output('redis_store', self)
6
+
7
+ helpers :compat_parameters
8
+
9
+ DEFAULT_BUFFER_TYPE = "memory"
10
+
11
+ # redis connection
12
+ config_param :sentinel_host, :string, :default => '127.0.0.1'
13
+ config_param :port, :integer, :default => 6379
14
+ config_param :path, :string, :default => nil
15
+ config_param :group_name, :string, :default => 'redis-master'
16
+ config_param :password, :string, :default => nil
17
+ config_param :db, :integer, :default => 0
18
+ config_param :timeout, :float, :default => 5.0
19
+
20
+ # redis command and parameters
21
+ config_param :format_type, :string, :default => 'json'
22
+ config_param :store_type, :string, :default => 'zset'
23
+ config_param :key_prefix, :string, :default => ''
24
+ config_param :key_suffix, :string, :default => ''
25
+ config_param :key, :string, :default => nil
26
+ config_param :key_path, :string, :default => nil
27
+ config_param :score_path, :string, :default => nil
28
+ config_param :value_path, :string, :default => ''
29
+ config_param :key_expire, :integer, :default => -1
30
+ config_param :value_expire, :integer, :default => -1
31
+ config_param :value_length, :integer, :default => -1
32
+ config_param :order, :string, :default => 'asc'
33
+ config_param :collision_policy, :string, :default => nil
34
+ config_set_default :flush_interval, 1
35
+
36
+ config_section :buffer do
37
+ config_set_default :@type, DEFAULT_BUFFER_TYPE
38
+ end
39
+
40
+ def initialize
41
+ super
42
+ require 'redis' unless defined?(Redis) == 'constant'
43
+ require 'msgpack'
44
+ end
45
+
46
+ def configure(conf)
47
+ compat_parameters_convert(conf, :buffer)
48
+ super
49
+
50
+ if @key_path == nil and @key == nil
51
+ raise Fluent::ConfigError, "either key_path or key is required"
52
+ end
53
+ end
54
+
55
+ def start
56
+ super
57
+
58
+ host=@sentinel_host
59
+ hosts = host.split(",")
60
+
61
+ # Initialize Sentinel Empty Array
62
+ sentinels = []
63
+
64
+ # Loop through each hosts and add it to sentinel array
65
+ if hosts.instance_of? Array
66
+ hosts.each do |host|
67
+ sentinels << {"host":host,"port":@port}
68
+ end
69
+ else
70
+ sentinels << {"host":hosts,"port":@port}
71
+ end
72
+
73
+ # Printing Sentinel Server List
74
+ $stdout.puts "Sentinel Server List #{sentinels}"
75
+
76
+
77
+ @redis = Redis.new(name:@group_name,sentinels:sentinels,role: :master, timeout: @timeout)
78
+
79
+ end
80
+
81
+ def shutdown
82
+ @redis.quit
83
+ super
84
+ end
85
+
86
+ def format(tag, time, record)
87
+ [tag, time.to_f, record].to_msgpack
88
+ end
89
+
90
+ def formatted_to_msgpack_binary?
91
+ true
92
+ end
93
+
94
+ def multi_workers_ready?
95
+ true
96
+ end
97
+
98
+ def write(chunk)
99
+ @redis.pipelined {
100
+ chunk.open { |io|
101
+ begin
102
+ MessagePack::Unpacker.new(io).each { |message|
103
+ begin
104
+ (_, time, record) = message
105
+ case @store_type
106
+ when 'zset'
107
+ operation_for_zset(record, time)
108
+ when 'set'
109
+ operation_for_set(record)
110
+ when 'list'
111
+ operation_for_list(record)
112
+ when 'string'
113
+ operation_for_string(record)
114
+ when 'publish'
115
+ operation_for_publish(record)
116
+ end
117
+ rescue NoMethodError => e
118
+ puts e
119
+ rescue Encoding::UndefinedConversionError => e
120
+ log.error "Plugin error: " + e.to_s
121
+ log.error "Original record: " + record.to_s
122
+ puts e
123
+ rescue Redis::CannotConnectError => e
124
+ log.error "Connection Error: #{e.message}"
125
+ log.error "Original record: " + record.to_s
126
+ log.info @redis
127
+ log.info "Retrying Redis Connection"
128
+ @redis = Redis.new(name:@group_name,sentinels:sentinels,role: :master, timeout: @timeout)
129
+ end
130
+ }
131
+ rescue EOFError
132
+ # EOFError always occured when reached end of chunk.
133
+ end
134
+ }
135
+ }
136
+ end
137
+
138
+ def operation_for_zset(record, time)
139
+ key = get_key_from(record)
140
+ value = get_value_from(record)
141
+ score = get_score_from(record, time)
142
+ if @collision_policy
143
+ if @collision_policy == 'NX'
144
+ @redis.zadd(key, score, value, :nx => true)
145
+ elsif @collision_policy == 'XX'
146
+ @redis.zadd(key, score, value, :xx => true)
147
+ end
148
+ else
149
+ @redis.zadd(key, score, value)
150
+ end
151
+
152
+ set_key_expire key
153
+ if 0 < @value_expire
154
+ now = Time.now.to_i
155
+ @redis.zremrangebyscore key , '-inf' , (now - @value_expire)
156
+ end
157
+ if 0 < @value_length
158
+ script = generate_zremrangebyrank_script(key, @value_length, @order)
159
+ @redis.eval script
160
+ end
161
+ end
162
+
163
+ def operation_for_set(record)
164
+ key = get_key_from(record)
165
+ value = get_value_from(record)
166
+ @redis.sadd key, value
167
+ set_key_expire key
168
+ end
169
+
170
+ def operation_for_list(record)
171
+ key = get_key_from(record)
172
+ value = get_value_from(record)
173
+
174
+ if @order == 'asc'
175
+ @redis.rpush key, value
176
+ else
177
+ @redis.lpush key, value
178
+ end
179
+ set_key_expire key
180
+ if 0 < @value_length
181
+ script = generate_ltrim_script(key, @value_length, @order)
182
+ @redis.eval script
183
+ end
184
+ end
185
+
186
+ def operation_for_string(record)
187
+ key = get_key_from(record)
188
+ value = get_value_from(record)
189
+ @redis.set key, value
190
+
191
+ set_key_expire key
192
+ end
193
+
194
+ def operation_for_publish(record)
195
+ key = get_key_from(record)
196
+ value = get_value_from(record)
197
+ @redis.publish key, value
198
+ end
199
+
200
+ def generate_zremrangebyrank_script(key, maxlen, order)
201
+ script = "local key = '" + key.to_s + "'\n"
202
+ script += "local maxlen = " + maxlen.to_s + "\n"
203
+ script += "local order ='" + order.to_s + "'\n"
204
+ script += "local len = tonumber(redis.call('ZCOUNT', key, '-inf', '+inf'))\n"
205
+ script += "if len > maxlen then\n"
206
+ script += " if order == 'asc' then\n"
207
+ script += " local l = len - maxlen\n"
208
+ script += " if l >= 0 then\n"
209
+ script += " return redis.call('ZREMRANGEBYRANK', key, 0, l)\n"
210
+ script += " end\n"
211
+ script += " else\n"
212
+ script += " return redis.call('ZREMRANGEBYRANK', key, maxlen, -1)\n"
213
+ script += " end\n"
214
+ script += "end\n"
215
+ return script
216
+ end
217
+
218
+ def generate_ltrim_script(key, maxlen, order)
219
+ script = "local key = '" + key.to_s + "'\n"
220
+ script += "local maxlen = " + maxlen.to_s + "\n"
221
+ script += "local order ='" + order.to_s + "'\n"
222
+ script += "local len = tonumber(redis.call('LLEN', key))\n"
223
+ script += "if len > maxlen then\n"
224
+ script += " if order == 'asc' then\n"
225
+ script += " local l = len - maxlen\n"
226
+ script += " return redis.call('LTRIM', key, l, -1)\n"
227
+ script += " else\n"
228
+ script += " return redis.call('LTRIM', key, 0, maxlen - 1)\n"
229
+ script += " end\n"
230
+ script += "end\n"
231
+ return script
232
+ end
233
+
234
+ def traverse(data, key)
235
+ val = data
236
+ key.split('.').each{ |k|
237
+ if val.has_key?(k)
238
+ val = val[k]
239
+ else
240
+ return nil
241
+ end
242
+ }
243
+ return val
244
+ end
245
+
246
+ def get_key_from(record)
247
+ if @key
248
+ k = @key
249
+ else
250
+ k = traverse(record, @key_path).to_s
251
+ end
252
+ key = @key_prefix + k + @key_suffix
253
+
254
+ raise Fluent::ConfigError, "key is empty" if key == ''
255
+ key
256
+ end
257
+
258
+ def get_value_from(record)
259
+ value = traverse(record, @value_path)
260
+ case @format_type
261
+ when 'json'
262
+ value.to_json
263
+ when 'msgpack'
264
+ value.to_msgpack
265
+ else
266
+ value
267
+ end
268
+ end
269
+
270
+ def get_score_from(record, time)
271
+ if @score_path
272
+ traverse(record, @score_path)
273
+ else
274
+ time
275
+ end
276
+ end
277
+
278
+ def set_key_expire(key)
279
+ if 0 < @key_expire
280
+ @redis.expire key, @key_expire
281
+ end
282
+ end
283
+
284
+ end
285
+ end
data/test/helpers.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ require 'fluent/test/driver/output'
16
+ require 'fluent/test/helpers'
17
+ unless ENV.has_key?('VERBOSE')
18
+ nulllogger = Object.new
19
+ nulllogger.instance_eval {|obj|
20
+ def method_missing(method, *args)
21
+ # pass
22
+ end
23
+ }
24
+ $log = nulllogger
25
+ end
26
+
27
+ require 'fluent/plugin/out_redis_store'
28
+
29
+ class Test::Unit::TestCase
30
+ include Fluent::Test::Helpers
31
+ end
@@ -0,0 +1,398 @@
1
+ require 'helpers'
2
+
3
+ $channel = nil
4
+ $message = nil
5
+
6
+ class Redis
7
+ def initialize(options = {})
8
+ end
9
+
10
+ def pipelined
11
+ yield self
12
+ end
13
+
14
+ def set(key, message)
15
+ $command = :set
16
+ $key = key
17
+ $message = message
18
+ end
19
+
20
+ def rpush(key, message)
21
+ $command = :rpush
22
+ $key = key
23
+ $message = message
24
+ end
25
+
26
+ def lpush(key, message)
27
+ $command = :lpush
28
+ $key = key
29
+ $message = message
30
+ end
31
+
32
+ def sadd(key, message)
33
+ $command = :sadd
34
+ $key = key
35
+ $message = message
36
+ end
37
+
38
+ def zadd(key, score, message)
39
+ $command = :zadd
40
+ $key = key
41
+ $score = score
42
+ $message = message
43
+ end
44
+
45
+ def expire(key, ttl)
46
+ $expire_key = key
47
+ $ttl = ttl
48
+ end
49
+
50
+ def publish(channel, message)
51
+ $command = :publish
52
+ $channel = channel
53
+ $message = message
54
+ end
55
+
56
+ def quit
57
+ end
58
+ end
59
+
60
+ class RedisStoreOutputTest < Test::Unit::TestCase
61
+ def setup
62
+ Fluent::Test.setup
63
+ end
64
+
65
+ def create_driver(conf)
66
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::RedisStoreOutput).configure(conf)
67
+ end
68
+
69
+ def test_configure_defaults
70
+ config = %[
71
+ key_path a
72
+ score_path b
73
+ ]
74
+ d = create_driver(config)
75
+ assert_equal("127.0.0.1", d.instance.host)
76
+ assert_equal(6379, d.instance.port)
77
+ assert_equal(nil, d.instance.path)
78
+ assert_equal(nil, d.instance.password)
79
+ assert_equal(0, d.instance.db)
80
+ assert_equal(5.0, d.instance.timeout)
81
+ assert_equal('json', d.instance.format_type)
82
+ assert_equal('', d.instance.key_prefix)
83
+ assert_equal('', d.instance.key_suffix)
84
+ assert_equal('zset', d.instance.store_type)
85
+ assert_equal('a', d.instance.key_path)
86
+ assert_equal(nil, d.instance.key)
87
+ assert_equal('b', d.instance.score_path)
88
+ assert_equal('', d.instance.value_path)
89
+ assert_equal(-1, d.instance.key_expire)
90
+ assert_equal(-1, d.instance.value_expire)
91
+ assert_equal(-1, d.instance.value_length)
92
+ assert_equal('asc', d.instance.order)
93
+ assert_equal(nil, d.instance.collision_policy)
94
+ end
95
+
96
+ def test_configure_host_port_db
97
+ config = %[
98
+ host 192.168.2.3
99
+ port 9999
100
+ password abc
101
+ db 3
102
+ timeout 7
103
+ key a
104
+ score_path b
105
+ ]
106
+ d = create_driver(config)
107
+ assert_equal "192.168.2.3", d.instance.host
108
+ assert_equal 9999, d.instance.port
109
+ assert_equal nil, d.instance.path
110
+ assert_equal 'abc', d.instance.password
111
+ assert_equal 3, d.instance.db
112
+ assert_equal 7.0, d.instance.timeout
113
+ assert_equal nil, d.instance.key_path
114
+ assert_equal 'a', d.instance.key
115
+ end
116
+
117
+ def test_configure_path
118
+ config = %[
119
+ path /tmp/foo.sock
120
+ key a
121
+ score_path b
122
+ ]
123
+ d = create_driver(config)
124
+ assert_equal "/tmp/foo.sock", d.instance.path
125
+ end
126
+
127
+ def test_configure_exception
128
+ assert_raise(Fluent::ConfigError) do
129
+ create_driver(%[])
130
+ end
131
+ end
132
+
133
+ # def test_write
134
+ # d = create_driver(CONFIG1)
135
+ #
136
+ # time = event_time("2011-01-02 13:14:15 UTC")
137
+ # d.run(default_tag 'test') do
138
+ # d.feed({ "foo" => "bar" }, time)
139
+ # end
140
+ #
141
+ # assert_equal "test", $channel
142
+ # assert_equal(%Q[{"foo":"bar","time":#{time}}], $message)
143
+ # end
144
+
145
+ def get_time
146
+ event_time("2011-01-02 13:14:15 UTC")
147
+ end
148
+
149
+ # it should return whole message
150
+ def test_omit_value_path
151
+ config = %[
152
+ format_type plain
153
+ store_type string
154
+ key_path user
155
+ ]
156
+ d = create_driver(config)
157
+ message = {
158
+ 'user' => 'george',
159
+ 'stat' => { 'attack' => 7 }
160
+ }
161
+ $ttl = nil
162
+ d.run(default_tag: 'test') do
163
+ d.feed(get_time, message)
164
+ end
165
+
166
+ assert_equal "george", $key
167
+ assert_equal message, $message
168
+ assert_equal nil, $ttl
169
+ end
170
+
171
+ def test_key_value_paths
172
+ config = %[
173
+ format_type plain
174
+ store_type string
175
+ key_path user.name
176
+ value_path stat.attack
177
+ key_expire 3
178
+ ]
179
+ d = create_driver(config)
180
+ message = {
181
+ 'user' => { 'name' => 'george' },
182
+ 'stat' => { 'attack' => 7 }
183
+ }
184
+ $ttl = nil
185
+ d.run(default_tag: 'test') do
186
+ d.feed(get_time, message)
187
+ end
188
+
189
+ assert_equal "george", $key
190
+ assert_equal 7, $message
191
+ assert_equal 3, $ttl
192
+ end
193
+
194
+ def test_json
195
+ config = %[
196
+ format_type json
197
+ store_type string
198
+ key_path user
199
+ ]
200
+ d = create_driver(config)
201
+ message = {
202
+ 'user' => 'george',
203
+ 'stat' => { 'attack' => 7 }
204
+ }
205
+ $ttl = nil
206
+ d.run(default_tag: 'test') do
207
+ d.feed(get_time, message)
208
+ end
209
+
210
+ assert_equal "george", $key
211
+ assert_equal message.to_json, $message
212
+ end
213
+
214
+ def test_msgpack
215
+ config = %[
216
+ format_type msgpack
217
+ store_type string
218
+ key_path user
219
+ ]
220
+ d = create_driver(config)
221
+ message = {
222
+ 'user' => 'george',
223
+ 'stat' => { 'attack' => 7 }
224
+ }
225
+ $ttl = nil
226
+ d.run(default_tag: 'test') do
227
+ d.feed(get_time, message)
228
+ end
229
+
230
+ assert_equal "george", $key
231
+ assert_equal message.to_msgpack, $message
232
+ end
233
+
234
+ def test_list_asc
235
+ config = %[
236
+ format_type plain
237
+ store_type list
238
+ key_path user
239
+ ]
240
+ d = create_driver(config)
241
+ message = {
242
+ 'user' => 'george',
243
+ 'stat' => { 'attack' => 7 }
244
+ }
245
+ d.run(default_tag: 'test') do
246
+ d.feed(get_time, message)
247
+ end
248
+
249
+ assert_equal :rpush, $command
250
+ assert_equal "george", $key
251
+ assert_equal message, $message
252
+ end
253
+
254
+ def test_list_desc
255
+ config = %[
256
+ format_type plain
257
+ store_type list
258
+ key_path user
259
+ order desc
260
+ ]
261
+ d = create_driver(config)
262
+ message = {
263
+ 'user' => 'george',
264
+ 'stat' => { 'attack' => 7 }
265
+ }
266
+ d.run(default_tag: 'test') do
267
+ d.feed(get_time, message)
268
+ end
269
+
270
+ assert_equal :lpush, $command
271
+ assert_equal "george", $key
272
+ assert_equal message, $message
273
+ end
274
+
275
+ def test_set
276
+ config = %[
277
+ format_type plain
278
+ store_type set
279
+ key_path user
280
+ order desc
281
+ ]
282
+ d = create_driver(config)
283
+ message = {
284
+ 'user' => 'george',
285
+ 'stat' => { 'attack' => 7 }
286
+ }
287
+ d.run(default_tag: 'test') do
288
+ d.feed(get_time, message)
289
+ end
290
+
291
+ assert_equal :sadd, $command
292
+ assert_equal "george", $key
293
+ assert_equal message, $message
294
+ end
295
+
296
+ def test_zset
297
+ config = %[
298
+ format_type plain
299
+ store_type zset
300
+ key_path user
301
+ score_path result
302
+ ]
303
+
304
+ d = create_driver(config)
305
+ message = {
306
+ 'user' => 'george',
307
+ 'stat' => { 'attack' => 7 },
308
+ 'result' => 81
309
+ }
310
+ d.run(default_tag: 'test') do
311
+ d.feed(get_time, message)
312
+ end
313
+
314
+ assert_equal :zadd, $command
315
+ assert_equal "george", $key
316
+ assert_equal 81, $score
317
+ assert_equal message, $message
318
+ end
319
+
320
+ def test_zset_with_no_score_path
321
+ config = %[
322
+ format_type plain
323
+ store_type zset
324
+ key_path user
325
+ ]
326
+
327
+ d = create_driver(config)
328
+ message = {
329
+ 'user' => 'george',
330
+ 'stat' => { 'attack' => 7 },
331
+ 'result' => 81
332
+ }
333
+ d.run(default_tag: 'test') do
334
+ d.feed(get_time, message)
335
+ end
336
+
337
+ assert_equal :zadd, $command
338
+ assert_equal "george", $key
339
+ assert_equal get_time, $score
340
+ assert_equal message, $message
341
+ end
342
+
343
+ def test_publish
344
+ config = %[
345
+ format_type plain
346
+ store_type publish
347
+ key_path user
348
+ ]
349
+
350
+ d = create_driver(config)
351
+ message = {
352
+ 'user' => 'george'
353
+ }
354
+ d.run(default_tag: 'test') do
355
+ d.feed(get_time, message)
356
+ end
357
+
358
+ assert_equal :publish, $command
359
+ assert_equal "george", $channel
360
+ assert_equal message, $message
361
+ end
362
+
363
+ def test_empty_key
364
+ config = %[
365
+ format_type plain
366
+ store_type string
367
+ key_path none
368
+ ]
369
+
370
+ d = create_driver(config)
371
+ message = { 'user' => 'george' }
372
+ suppress_output do
373
+ assert_raise(Fluent::ConfigError) do
374
+ d.run(default_tag: 'test') do
375
+ d.feed(get_time, message)
376
+ end
377
+ end
378
+ end
379
+ end
380
+
381
+ def suppress_output
382
+ begin
383
+ original_stderr = $stderr.clone
384
+ original_stdout = $stdout.clone
385
+ $stderr.reopen(File.new('/dev/null', 'w'))
386
+ $stdout.reopen(File.new('/dev/null', 'w'))
387
+ retval = yield
388
+ rescue Exception => e
389
+ $stdout.reopen(original_stdout)
390
+ $stderr.reopen(original_stderr)
391
+ raise e
392
+ ensure
393
+ $stdout.reopen(original_stdout)
394
+ $stderr.reopen(original_stderr)
395
+ end
396
+ retval
397
+ end
398
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-redis-sentinel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - A360
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
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: test-unit
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.14.15
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.14.15
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '2'
61
+ - !ruby/object:Gem::Dependency
62
+ name: redis
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '='
66
+ - !ruby/object:Gem::Version
67
+ version: 5.0.7
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '='
73
+ - !ruby/object:Gem::Version
74
+ version: 5.0.7
75
+ description: Redis(zset/set/list/string/publish) output plugin for Fluentd...
76
+ email: gp@path.com
77
+ executables: []
78
+ extensions: []
79
+ extra_rdoc_files: []
80
+ files:
81
+ - ".gitignore"
82
+ - AUTHORS
83
+ - Gemfile
84
+ - README.md
85
+ - Rakefile
86
+ - fluent-plugin-redis-store.gemspec
87
+ - lib/fluent/plugin/out_redis_store.rb
88
+ - test/helpers.rb
89
+ - test/plugin/test_out_redis_publish.rb
90
+ homepage: https://github.com/pokehanai/fluent-plugin-redis-store
91
+ licenses:
92
+ - Apache License Version 2.0
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.1.2
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Redis(zset/set/list/string/publish) output plugin for Fluentd
113
+ test_files:
114
+ - test/helpers.rb
115
+ - test/plugin/test_out_redis_publish.rb