fluent-plugin-redis-store 0.1.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6d5c8e74473ada6d1883030ccd153f6a246a0cc
4
- data.tar.gz: '029eda873dfb56bbf74a7cbadc3edb17797cfd75'
3
+ metadata.gz: 8055a7eb193c6aba6625c44505354898b2ccb147
4
+ data.tar.gz: d173101f80f617b44bb57fff38fb43b954e32e94
5
5
  SHA512:
6
- metadata.gz: ad5023960c0b604a27e5efe343127be8544d5fc1a6906fceba10c573f9f5c845e095b38488826ee6f0dd0483ecde09636907c833459ef08e10b003948d406a54
7
- data.tar.gz: 78d5c22c9c417a9ce4a3f5679263fdc95173792dbe19e695cec53618f9740204ae96e5fd2b010965c886d2346ae5f8c4e63ee9e302b83a89c5a3e49bde6e6085
6
+ metadata.gz: f72795d871fc200ca056b3efce938a68c855665b090f7a26f3979e7314776be8fc3af69169b91b954d294586083c7a8c1774e4016f5bf1ee7fe74a4c0847d574
7
+ data.tar.gz: bc433609670879c4a05524bdcc0315aec37b1623a0fcd9cdb40b33375de849f15d722181255812b52783338f81e091a736bbe98ed1dbbd50e80c2d1912a8c0c1
@@ -0,0 +1 @@
1
+ *.gem
data/README.md CHANGED
@@ -43,7 +43,7 @@ For _key_, the plugin supports either way;
43
43
  type redis_store
44
44
  key userdata
