logster 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -19
  3. data/.rubocop.yml +1 -1
  4. data/.travis.yml +16 -16
  5. data/CHANGELOG.md +169 -166
  6. data/Gemfile +4 -4
  7. data/Guardfile +8 -8
  8. data/LICENSE.txt +22 -22
  9. data/README.md +99 -99
  10. data/Rakefile +21 -21
  11. data/assets/fonts/FontAwesome.otf +0 -0
  12. data/assets/fonts/fontawesome-webfont.eot +0 -0
  13. data/assets/fonts/fontawesome-webfont.svg +639 -639
  14. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  15. data/assets/fonts/fontawesome-webfont.woff +0 -0
  16. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  17. data/assets/images/Icon-144_rounded.png +0 -0
  18. data/assets/images/Icon-144_square.png +0 -0
  19. data/assets/images/icon_144x144.png +0 -0
  20. data/assets/images/icon_64x64.png +0 -0
  21. data/assets/javascript/client-app.js +100 -100
  22. data/assets/stylesheets/client-app.css +0 -0
  23. data/build_client_app.sh +0 -0
  24. data/client-app/.editorconfig +20 -20
  25. data/client-app/.ember-cli +9 -9
  26. data/client-app/.eslintignore +19 -19
  27. data/client-app/.eslintrc.js +46 -46
  28. data/client-app/.gitignore +23 -23
  29. data/client-app/.travis.yml +27 -27
  30. data/client-app/.watchmanconfig +3 -3
  31. data/client-app/README.md +57 -57
  32. data/client-app/app/app.js +14 -14
  33. data/client-app/app/components/actions-menu.js +37 -37
  34. data/client-app/app/components/env-tab.js +44 -44
  35. data/client-app/app/components/message-info.js +65 -65
  36. data/client-app/app/components/message-row.js +45 -45
  37. data/client-app/app/components/panel-resizer.js +74 -74
  38. data/client-app/app/components/tab-contents.js +27 -27
  39. data/client-app/app/components/tab-link.js +5 -5
  40. data/client-app/app/components/tabbed-section.js +32 -32
  41. data/client-app/app/components/time-formatter.js +25 -25
  42. data/client-app/app/components/update-time.js +21 -21
  43. data/client-app/app/controllers/index.js +105 -105
  44. data/client-app/app/controllers/show.js +13 -13
  45. data/client-app/app/index.html +29 -29
  46. data/client-app/app/initializers/app-init.js +72 -72
  47. data/client-app/app/lib/preload.js +14 -14
  48. data/client-app/app/lib/utilities.js +140 -140
  49. data/client-app/app/models/message-collection.js +178 -178
  50. data/client-app/app/models/message.js +100 -100
  51. data/client-app/app/resolver.js +3 -3
  52. data/client-app/app/router.js +14 -14
  53. data/client-app/app/routes/index.js +57 -57
  54. data/client-app/app/routes/show.js +14 -14
  55. data/client-app/app/styles/app.css +521 -521
  56. data/client-app/app/templates/application.hbs +2 -2
  57. data/client-app/app/templates/components/actions-menu.hbs +12 -12
  58. data/client-app/app/templates/components/env-tab.hbs +10 -10
  59. data/client-app/app/templates/components/message-info.hbs +41 -41
  60. data/client-app/app/templates/components/message-row.hbs +15 -15
  61. data/client-app/app/templates/components/panel-resizer.hbs +3 -3
  62. data/client-app/app/templates/components/tabbed-section.hbs +10 -10
  63. data/client-app/app/templates/components/time-formatter.hbs +1 -1
  64. data/client-app/app/templates/index.hbs +58 -58
  65. data/client-app/app/templates/show.hbs +7 -7
  66. data/client-app/config/environment.js +51 -51
  67. data/client-app/config/optional-features.json +3 -3
  68. data/client-app/config/targets.js +18 -18
  69. data/client-app/ember-cli-build.js +29 -29
  70. data/client-app/package-lock.json +11365 -11365
  71. data/client-app/package.json +56 -56
  72. data/client-app/testem.js +25 -25
  73. data/client-app/tests/index.html +34 -34
  74. data/client-app/tests/integration/components/actions-menu-test.js +26 -26
  75. data/client-app/tests/integration/components/env-tab-test.js +73 -73
  76. data/client-app/tests/integration/components/message-info-test.js +26 -26
  77. data/client-app/tests/integration/components/message-row-test.js +26 -26
  78. data/client-app/tests/integration/components/panel-resizer-test.js +26 -26
  79. data/client-app/tests/integration/components/tab-contents-test.js +26 -26
  80. data/client-app/tests/integration/components/tab-link-test.js +26 -26
  81. data/client-app/tests/integration/components/tabbed-section-test.js +26 -26
  82. data/client-app/tests/integration/components/time-formatter-test.js +26 -26
  83. data/client-app/tests/integration/components/update-time-test.js +26 -26
  84. data/client-app/tests/test-helper.js +8 -8
  85. data/client-app/tests/unit/controllers/index-test.js +12 -12
  86. data/client-app/tests/unit/controllers/show-test.js +12 -12
  87. data/client-app/tests/unit/initializers/app-init-test.js +31 -31
  88. data/client-app/tests/unit/routes/index-test.js +11 -11
  89. data/client-app/tests/unit/routes/show-test.js +11 -11
  90. data/lib/examples/sidekiq_logster_reporter.rb +21 -21
  91. data/lib/logster.rb +54 -54
  92. data/lib/logster/base_store.rb +141 -141
  93. data/lib/logster/configuration.rb +25 -25
  94. data/lib/logster/defer_logger.rb +14 -14
  95. data/lib/logster/ignore_pattern.rb +65 -65
  96. data/lib/logster/logger.rb +113 -113
  97. data/lib/logster/message.rb +212 -212
  98. data/lib/logster/middleware/debug_exceptions.rb +26 -26
  99. data/lib/logster/middleware/reporter.rb +55 -55
  100. data/lib/logster/middleware/viewer.rb +221 -221
  101. data/lib/logster/rails/railtie.rb +63 -63
  102. data/lib/logster/redis_store.rb +566 -566
  103. data/lib/logster/scheduler.rb +54 -40
  104. data/lib/logster/version.rb +3 -3
  105. data/lib/logster/web.rb +14 -14
  106. data/logster.gemspec +35 -35
  107. data/test/examples/test_sidekiq_reporter_example.rb +46 -46
  108. data/test/fake_data/Gemfile +4 -4
  109. data/test/fake_data/generate.rb +10 -10
  110. data/test/logster/middleware/test_reporter.rb +19 -19
  111. data/test/logster/middleware/test_viewer.rb +96 -96
  112. data/test/logster/test_base_store.rb +147 -147
  113. data/test/logster/test_defer_logger.rb +34 -34
  114. data/test/logster/test_ignore_pattern.rb +41 -41
  115. data/test/logster/test_logger.rb +86 -86
  116. data/test/logster/test_message.rb +119 -119
  117. data/test/logster/test_redis_rate_limiter.rb +230 -230
  118. data/test/logster/test_redis_store.rb +720 -720
  119. data/test/test_helper.rb +38 -38
  120. data/vendor/assets/javascripts/logster.js.erb +39 -39
  121. metadata +2 -2
