logster 1.1.1 → 1.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: 10338f67f3b0de4bc895fab64a21addb21987b02
4
- data.tar.gz: 3d4b900cba51c32ccbf7aad9b15843c3f2cb5a97
3
+ metadata.gz: 97266a5b02f788e8537daaf28e0adff771a3bf6b
4
+ data.tar.gz: f43b618a847f9e98f54ecb9e469a29e0354a6947
5
5
  SHA512:
6
- metadata.gz: 6ff41f127c57daf3404518e1311d980887b25366f20b7330d73b8b0814e8d5ca9ceed7ad5df4d33cc270806d9eb7a1c3f81787ba805566102dfd06eda42a9186
7
- data.tar.gz: 9f62de9005f735c84c121ac9a7dc09259afc42dc8c032a162b7d0770bb96b62f8045a0e679febbc9d8a74af8fb2488fa27e08cb077a3aea1bce185a252929075
6
+ metadata.gz: 22657415d4f4173ed2a1850e43a146d81db3c53e33d6009f99069fbe81671fb65d88809fc79a963b06744a17e288364706d1ef63127bcacb3076cc9be789e28d
7
+ data.tar.gz: 7e57a8c7862c3375948e2a097b89c1c1d3f023e33a32c928196371e3c7ef4c02b90df6828790d12fafb49c21acccf5b7810abe32220f4030e012ed463a271081
data/README.md CHANGED
@@ -97,6 +97,10 @@ Logster UI is built using [Ember.js](http://emberjs.com/)
97
97
 
98
98
  # CHANGELOG
99
99
 
100
+ - 2015-03-18: Version 1.2.0
101
+ - Fix: Move Redis configuration into RedisStore.
102
+ - Feature: Allow `RedisStore#redis_prefix` to either be a String or a Proc.
103
+
100
104
  - 2015-02-11: Version 1.1.1
101
105
  - Feature: Error rate can now be tracked in one minute and one hour buckets.
102
106
 
@@ -1,7 +1,7 @@
1
1
  module Logster
2
2
  class Configuration
3
3
  attr_accessor :current_context, :allow_grouping, :environments,
4
- :application_version, :web_title, :redis_prefix, :redis_raw_connection
4
+ :application_version, :web_title
5
5
 
6
6
  attr_writer :subdirectory
7
7
 
@@ -4,20 +4,15 @@ require 'logster/base_store'
4
4
  module Logster
5
5
  class RedisRateLimiter
6
6
  BUCKETS = 6
7
+ PREFIX = "__LOGSTER__RATE_LIMIT".freeze
7
8
 
8
- attr_reader :key, :callback_key
9
-
10
- def initialize(redis, severities, limit, duration, callback = nil)
11
- @redis = use_raw_connection? ? Logster.config.redis_raw_connection : redis
9
+ def initialize(redis, severities, limit, duration, redis_prefix = nil, callback = nil)
12
10
  @severities = severities
13
11
  @limit = limit
14
12
  @duration = duration
15
13
  @callback = callback
16
-
17
- # "_LOGSTER_RATE_LIMIT:012:20:30"
18
- # Triggers callback when log levels of :debug, :info and :warn occurs 20 times within 30 secs
19
- @key = "#{key_prefix}#{@severities.join("")}:#{@limit}:#{@duration}"
20
- @callback_key = "#{@key}:callback_triggered"
14
+ @redis_prefix = redis_prefix
15
+ @redis = redis
21
16
  @bucket_range = @duration / BUCKETS
22
17
  end
23
18
 
@@ -25,7 +20,7 @@ module Logster
25
20
  return unless @severities.include?(severity)
26
21
  time = Time.now.to_i
27
22
  num = bucket_number(time)
28
- redis_key = "#{@key}:#{num}"
23
+ redis_key = "#{key}:#{num}"
29
24
 
30
25
  current_rate = @redis.eval <<-LUA
31
26
  local bucket_number = #{num}
@@ -48,20 +43,32 @@ module Logster
48
43
  return (retrieve_rate() + bucket_count)
49
44
  LUA
50
45
 
51
- if !@redis.get(@callback_key) && (current_rate >= @limit)
46
+ if !@redis.get(callback_key) && (current_rate >= @limit)
52
47
  @callback.call(current_rate) if @callback
53
- @redis.set(@callback_key, 1)
48
+ @redis.set(callback_key, 1)
54
49
  end
55
50
 
56
51
  current_rate
57
52
  end
58
53
 
54
+ def key
55
+ # "_LOGSTER_RATE_LIMIT:012:20:30"
56
+ # Triggers callback when log levels of :debug, :info and :warn occurs 20 times within 30 secs
57
+ "#{key_prefix}:#{@severities.join("")}:#{@limit}:#{@duration}"
58
+ end
59
+
60
+ def callback_key
61
+ "#{@key}:callback_triggered"
62
+ end
63
+
59
64
  private
60
65
 
61
66
  def key_prefix
62
- prefix = "__LOGSTER__RATE_LIMIT:".freeze
63
- prefix = "#{Logster.config.redis_prefix}:#{prefix}" if use_raw_connection?
64
- prefix
67
+ if @redis_prefix
68
+ "#{@redis_prefix.call}:#{PREFIX}"
69
+ else
70
+ PREFIX
71
+ end
65
72
  end
66
73
 
67
74
  def mget_keys(bucket_num)
@@ -78,15 +85,12 @@ module Logster
78
85
  def bucket_expiry(time)
79
86
  @duration - ((time % @duration) % @bucket_range)
80
87
  end
81
-
82
- def use_raw_connection?
83
- Logster.config.redis_prefix && Logster.config.redis_raw_connection
84
- end
85
88
  end
86
89
 
87
90
  class RedisStore < BaseStore
88
91
 
89
- attr_accessor :redis, :max_backlog
92
+ attr_accessor :redis, :max_backlog, :redis_raw_connection
93
+ attr_writer :redis_prefix
90
94
 
91
95
  def initialize(redis = nil)
92
96
  super()
@@ -269,10 +273,16 @@ module Logster
269
273
  register_rate_limit(severities, limit, 3600, block)
270
274
  end
271
275
 
276
+ def redis_prefix
277
+ return 'default'.freeze if !@redis_prefix
278
+ @prefix_is_proc ||= @redis_prefix.respond_to?(:call)
279
+ @prefix_is_proc ? @redis_prefix.call : @redis_prefix
280
+ end
281
+
272
282
  protected
273
283
 
274
284
  def rate_limits
275
- @rate_limits ||= []
285
+ @rate_limits ||= {}
276
286
  end
277
287
 
278
288
  def clear_solved(count = nil)
@@ -395,7 +405,9 @@ module Logster
395
405
  end
396
406
 
397
407
  def check_rate_limits(severity)
398
- rate_limits.each { |rate_limit| rate_limit.check(severity) }
408
+ rate_limits_to_check = rate_limits[self.redis_prefix]
409
+ return if !rate_limits_to_check
410
+ rate_limits_to_check.each { |rate_limit| rate_limit.check(severity) }
399
411
  end
400
412
 
401
413
  def solved_key
@@ -422,8 +434,14 @@ module Logster
422
434
 
423
435
  def register_rate_limit(severities, limit, duration, callback)
424
436
  severities = [severities] unless severities.is_a?(Array)
425
- rate_limiter = RedisRateLimiter.new(@redis, severities, limit, duration, callback)
426
- rate_limits << rate_limiter
437
+ redis = (@redis_raw_connection && @redis_prefix) ? @redis_raw_connection : @redis
438
+
439
+ rate_limiter = RedisRateLimiter.new(
440
+ redis, severities, limit, duration, Proc.new { redis_prefix }, callback
441
+ )
442
+
443
+ rate_limits[self.redis_prefix] ||= []
444
+ rate_limits[self.redis_prefix] << rate_limiter
427
445
  rate_limiter
428
446
  end
429
447
  end
@@ -1,3 +1,3 @@
1
1
  module Logster
2
- VERSION = "1.1.1"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -17,7 +17,7 @@ class TestRedisRateLimiter < Minitest::Test
17
17
  called = 0
18
18
 
19
19
  @rate_limiter = Logster::RedisRateLimiter.new(
20
- @redis, [Logger::WARN], 8, 60, Proc.new { called += 1 }
20
+ @redis, [Logger::WARN], 8, 60, nil, Proc.new { called += 1 }
21
21
  )
22
22
 
23
23
  assert_equal(1, @rate_limiter.check(Logger::WARN))
@@ -82,7 +82,7 @@ class TestRedisRateLimiter < Minitest::Test
82
82
  called = 0
83
83
 
84
84
  @rate_limiter = Logster::RedisRateLimiter.new(
85
- @redis, [Logger::WARN, Logger::ERROR], 4, 60, Proc.new { called += 1 }
85
+ @redis, [Logger::WARN, Logger::ERROR], 4, 60, nil, Proc.new { called += 1 }
86
86
  )
87
87
 
88
88
  assert_equal(1, @rate_limiter.check(Logger::WARN))
@@ -138,14 +138,19 @@ class TestRedisRateLimiter < Minitest::Test
138
138
  def test_raw_connection
139
139
  time = Time.new(2015, 1, 1, 1, 1)
140
140
  Timecop.freeze(time)
141
- Logster.config.redis_prefix = "lobster"
142
- Logster.config.redis_raw_connection = @redis
143
-
144
- @rate_limiter = Logster::RedisRateLimiter.new(nil, [Logger::WARN], 1, 60)
141
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60, Proc.new { "lobster" })
145
142
 