45
45
  ```
46
-
46
+
47
47
  2. Lookup a key string in every event data by a lookup path.
48
48
  If event data have structured data like
49
49
 
@@ -83,7 +83,12 @@ To determine what _value_ in every event data to be srtored, you have two option
83
83
  Installation
84
84
  ------------
85
85
 
86
- /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-redis-store
86
+ ```bash
87
+ fluent-gem install fluent-plugin-redis-store
88
+
89
+ # or if you are using td-agent:
90
+ td-agent-gem install fluent-plugin-redis-store
91
+ ```
87
92
 
88
93
  Configuration
89
94
  -------------
@@ -92,7 +97,7 @@ Configuration
92
97
 
93
98
  | Key | Type | Required? | Default | Description |
94
99
  | :---- | :----- | :---------- | :----------------------- | :------------ |
95
- | `host` | string | Optional | 127.0.0.1 | host name of Redis server |
100
+ | `host` | string | Optional | 127.0.0.1 | host name of Redis server |
96
101
  | `port` | int | Optional | 6379 | port number of Redis server |
97
102
  | `password` | string | Optional | | password for Redis connection |
98
103
  | `path` | string | Optional | | To connect via Unix socket, try '/tmp/redis.sock' |
@@ -101,17 +106,17 @@ Configuration
101
106
 
102
107
  ### common options for storages
103
108
 
104
- | Key | Type | Default | Description |
105
- | :---- | :----- | :----------------------- | :------------ |
106
- | `key` | string | | Fixed _key_ used to store(publish) in Redis |
107
- | `key_path` | string | | path to lookup for _key_ in the event data |
108
- | `key_prefix` | string | | prefix of _key_ |
109
- | `key_suffix` | string | | suffix of _key_ |
110
- | `value_path` | string | (whole event data) | path to lookup for _value_ in the event data |
111
- | `store_type` | string | zset | `string`/`list`/`set`/`zset`/`publish` |
112
- | `format_type` | string | plain | format type for _value_ (`plain`/`json`/`msgpack`) |
113
- | `key_expire` | int | -1 | If set, the key will be expired in specified seconds |
114
- | `flush_interval` | time | 1 | Time interval which events will be flushed to Redis |
109
+ | Key | Type | Default | Description |
110
+ | :---- | :----- | :----------------------- | :------------ |
111
+ | `key` | string | | Fixed _key_ used to store(publish) in Redis |
112
+ | `key_path` | string | | path to lookup for _key_ in the event data |
113
+ | `key_prefix` | string | | prefix of _key_ |
114
+ | `key_suffix` | string | | suffix of _key_ |
115
+ | `value_path` | string | (whole event data) | path to lookup for _value_ in the event data |
116
+ | `store_type` | string | zset | `string`/`list`/`set`/`zset`/`publish` |
117
+ | `format_type` | string | plain | format type for _value_ (`plain`/`json`/`msgpack`) |
118
+ | `key_expire` | int | -1 | If set, the key will be expired in specified seconds |
119
+ | `flush_interval` | time | 1 | Time interval which events will be flushed to Redis |
115
120
 
116
121
  Note: either `key` or `key_path` is required.
117
122
 
@@ -134,10 +139,11 @@ No more options than common options.
134
139
 
135
140
  ### `zset` storage specific options
136
141
 
137
- | Key | Type | Default | Description |
138
- | :---- | :----- | :----------------------- | :------------ |
139
- | `score_path` | string | (_time_ of log event) | path to lookup for _score_ in the event data |
140
- | `value_expire` | int | | value expiration in seconds |
142
+ | Key | Type | Default | Description |
143
+ | :---- | :----- | :----------------------- | :------------ |
144
+ | `score_path` | string | (_time_ of log event) | path to lookup for _score_ in the event data |
145
+ | `collision_policy` | string | (nil) | Only update elements that already exist (XX) or add a new element (NX) |
146
+ | `value_expire` | int | | value expiration in seconds |
141
147
 
142
148
  If `value_expire` is set, the plugin assumes that the _score_ in the **SortedSet** is
143
149
  based on *timestamp* and it deletes expired _members_ every after new event data arrives.
@@ -147,6 +153,17 @@ based on *timestamp* and it deletes expired _members_ every after new event data
147
153
  No more options than common options.
148
154
 
149
155
 
156
+ Contributors
157
+ ------------
158
+
159
+ moaikids
160
+ HANAI tohru
161
+ Mohit Khanna
162
+ yamada-shinji
163
+ Heitor de Souza
164
+ Hiroshi Hatake
165
+ Gabriel Bordeaux
166
+
150
167
  Copyright
151
168
  ---------
152
169
 
@@ -2,7 +2,7 @@
2
2
  Gem::Specification.new do |gem|
3
3
  gem.name = "fluent-plugin-redis-store"
4
4
  gem.email = "hanai@pokelabo.co.jp"
5
- gem.version = "0.1.2"
5
+ gem.version = "0.2.0"
6
6
  gem.authors = ["moaikids", "HANAI Tohru aka pokehanai"]
7
7
  gem.licenses = ["Apache License Version 2.0"]
8
8
  gem.summary = %q{Redis(zset/set/list/string/publish) output plugin for Fluentd}
@@ -16,6 +16,6 @@ Gem::Specification.new do |gem|
16
16
 
17
17
  gem.add_development_dependency "rake"
18
18
  gem.add_development_dependency "test-unit"
19
- gem.add_runtime_dependency "fluentd", "~> 0.12.0"
19
+ gem.add_runtime_dependency "fluentd", [">= 0.14.15", "< 2"]
20
20
  gem.add_runtime_dependency "redis"
21
21
  end
@@ -1,7 +1,13 @@
1
- module Fluent
2
- class RedisStoreOutput < BufferedOutput
1
+ require 'fluent/plugin/output'
2
+
3
+ module Fluent::Plugin
4
+ class RedisStoreOutput < Output
3
5
  Fluent::Plugin.register_output('redis_store', self)
4
6
 
7
+ helpers :compat_parameters
8
+
9
+ DEFAULT_BUFFER_TYPE = "memory"
10
+
5
11
  # redis connection
6
12
  config_param :host, :string, :default => '127.0.0.1'
7
13
  config_param :port, :integer, :default => 6379
@@ -11,27 +17,33 @@ module Fluent
11
17
  config_param :timeout, :float, :default => 5.0
12
18
 
13
19
  # redis command and parameters
14
- config_param :format_type, :string, :default => 'json'
15
- config_param :store_type, :string, :default => 'zset'
16
- config_param :key_prefix, :string, :default => ''
17
- config_param :key_suffix, :string, :default => ''
18
- config_param :key, :string, :default => nil
19
- config_param :key_path, :string, :default => nil
20
- config_param :score_path, :string, :default => nil
21
- config_param :value_path, :string, :default => ''
22
- config_param :key_expire, :integer, :default => -1
23
- config_param :value_expire, :integer, :default => -1
24
- config_param :value_length, :integer, :default => -1
25
- config_param :order, :string, :default => 'asc'
20
+ config_param :format_type, :string, :default => 'json'
21
+ config_param :store_type, :string, :default => 'zset'
22
+ config_param :key_prefix, :string, :default => ''
23
+ config_param :key_suffix, :string, :default => ''
24
+ config_param :key, :string, :default => nil
25
+ config_param :key_path, :string, :default => nil
26
+ config_param :score_path, :string, :default => nil
27
+ config_param :value_path, :string, :default => ''
28
+ config_param :key_expire, :integer, :default => -1
29
+ config_param :value_expire, :integer, :default => -1
30
+ config_param :value_length, :integer, :default => -1
31
+ config_param :order, :string, :default => 'asc'
32
+ config_param :collision_policy, :string, :default => nil
26
33
  config_set_default :flush_interval, 1
27
34
 
35
+ config_section :buffer do
36
+ config_set_default :@type, DEFAULT_BUFFER_TYPE
37
+ end
38
+
28
39
  def initialize
29
40
  super
30
- require 'redis'
41
+ require 'redis' unless defined?(Redis) == 'constant'
31
42
  require 'msgpack'
32
43
  end
33
44
 
34
45
  def configure(conf)
46
+ compat_parameters_convert(conf, :buffer)
35
47
  super
36
48
 
37
49
  if @key_path == nil and @key == nil
@@ -52,10 +64,19 @@ module Fluent
52
64
 
53
65
  def shutdown
54
66
  @redis.quit
67
+ super
55
68
  end
56
69
 
57
70
  def format(tag, time, record)
58
- [tag, time, record].to_msgpack
71
+ [tag, time.to_f, record].to_msgpack
72
+ end
73
+
74
+ def formatted_to_msgpack_binary?
75
+ true
76
+ end
77
+
78
+ def multi_workers_ready?
79
+ true
59
80
  end
60
81
 
61
82
  def write(chunk)
@@ -64,7 +85,7 @@ module Fluent
64
85
  begin
65
86
  MessagePack::Unpacker.new(io).each { |message|
66
87
  begin
67
- (tag, time, record) = message
88
+ (_, time, record) = message
68
89
  case @store_type
69
90
  when 'zset'
70
91
  operation_for_zset(record, time)
@@ -79,6 +100,10 @@ module Fluent
79
100
  end
80
101
  rescue NoMethodError => e
81
102
  puts e
103
+ rescue Encoding::UndefinedConversionError => e
104
+ log.error "Plugin error: " + e.to_s
105
+ log.error "Original record: " + record.to_s
106
+ puts e
82
107
  end
83
108
  }
84
109
  rescue EOFError
@@ -92,7 +117,15 @@ module Fluent
92
117
  key = get_key_from(record)
93
118
  value = get_value_from(record)
94
119
  score = get_score_from(record, time)
95
- @redis.zadd key, score, value
120
+ if @collision_policy
121
+ if @collision_policy == 'NX'
122
+ @redis.zadd(key, score, value, :nx => true)
123
+ elsif @collision_policy == 'XX'
124
+ @redis.zadd(key, score, value, :xx => true)
125
+ end
126
+ else
127
+ @redis.zadd(key, score, value)
128
+ end
96
129
 
97
130
  set_key_expire key
98
131
  if 0 < @value_expire
@@ -12,6 +12,8 @@ require 'test/unit'
12
12
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
13
  $LOAD_PATH.unshift(File.dirname(__FILE__))
14
14
  require 'fluent/test'
15
+ require 'fluent/test/driver/output'
16
+ require 'fluent/test/helpers'
15
17
  unless ENV.has_key?('VERBOSE')
16
18
  nulllogger = Object.new
17
19
  nulllogger.instance_eval {|obj|
@@ -25,4 +27,5 @@ end
25
27
  require 'fluent/plugin/out_redis_store'
26
28
 
27
29
  class Test::Unit::TestCase
30
+ include Fluent::Test::Helpers
28
31
  end
@@ -1,7 +1,5 @@
1
1
  require 'helpers'
2
2
 
3
- require 'redis'
4
-
5
3
  $channel = nil
6
4
  $message = nil
7
5
 
@@ -65,7 +63,7 @@ class RedisStoreOutputTest < Test::Unit::TestCase
65
63
  end
66
64
 
67
65
  def create_driver(conf)
68
- Fluent::Test::BufferedOutputTestDriver.new(Fluent::RedisStoreOutput).configure(conf)
66
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::RedisStoreOutput).configure(conf)
69
67
  end
70
68
 
71
69
  def test_configure_defaults
@@ -74,24 +72,25 @@ class RedisStoreOutputTest < Test::Unit::TestCase
74
72
  score_path b
75
73
  ]
76
74
  d = create_driver(config)
77
- assert_equal "127.0.0.1", d.instance.host
78
- assert_equal 6379, d.instance.port
79
- assert_equal nil, d.instance.path
80
- assert_equal nil, d.instance.password
81
- assert_equal 0, d.instance.db
82
- assert_equal 5.0, d.instance.timeout
83
- assert_equal 'json', d.instance.format_type
84
- assert_equal '', d.instance.key_prefix
85
- assert_equal '', d.instance.key_suffix
86
- assert_equal 'zset', d.instance.store_type
87
- assert_equal 'a', d.instance.key_path
88
- assert_equal nil, d.instance.key
89
- assert_equal 'b', d.instance.score_path
90
- assert_equal '', d.instance.value_path
91
- assert_equal -1, d.instance.key_expire
92
- assert_equal -1, d.instance.value_expire
93
- assert_equal -1, d.instance.value_length
94
- assert_equal 'asc', d.instance.order
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)
95
94
  end
96
95
 
97
96
  def test_configure_host_port_db
@@ -134,16 +133,17 @@ class RedisStoreOutputTest < Test::Unit::TestCase
134
133
  # def test_write
135
134
  # d = create_driver(CONFIG1)
136
135
  #
137
- # time = Time.parse("2011-01-02 13:14:15 UTC").to_i
138
- # d.emit({ "foo" => "bar" }, time)
139
- # d.run
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
140
  #
141
141
  # assert_equal "test", $channel
142
142
  # assert_equal(%Q[{"foo":"bar","time":#{time}}], $message)
143
143
  # end
144
144
 
145
145
  def get_time
146
- Time.parse("2011-01-02 13:14:15 UTC").to_i
146
+ event_time("2011-01-02 13:14:15 UTC")
147
147
  end
148
148
 
149
149
  # it should return whole message
@@ -159,8 +159,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
159
159
  'stat' => { 'attack' => 7 }
160
160
  }
161
161
  $ttl = nil
162
- d.emit(message, get_time)
163
- d.run
162
+ d.run(default_tag: 'test') do
163
+ d.feed(get_time, message)
164
+ end
164
165
 
165
166
  assert_equal "george", $key
166
167
  assert_equal message, $message
@@ -181,8 +182,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
181
182
  'stat' => { 'attack' => 7 }
182
183
  }
183
184
  $ttl = nil
184
- d.emit(message, get_time)
185
- d.run
185
+ d.run(default_tag: 'test') do
186
+ d.feed(get_time, message)
187
+ end
186
188
 
187
189
  assert_equal "george", $key
188
190
  assert_equal 7, $message
@@ -201,8 +203,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
201
203
  'stat' => { 'attack' => 7 }
202
204
  }
203
205
  $ttl = nil
204
- d.emit(message, get_time)
205
- d.run
206
+ d.run(default_tag: 'test') do
207
+ d.feed(get_time, message)
208
+ end
206
209
 
207
210
  assert_equal "george", $key
208
211
  assert_equal message.to_json, $message
@@ -220,8 +223,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
220
223
  'stat' => { 'attack' => 7 }
221
224
  }
222
225
  $ttl = nil
223
- d.emit(message, get_time)
224
- d.run
226
+ d.run(default_tag: 'test') do
227
+ d.feed(get_time, message)
228
+ end
225
229
 
226
230
  assert_equal "george", $key
227
231
  assert_equal message.to_msgpack, $message
@@ -238,8 +242,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
238
242
  'user' => 'george',
239
243
  'stat' => { 'attack' => 7 }
240
244
  }
241
- d.emit(message, get_time)
242
- d.run
245
+ d.run(default_tag: 'test') do
246
+ d.feed(get_time, message)
247
+ end
243
248
 
244
249
  assert_equal :rpush, $command
245
250
  assert_equal "george", $key
@@ -258,8 +263,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
258
263
  'user' => 'george',
259
264
  'stat' => { 'attack' => 7 }
260
265
  }
261
- d.emit(message, get_time)
262
- d.run
266
+ d.run(default_tag: 'test') do
267
+ d.feed(get_time, message)
268
+ end
263
269
 
264
270
  assert_equal :lpush, $command
265
271
  assert_equal "george", $key
@@ -278,8 +284,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
278
284
  'user' => 'george',
279
285
  'stat' => { 'attack' => 7 }
280
286
  }
281
- d.emit(message, get_time)
282
- d.run
287
+ d.run(default_tag: 'test') do
288
+ d.feed(get_time, message)
289
+ end
283
290
 
284
291
  assert_equal :sadd, $command
285
292
  assert_equal "george", $key
@@ -300,8 +307,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
300
307
  'stat' => { 'attack' => 7 },
301
308
  'result' => 81
302
309
  }
303
- d.emit(message, get_time)
304
- d.run
310
+ d.run(default_tag: 'test') do
311
+ d.feed(get_time, message)
312
+ end
305
313
 
306
314
  assert_equal :zadd, $command
307
315
  assert_equal "george", $key
@@ -322,8 +330,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
322
330
  'stat' => { 'attack' => 7 },
323
331
  'result' => 81
324
332
  }
325
- d.emit(message, get_time)
326
- d.run
333
+ d.run(default_tag: 'test') do
334
+ d.feed(get_time, message)
335
+ end
327
336
 
328
337
  assert_equal :zadd, $command
329
338
  assert_equal "george", $key
@@ -342,8 +351,9 @@ class RedisStoreOutputTest < Test::Unit::TestCase
342
351
  message = {
343
352
  'user' => 'george'
344
353
  }
345
- d.emit(message, get_time)
346
- d.run
354
+ d.run(default_tag: 'test') do
355
+ d.feed(get_time, message)
356
+ end
347
357
 
348
358
  assert_equal :publish, $command
349
359
  assert_equal "george", $channel
@@ -359,9 +369,30 @@ class RedisStoreOutputTest < Test::Unit::TestCase
359
369
 
360
370
  d = create_driver(config)
361
371
  message = { 'user' => 'george' }
362
- d.emit(message, get_time)
363
- assert_raise(Fluent::ConfigError) do
364
- d.run
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)
365
395
  end
396
+ retval
366
397
  end
367
398
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-redis-store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - moaikids
@@ -43,16 +43,22 @@ dependencies:
43
43
  name: fluentd
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 0.14.15
49
+ - - "<"
47
50
  - !ruby/object:Gem::Version
48
- version: 0.12.0
51
+ version: '2'
49
52
  type: :runtime
50
53
  prerelease: false
51
54
  version_requirements: !ruby/object:Gem::Requirement
52
55
  requirements:
53
- - - "~>"
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 0.14.15
59
+ - - "<"
54
60
  - !ruby/object:Gem::Version
55
- version: 0.12.0
61
+ version: '2'
56
62
  - !ruby/object:Gem::Dependency
57
63
  name: redis
58
64
  requirement: !ruby/object:Gem::Requirement
@@ -73,6 +79,7 @@ executables: []
73
79
  extensions: []
74
80
  extra_rdoc_files: []
75
81
  files:
82
+ - ".gitignore"
76
83
  - AUTHORS
77
84
  - Gemfile
78
85
  - README.md