@@ -1,119 +1,119 @@
1
- require_relative '../test_helper'
2
- require 'logster/message'
3
-
4
- class TestMessage < MiniTest::Test
5
-
6
- def test_merge_similar
7
- msg1 = Logster::Message.new(0, '', 'test', 10)
8
- msg1.populate_from_env(a: "1", b: "2")
9
-
10
- msg2 = Logster::Message.new(0, '', 'test', 20)
11
- msg2.populate_from_env(a: "2", c: "3")
12
-
13
- assert_equal(msg2.grouping_key, msg1.grouping_key)
14
-
15
- msg1.merge_similar_message(msg2)
16
-
17
- assert_equal(20, msg1.timestamp)
18
- assert_equal(10, msg1.first_timestamp)
19
-
20
- assert Array === msg1.env
21
- assert_equal(msg1.env.size, 2)
22
- assert({ a: "1", b: "2" } <= msg1.env[0])
23
- assert({ "a" => "2", "c" => "3" } <= msg1.env[1])
24
- end
25
-
26
- def test_merge_messages_both_with_array_envs
27
- msg1 = Logster::Message.new(0, '', 'test', 10)
28
- msg1.env = [{ a: "aa", b: "bb" }, { c: "cc", d: "dd" }]
29
-
30
- msg2 = Logster::Message.new(0, '', 'test', 20)
31
- msg2.env = [{ e: "ee", f: "ff" }, { g: "gg", h: "hh" }]
32
-
33
- msg1.merge_similar_message(msg2)
34
-
35
- # new env should be an array, but it should never have
36
- # another array of envs within itself (hence flatten(1))
37
- assert_equal(msg1.env.size, 4)
38
- assert_equal(msg1.env.map(&:keys).flatten(1).map(&:to_s), %w{a b c d e f g h})
39
- assert_equal(msg1.env.map(&:values).flatten(1).map(&:to_s), %w{aa bb cc dd ee ff gg hh})
40
- end
41
-
42
- def test_merge_messages_one_with_array_envs
43
- msg1 = Logster::Message.new(0, '', 'test', 10)
44
- msg1.env = [{ a: "aa", b: "bb" }, { c: "cc", d: "dd" }]
45
-
46
- msg2 = Logster::Message.new(0, '', 'test', 20)
47
- msg2.env = { e: "ee", f: "ff" }
48
-
49
- msg1.merge_similar_message(msg2)
50
-
51
- assert_equal(msg1.env.size, 3)
52
- assert_equal(msg1.env.map(&:keys).flatten(1).map(&:to_s), %w{a b c d e f})
53
- assert_equal(msg1.env.map(&:values).flatten(1).map(&:to_s), %w{aa bb cc dd ee ff})
54
- end
55
-
56
- def test_adds_application_version
57
- Logster.config.application_version = "abc"
58
- msg = Logster::Message.new(0, '', 'test', 10)
59
- msg.populate_from_env({})
60
-
61
- assert_equal("abc", msg.env["application_version"])
62
-
63
- ensure
64
- Logster.config.application_version = nil
65
- end
66
-
67
- def test_merging_sums_count_for_both_messages
68
- msg1 = Logster::Message.new(0, '', 'test', 10, count: 15)
69
- msg2 = Logster::Message.new(0, '', 'test', 20, count: 13)
70
- msg2.env = {}
71
-
72
- assert_equal(msg1.grouping_key, msg2.grouping_key)
73
-
74
- save_env = msg1.merge_similar_message(msg2)
75
- assert(save_env)
76
- assert_equal(msg1.count, 15 + 13)
77
- end
78
-
79
- def test_populate_from_env_works_on_array
80
- msg = Logster::Message.new(0, '', 'test', 10)
81
- hash = { "custom_key" => "key" }
82
- msg.populate_from_env([hash])
83
-
84
- assert Array === msg.env
85
- assert_equal(msg.env.size, 1)
86
- assert hash <= msg.env[0]
87
- end
88
-
89
- def test_ensure_env_samples_dont_exceed_50
90
- msg1 = Logster::Message.new(0, '', 'test', 10, count: 50)
91
- msg1.env = [{ a: 1 }]
92
- msg2 = Logster::Message.new(0, '', 'test', 20, count: 13)
93
- msg2.env = { b: 2 }
94
-
95
- assert_equal(msg1.grouping_key, msg2.grouping_key)
96
-
97
- save_env = msg1.merge_similar_message(msg2)
98
-
99
- refute(save_env)
100
- assert_equal(63, msg1.count) # update count
101
- assert_equal([{ a: 1 }], msg1.env) # but don't merge msg2's env into msg1's
102
- end
103
-
104
- def test_message_to_h_respects_params
105
- msg = Logster::Message.new(0, "", "test")
106
- test_hash = { test_key: "this is a test" }
107
- msg.env = test_hash
108
- assert_equal(test_hash, msg.to_h[:env])
109
- assert_nil(msg.to_h(exclude_env: true)[:env])
110
- end
111
-
112
- def test_message_to_json_respects_params
113
- msg = Logster::Message.new(0, "", "test")
114
- test_hash = { test_key: "this is a test" }
115
- msg.env = test_hash
116
- assert_includes(msg.to_json, test_hash.to_json)
117
- refute_includes(msg.to_json(exclude_env: true), test_hash.to_json)
118
- end
119
- end
1
+ require_relative '../test_helper'
2
+ require 'logster/message'
3
+
4
+ class TestMessage < MiniTest::Test
5
+
6
+ def test_merge_similar
7
+ msg1 = Logster::Message.new(0, '', 'test', 10)
8
+ msg1.populate_from_env(a: "1", b: "2")
9
+
10
+ msg2 = Logster::Message.new(0, '', 'test', 20)
11
+ msg2.populate_from_env(a: "2", c: "3")
12
+
13
+ assert_equal(msg2.grouping_key, msg1.grouping_key)
14
+
15
+ msg1.merge_similar_message(msg2)
16
+
17
+ assert_equal(20, msg1.timestamp)
18
+ assert_equal(10, msg1.first_timestamp)
19
+
20
+ assert Array === msg1.env
21
+ assert_equal(msg1.env.size, 2)
22
+ assert({ a: "1", b: "2" } <= msg1.env[0])
23
+ assert({ "a" => "2", "c" => "3" } <= msg1.env[1])
24
+ end
25
+
26
+ def test_merge_messages_both_with_array_envs
27
+ msg1 = Logster::Message.new(0, '', 'test', 10)
28
+ msg1.env = [{ a: "aa", b: "bb" }, { c: "cc", d: "dd" }]
29
+
30
+ msg2 = Logster::Message.new(0, '', 'test', 20)
31
+ msg2.env = [{ e: "ee", f: "ff" }, { g: "gg", h: "hh" }]
32
+
33
+ msg1.merge_similar_message(msg2)
34
+
35
+ # new env should be an array, but it should never have
36
+ # another array of envs within itself (hence flatten(1))
37
+ assert_equal(msg1.env.size, 4)
38
+ assert_equal(msg1.env.map(&:keys).flatten(1).map(&:to_s), %w{a b c d e f g h})
39
+ assert_equal(msg1.env.map(&:values).flatten(1).map(&:to_s), %w{aa bb cc dd ee ff gg hh})
40
+ end
41
+
42
+ def test_merge_messages_one_with_array_envs
43
+ msg1 = Logster::Message.new(0, '', 'test', 10)
44
+ msg1.env = [{ a: "aa", b: "bb" }, { c: "cc", d: "dd" }]
45
+
46
+ msg2 = Logster::Message.new(0, '', 'test', 20)
47
+ msg2.env = { e: "ee", f: "ff" }
48
+
49
+ msg1.merge_similar_message(msg2)
50
+
51
+ assert_equal(msg1.env.size, 3)
52
+ assert_equal(msg1.env.map(&:keys).flatten(1).map(&:to_s), %w{a b c d e f})
53
+ assert_equal(msg1.env.map(&:values).flatten(1).map(&:to_s), %w{aa bb cc dd ee ff})
54
+ end
55
+
56
+ def test_adds_application_version
57
+ Logster.config.application_version = "abc"
58
+ msg = Logster::Message.new(0, '', 'test', 10)
59
+ msg.populate_from_env({})
60
+
61
+ assert_equal("abc", msg.env["application_version"])
62
+
63
+ ensure
64
+ Logster.config.application_version = nil
65
+ end
66
+
67
+ def test_merging_sums_count_for_both_messages
68
+ msg1 = Logster::Message.new(0, '', 'test', 10, count: 15)
69
+ msg2 = Logster::Message.new(0, '', 'test', 20, count: 13)
70
+ msg2.env = {}
71
+
72
+ assert_equal(msg1.grouping_key, msg2.grouping_key)
73
+
74
+ save_env = msg1.merge_similar_message(msg2)
75
+ assert(save_env)
76
+ assert_equal(msg1.count, 15 + 13)
77
+ end
78
+
79
+ def test_populate_from_env_works_on_array
80
+ msg = Logster::Message.new(0, '', 'test', 10)
81
+ hash = { "custom_key" => "key" }
82
+ msg.populate_from_env([hash])
83
+
84
+ assert Array === msg.env
85
+ assert_equal(msg.env.size, 1)
86
+ assert hash <= msg.env[0]
87
+ end
88
+
89
+ def test_ensure_env_samples_dont_exceed_50
90
+ msg1 = Logster::Message.new(0, '', 'test', 10, count: 50)
91
+ msg1.env = [{ a: 1 }]
92
+ msg2 = Logster::Message.new(0, '', 'test', 20, count: 13)
93
+ msg2.env = { b: 2 }
94
+
95
+ assert_equal(msg1.grouping_key, msg2.grouping_key)
96
+
97
+ save_env = msg1.merge_similar_message(msg2)
98
+
99
+ refute(save_env)
100
+ assert_equal(63, msg1.count) # update count
101
+ assert_equal([{ a: 1 }], msg1.env) # but don't merge msg2's env into msg1's
102
+ end
103
+
104
+ def test_message_to_h_respects_params
105
+ msg = Logster::Message.new(0, "", "test")
106
+ test_hash = { test_key: "this is a test" }
107
+ msg.env = test_hash
108
+ assert_equal(test_hash, msg.to_h[:env])
109
+ assert_nil(msg.to_h(exclude_env: true)[:env])
110
+ end
111
+
112
+ def test_message_to_json_respects_params
113
+ msg = Logster::Message.new(0, "", "test")
114
+ test_hash = { test_key: "this is a test" }
115
+ msg.env = test_hash
116
+ assert_includes(msg.to_json, test_hash.to_json)
117
+ refute_includes(msg.to_json(exclude_env: true), test_hash.to_json)
118
+ end
119
+ end
@@ -1,230 +1,230 @@
1
- require_relative '../test_helper'
2
- require 'logster/redis_store'
3
- require 'rack'
4
-
5
- class TestRedisRateLimiter < Minitest::Test
6
- def setup
7
- @redis = Redis.new
8
- end
9
-
10
- def teardown
11
- @redis.flushall
12
- Timecop.return
13
- end
14
-
15
- def test_clear_all
16
- called = 0
17
-
18
- @redis.set("dont_nuke", "1")
19
-
20
- @rate_limiter = Logster::RedisRateLimiter.new(
21
- @redis, [Logger::WARN], 8, 60, Proc.new { "prefix" }, Proc.new { called += 1 }
22
- )
23
-
24
- 9.times do
25
- @rate_limiter.check(Logger::WARN)
26
- end
27
-
28
- assert_equal 10, @rate_limiter.check(Logger::WARN)
29
-
30
- Logster::RedisRateLimiter.clear_all(@redis, Proc.new { "prefix" })
31
-
32
- assert_equal 1, @rate_limiter.check(Logger::WARN)
33
-
34
- # also clears when prefix missing
35
- Logster::RedisRateLimiter.clear_all(@redis)
36
-
37
- assert_equal 1, @rate_limiter.check(Logger::WARN)
38
-
39
- assert_equal "1", @redis.get("dont_nuke")
40
- @redis.del("dont_nuke")
41
-
42
- end
43
-
44
- def test_check
45
- time = Time.new(2015, 1, 1, 1, 1)
46
- Timecop.freeze(time)
47
- called = 0
48
-
49
- @rate_limiter = Logster::RedisRateLimiter.new(
50
- @redis, [Logger::WARN], 8, 60, nil, Proc.new { called += 1 }
51
- )
52
-
53
- assert_equal(1, @rate_limiter.check(Logger::WARN))
54
- assert_redis_key(60, 0)
55
- assert_equal(1, number_of_buckets)
56
-
57
- Timecop.freeze(time + 10) do
58
- assert_equal(2, @rate_limiter.check(Logger::WARN))
59
- assert_redis_key(60, 1)
60
- assert_equal(3, @rate_limiter.check(Logger::WARN))
61
- assert_equal(2, number_of_buckets)
62
- end
63
-
64
- Timecop.freeze(time + 20) do
65
- assert_equal(4, @rate_limiter.check(Logger::WARN))
66
- assert_redis_key(60, 2)
67
- assert_equal(3, number_of_buckets)
68
- end
69
-
70
- Timecop.freeze(time + 30) do
71
- assert_equal(5, @rate_limiter.check(Logger::WARN))
72
- assert_redis_key(60, 3)
73
- assert_equal(4, number_of_buckets)
74
- end
75
-
76
- Timecop.freeze(time + 40) do
77
- assert_equal(6, @rate_limiter.check(Logger::WARN))
78
- assert_redis_key(60, 4)
79
- assert_equal(5, number_of_buckets)
80
- end
81
-
82
- Timecop.freeze(time + 50) do
83
- assert_equal(7, @rate_limiter.check(Logger::WARN))
84
- assert_redis_key(60, 5)
85
- assert_equal(6, number_of_buckets)
86
- end
87
-
88
- Timecop.freeze(time + 60) do
89
- @redis.del("#{key}:0")
90
- assert_equal(5, number_of_buckets)
91
-
92
- assert_equal(7, @rate_limiter.check(Logger::WARN))
93
- assert_redis_key(60, 0)
94
- assert_equal(6, number_of_buckets)
95
-
96
- assert_equal(8, @rate_limiter.check(Logger::WARN))
97
- assert_equal(1, called)
98
- assert_equal(6, number_of_buckets)
99
- assert_equal("1", @redis.get(@rate_limiter.callback_key))
100
- end
101
-
102
- Timecop.freeze(time + 70) do
103
- @redis.del("#{key}:1")
104
- assert_equal(7, @rate_limiter.check(Logger::WARN))
105
- assert_nil(@redis.get(@rate_limiter.callback_key))
106
- end
107
- end
108
-
109
- def test_check_with_multiple_severities
110
- time = Time.new(2015, 1, 1, 1, 1)
111
- Timecop.freeze(time)
112
- called = 0
113
-
114
- @rate_limiter = Logster::RedisRateLimiter.new(
115
- @redis, [Logger::WARN, Logger::ERROR], 4, 60, nil, Proc.new { called += 1 }
116
- )
117
-
118
- assert_equal(1, @rate_limiter.check(Logger::WARN))
119
- assert_equal(2, @rate_limiter.check(Logger::ERROR))
120
-
121
- Timecop.freeze(time + 50) do
122
- assert_equal(3, @rate_limiter.check(Logger::WARN))
123
- assert_equal(4, @rate_limiter.check(Logger::ERROR))
124
- assert_equal(2, number_of_buckets)
125
- end
126
-
127
- assert_equal(5, @rate_limiter.check(Logger::ERROR))
128
- assert_equal(1, called)
129
- end
130
-
131
- def test_bucket_number_per_minute
132
- time = Time.new(2015, 1, 1, 1, 1)
133
- Timecop.freeze(time)
134
- @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
135
-
136
- assert_bucket_number(0, time)
137
- assert_bucket_number(0, time + 9)
138
- assert_bucket_number(1, time + 11)
139
- assert_bucket_number(5, time + 59)
140
- end
141
-
142
- def test_bucket_number_per_hour
143
- time = Time.new(2015, 1, 1, 1, 0)
144
- Timecop.freeze(time)
145
- @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 3600)
146
-
147
- assert_bucket_number(0, time)
148
- assert_bucket_number(1, time + 1199)
149
- assert_bucket_number(2, time + 1200)
150
- assert_bucket_number(5, time + 3599)
151
- end
152
-
153
- def test_bucket_expiry
154
- time = Time.new(2015, 1, 1, 1, 1)
155
- Timecop.freeze(time)
156
- @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
157
-
158
- assert_bucket_expiry(60, time)
159
- assert_bucket_expiry(55, time + 5)
160
- assert_bucket_expiry(60, time + 10)
161
- assert_bucket_expiry(58, time + 12)
162
- assert_bucket_expiry(55, time + 15)
163
- assert_bucket_expiry(51, time + 19)
164
- assert_bucket_expiry(60, time + 20)
165
- assert_bucket_expiry(55, time + 35)
166
- end
167
-
168
- def test_raw_connection
169
- time = Time.new(2015, 1, 1, 1, 1)
170
- Timecop.freeze(time)
171
- @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60, Proc.new { "lobster" })
172
-
173
- assert_equal(1, @rate_limiter.check(Logger::WARN))
174
- assert_redis_key(60, 0)
175
-
176
- toggle = true
177
-
178
- @rate_limiter = Logster::RedisRateLimiter.new(
179
- @redis, [Logger::WARN], 1, 60, Proc.new { toggle ? 'lobster1' : 'lobster2' }
180
- )
181
-
182
- assert_includes(key, "lobster1")
183
-
184
- toggle = false
185
- assert_includes(key, "lobster2")
186
- end
187
-
188
- def test_retrieve_rate
189
- time = Time.new(2015, 1, 1, 1 , 1)
190
- Timecop.freeze(time)
191
-
192
- @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
193
-
194
- @rate_limiter.check(Logger::WARN)
195
- assert_equal(@rate_limiter.retrieve_rate, 1)
196
-
197
- Timecop.freeze(time + 50) do
198
- @rate_limiter.check(Logger::WARN)
199
- assert_equal(@rate_limiter.retrieve_rate, 2)
200
- end
201
- end
202
-
203
- private
204
-
205
- def key
206
- @rate_limiter.key
207
- end
208
-
209
- def number_of_buckets
210
- @redis.keys("#{key}:[0-#{Logster::RedisRateLimiter::BUCKETS}]").size
211
- end
212
-
213
- def assert_bucket_number(expected, time)
214
- Timecop.freeze(time) do
215
- assert_equal(expected, @rate_limiter.send(:bucket_number, Time.now.to_i))
216
- end
217
- end
218
-
219
- def assert_bucket_expiry(expected, time)
220
- Timecop.freeze(time) do
221
- assert_equal(expected, @rate_limiter.send(:bucket_expiry, Time.now.to_i))
222
- end
223
- end
224
-
225
- def assert_redis_key(expected_ttl, expected_bucket_number)
226
- redis_key = "#{key}:#{expected_bucket_number}"
227
- assert(@redis.get(redis_key), "the right bucket should be created")
228
- assert_equal(expected_ttl, @redis.ttl(redis_key))
229
- end
230
- end
1
+ require_relative '../test_helper'
2
+ require 'logster/redis_store'
3
+ require 'rack'
4
+
5
+ class TestRedisRateLimiter < Minitest::Test
6
+ def setup
7
+ @redis = Redis.new
8
+ end
9
+
10
+ def teardown
11
+ @redis.flushall
12
+ Timecop.return
13
+ end
14
+
15
+ def test_clear_all
16
+ called = 0
17
+
18
+ @redis.set("dont_nuke", "1")
19
+
20
+ @rate_limiter = Logster::RedisRateLimiter.new(
21
+ @redis, [Logger::WARN], 8, 60, Proc.new { "prefix" }, Proc.new { called += 1 }
22
+ )
23
+
24
+ 9.times do
25
+ @rate_limiter.check(Logger::WARN)
26
+ end
27
+
28
+ assert_equal 10, @rate_limiter.check(Logger::WARN)
29
+
30
+ Logster::RedisRateLimiter.clear_all(@redis, Proc.new { "prefix" })
31
+
32
+ assert_equal 1, @rate_limiter.check(Logger::WARN)
33
+
34
+ # also clears when prefix missing
35
+ Logster::RedisRateLimiter.clear_all(@redis)
36
+
37
+ assert_equal 1, @rate_limiter.check(Logger::WARN)
38
+
39
+ assert_equal "1", @redis.get("dont_nuke")
40
+ @redis.del("dont_nuke")
41
+
42
+ end
43
+
44
+ def test_check
45
+ time = Time.new(2015, 1, 1, 1, 1)
46
+ Timecop.freeze(time)
47
+ called = 0
48
+
49
+ @rate_limiter = Logster::RedisRateLimiter.new(
50
+ @redis, [Logger::WARN], 8, 60, nil, Proc.new { called += 1 }
51
+ )
52
+
53
+ assert_equal(1, @rate_limiter.check(Logger::WARN))
54
+ assert_redis_key(60, 0)
55
+ assert_equal(1, number_of_buckets)
56
+
57
+ Timecop.freeze(time + 10) do
58
+ assert_equal(2, @rate_limiter.check(Logger::WARN))
59
+ assert_redis_key(60, 1)
60
+ assert_equal(3, @rate_limiter.check(Logger::WARN))
61
+ assert_equal(2, number_of_buckets)
62
+ end
63
+
64
+ Timecop.freeze(time + 20) do
65
+ assert_equal(4, @rate_limiter.check(Logger::WARN))
66
+ assert_redis_key(60, 2)
67
+ assert_equal(3, number_of_buckets)
68
+ end
69
+
70
+ Timecop.freeze(time + 30) do
71
+ assert_equal(5, @rate_limiter.check(Logger::WARN))
72
+ assert_redis_key(60, 3)
73
+ assert_equal(4, number_of_buckets)
74
+ end
75
+
76
+ Timecop.freeze(time + 40) do
77
+ assert_equal(6, @rate_limiter.check(Logger::WARN))
78
+ assert_redis_key(60, 4)
79
+ assert_equal(5, number_of_buckets)
80
+ end
81
+
82
+ Timecop.freeze(time + 50) do
83
+ assert_equal(7, @rate_limiter.check(Logger::WARN))
84
+ assert_redis_key(60, 5)
85
+ assert_equal(6, number_of_buckets)
86
+ end
87
+
88
+ Timecop.freeze(time + 60) do
89
+ @redis.del("#{key}:0")
90
+ assert_equal(5, number_of_buckets)
91
+
92
+ assert_equal(7, @rate_limiter.check(Logger::WARN))
93
+ assert_redis_key(60, 0)
94
+ assert_equal(6, number_of_buckets)
95
+
96
+ assert_equal(8, @rate_limiter.check(Logger::WARN))
97
+ assert_equal(1, called)
98
+ assert_equal(6, number_of_buckets)
99
+ assert_equal("1", @redis.get(@rate_limiter.callback_key))
100
+ end
101
+
102
+ Timecop.freeze(time + 70) do
103
+ @redis.del("#{key}:1")
104
+ assert_equal(7, @rate_limiter.check(Logger::WARN))
105
+ assert_nil(@redis.get(@rate_limiter.callback_key))
106
+ end
107
+ end
108
+
109
+ def test_check_with_multiple_severities
110
+ time = Time.new(2015, 1, 1, 1, 1)
111
+ Timecop.freeze(time)
112
+ called = 0
113
+
114
+ @rate_limiter = Logster::RedisRateLimiter.new(
115
+ @redis, [Logger::WARN, Logger::ERROR], 4, 60, nil, Proc.new { called += 1 }
116
+ )
117
+
118
+ assert_equal(1, @rate_limiter.check(Logger::WARN))
119
+ assert_equal(2, @rate_limiter.check(Logger::ERROR))
120
+
121
+ Timecop.freeze(time + 50) do
122
+ assert_equal(3, @rate_limiter.check(Logger::WARN))
123
+ assert_equal(4, @rate_limiter.check(Logger::ERROR))
124
+ assert_equal(2, number_of_buckets)
125
+ end
126
+
127
+ assert_equal(5, @rate_limiter.check(Logger::ERROR))
128
+ assert_equal(1, called)
129
+ end
130
+
131
+ def test_bucket_number_per_minute
132
+ time = Time.new(2015, 1, 1, 1, 1)
133
+ Timecop.freeze(time)
134
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
135
+
136
+ assert_bucket_number(0, time)
137
+ assert_bucket_number(0, time + 9)
138
+ assert_bucket_number(1, time + 11)
139
+ assert_bucket_number(5, time + 59)
140
+ end
141
+
142
+ def test_bucket_number_per_hour
143
+ time = Time.new(2015, 1, 1, 1, 0)
144
+ Timecop.freeze(time)
145
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 3600)
146
+
147
+ assert_bucket_number(0, time)
148
+ assert_bucket_number(1, time + 1199)
149
+ assert_bucket_number(2, time + 1200)
150
+ assert_bucket_number(5, time + 3599)
151
+ end
152
+
153
+ def test_bucket_expiry
154
+ time = Time.new(2015, 1, 1, 1, 1)
155
+ Timecop.freeze(time)
156
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
157
+
158
+ assert_bucket_expiry(60, time)
159
+ assert_bucket_expiry(55, time + 5)
160
+ assert_bucket_expiry(60, time + 10)
161
+ assert_bucket_expiry(58, time + 12)
162
+ assert_bucket_expiry(55, time + 15)
163
+ assert_bucket_expiry(51, time + 19)
164
+ assert_bucket_expiry(60, time + 20)
165
+ assert_bucket_expiry(55, time + 35)
166
+ end
167
+
168
+ def test_raw_connection
169
+ time = Time.new(2015, 1, 1, 1, 1)
170
+ Timecop.freeze(time)
171
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60, Proc.new { "lobster" })
172
+
173
+ assert_equal(1, @rate_limiter.check(Logger::WARN))
174
+ assert_redis_key(60, 0)
175
+
176
+ toggle = true
177
+
178
+ @rate_limiter = Logster::RedisRateLimiter.new(
179
+ @redis, [Logger::WARN], 1, 60, Proc.new { toggle ? 'lobster1' : 'lobster2' }
180
+ )
181
+
182
+ assert_includes(key, "lobster1")
183
+
184
+ toggle = false
185
+ assert_includes(key, "lobster2")
186
+ end
187
+
188
+ def test_retrieve_rate
189
+ time = Time.new(2015, 1, 1, 1 , 1)
190
+ Timecop.freeze(time)
191
+
192
+ @rate_limiter = Logster::RedisRateLimiter.new(@redis, [Logger::WARN], 1, 60)
193
+
194
+ @rate_limiter.check(Logger::WARN)
195
+ assert_equal(@rate_limiter.retrieve_rate, 1)
196
+
197
+ Timecop.freeze(time + 50) do
198
+ @rate_limiter.check(Logger::WARN)
199
+ assert_equal(@rate_limiter.retrieve_rate, 2)
200
+ end
201
+ end
202
+
203
+ private
204
+
205
+ def key
206
+ @rate_limiter.key
207
+ end
208
+
209
+ def number_of_buckets
210
+ @redis.keys("#{key}:[0-#{Logster::RedisRateLimiter::BUCKETS}]").size
211
+ end
212
+
213
+ def assert_bucket_number(expected, time)
214
+ Timecop.freeze(time) do
215
+ assert_equal(expected, @rate_limiter.send(:bucket_number, Time.now.to_i))
216
+ end
217
+ end
218
+
219
+ def assert_bucket_expiry(expected, time)
220
+ Timecop.freeze(time) do
221
+ assert_equal(expected, @rate_limiter.send(:bucket_expiry, Time.now.to_i))
222
+ end
223
+ end
224
+
225
+ def assert_redis_key(expected_ttl, expected_bucket_number)
226
+ redis_key = "#{key}:#{expected_bucket_number}"
227
+ assert(@redis.get(redis_key), "the right bucket should be created")
228
+ assert_equal(expected_ttl, @redis.ttl(redis_key))
229
+ end
230
+ end