146
143
  assert_equal(1, @rate_limiter.check(Logger::WARN))
147
- assert_includes(key, "lobster")
148
144
  assert_redis_key(60, 0)
145
+
146
+ array = ['lobster1', 'lobster2']
147
+
148
+ @rate_limiter = Logster::RedisRateLimiter.new(
149
+ @redis, [Logger::WARN], 1, 60, Proc.new { array.delete_at(0) }
150
+ )
151
+
152
+ assert_includes(key, "lobster1")
153
+ assert_includes(key, "lobster2")
149
154
  end
150
155
 
151
156
  private
@@ -172,7 +177,7 @@ class TestRedisRateLimiter < Minitest::Test
172
177
 
173
178
  def assert_redis_key(expected_ttl, expected_bucket_number)
174
179
  redis_key = "#{key}:#{expected_bucket_number}"
175
- assert(@redis.get(redis_key))
180
+ assert(@redis.get(redis_key), "the right bucket should be created")
176
181
  assert_equal(expected_ttl, @redis.ttl(redis_key))
177
182
  end
178
183
  end
@@ -326,19 +326,61 @@ class TestRedisStore < Minitest::Test
326
326
  assert_equal(orig, env)
327
327
  end
328
328
 
329
- %w{minute hour}.each do |duration|
330
- define_method "test_register_rate_limit_per_#{duration}" do
331
- called = false
329
+ def test_rate_limits
330
+ %w{minute hour}.each do |duration|
331
+ begin
332
+ called = false
333
+
334
+ assert_instance_of(
335
+ Logster::RedisRateLimiter,
336
+ @store.public_send("register_rate_limit_per_#{duration}", Logger::WARN, 0) do
337
+ called = true
338
+ end
339
+ )
340
+
341
+ @store.report(Logger::WARN, "test", "test")
342
+ assert called
343
+ ensure
344
+ reset_redis
345
+ end
346
+ end
347
+ end
348
+
349
+ def test_rate_limits_with_prefix
350
+ begin
351
+ time = Time.now
352
+ Timecop.freeze(time)
353
+ current_namespace = 'first'
354
+ @store.redis_prefix = Proc.new { current_namespace }
355
+
356
+ called_first = 0
357
+ called_second = 0
332
358
 
