fluent-plugin-redis-store 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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