fluent-plugin-redis-render 0.2.2

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: f88cba02f14dcd45add8833b10f8db1c1abe9e8be4deed2a0c890ff6dd30f4f3
4
+ data.tar.gz: 2ec2723f356b89cbb3e791e691e4bc40398e3c9be005e33d03d6201253c8c6cf
5
+ SHA512:
6
+ metadata.gz: 86ba7d0f40051f12910dba8104d5dcdde6de5db27b16cc4d793bbc4570ea94fdd2acc4be39be88998fefcd1c1fc1ebd773e09d368e19195a95f38055395e980a
7
+ data.tar.gz: 2d2be36e3c733b27a49f380529c05bc67409765e0ce4e15a9f380d8bc477cf3c1708f83072be5fabfc371decfe5b7da1fd4c2f2c45512f644bdbe303df63107d
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/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fluent-plugin-redis-render (0.2.1)
5
+ fluentd (>= 0.14.15, < 2)
6
+ redis
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ cool.io (1.5.4)
12
+ dig_rb (1.0.1)
13
+ fluentd (1.4.2)
14
+ cool.io (>= 1.4.5, < 2.0.0)
15
+ dig_rb (~> 1.0.0)
16
+ http_parser.rb (>= 0.5.1, < 0.7.0)
17
+ msgpack (>= 0.7.0, < 2.0.0)
18
+ serverengine (>= 2.0.4, < 3.0.0)
19
+ sigdump (~> 0.2.2)
20
+ strptime (>= 0.2.2, < 1.0.0)
21
+ tzinfo (~> 1.0)
22
+ tzinfo-data (~> 1.0)
23
+ yajl-ruby (~> 1.0)
24
+ http_parser.rb (0.6.0)
25
+ msgpack (1.2.10)
26
+ power_assert (1.1.4)
27
+ rake (12.3.2)
28
+ redis (4.1.0)
29
+ serverengine (2.1.0)
30
+ sigdump (~> 0.2.2)
31
+ sigdump (0.2.4)
32
+ strptime (0.2.3)
33
+ test-unit (3.3.2)
34
+ power_assert
35
+ thread_safe (0.3.6)
36
+ tzinfo (1.2.5)
37
+ thread_safe (~> 0.1)
38
+ tzinfo-data (1.2019.1)
39
+ tzinfo (>= 1.0.0)
40
+ yajl-ruby (1.4.1)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ fluent-plugin-redis-render!
47
+ rake
48
+ test-unit
49
+
50
+ BUNDLED WITH
51
+ 2.0.1
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 forked 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-render"
4
+ gem.email = "hanai@pokelabo.co.jp"
5
+ gem.version = "0.2.2"
6
+ gem.authors = ["moaikids", "HANAI Tohru aka pokehanai"]
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/renderinc/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"
21
+ end
@@ -0,0 +1,266 @@
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 :host, :string, :default => '127.0.0.1'
13
+ config_param :port, :integer, :default => 6379
14
+ config_param :path, :string, :default => nil
15
+ config_param :password, :string, :default => nil
16
+ config_param :db, :integer, :default => 0
17
+ config_param :timeout, :float, :default => 5.0
18
+ config_param :cluster_nodes, :string, :default => nil
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
+ if @path
58
+ @redis = Redis.new(:path => @path, :password => @password,
59
+ :timeout => @timeout, :thread_safe => true, :db => @db)
60
+ elsif @cluster_nodes
61
+ nodes = @cluster_nodes.split(' ')
62
+ @redis = Redis.new(:cluster => nodes, :password => @password,
63
+ :timeout => @timeout, :thread_safe => true, :db => @db)
64
+ else
65
+ @redis = Redis.new(:host => @host, :port => @port, :password => @password,
66
+ :timeout => @timeout, :thread_safe => true, :db => @db)
67
+ end
68
+ end
69
+
70
+ def shutdown
71
+ @redis.quit
72
+ super
73
+ end
74
+
75
+ def format(tag, time, record)
76
+ [tag, time.to_f, record].to_msgpack
77
+ end
78
+
79
+ def formatted_to_msgpack_binary?
80
+ true
81
+ end
82
+
83
+ def multi_workers_ready?
84
+ true
85
+ end
86
+
87
+ def write(chunk)
88
+ chunk.open {|io|
89
+ begin
90
+ MessagePack::Unpacker.new(io).each {|message|
91
+ begin
92
+ (_, time, record) = message
93
+ case @store_type
94
+ when 'zset'
95
+ operation_for_zset(record, time)
96
+ when 'set'
97
+ operation_for_set(record)
98
+ when 'list'
99
+ operation_for_list(record)
100
+ when 'string'
101
+ operation_for_string(record)
102
+ when 'publish'
103
+ operation_for_publish(record)
104
+ end
105
+ rescue NoMethodError => e
106
+ puts e
107
+ rescue Encoding::UndefinedConversionError => e
108
+ log.error "Plugin error: " + e.to_s
109
+ log.error "Original record: " + record.to_s
110
+ puts e
111
+ end
112
+ }
113
+ rescue EOFError
114
+ # EOFError always occured when reached end of chunk.
115
+ end
116
+ }
117
+ end
118
+
119
+ def operation_for_zset(record, time)
120
+ key = get_key_from(record)
121
+ value = get_value_from(record)
122
+ score = get_score_from(record, time)
123
+ if @collision_policy
124
+ if @collision_policy == 'NX'
125
+ @redis.zadd(key, score, value, :nx => true)
126
+ elsif @collision_policy == 'XX'
127
+ @redis.zadd(key, score, value, :xx => true)
128
+ end
129
+ else
130
+ @redis.zadd(key, score, value)
131
+ end
132
+
133
+ set_key_expire key
134
+ if 0 < @value_expire
135
+ now = Time.now.to_i
136
+ @redis.zremrangebyscore key, '-inf', (now - @value_expire)
137
+ end
138
+ if 0 < @value_length
139
+ script = generate_zremrangebyrank_script(key, @value_length, @order)
140
+ @redis.eval script
141
+ end
142
+ end
143
+
144
+ def operation_for_set(record)
145
+ key = get_key_from(record)
146
+ value = get_value_from(record)
147
+ @redis.sadd key, value
148
+ set_key_expire key
149
+ end
150
+
151
+ def operation_for_list(record)
152
+ key = get_key_from(record)
153
+ value = get_value_from(record)
154
+
155
+ if @order == 'asc'
156
+ @redis.rpush key, value
157
+ else
158
+ @redis.lpush key, value
159
+ end
160
+ set_key_expire key
161
+ if 0 < @value_length
162
+ script = generate_ltrim_script(key, @value_length, @order)
163
+ @redis.eval script
164
+ end
165
+ end
166
+
167
+ def operation_for_string(record)
168
+ key = get_key_from(record)
169
+ value = get_value_from(record)
170
+ @redis.set key, value
171
+
172
+ set_key_expire key
173
+ end
174
+
175
+ def operation_for_publish(record)
176
+ key = get_key_from(record)
177
+ value = get_value_from(record)
178
+ @redis.publish key, value
179
+ end
180
+
181
+ def generate_zremrangebyrank_script(key, maxlen, order)
182
+ script = "local key = '" + key.to_s + "'\n"
183
+ script += "local maxlen = " + maxlen.to_s + "\n"
184
+ script += "local order ='" + order.to_s + "'\n"
185
+ script += "local len = tonumber(redis.call('ZCOUNT', key, '-inf', '+inf'))\n"
186
+ script += "if len > maxlen then\n"
187
+ script += " if order == 'asc' then\n"
188
+ script += " local l = len - maxlen\n"
189
+ script += " if l >= 0 then\n"
190
+ script += " return redis.call('ZREMRANGEBYRANK', key, 0, l)\n"
191
+ script += " end\n"
192
+ script += " else\n"
193
+ script += " return redis.call('ZREMRANGEBYRANK', key, maxlen, -1)\n"
194
+ script += " end\n"
195
+ script += "end\n"
196
+ return script
197
+ end
198
+
199
+ def generate_ltrim_script(key, maxlen, order)
200
+ script = "local key = '" + key.to_s + "'\n"
201
+ script += "local maxlen = " + maxlen.to_s + "\n"
202
+ script += "local order ='" + order.to_s + "'\n"
203
+ script += "local len = tonumber(redis.call('LLEN', key))\n"
204
+ script += "if len > maxlen then\n"
205
+ script += " if order == 'asc' then\n"
206
+ script += " local l = len - maxlen\n"
207
+ script += " return redis.call('LTRIM', key, l, -1)\n"
208
+ script += " else\n"
209
+ script += " return redis.call('LTRIM', key, 0, maxlen - 1)\n"
210
+ script += " end\n"
211
+ script += "end\n"
212
+ return script
213
+ end
214
+
215
+ def traverse(data, key)
216
+ val = data
217
+ key.split('.').each {|k|
218
+ if val.has_key?(k)
219
+ val = val[k]
220
+ else
221
+ return nil
222
+ end
223
+ }
224
+ return val
225
+ end
226
+
227
+ def get_key_from(record)
228
+ if @key
229
+ k = @key
230
+ else
231
+ k = traverse(record, @key_path).to_s
232
+ end
233
+ key = @key_prefix + k + @key_suffix
234
+
235
+ raise Fluent::ConfigError, "key is empty" if key == ''
236
+ key
237
+ end
238
+
239
+ def get_value_from(record)
240
+ value = traverse(record, @value_path)
241
+ case @format_type
242
+ when 'json'
243
+ value.to_json
244
+ when 'msgpack'
245
+ value.to_msgpack
246
+ else
247
+ value
248
+ end
249
+ end
250
+
251
+ def get_score_from(record, time)
252
+ if @score_path
253
+ traverse(record, @score_path)
254
+ else
255
+ time
256
+ end
257
+ end
258
+
259
+ def set_key_expire(key)
260
+ if 0 < @key_expire
261
+ @redis.expire key, @key_expire
262
+ end
263
+ end
264
+
265
+ end
266
+ 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,399 @@
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
+ assert_equal(nil, d.instance.cluster_nodes)
95
+ end
96
+
97
+ def test_configure_host_port_db
98
+ config = %[
99
+ host 192.168.2.3
100
+ port 9999
101
+ password abc
102
+ db 3
103
+ timeout 7
104
+ key a
105
+ score_path b
106
+ ]
107
+ d = create_driver(config)
108
+ assert_equal "192.168.2.3", d.instance.host
109
+ assert_equal 9999, d.instance.port
110
+ assert_equal nil, d.instance.path
111
+ assert_equal 'abc', d.instance.password
112
+ assert_equal 3, d.instance.db
113
+ assert_equal 7.0, d.instance.timeout
114
+ assert_equal nil, d.instance.key_path
115
+ assert_equal 'a', d.instance.key
116
+ end
117
+
118
+ def test_configure_path
119
+ config = %[
120
+ path /tmp/foo.sock
121
+ key a
122
+ score_path b
123
+ ]
124
+ d = create_driver(config)
125
+ assert_equal "/tmp/foo.sock", d.instance.path
126
+ end
127
+
128
+ def test_configure_exception
129
+ assert_raise(Fluent::ConfigError) do
130
+ create_driver(%[])
131
+ end
132
+ end
133
+
134
+ # def test_write
135
+ # d = create_driver(CONFIG1)
136
+ #
137
+ # time = event_time("2011-01-02 13:14:15 UTC")
138
+ # d.run(default_tag 'test') do
139
+ # d.feed({ "foo" => "bar" }, time)
140
+ # end
141
+ #
142
+ # assert_equal "test", $channel
143
+ # assert_equal(%Q[{"foo":"bar","time":#{time}}], $message)
144
+ # end
145
+
146
+ def get_time
147
+ event_time("2011-01-02 13:14:15 UTC")
148
+ end
149
+
150
+ # it should return whole message
151
+ def test_omit_value_path
152
+ config = %[
153
+ format_type plain
154
+ store_type string
155
+ key_path user
156
+ ]
157
+ d = create_driver(config)
158
+ message = {
159
+ 'user' => 'george',
160
+ 'stat' => { 'attack' => 7 }
161
+ }
162
+ $ttl = nil
163
+ d.run(default_tag: 'test') do
164
+ d.feed(get_time, message)
165
+ end
166
+
167
+ assert_equal "george", $key
168
+ assert_equal message, $message
169
+ assert_equal nil, $ttl
170
+ end
171
+
172
+ def test_key_value_paths
173
+ config = %[
174
+ format_type plain
175
+ store_type string
176
+ key_path user.name
177
+ value_path stat.attack
178
+ key_expire 3
179
+ ]
180
+ d = create_driver(config)
181
+ message = {
182
+ 'user' => { 'name' => 'george' },
183
+ 'stat' => { 'attack' => 7 }
184
+ }
185
+ $ttl = nil
186
+ d.run(default_tag: 'test') do
187
+ d.feed(get_time, message)
188
+ end
189
+
190
+ assert_equal "george", $key
191
+ assert_equal 7, $message
192
+ assert_equal 3, $ttl
193
+ end
194
+
195
+ def test_json
196
+ config = %[
197
+ format_type json
198
+ store_type string
199
+ key_path user
200
+ ]
201
+ d = create_driver(config)
202
+ message = {
203
+ 'user' => 'george',
204
+ 'stat' => { 'attack' => 7 }
205
+ }
206
+ $ttl = nil
207
+ d.run(default_tag: 'test') do
208
+ d.feed(get_time, message)
209
+ end
210
+
211
+ assert_equal "george", $key
212
+ assert_equal message.to_json, $message
213
+ end
214
+
215
+ def test_msgpack
216
+ config = %[
217
+ format_type msgpack
218
+ store_type string
219
+ key_path user
220
+ ]
221
+ d = create_driver(config)
222
+ message = {
223
+ 'user' => 'george',
224
+ 'stat' => { 'attack' => 7 }
225
+ }
226
+ $ttl = nil
227
+ d.run(default_tag: 'test') do
228
+ d.feed(get_time, message)
229
+ end
230
+
231
+ assert_equal "george", $key
232
+ assert_equal message.to_msgpack, $message
233
+ end
234
+
235
+ def test_list_asc
236
+ config = %[
237
+ format_type plain
238
+ store_type list
239
+ key_path user
240
+ ]
241
+ d = create_driver(config)
242
+ message = {
243
+ 'user' => 'george',
244
+ 'stat' => { 'attack' => 7 }
245
+ }
246
+ d.run(default_tag: 'test') do
247
+ d.feed(get_time, message)
248
+ end
249
+
250
+ assert_equal :rpush, $command
251
+ assert_equal "george", $key
252
+ assert_equal message, $message
253
+ end
254
+
255
+ def test_list_desc
256
+ config = %[
257
+ format_type plain
258
+ store_type list
259
+ key_path user
260
+ order desc
261
+ ]
262
+ d = create_driver(config)
263
+ message = {
264
+ 'user' => 'george',
265
+ 'stat' => { 'attack' => 7 }
266
+ }
267
+ d.run(default_tag: 'test') do
268
+ d.feed(get_time, message)
269
+ end
270
+
271
+ assert_equal :lpush, $command
272
+ assert_equal "george", $key
273
+ assert_equal message, $message
274
+ end
275
+
276
+ def test_set
277
+ config = %[
278
+ format_type plain
279
+ store_type set
280
+ key_path user
281
+ order desc
282
+ ]
283
+ d = create_driver(config)
284
+ message = {
285
+ 'user' => 'george',
286
+ 'stat' => { 'attack' => 7 }
287
+ }
288
+ d.run(default_tag: 'test') do
289
+ d.feed(get_time, message)
290
+ end
291
+
292
+ assert_equal :sadd, $command
293
+ assert_equal "george", $key
294
+ assert_equal message, $message
295
+ end
296
+
297
+ def test_zset
298
+ config = %[
299
+ format_type plain
300
+ store_type zset
301
+ key_path user
302
+ score_path result
303
+ ]
304
+
305
+ d = create_driver(config)
306
+ message = {
307
+ 'user' => 'george',
308
+ 'stat' => { 'attack' => 7 },
309
+ 'result' => 81
310
+ }
311
+ d.run(default_tag: 'test') do
312
+ d.feed(get_time, message)
313
+ end
314
+
315
+ assert_equal :zadd, $command
316
+ assert_equal "george", $key
317
+ assert_equal 81, $score
318
+ assert_equal message, $message
319
+ end
320
+
321
+ def test_zset_with_no_score_path
322
+ config = %[
323
+ format_type plain
324
+ store_type zset
325
+ key_path user
326
+ ]
327
+
328
+ d = create_driver(config)
329
+ message = {
330
+ 'user' => 'george',
331
+ 'stat' => { 'attack' => 7 },
332
+ 'result' => 81
333
+ }
334
+ d.run(default_tag: 'test') do
335
+ d.feed(get_time, message)
336
+ end
337
+
338
+ assert_equal :zadd, $command
339
+ assert_equal "george", $key
340
+ assert_equal get_time, $score
341
+ assert_equal message, $message
342
+ end
343
+
344
+ def test_publish
345
+ config = %[
346
+ format_type plain
347
+ store_type publish
348
+ key_path user
349
+ ]
350
+
351
+ d = create_driver(config)
352
+ message = {
353
+ 'user' => 'george'
354
+ }
355
+ d.run(default_tag: 'test') do
356
+ d.feed(get_time, message)
357
+ end
358
+
359
+ assert_equal :publish, $command
360
+ assert_equal "george", $channel
361
+ assert_equal message, $message
362
+ end
363
+
364
+ def test_empty_key
365
+ config = %[
366
+ format_type plain
367
+ store_type string
368
+ key_path none
369
+ ]
370
+
371
+ d = create_driver(config)
372
+ message = { 'user' => 'george' }
373
+ suppress_output do
374
+ assert_raise(Fluent::ConfigError) do
375
+ d.run(default_tag: 'test') do
376
+ d.feed(get_time, message)
377
+ end
378
+ end
379
+ end
380
+ end
381
+
382
+ def suppress_output
383
+ begin
384
+ original_stderr = $stderr.clone
385
+ original_stdout = $stdout.clone
386
+ $stderr.reopen(File.new('/dev/null', 'w'))
387
+ $stdout.reopen(File.new('/dev/null', 'w'))
388
+ retval = yield
389
+ rescue Exception => e
390
+ $stdout.reopen(original_stdout)
391
+ $stderr.reopen(original_stderr)
392
+ raise e
393
+ ensure
394
+ $stdout.reopen(original_stdout)
395
+ $stderr.reopen(original_stderr)
396
+ end
397
+ retval
398
+ end
399
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-redis-render
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - moaikids
8
+ - HANAI Tohru aka pokehanai
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-04-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: test-unit
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: fluentd
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 0.14.15
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '2'
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 0.14.15
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: redis
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ description: Redis(zset/set/list/string/publish) output plugin for Fluentd...
77
+ email: hanai@pokelabo.co.jp
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - ".gitignore"
83
+ - AUTHORS
84
+ - Gemfile
85
+ - Gemfile.lock
86
+ - README.md
87
+ - Rakefile
88
+ - fluent-plugin-redis-store.gemspec
89
+ - lib/fluent/plugin/out_redis_store.rb
90
+ - test/helpers.rb
91
+ - test/plugin/test_out_redis_publish.rb
92
+ homepage: https://github.com/renderinc/fluent-plugin-redis-store
93
+ licenses:
94
+ - Apache License Version 2.0
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.0.3
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Redis(zset/set/list/string/publish) output plugin for Fluentd
115
+ test_files:
116
+ - test/helpers.rb
117
+ - test/plugin/test_out_redis_publish.rb