333
- assert_instance_of(
334
- Logster::RedisRateLimiter,
335
- @store.public_send("register_rate_limit_per_#{duration}", Logger::WARN, 0) do
336
- called = true
337
- end
338
- )
359
+ @store.register_rate_limit_per_minute(Logger::WARN, 0) { called_first += 1 }
360
+ @store.report(Logger::WARN, "test", "test")
361
+ assert_equal(1, called_first)
339
362
 
363
+ current_namespace = 'second'
364
+ @store.register_rate_limit_per_minute(Logger::WARN, 0) { called_second += 1 }
340
365
  @store.report(Logger::WARN, "test", "test")
341
- assert called
366
+ assert_equal(1, called_first)
367
+ assert_equal(1, called_second)
368
+
369
+ Timecop.freeze(time + 10) do
370
+ current_namespace = 'first'
371
+ @store.report(Logger::WARN, "test", "test")
372
+
373
+ assert_equal(2, called_first)
374
+ assert_equal(1, called_second)
375
+ end
376
+ ensure
377
+ reset_redis
342
378
  end
343
379
  end
380
+
381
+ private
382
+
383
+ def reset_redis
384
+ @store.redis.flushall
385
+ end
344
386
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logster
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - UI for viewing logs in Rack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-22 00:00:00.000000000 Z
11
+ date: 2016-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler