logster 2.1.1 → 2.1.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 +4 -4
- data/.gitignore +19 -19
- data/.rubocop.yml +1 -1
- data/.travis.yml +16 -16
- data/CHANGELOG.md +172 -169
- data/Gemfile +4 -4
- data/Guardfile +8 -8
- data/LICENSE.txt +22 -22
- data/README.md +99 -99
- data/Rakefile +21 -21
- data/assets/fonts/FontAwesome.otf +0 -0
- data/assets/fonts/fontawesome-webfont.eot +0 -0
- data/assets/fonts/fontawesome-webfont.svg +639 -639
- data/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/assets/fonts/fontawesome-webfont.woff +0 -0
- data/assets/fonts/fontawesome-webfont.woff2 +0 -0
- data/assets/images/Icon-144_rounded.png +0 -0
- data/assets/images/Icon-144_square.png +0 -0
- data/assets/images/icon_144x144.png +0 -0
- data/assets/images/icon_64x64.png +0 -0
- data/assets/javascript/client-app.js +106 -100
- data/assets/stylesheets/client-app.css +1 -1
- data/build_client_app.sh +0 -0
- data/client-app/.editorconfig +20 -20
- data/client-app/.ember-cli +9 -9
- data/client-app/.eslintignore +19 -19
- data/client-app/.eslintrc.js +46 -46
- data/client-app/.gitignore +23 -23
- data/client-app/.travis.yml +27 -27
- data/client-app/.watchmanconfig +3 -3
- data/client-app/README.md +57 -57
- data/client-app/app/app.js +0 -0
- data/client-app/app/components/actions-menu.js +43 -37
- data/client-app/app/components/env-tab.js +80 -44
- data/client-app/app/components/message-info.js +0 -0
- data/client-app/app/components/message-row.js +0 -0
- data/client-app/app/components/panel-resizer.js +0 -0
- data/client-app/app/components/tab-contents.js +27 -27
- data/client-app/app/components/tabbed-section.js +0 -0
- data/client-app/app/components/time-formatter.js +0 -0
- data/client-app/app/components/update-time.js +0 -0
- data/client-app/app/controllers/index.js +0 -0
- data/client-app/app/controllers/show.js +0 -0
- data/client-app/app/index.html +29 -29
- data/client-app/app/initializers/app-init.js +67 -72
- data/client-app/app/lib/preload.js +20 -14
- data/client-app/app/lib/utilities.js +149 -140
- data/client-app/app/models/message-collection.js +0 -0
- data/client-app/app/models/message.js +100 -100
- data/client-app/app/resolver.js +0 -0
- data/client-app/app/router.js +0 -0
- data/client-app/app/routes/index.js +0 -0
- data/client-app/app/routes/show.js +0 -0
- data/client-app/app/styles/app.css +527 -521
- data/client-app/app/templates/application.hbs +2 -2
- data/client-app/app/templates/components/actions-menu.hbs +12 -12
- data/client-app/app/templates/components/env-tab.hbs +10 -10
- data/client-app/app/templates/components/message-info.hbs +41 -41
- data/client-app/app/templates/components/message-row.hbs +15 -15
- data/client-app/app/templates/components/panel-resizer.hbs +3 -3
- data/client-app/app/templates/components/tabbed-section.hbs +10 -10
- data/client-app/app/templates/components/time-formatter.hbs +1 -1
- data/client-app/app/templates/index.hbs +58 -58
- data/client-app/app/templates/show.hbs +7 -7
- data/client-app/config/environment.js +51 -51
- data/client-app/config/optional-features.json +3 -3
- data/client-app/config/targets.js +18 -18
- data/client-app/ember-cli-build.js +29 -29
- data/client-app/package-lock.json +11365 -11365
- data/client-app/package.json +56 -56
- data/client-app/testem.js +25 -25
- data/client-app/tests/index.html +34 -34
- data/client-app/tests/integration/components/env-tab-test.js +123 -73
- data/client-app/tests/integration/components/message-info-test.js +111 -26
- data/client-app/tests/test-helper.js +8 -8
- data/client-app/tests/unit/controllers/index-test.js +12 -12
- data/client-app/tests/unit/controllers/show-test.js +12 -12
- data/client-app/tests/unit/initializers/app-init-test.js +31 -31
- data/client-app/tests/unit/routes/index-test.js +11 -11
- data/client-app/tests/unit/routes/show-test.js +11 -11
- data/lib/examples/sidekiq_logster_reporter.rb +21 -21
- data/lib/logster.rb +54 -54
- data/lib/logster/base_store.rb +141 -141
- data/lib/logster/configuration.rb +26 -25
- data/lib/logster/defer_logger.rb +14 -14
- data/lib/logster/ignore_pattern.rb +65 -65
- data/lib/logster/logger.rb +113 -113
- data/lib/logster/message.rb +212 -212
- data/lib/logster/middleware/debug_exceptions.rb +26 -26
- data/lib/logster/middleware/reporter.rb +55 -55
- data/lib/logster/middleware/viewer.rb +222 -221
- data/lib/logster/rails/railtie.rb +63 -63
- data/lib/logster/redis_store.rb +566 -566
- data/lib/logster/scheduler.rb +54 -54
- data/lib/logster/version.rb +3 -3
- data/lib/logster/web.rb +14 -14
- data/logster.gemspec +35 -35
- data/test/examples/test_sidekiq_reporter_example.rb +46 -46
- data/test/fake_data/Gemfile +4 -4
- data/test/fake_data/generate.rb +10 -10
- data/test/logster/middleware/test_reporter.rb +19 -19
- data/test/logster/middleware/test_viewer.rb +96 -96
- data/test/logster/test_base_store.rb +147 -147
- data/test/logster/test_defer_logger.rb +34 -34
- data/test/logster/test_ignore_pattern.rb +41 -41
- data/test/logster/test_logger.rb +86 -86
- data/test/logster/test_message.rb +119 -119
- data/test/logster/test_redis_rate_limiter.rb +230 -230
- data/test/logster/test_redis_store.rb +720 -720
- data/test/test_helper.rb +38 -38
- data/vendor/assets/javascripts/logster.js.erb +39 -39
- metadata +1 -10
- data/client-app/app/components/tab-link.js +0 -5
- data/client-app/tests/integration/components/actions-menu-test.js +0 -26
- data/client-app/tests/integration/components/message-row-test.js +0 -26
- data/client-app/tests/integration/components/panel-resizer-test.js +0 -26
- data/client-app/tests/integration/components/tab-contents-test.js +0 -26
- data/client-app/tests/integration/components/tab-link-test.js +0 -26
- data/client-app/tests/integration/components/tabbed-section-test.js +0 -26
- data/client-app/tests/integration/components/time-formatter-test.js +0 -26
- data/client-app/tests/integration/components/update-time-test.js +0 -26
|
@@ -1,720 +1,720 @@
|
|
|
1
|
-
require_relative '../test_helper'
|
|
2
|
-
require 'logster/redis_store'
|
|
3
|
-
require 'rack'
|
|
4
|
-
|
|
5
|
-
class TestRedisStore < Minitest::Test
|
|
6
|
-
|
|
7
|
-
def setup
|
|
8
|
-
@store = Logster::RedisStore.new(Redis.new)
|
|
9
|
-
@store.clear_all
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def teardown
|
|
13
|
-
@store.clear_all
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def test_delete
|
|
17
|
-
env = { test_env: "this is env" }
|
|
18
|
-
msg = @store.report(Logger::WARN, "test", "testing", env: env)
|
|
19
|
-
@store.delete(msg)
|
|
20
|
-
latest = @store.latest
|
|
21
|
-
|
|
22
|
-
assert_equal(0, latest.length)
|
|
23
|
-
assert_nil(@store.get_env(msg.key))
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def test_latest
|
|
27
|
-
@store.report(Logger::WARN, "test", "IGNORE")
|
|
28
|
-
@store.report(Logger::WARN, "test", "This is a warning")
|
|
29
|
-
@store.report(Logger::WARN, "test", "This is another warning")
|
|
30
|
-
|
|
31
|
-
latest = @store.latest(limit: 2)
|
|
32
|
-
|
|
33
|
-
assert_equal(2, latest.length)
|
|
34
|
-
assert_equal("This is a warning", latest[0].message)
|
|
35
|
-
assert_equal("This is another warning", latest[1].message)
|
|
36
|
-
assert_equal(Logger::WARN, latest[1].severity)
|
|
37
|
-
assert_equal("test", latest[1].progname)
|
|
38
|
-
assert(!latest[1].key.nil?)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def test_latest_after
|
|
42
|
-
10.times do |i|
|
|
43
|
-
@store.report(Logger::WARN, "test", "A#{i}")
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
message = @store.latest[-1]
|
|
47
|
-
|
|
48
|
-
3.times do |i|
|
|
49
|
-
@store.report(Logger::WARN, "test", i.to_s)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
message = @store.latest(after: message.key, limit: 3)[0]
|
|
53
|
-
|
|
54
|
-
assert_equal("0", message.message)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def test_latest_before
|
|
58
|
-
10.times do
|
|
59
|
-
@store.report(Logger::WARN, "test", "A")
|
|
60
|
-
end
|
|
61
|
-
10.times do
|
|
62
|
-
@store.report(Logger::WARN, "test", "B")
|
|
63
|
-
end
|
|
64
|
-
10.times do
|
|
65
|
-
@store.report(Logger::WARN, "test", "C")
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
messages = @store.latest(limit: 10)
|
|
69
|
-
assert_equal("C", messages[0].message)
|
|
70
|
-
assert_equal(10, messages.length)
|
|
71
|
-
|
|
72
|
-
messages = @store.latest(limit: 10, before: messages[0].key)
|
|
73
|
-
assert_equal("B", messages[0].message)
|
|
74
|
-
assert_equal(10, messages.length)
|
|
75
|
-
|
|
76
|
-
messages = @store.latest(limit: 10, before: messages[0].key)
|
|
77
|
-
assert_equal("A", messages[0].message)
|
|
78
|
-
assert_equal(10, messages.length)
|
|
79
|
-
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def test_get
|
|
83
|
-
a_env = { "a_message" => "A MESSAGE" }
|
|
84
|
-
a_message = @store.report(Logger::WARN, "test", "A", env: a_env)
|
|
85
|
-
b_message = @store.report(Logger::WARN, "test", "B")
|
|
86
|
-
@store.report(Logger::WARN, "test", "C")
|
|
87
|
-
|
|
88
|
-
a_message = @store.get(a_message.key)
|
|
89
|
-
assert_equal("A", a_message.message)
|
|
90
|
-
assert_equal("B", b_message.message)
|
|
91
|
-
assert(a_env <= a_message.env)
|
|
92
|
-
|
|
93
|
-
a_message = @store.get(a_message.key, load_env: false)
|
|
94
|
-
assert_equal("A", a_message.message)
|
|
95
|
-
assert_nil(a_message.env)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def test_save_saves_env_separately
|
|
99
|
-
env = { "myenv" => "thisisenv" }
|
|
100
|
-
message = @store.report(Logger::WARN, "test", "title", env: env)
|
|
101
|
-
message = @store.get(message.key, load_env: false)
|
|
102
|
-
assert_nil(message.env)
|
|
103
|
-
|
|
104
|
-
message = @store.get(message.key)
|
|
105
|
-
assert(env <= message.env)
|
|
106
|
-
|
|
107
|
-
assert(env <= @store.get_env(message.key))
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def test_bulk_get
|
|
111
|
-
keys = []
|
|
112
|
-
|
|
113
|
-
5.times do |n|
|
|
114
|
-
env = n == 0 ? nil : { "test_#{n}" => "envsss" }
|
|
115
|
-
keys << @store.report(Logger::WARN, "progname", "test_#{n}", env: env).key
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
messages = @store.bulk_get(keys)
|
|
119
|
-
|
|
120
|
-
5.times do |n|
|
|
121
|
-
msg = messages[n]
|
|
122
|
-
assert_equal("test_#{n}", msg.message)
|
|
123
|
-
if n == 0
|
|
124
|
-
assert_equal(Logster::Message.default_env, msg.env)
|
|
125
|
-
else
|
|
126
|
-
assert({ "test_#{n}" => "envsss" } <= msg.env)
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def test_get_env
|
|
132
|
-
env = { "my_little_env" => "some value" }
|
|
133
|
-
message = @store.report(Logger::WARN, "test", "A", env: env)
|
|
134
|
-
assert(env <= @store.get_env(message.key))
|
|
135
|
-
assert_nil(@store.get_env("nonexistentkey"))
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def test_replace_and_bump
|
|
139
|
-
old_env = { "old_env" => "old value" }
|
|
140
|
-
message = @store.report(Logger::WARN, "test", "A", env: old_env)
|
|
141
|
-
|
|
142
|
-
unsaved_env = { "unsaved_env" => "lost value" }
|
|
143
|
-
message.env = unsaved_env
|
|
144
|
-
|
|
145
|
-
@store.replace_and_bump(message, save_env: false)
|
|
146
|
-
|
|
147
|
-
message = @store.get(message.key)
|
|
148
|
-
assert(old_env <= message.env)
|
|
149
|
-
refute(unsaved_env <= message.env)
|
|
150
|
-
|
|
151
|
-
saved_env = { "saved_env" => "saved value!" }
|
|
152
|
-
message.env = saved_env
|
|
153
|
-
|
|
154
|
-
@store.replace_and_bump(message)
|
|
155
|
-
|
|
156
|
-
message = @store.get(message.key)
|
|
157
|
-
assert(saved_env == message.env)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def test_backward_compatibility_no_loss_of_data
|
|
161
|
-
# previously we were storing env samples as a part of the main message json
|
|
162
|
-
# now we've switched to storing samples separately from the main message
|
|
163
|
-
# we need to make we don't lose env data of messages stored the old way
|
|
164
|
-
# when we migrate to the new system
|
|
165
|
-
|
|
166
|
-
# it probably makes sense to remove this test after a while (say 6-12 months)
|
|
167
|
-
|
|
168
|
-
Logster.config.allow_grouping = true
|
|
169
|
-
backtrace = "fake backtrace"
|
|
170
|
-
env = { "some_env" => "some env" }
|
|
171
|
-
message = Logster::Message.new(Logger::WARN, "", "title", count: 60)
|
|
172
|
-
message.env = env
|
|
173
|
-
message.backtrace = backtrace
|
|
174
|
-
|
|
175
|
-
@store.save(message)
|
|
176
|
-
|
|
177
|
-
# hack to force env to be stored with the main message json
|
|
178
|
-
@store.redis.hset(@store.send("hash_key"), message.key, message.to_json(exclude_env: false))
|
|
179
|
-
|
|
180
|
-
another_env = { "another_env" => "more env" }
|
|
181
|
-
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
182
|
-
message = @store.get(message.key)
|
|
183
|
-
|
|
184
|
-
assert(env <= message.env)
|
|
185
|
-
assert_equal(61, message.count)
|
|
186
|
-
# another_env is not merged cause count is 60, only the count is updated
|
|
187
|
-
|
|
188
|
-
# make sure we are now storing env samples separately
|
|
189
|
-
message = @store.get(message.key, load_env: false)
|
|
190
|
-
assert_nil(message.env)
|
|
191
|
-
ensure
|
|
192
|
-
Logster.config.allow_grouping = false
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
def test_backward_compatibility_no_loss_of_data_2
|
|
196
|
-
# same story as the test above, just a bit different
|
|
197
|
-
|
|
198
|
-
Logster.config.allow_grouping = true
|
|
199
|
-
backtrace = "fake backtrace"
|
|
200
|
-
env = { "some_env" => "some env" }
|
|
201
|
-
message = Logster::Message.new(Logger::WARN, "", "title")
|
|
202
|
-
message.env = env
|
|
203
|
-
message.backtrace = backtrace
|
|
204
|
-
|
|
205
|
-
@store.save(message)
|
|
206
|
-
|
|
207
|
-
# hack to force env to be stored with the main message json
|
|
208
|
-
@store.redis.hset(@store.send("hash_key"), message.key, message.to_json(exclude_env: false))
|
|
209
|
-
|
|
210
|
-
another_env = { "another_env" => "more env" }
|
|
211
|
-
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
212
|
-
message = @store.get(message.key)
|
|
213
|
-
|
|
214
|
-
assert_instance_of(Array, message.env)
|
|
215
|
-
assert(env <= message.env[0])
|
|
216
|
-
assert(another_env <= message.env[1])
|
|
217
|
-
assert_equal(2, message.env.size)
|
|
218
|
-
assert_equal(2, message.count)
|
|
219
|
-
|
|
220
|
-
# make sure we are now storing env samples separately
|
|
221
|
-
message = @store.get(message.key, load_env: false)
|
|
222
|
-
assert_nil(message.env)
|
|
223
|
-
ensure
|
|
224
|
-
Logster.config.allow_grouping = false
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def test_merging_performance
|
|
228
|
-
Logster.config.allow_grouping = true
|
|
229
|
-
backtrace = "fake backtrace"
|
|
230
|
-
env = { "some_env" => "some env" }
|
|
231
|
-
another_env = { "another_env" => "more env" }
|
|
232
|
-
yet_another_env = { "moaar_env" => "more env" }
|
|
233
|
-
|
|
234
|
-
@store.report(Logger::WARN, "", "title", backtrace: backtrace, env: env, count: 49)
|
|
235
|
-
|
|
236
|
-
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
237
|
-
assert_instance_of(Array, message.env)
|
|
238
|
-
assert_equal(2, message.env.size)
|
|
239
|
-
assert(env <= message.env[0])
|
|
240
|
-
assert(another_env <= message.env[1])
|
|
241
|
-
|
|
242
|
-
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: yet_another_env)
|
|
243
|
-
# we don't need to load env from redis cause we don't
|
|
244
|
-
# need to merge new env samples if count is 50 or more
|
|
245
|
-
assert_nil(message.env)
|
|
246
|
-
ensure
|
|
247
|
-
Logster.config.allow_grouping = false
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def test_backlog
|
|
251
|
-
env = { "backlog_test" => "BACKLOG" }
|
|
252
|
-
@store.max_backlog = 1
|
|
253
|
-
deleted_msg = @store.report(Logger::WARN, "test", "A")
|
|
254
|
-
@store.report(Logger::WARN, "test", "A")
|
|
255
|
-
@store.report(Logger::WARN, "test", "A")
|
|
256
|
-
@store.report(Logger::WARN, "test", "B", env: env)
|
|
257
|
-
|
|
258
|
-
latest = @store.latest
|
|
259
|
-
|
|
260
|
-
assert_equal(1, latest.length)
|
|
261
|
-
assert_equal("B", latest[0].message)
|
|
262
|
-
assert(env <= latest[0].env)
|
|
263
|
-
assert_nil(@store.get(deleted_msg.key))
|
|
264
|
-
assert_nil(@store.get_env(deleted_msg.key))
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
def test_save_unsave
|
|
268
|
-
@store.max_backlog = 3
|
|
269
|
-
@store.report(Logger::WARN, "test", "A")
|
|
270
|
-
b_message = @store.report(Logger::WARN, "test", "B")
|
|
271
|
-
@store.protect b_message.key
|
|
272
|
-
c_message = @store.report(Logger::WARN, "test", "C")
|
|
273
|
-
@store.protect c_message.key
|
|
274
|
-
@store.report(Logger::WARN, "test", "D")
|
|
275
|
-
|
|
276
|
-
latest = @store.latest
|
|
277
|
-
|
|
278
|
-
assert_equal(3, latest.length)
|
|
279
|
-
assert_equal("B", latest[0].message)
|
|
280
|
-
assert_equal("C", latest[1].message)
|
|
281
|
-
assert_equal(true, latest[1].protected)
|
|
282
|
-
assert_equal("D", latest[2].message)
|
|
283
|
-
|
|
284
|
-
# Saved messages still accessible by key
|
|
285
|
-
assert_equal("B", @store.get(b_message.key).message)
|
|
286
|
-
assert_equal(true, @store.get(b_message.key).protected)
|
|
287
|
-
|
|
288
|
-
# Unsave does not delete message if still recent
|
|
289
|
-
@store.unprotect c_message.key
|
|
290
|
-
assert_equal("C", @store.get(c_message.key).message)
|
|
291
|
-
assert_equal(false, @store.get(c_message.key).protected)
|
|
292
|
-
end
|
|
293
|
-
|
|
294
|
-
def test_clear
|
|
295
|
-
env = { "clear_env" => "cllleear" }
|
|
296
|
-
@store.max_backlog = 25
|
|
297
|
-
a_message = @store.report(Logger::WARN, "test", "A", timestamp: Time.now - (24 * 60 * 60), env: env)
|
|
298
|
-
@store.protect a_message.key
|
|
299
|
-
20.times do
|
|
300
|
-
@store.report(Logger::WARN, "test", "B", env: env)
|
|
301
|
-
end
|
|
302
|
-
c_message = @store.report(Logger::WARN, "test", "C", timestamp: Time.now + (24 * 60 * 60), env: env)
|
|
303
|
-
@store.protect c_message.key
|
|
304
|
-
d_message = @store.report(Logger::WARN, "test", "D", env: env)
|
|
305
|
-
10.times do
|
|
306
|
-
@store.report(Logger::WARN, "test", "E", env: env)
|
|
307
|
-
end
|
|
308
|
-
|
|
309
|
-
latest = @store.latest
|
|
310
|
-
assert_equal(25, latest.length)
|
|
311
|
-
|
|
312
|
-
@store.clear
|
|
313
|
-
|
|
314
|
-
# Protected messages are still accessible by their key
|
|
315
|
-
assert_equal("C", @store.get(c_message.key).message)
|
|
316
|
-
assert(env <= @store.get_env(c_message.key))
|
|
317
|
-
# Unprotected messages are gone
|
|
318
|
-
assert_nil(@store.get(d_message.key))
|
|
319
|
-
assert_nil(@store.get_env(d_message.key))
|
|
320
|
-
|
|
321
|
-
# The latest list is rebuilt with protected messages, earliest first
|
|
322
|
-
# Including messages that previously fell off (A)
|
|
323
|
-
latest = @store.latest
|
|
324
|
-
assert_equal(2, latest.length)
|
|
325
|
-
assert_equal("A", latest[0].message)
|
|
326
|
-
assert_equal("C", latest[1].message)
|
|
327
|
-
assert(env <= latest[0].env)
|
|
328
|
-
assert(env <= latest[1].env)
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
def test_hash_cleanup
|
|
332
|
-
@store.max_backlog = 2
|
|
333
|
-
a_message = @store.report(Logger::WARN, "test", "A")
|
|
334
|
-
@store.report(Logger::WARN, "test", "B")
|
|
335
|
-
@store.report(Logger::WARN, "test", "C")
|
|
336
|
-
|
|
337
|
-
assert_nil(@store.get(a_message.key))
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
def test_filter_latest
|
|
341
|
-
@store.report(Logger::INFO, "test", "A")
|
|
342
|
-
@store.report(Logger::WARN, "test", "B")
|
|
343
|
-
|
|
344
|
-
messages = @store.latest
|
|
345
|
-
assert_equal(2, messages.length)
|
|
346
|
-
|
|
347
|
-
messages = @store.latest(after: messages.last.key)
|
|
348
|
-
assert_equal(0, messages.length)
|
|
349
|
-
|
|
350
|
-
10.times do
|
|
351
|
-
@store.report(Logger::INFO, "test", "A")
|
|
352
|
-
end
|
|
353
|
-
@store.report(Logger::ERROR, "test", "C")
|
|
354
|
-
10.times do
|
|
355
|
-
@store.report(Logger::INFO, "test", "A")
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2)
|
|
359
|
-
|
|
360
|
-
assert_equal(2, latest.length)
|
|
361
|
-
assert_equal("B", latest[0].message)
|
|
362
|
-
assert_equal("C", latest[1].message)
|
|
363
|
-
|
|
364
|
-
@store.report(Logger::ERROR, "test", "E")
|
|
365
|
-
# respects after
|
|
366
|
-
latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2, after: latest[1].key)
|
|
367
|
-
assert_equal(1, latest.length)
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
def test_search
|
|
371
|
-
@store.report(Logger::INFO, "test", "ABCDEFG")
|
|
372
|
-
@store.report(Logger::INFO, "test", "TUVWXYZ")
|
|
373
|
-
|
|
374
|
-
messages = @store.latest
|
|
375
|
-
assert_equal(2, messages.length)
|
|
376
|
-
|
|
377
|
-
latest = @store.latest(search: "TUVWXYZ")
|
|
378
|
-
|
|
379
|
-
assert_equal(1, latest.length)
|
|
380
|
-
assert_equal("TUVWXYZ", latest[0].message)
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def test_search_exclude_results
|
|
384
|
-
@store.report(Logger::INFO, "test", "ABCDEFG")
|
|
385
|
-
@store.report(Logger::INFO, "test", "TUVWXYZ")
|
|
386
|
-
|
|
387
|
-
messages = @store.latest
|
|
388
|
-
assert_equal(2, messages.length)
|
|
389
|
-
|
|
390
|
-
latest = @store.latest(search: "-ABCD")
|
|
391
|
-
|
|
392
|
-
assert_equal(1, latest.length)
|
|
393
|
-
assert_equal("TUVWXYZ", latest[0].message)
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
def test_regex_search
|
|
397
|
-
@store.report(Logger::INFO, "test", "pattern_1")
|
|
398
|
-
@store.report(Logger::INFO, "test", "pattern_2")
|
|
399
|
-
|
|
400
|
-
messages = @store.latest
|
|
401
|
-
assert_equal(2, messages.length)
|
|
402
|
-
|
|
403
|
-
latest = @store.latest(search: /^pattern_[1]$/)
|
|
404
|
-
|
|
405
|
-
assert_equal(1, latest.length)
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
def test_env_search
|
|
409
|
-
@store.report(Logger::INFO, "test", "message ABCD", env: { cluster: "business5" })
|
|
410
|
-
@store.report(Logger::INFO, "test", "message WXYZ", env: { cluster: "business7" })
|
|
411
|
-
|
|
412
|
-
messages = @store.latest
|
|
413
|
-
assert_equal(2, messages.length)
|
|
414
|
-
|
|
415
|
-
latest = @store.latest(search: "business5")
|
|
416
|
-
|
|
417
|
-
assert_equal(1, latest.length)
|
|
418
|
-
assert_equal("message ABCD", latest[0].message)
|
|
419
|
-
|
|
420
|
-
latest = @store.latest(search: "-business5")
|
|
421
|
-
|
|
422
|
-
assert_equal(1, latest.length)
|
|
423
|
-
assert_equal("message WXYZ", latest[0].message)
|
|
424
|
-
|
|
425
|
-
latest = @store.latest(search: /business/)
|
|
426
|
-
|
|
427
|
-
assert_equal(2, latest.length)
|
|
428
|
-
assert_equal(["message ABCD", "message WXYZ"], latest.map(&:message).sort)
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
def test_array_env_search_preserve_env
|
|
432
|
-
m1_original_env = [{ cluster: "business5" }, { cluster: "standard3" }]
|
|
433
|
-
m2_original_env = [{ cluster: "business2" }, { cluster: "standard7" }]
|
|
434
|
-
|
|
435
|
-
@store.report(Logger::INFO, "test", "message ABCD", env: m1_original_env, count: 2)
|
|
436
|
-
@store.report(Logger::INFO, "test", "message WXYZ", env: m2_original_env, count: 2)
|
|
437
|
-
|
|
438
|
-
messages = @store.latest
|
|
439
|
-
assert_equal(2, messages.length)
|
|
440
|
-
|
|
441
|
-
m1_key = messages[0].key
|
|
442
|
-
m2_key = messages[1].key
|
|
443
|
-
|
|
444
|
-
messages = @store.latest(search: "business")
|
|
445
|
-
assert_equal(2, messages.size)
|
|
446
|
-
|
|
447
|
-
# any hashes that don't match should be stripped from the env
|
|
448
|
-
# array but only temporarily until it's sent to the client
|
|
449
|
-
# env array should remain untouched in redis memory
|
|
450
|
-
assert_equal(["business5"], messages[0].env.map { |env| env["cluster"] })
|
|
451
|
-
assert_equal(1, messages[0].count)
|
|
452
|
-
assert_equal(["business2"], messages[1].env.map { |env| env["cluster"] })
|
|
453
|
-
assert_equal(1, messages[1].count)
|
|
454
|
-
|
|
455
|
-
m1 = @store.get(m1_key)
|
|
456
|
-
m2 = @store.get(m2_key)
|
|
457
|
-
# original env should preserved in redis memory
|
|
458
|
-
assert_equal(["business5", "standard3"], m1.env.map { |env| env["cluster"] })
|
|
459
|
-
assert_equal(["business2", "standard7"], m2.env.map { |env| env["cluster"] })
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
def test_both_env_and_title_match_search
|
|
463
|
-
@store.report(Logger::INFO, "test", "message", env: [{ cluster: "business15" }])
|
|
464
|
-
@store.report(Logger::INFO, "test", "message2", env: { cluster: "business15" })
|
|
465
|
-
|
|
466
|
-
messages = @store.latest
|
|
467
|
-
assert_equal(2, messages.size)
|
|
468
|
-
|
|
469
|
-
messages = @store.latest(search: "-business15")
|
|
470
|
-
assert_equal(0, messages.size)
|
|
471
|
-
end
|
|
472
|
-
|
|
473
|
-
def test_data_kept_intact_on_report_when_env_matches_an_ignore_pattern
|
|
474
|
-
begin
|
|
475
|
-
Logster.config.allow_grouping = true
|
|
476
|
-
backtrace = caller
|
|
477
|
-
message = @store.report(Logger::WARN, "", "my error", env: { whatever: "something", backtrace: backtrace })
|
|
478
|
-
|
|
479
|
-
@store.ignore = [
|
|
480
|
-
Logster::IgnorePattern.new("business")
|
|
481
|
-
]
|
|
482
|
-
@store.report(Logger::WARN, "", "my error", env: { cluster: "business17", backtrace: backtrace })
|
|
483
|
-
|
|
484
|
-
message = @store.get(message.key)
|
|
485
|
-
assert(Array === message.env)
|
|
486
|
-
assert_equal(2, message.env.size)
|
|
487
|
-
# message2 shouldn't vanish even if
|
|
488
|
-
# its env matches an ignore pattern
|
|
489
|
-
# however it should be merged with message1
|
|
490
|
-
assert_equal("business17", message.env[1]["cluster"])
|
|
491
|
-
ensure
|
|
492
|
-
# reset so it doesn't affect other tests
|
|
493
|
-
@store.ignore = nil
|
|
494
|
-
Logster.config.allow_grouping = false
|
|
495
|
-
end
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
def test_array_env_negative_search
|
|
499
|
-
@store.report(Logger::INFO, "test", "message ABCD", env: [{ cluster: "business5" }, { cluster: "standard3" }], count: 2)
|
|
500
|
-
@store.report(Logger::INFO, "test", "message WXYZ", env: [{ cluster: "business2" }, { cluster: "standard7" }], count: 2)
|
|
501
|
-
|
|
502
|
-
messages = @store.latest
|
|
503
|
-
assert_equal(2, messages.length)
|
|
504
|
-
|
|
505
|
-
messages = @store.latest(search: "-business")
|
|
506
|
-
assert_equal(2, messages.size)
|
|
507
|
-
|
|
508
|
-
assert_equal(["standard3"], messages[0].env.map { |env| env["cluster"] })
|
|
509
|
-
assert_equal(1, messages[0].count)
|
|
510
|
-
assert_equal(["standard7"], messages[1].env.map { |env| env["cluster"] })
|
|
511
|
-
assert_equal(1, messages[1].count)
|
|
512
|
-
end
|
|
513
|
-
|
|
514
|
-
def test_negative_search_MUST_not_match_title_in_order_to_include_message
|
|
515
|
-
@store.report(Logger::INFO, "test", "message ABCD", env: [{ cluster: "business5" }, { cluster: "standard3" }], count: 2)
|
|
516
|
-
|
|
517
|
-
messages = @store.latest(search: "-ABCD")
|
|
518
|
-
assert_equal(0, messages.size) # cause title has ABCD
|
|
519
|
-
end
|
|
520
|
-
|
|
521
|
-
def test_positive_search_looks_at_title_OR_env
|
|
522
|
-
@store.report(Logger::INFO, "test", "message", env: [{ cluster: "business5 ABCDEFG" }, { cluster: "standard3" }], count: 2)
|
|
523
|
-
|
|
524
|
-
messages = @store.latest(search: "ABCDEFG")
|
|
525
|
-
assert_equal(1, messages.size)
|
|
526
|
-
assert_equal(1, messages[0].env.size)
|
|
527
|
-
assert_equal("business5 ABCDEFG", messages[0].env[0]["cluster"])
|
|
528
|
-
end
|
|
529
|
-
|
|
530
|
-
def test_backtrace
|
|
531
|
-
@store.report(Logger::INFO, "test", "pattern_1")
|
|
532
|
-
message = @store.latest(limit: 1).first
|
|
533
|
-
assert_match("test_backtrace", message.backtrace)
|
|
534
|
-
end
|
|
535
|
-
|
|
536
|
-
def test_ignore
|
|
537
|
-
@store.ignore = [/^test/]
|
|
538
|
-
@store.report(Logger::INFO, "test", "test it")
|
|
539
|
-
@store.report(Logger::INFO, "test", " test it")
|
|
540
|
-
|
|
541
|
-
assert_equal(1, @store.latest.count)
|
|
542
|
-
end
|
|
543
|
-
|
|
544
|
-
def test_solve
|
|
545
|
-
Logster.config.application_version = "abc"
|
|
546
|
-
|
|
547
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
548
|
-
m = @store.report(Logger::WARN, "application", "test error2", backtrace: "backtrace1")
|
|
549
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace2")
|
|
550
|
-
|
|
551
|
-
assert_equal(3, @store.latest.count)
|
|
552
|
-
|
|
553
|
-
@store.solve(m.key)
|
|
554
|
-
|
|
555
|
-
assert_equal(1, @store.latest.count)
|
|
556
|
-
|
|
557
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
558
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
559
|
-
|
|
560
|
-
assert_equal(2, @store.latest.count)
|
|
561
|
-
|
|
562
|
-
ensure
|
|
563
|
-
Logster.config.application_version = nil
|
|
564
|
-
end
|
|
565
|
-
|
|
566
|
-
def test_solve_grouped
|
|
567
|
-
Logster.config.allow_grouping = true
|
|
568
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
569
|
-
m = @store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "efg" })
|
|
570
|
-
|
|
571
|
-
assert_equal(1, @store.latest.count)
|
|
572
|
-
|
|
573
|
-
@store.solve(m.key)
|
|
574
|
-
|
|
575
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
576
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "efg" })
|
|
577
|
-
|
|
578
|
-
assert_equal(0, @store.latest.count)
|
|
579
|
-
|
|
580
|
-
ensure
|
|
581
|
-
Logster.config.allow_grouping = false
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
def test_clears_solved
|
|
585
|
-
m = @store.report(Logger::WARN, "application", "test error2", backtrace: "backtrace1", env: { "application_version" => "abc" })
|
|
586
|
-
@store.solve(m.key)
|
|
587
|
-
|
|
588
|
-
assert_equal(1, @store.solved.length)
|
|
589
|
-
|
|
590
|
-
@store.clear
|
|
591
|
-
assert_equal(0, @store.solved.length)
|
|
592
|
-
end
|
|
593
|
-
|
|
594
|
-
def test_solving_with_some_missing_version
|
|
595
|
-
|
|
596
|
-
m = @store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
597
|
-
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
598
|
-
|
|
599
|
-
@store.solve(m.key)
|
|
600
|
-
|
|
601
|
-
assert_equal(1, @store.latest.count)
|
|
602
|
-
end
|
|
603
|
-
|
|
604
|
-
def test_env
|
|
605
|
-
env = Rack::MockRequest.env_for("/test").merge(
|
|
606
|
-
"HTTP_HOST" => "www.site.com",
|
|
607
|
-
"HTTP_USER_AGENT" => "SOME WHERE"
|
|
608
|
-
)
|
|
609
|
-
orig = env.dup
|
|
610
|
-
orig["test"] = "tests"
|
|
611
|
-
orig["test1"] = "tests1"
|
|
612
|
-
Logster.add_to_env(env, "test", "tests")
|
|
613
|
-
Logster.add_to_env(env, "test1", "tests1")
|
|
614
|
-
|
|
615
|
-
orig.delete_if do |k, v|
|
|
616
|
-
!%w{
|
|
617
|
-
HTTP_HOST
|
|
618
|
-
REQUEST_METHOD
|
|
619
|
-
HTTP_USER_AGENT
|
|
620
|
-
test
|
|
621
|
-
test1
|
|
622
|
-
}.include? k
|
|
623
|
-
end
|
|
624
|
-
|
|
625
|
-
@store.report(Logger::INFO, "test", "test", env: env)
|
|
626
|
-
|
|
627
|
-
env = @store.latest.last.env
|
|
628
|
-
|
|
629
|
-
env.delete "hostname"
|
|
630
|
-
env.delete "process_id"
|
|
631
|
-
|
|
632
|
-
assert_equal(orig, env)
|
|
633
|
-
end
|
|
634
|
-
|
|
635
|
-
def test_rate_limits
|
|
636
|
-
%w{minute hour}.each do |duration|
|
|
637
|
-
begin
|
|
638
|
-
called = false
|
|
639
|
-
|
|
640
|
-
assert_instance_of(
|
|
641
|
-
Logster::RedisRateLimiter,
|
|
642
|
-
@store.public_send("register_rate_limit_per_#{duration}", Logger::WARN, 0) do
|
|
643
|
-
called = true
|
|
644
|
-
end
|
|
645
|
-
)
|
|
646
|
-
|
|
647
|
-
@store.report(Logger::WARN, "test", "test")
|
|
648
|
-
assert called
|
|
649
|
-
ensure
|
|
650
|
-
reset_redis
|
|
651
|
-
end
|
|
652
|
-
end
|
|
653
|
-
end
|
|
654
|
-
|
|
655
|
-
def test_rate_limits_only_checks_when_message_is_bumped_or_saved
|
|
656
|
-
Logster.config.allow_grouping = true
|
|
657
|
-
Logster.config.application_version = 'abc'
|
|
658
|
-
|
|
659
|
-
@store.ignore = [/^ActiveRecord::RecordNotFound/]
|
|
660
|
-
rate_limit = @store.register_rate_limit_per_minute(Logger::WARN, 0)
|
|
661
|
-
|
|
662
|
-
message = @store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
663
|
-
assert_equal(1, rate_limit.retrieve_rate)
|
|
664
|
-
|
|
665
|
-
@store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
666
|
-
assert_equal(2, rate_limit.retrieve_rate)
|
|
667
|
-
|
|
668
|
-
@store.solve(message.key)
|
|
669
|
-
@store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
670
|
-
assert_equal(2, rate_limit.retrieve_rate)
|
|
671
|
-
|
|
672
|
-
@store.report(Logger::WARN, 'message 2', "Error!")
|
|
673
|
-
assert_equal(3, rate_limit.retrieve_rate)
|
|
674
|
-
|
|
675
|
-
@store.report(Logger::WARN, 'message 3', "ActiveRecord::RecordNotFound")
|
|
676
|
-
assert_equal(3, rate_limit.retrieve_rate)
|
|
677
|
-
ensure
|
|
678
|
-
Logster.config.allow_grouping = false
|
|
679
|
-
Logster.config.application_version = nil
|
|
680
|
-
reset_redis
|
|
681
|
-
end
|
|
682
|
-
|
|
683
|
-
def test_rate_limits_with_prefix
|
|
684
|
-
begin
|
|
685
|
-
time = Time.now
|
|
686
|
-
Timecop.freeze(time)
|
|
687
|
-
current_namespace = 'first'
|
|
688
|
-
@store.redis_prefix = Proc.new { current_namespace }
|
|
689
|
-
|
|
690
|
-
called_first = 0
|
|
691
|
-
called_second = 0
|
|
692
|
-
|
|
693
|
-
@store.register_rate_limit_per_minute(Logger::WARN, 0) { called_first += 1 }
|
|
694
|
-
@store.report(Logger::WARN, "test", "test")
|
|
695
|
-
assert_equal(1, called_first)
|
|
696
|
-
|
|
697
|
-
current_namespace = 'second'
|
|
698
|
-
@store.register_rate_limit_per_minute(Logger::WARN, 0) { called_second += 1 }
|
|
699
|
-
@store.report(Logger::WARN, "test", "test")
|
|
700
|
-
assert_equal(1, called_first)
|
|
701
|
-
assert_equal(1, called_second)
|
|
702
|
-
|
|
703
|
-
Timecop.freeze(time + 10) do
|
|
704
|
-
current_namespace = 'first'
|
|
705
|
-
@store.report(Logger::WARN, "test", "test")
|
|
706
|
-
|
|
707
|
-
assert_equal(2, called_first)
|
|
708
|
-
assert_equal(1, called_second)
|
|
709
|
-
end
|
|
710
|
-
ensure
|
|
711
|
-
reset_redis
|
|
712
|
-
end
|
|
713
|
-
end
|
|
714
|
-
|
|
715
|
-
private
|
|
716
|
-
|
|
717
|
-
def reset_redis
|
|
718
|
-
@store.redis.flushall
|
|
719
|
-
end
|
|
720
|
-
end
|
|
1
|
+
require_relative '../test_helper'
|
|
2
|
+
require 'logster/redis_store'
|
|
3
|
+
require 'rack'
|
|
4
|
+
|
|
5
|
+
class TestRedisStore < Minitest::Test
|
|
6
|
+
|
|
7
|
+
def setup
|
|
8
|
+
@store = Logster::RedisStore.new(Redis.new)
|
|
9
|
+
@store.clear_all
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def teardown
|
|
13
|
+
@store.clear_all
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_delete
|
|
17
|
+
env = { test_env: "this is env" }
|
|
18
|
+
msg = @store.report(Logger::WARN, "test", "testing", env: env)
|
|
19
|
+
@store.delete(msg)
|
|
20
|
+
latest = @store.latest
|
|
21
|
+
|
|
22
|
+
assert_equal(0, latest.length)
|
|
23
|
+
assert_nil(@store.get_env(msg.key))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_latest
|
|
27
|
+
@store.report(Logger::WARN, "test", "IGNORE")
|
|
28
|
+
@store.report(Logger::WARN, "test", "This is a warning")
|
|
29
|
+
@store.report(Logger::WARN, "test", "This is another warning")
|
|
30
|
+
|
|
31
|
+
latest = @store.latest(limit: 2)
|
|
32
|
+
|
|
33
|
+
assert_equal(2, latest.length)
|
|
34
|
+
assert_equal("This is a warning", latest[0].message)
|
|
35
|
+
assert_equal("This is another warning", latest[1].message)
|
|
36
|
+
assert_equal(Logger::WARN, latest[1].severity)
|
|
37
|
+
assert_equal("test", latest[1].progname)
|
|
38
|
+
assert(!latest[1].key.nil?)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_latest_after
|
|
42
|
+
10.times do |i|
|
|
43
|
+
@store.report(Logger::WARN, "test", "A#{i}")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
message = @store.latest[-1]
|
|
47
|
+
|
|
48
|
+
3.times do |i|
|
|
49
|
+
@store.report(Logger::WARN, "test", i.to_s)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
message = @store.latest(after: message.key, limit: 3)[0]
|
|
53
|
+
|
|
54
|
+
assert_equal("0", message.message)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_latest_before
|
|
58
|
+
10.times do
|
|
59
|
+
@store.report(Logger::WARN, "test", "A")
|
|
60
|
+
end
|
|
61
|
+
10.times do
|
|
62
|
+
@store.report(Logger::WARN, "test", "B")
|
|
63
|
+
end
|
|
64
|
+
10.times do
|
|
65
|
+
@store.report(Logger::WARN, "test", "C")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
messages = @store.latest(limit: 10)
|
|
69
|
+
assert_equal("C", messages[0].message)
|
|
70
|
+
assert_equal(10, messages.length)
|
|
71
|
+
|
|
72
|
+
messages = @store.latest(limit: 10, before: messages[0].key)
|
|
73
|
+
assert_equal("B", messages[0].message)
|
|
74
|
+
assert_equal(10, messages.length)
|
|
75
|
+
|
|
76
|
+
messages = @store.latest(limit: 10, before: messages[0].key)
|
|
77
|
+
assert_equal("A", messages[0].message)
|
|
78
|
+
assert_equal(10, messages.length)
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_get
|
|
83
|
+
a_env = { "a_message" => "A MESSAGE" }
|
|
84
|
+
a_message = @store.report(Logger::WARN, "test", "A", env: a_env)
|
|
85
|
+
b_message = @store.report(Logger::WARN, "test", "B")
|
|
86
|
+
@store.report(Logger::WARN, "test", "C")
|
|
87
|
+
|
|
88
|
+
a_message = @store.get(a_message.key)
|
|
89
|
+
assert_equal("A", a_message.message)
|
|
90
|
+
assert_equal("B", b_message.message)
|
|
91
|
+
assert(a_env <= a_message.env)
|
|
92
|
+
|
|
93
|
+
a_message = @store.get(a_message.key, load_env: false)
|
|
94
|
+
assert_equal("A", a_message.message)
|
|
95
|
+
assert_nil(a_message.env)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_save_saves_env_separately
|
|
99
|
+
env = { "myenv" => "thisisenv" }
|
|
100
|
+
message = @store.report(Logger::WARN, "test", "title", env: env)
|
|
101
|
+
message = @store.get(message.key, load_env: false)
|
|
102
|
+
assert_nil(message.env)
|
|
103
|
+
|
|
104
|
+
message = @store.get(message.key)
|
|
105
|
+
assert(env <= message.env)
|
|
106
|
+
|
|
107
|
+
assert(env <= @store.get_env(message.key))
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_bulk_get
|
|
111
|
+
keys = []
|
|
112
|
+
|
|
113
|
+
5.times do |n|
|
|
114
|
+
env = n == 0 ? nil : { "test_#{n}" => "envsss" }
|
|
115
|
+
keys << @store.report(Logger::WARN, "progname", "test_#{n}", env: env).key
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
messages = @store.bulk_get(keys)
|
|
119
|
+
|
|
120
|
+
5.times do |n|
|
|
121
|
+
msg = messages[n]
|
|
122
|
+
assert_equal("test_#{n}", msg.message)
|
|
123
|
+
if n == 0
|
|
124
|
+
assert_equal(Logster::Message.default_env, msg.env)
|
|
125
|
+
else
|
|
126
|
+
assert({ "test_#{n}" => "envsss" } <= msg.env)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_get_env
|
|
132
|
+
env = { "my_little_env" => "some value" }
|
|
133
|
+
message = @store.report(Logger::WARN, "test", "A", env: env)
|
|
134
|
+
assert(env <= @store.get_env(message.key))
|
|
135
|
+
assert_nil(@store.get_env("nonexistentkey"))
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_replace_and_bump
|
|
139
|
+
old_env = { "old_env" => "old value" }
|
|
140
|
+
message = @store.report(Logger::WARN, "test", "A", env: old_env)
|
|
141
|
+
|
|
142
|
+
unsaved_env = { "unsaved_env" => "lost value" }
|
|
143
|
+
message.env = unsaved_env
|
|
144
|
+
|
|
145
|
+
@store.replace_and_bump(message, save_env: false)
|
|
146
|
+
|
|
147
|
+
message = @store.get(message.key)
|
|
148
|
+
assert(old_env <= message.env)
|
|
149
|
+
refute(unsaved_env <= message.env)
|
|
150
|
+
|
|
151
|
+
saved_env = { "saved_env" => "saved value!" }
|
|
152
|
+
message.env = saved_env
|
|
153
|
+
|
|
154
|
+
@store.replace_and_bump(message)
|
|
155
|
+
|
|
156
|
+
message = @store.get(message.key)
|
|
157
|
+
assert(saved_env == message.env)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_backward_compatibility_no_loss_of_data
|
|
161
|
+
# previously we were storing env samples as a part of the main message json
|
|
162
|
+
# now we've switched to storing samples separately from the main message
|
|
163
|
+
# we need to make we don't lose env data of messages stored the old way
|
|
164
|
+
# when we migrate to the new system
|
|
165
|
+
|
|
166
|
+
# it probably makes sense to remove this test after a while (say 6-12 months)
|
|
167
|
+
|
|
168
|
+
Logster.config.allow_grouping = true
|
|
169
|
+
backtrace = "fake backtrace"
|
|
170
|
+
env = { "some_env" => "some env" }
|
|
171
|
+
message = Logster::Message.new(Logger::WARN, "", "title", count: 60)
|
|
172
|
+
message.env = env
|
|
173
|
+
message.backtrace = backtrace
|
|
174
|
+
|
|
175
|
+
@store.save(message)
|
|
176
|
+
|
|
177
|
+
# hack to force env to be stored with the main message json
|
|
178
|
+
@store.redis.hset(@store.send("hash_key"), message.key, message.to_json(exclude_env: false))
|
|
179
|
+
|
|
180
|
+
another_env = { "another_env" => "more env" }
|
|
181
|
+
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
182
|
+
message = @store.get(message.key)
|
|
183
|
+
|
|
184
|
+
assert(env <= message.env)
|
|
185
|
+
assert_equal(61, message.count)
|
|
186
|
+
# another_env is not merged cause count is 60, only the count is updated
|
|
187
|
+
|
|
188
|
+
# make sure we are now storing env samples separately
|
|
189
|
+
message = @store.get(message.key, load_env: false)
|
|
190
|
+
assert_nil(message.env)
|
|
191
|
+
ensure
|
|
192
|
+
Logster.config.allow_grouping = false
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_backward_compatibility_no_loss_of_data_2
|
|
196
|
+
# same story as the test above, just a bit different
|
|
197
|
+
|
|
198
|
+
Logster.config.allow_grouping = true
|
|
199
|
+
backtrace = "fake backtrace"
|
|
200
|
+
env = { "some_env" => "some env" }
|
|
201
|
+
message = Logster::Message.new(Logger::WARN, "", "title")
|
|
202
|
+
message.env = env
|
|
203
|
+
message.backtrace = backtrace
|
|
204
|
+
|
|
205
|
+
@store.save(message)
|
|
206
|
+
|
|
207
|
+
# hack to force env to be stored with the main message json
|
|
208
|
+
@store.redis.hset(@store.send("hash_key"), message.key, message.to_json(exclude_env: false))
|
|
209
|
+
|
|
210
|
+
another_env = { "another_env" => "more env" }
|
|
211
|
+
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
212
|
+
message = @store.get(message.key)
|
|
213
|
+
|
|
214
|
+
assert_instance_of(Array, message.env)
|
|
215
|
+
assert(env <= message.env[0])
|
|
216
|
+
assert(another_env <= message.env[1])
|
|
217
|
+
assert_equal(2, message.env.size)
|
|
218
|
+
assert_equal(2, message.count)
|
|
219
|
+
|
|
220
|
+
# make sure we are now storing env samples separately
|
|
221
|
+
message = @store.get(message.key, load_env: false)
|
|
222
|
+
assert_nil(message.env)
|
|
223
|
+
ensure
|
|
224
|
+
Logster.config.allow_grouping = false
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_merging_performance
|
|
228
|
+
Logster.config.allow_grouping = true
|
|
229
|
+
backtrace = "fake backtrace"
|
|
230
|
+
env = { "some_env" => "some env" }
|
|
231
|
+
another_env = { "another_env" => "more env" }
|
|
232
|
+
yet_another_env = { "moaar_env" => "more env" }
|
|
233
|
+
|
|
234
|
+
@store.report(Logger::WARN, "", "title", backtrace: backtrace, env: env, count: 49)
|
|
235
|
+
|
|
236
|
+
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: another_env)
|
|
237
|
+
assert_instance_of(Array, message.env)
|
|
238
|
+
assert_equal(2, message.env.size)
|
|
239
|
+
assert(env <= message.env[0])
|
|
240
|
+
assert(another_env <= message.env[1])
|
|
241
|
+
|
|
242
|
+
message = @store.report(Logger::WARN, "", "title", backtrace: backtrace, env: yet_another_env)
|
|
243
|
+
# we don't need to load env from redis cause we don't
|
|
244
|
+
# need to merge new env samples if count is 50 or more
|
|
245
|
+
assert_nil(message.env)
|
|
246
|
+
ensure
|
|
247
|
+
Logster.config.allow_grouping = false
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def test_backlog
|
|
251
|
+
env = { "backlog_test" => "BACKLOG" }
|
|
252
|
+
@store.max_backlog = 1
|
|
253
|
+
deleted_msg = @store.report(Logger::WARN, "test", "A")
|
|
254
|
+
@store.report(Logger::WARN, "test", "A")
|
|
255
|
+
@store.report(Logger::WARN, "test", "A")
|
|
256
|
+
@store.report(Logger::WARN, "test", "B", env: env)
|
|
257
|
+
|
|
258
|
+
latest = @store.latest
|
|
259
|
+
|
|
260
|
+
assert_equal(1, latest.length)
|
|
261
|
+
assert_equal("B", latest[0].message)
|
|
262
|
+
assert(env <= latest[0].env)
|
|
263
|
+
assert_nil(@store.get(deleted_msg.key))
|
|
264
|
+
assert_nil(@store.get_env(deleted_msg.key))
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def test_save_unsave
|
|
268
|
+
@store.max_backlog = 3
|
|
269
|
+
@store.report(Logger::WARN, "test", "A")
|
|
270
|
+
b_message = @store.report(Logger::WARN, "test", "B")
|
|
271
|
+
@store.protect b_message.key
|
|
272
|
+
c_message = @store.report(Logger::WARN, "test", "C")
|
|
273
|
+
@store.protect c_message.key
|
|
274
|
+
@store.report(Logger::WARN, "test", "D")
|
|
275
|
+
|
|
276
|
+
latest = @store.latest
|
|
277
|
+
|
|
278
|
+
assert_equal(3, latest.length)
|
|
279
|
+
assert_equal("B", latest[0].message)
|
|
280
|
+
assert_equal("C", latest[1].message)
|
|
281
|
+
assert_equal(true, latest[1].protected)
|
|
282
|
+
assert_equal("D", latest[2].message)
|
|
283
|
+
|
|
284
|
+
# Saved messages still accessible by key
|
|
285
|
+
assert_equal("B", @store.get(b_message.key).message)
|
|
286
|
+
assert_equal(true, @store.get(b_message.key).protected)
|
|
287
|
+
|
|
288
|
+
# Unsave does not delete message if still recent
|
|
289
|
+
@store.unprotect c_message.key
|
|
290
|
+
assert_equal("C", @store.get(c_message.key).message)
|
|
291
|
+
assert_equal(false, @store.get(c_message.key).protected)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def test_clear
|
|
295
|
+
env = { "clear_env" => "cllleear" }
|
|
296
|
+
@store.max_backlog = 25
|
|
297
|
+
a_message = @store.report(Logger::WARN, "test", "A", timestamp: Time.now - (24 * 60 * 60), env: env)
|
|
298
|
+
@store.protect a_message.key
|
|
299
|
+
20.times do
|
|
300
|
+
@store.report(Logger::WARN, "test", "B", env: env)
|
|
301
|
+
end
|
|
302
|
+
c_message = @store.report(Logger::WARN, "test", "C", timestamp: Time.now + (24 * 60 * 60), env: env)
|
|
303
|
+
@store.protect c_message.key
|
|
304
|
+
d_message = @store.report(Logger::WARN, "test", "D", env: env)
|
|
305
|
+
10.times do
|
|
306
|
+
@store.report(Logger::WARN, "test", "E", env: env)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
latest = @store.latest
|
|
310
|
+
assert_equal(25, latest.length)
|
|
311
|
+
|
|
312
|
+
@store.clear
|
|
313
|
+
|
|
314
|
+
# Protected messages are still accessible by their key
|
|
315
|
+
assert_equal("C", @store.get(c_message.key).message)
|
|
316
|
+
assert(env <= @store.get_env(c_message.key))
|
|
317
|
+
# Unprotected messages are gone
|
|
318
|
+
assert_nil(@store.get(d_message.key))
|
|
319
|
+
assert_nil(@store.get_env(d_message.key))
|
|
320
|
+
|
|
321
|
+
# The latest list is rebuilt with protected messages, earliest first
|
|
322
|
+
# Including messages that previously fell off (A)
|
|
323
|
+
latest = @store.latest
|
|
324
|
+
assert_equal(2, latest.length)
|
|
325
|
+
assert_equal("A", latest[0].message)
|
|
326
|
+
assert_equal("C", latest[1].message)
|
|
327
|
+
assert(env <= latest[0].env)
|
|
328
|
+
assert(env <= latest[1].env)
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def test_hash_cleanup
|
|
332
|
+
@store.max_backlog = 2
|
|
333
|
+
a_message = @store.report(Logger::WARN, "test", "A")
|
|
334
|
+
@store.report(Logger::WARN, "test", "B")
|
|
335
|
+
@store.report(Logger::WARN, "test", "C")
|
|
336
|
+
|
|
337
|
+
assert_nil(@store.get(a_message.key))
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def test_filter_latest
|
|
341
|
+
@store.report(Logger::INFO, "test", "A")
|
|
342
|
+
@store.report(Logger::WARN, "test", "B")
|
|
343
|
+
|
|
344
|
+
messages = @store.latest
|
|
345
|
+
assert_equal(2, messages.length)
|
|
346
|
+
|
|
347
|
+
messages = @store.latest(after: messages.last.key)
|
|
348
|
+
assert_equal(0, messages.length)
|
|
349
|
+
|
|
350
|
+
10.times do
|
|
351
|
+
@store.report(Logger::INFO, "test", "A")
|
|
352
|
+
end
|
|
353
|
+
@store.report(Logger::ERROR, "test", "C")
|
|
354
|
+
10.times do
|
|
355
|
+
@store.report(Logger::INFO, "test", "A")
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2)
|
|
359
|
+
|
|
360
|
+
assert_equal(2, latest.length)
|
|
361
|
+
assert_equal("B", latest[0].message)
|
|
362
|
+
assert_equal("C", latest[1].message)
|
|
363
|
+
|
|
364
|
+
@store.report(Logger::ERROR, "test", "E")
|
|
365
|
+
# respects after
|
|
366
|
+
latest = @store.latest(severity: [Logger::ERROR, Logger::WARN], limit: 2, after: latest[1].key)
|
|
367
|
+
assert_equal(1, latest.length)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def test_search
|
|
371
|
+
@store.report(Logger::INFO, "test", "ABCDEFG")
|
|
372
|
+
@store.report(Logger::INFO, "test", "TUVWXYZ")
|
|
373
|
+
|
|
374
|
+
messages = @store.latest
|
|
375
|
+
assert_equal(2, messages.length)
|
|
376
|
+
|
|
377
|
+
latest = @store.latest(search: "TUVWXYZ")
|
|
378
|
+
|
|
379
|
+
assert_equal(1, latest.length)
|
|
380
|
+
assert_equal("TUVWXYZ", latest[0].message)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def test_search_exclude_results
|
|
384
|
+
@store.report(Logger::INFO, "test", "ABCDEFG")
|
|
385
|
+
@store.report(Logger::INFO, "test", "TUVWXYZ")
|
|
386
|
+
|
|
387
|
+
messages = @store.latest
|
|
388
|
+
assert_equal(2, messages.length)
|
|
389
|
+
|
|
390
|
+
latest = @store.latest(search: "-ABCD")
|
|
391
|
+
|
|
392
|
+
assert_equal(1, latest.length)
|
|
393
|
+
assert_equal("TUVWXYZ", latest[0].message)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_regex_search
|
|
397
|
+
@store.report(Logger::INFO, "test", "pattern_1")
|
|
398
|
+
@store.report(Logger::INFO, "test", "pattern_2")
|
|
399
|
+
|
|
400
|
+
messages = @store.latest
|
|
401
|
+
assert_equal(2, messages.length)
|
|
402
|
+
|
|
403
|
+
latest = @store.latest(search: /^pattern_[1]$/)
|
|
404
|
+
|
|
405
|
+
assert_equal(1, latest.length)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def test_env_search
|
|
409
|
+
@store.report(Logger::INFO, "test", "message ABCD", env: { cluster: "business5" })
|
|
410
|
+
@store.report(Logger::INFO, "test", "message WXYZ", env: { cluster: "business7" })
|
|
411
|
+
|
|
412
|
+
messages = @store.latest
|
|
413
|
+
assert_equal(2, messages.length)
|
|
414
|
+
|
|
415
|
+
latest = @store.latest(search: "business5")
|
|
416
|
+
|
|
417
|
+
assert_equal(1, latest.length)
|
|
418
|
+
assert_equal("message ABCD", latest[0].message)
|
|
419
|
+
|
|
420
|
+
latest = @store.latest(search: "-business5")
|
|
421
|
+
|
|
422
|
+
assert_equal(1, latest.length)
|
|
423
|
+
assert_equal("message WXYZ", latest[0].message)
|
|
424
|
+
|
|
425
|
+
latest = @store.latest(search: /business/)
|
|
426
|
+
|
|
427
|
+
assert_equal(2, latest.length)
|
|
428
|
+
assert_equal(["message ABCD", "message WXYZ"], latest.map(&:message).sort)
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def test_array_env_search_preserve_env
|
|
432
|
+
m1_original_env = [{ cluster: "business5" }, { cluster: "standard3" }]
|
|
433
|
+
m2_original_env = [{ cluster: "business2" }, { cluster: "standard7" }]
|
|
434
|
+
|
|
435
|
+
@store.report(Logger::INFO, "test", "message ABCD", env: m1_original_env, count: 2)
|
|
436
|
+
@store.report(Logger::INFO, "test", "message WXYZ", env: m2_original_env, count: 2)
|
|
437
|
+
|
|
438
|
+
messages = @store.latest
|
|
439
|
+
assert_equal(2, messages.length)
|
|
440
|
+
|
|
441
|
+
m1_key = messages[0].key
|
|
442
|
+
m2_key = messages[1].key
|
|
443
|
+
|
|
444
|
+
messages = @store.latest(search: "business")
|
|
445
|
+
assert_equal(2, messages.size)
|
|
446
|
+
|
|
447
|
+
# any hashes that don't match should be stripped from the env
|
|
448
|
+
# array but only temporarily until it's sent to the client
|
|
449
|
+
# env array should remain untouched in redis memory
|
|
450
|
+
assert_equal(["business5"], messages[0].env.map { |env| env["cluster"] })
|
|
451
|
+
assert_equal(1, messages[0].count)
|
|
452
|
+
assert_equal(["business2"], messages[1].env.map { |env| env["cluster"] })
|
|
453
|
+
assert_equal(1, messages[1].count)
|
|
454
|
+
|
|
455
|
+
m1 = @store.get(m1_key)
|
|
456
|
+
m2 = @store.get(m2_key)
|
|
457
|
+
# original env should preserved in redis memory
|
|
458
|
+
assert_equal(["business5", "standard3"], m1.env.map { |env| env["cluster"] })
|
|
459
|
+
assert_equal(["business2", "standard7"], m2.env.map { |env| env["cluster"] })
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
def test_both_env_and_title_match_search
|
|
463
|
+
@store.report(Logger::INFO, "test", "message", env: [{ cluster: "business15" }])
|
|
464
|
+
@store.report(Logger::INFO, "test", "message2", env: { cluster: "business15" })
|
|
465
|
+
|
|
466
|
+
messages = @store.latest
|
|
467
|
+
assert_equal(2, messages.size)
|
|
468
|
+
|
|
469
|
+
messages = @store.latest(search: "-business15")
|
|
470
|
+
assert_equal(0, messages.size)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def test_data_kept_intact_on_report_when_env_matches_an_ignore_pattern
|
|
474
|
+
begin
|
|
475
|
+
Logster.config.allow_grouping = true
|
|
476
|
+
backtrace = caller
|
|
477
|
+
message = @store.report(Logger::WARN, "", "my error", env: { whatever: "something", backtrace: backtrace })
|
|
478
|
+
|
|
479
|
+
@store.ignore = [
|
|
480
|
+
Logster::IgnorePattern.new("business")
|
|
481
|
+
]
|
|
482
|
+
@store.report(Logger::WARN, "", "my error", env: { cluster: "business17", backtrace: backtrace })
|
|
483
|
+
|
|
484
|
+
message = @store.get(message.key)
|
|
485
|
+
assert(Array === message.env)
|
|
486
|
+
assert_equal(2, message.env.size)
|
|
487
|
+
# message2 shouldn't vanish even if
|
|
488
|
+
# its env matches an ignore pattern
|
|
489
|
+
# however it should be merged with message1
|
|
490
|
+
assert_equal("business17", message.env[1]["cluster"])
|
|
491
|
+
ensure
|
|
492
|
+
# reset so it doesn't affect other tests
|
|
493
|
+
@store.ignore = nil
|
|
494
|
+
Logster.config.allow_grouping = false
|
|
495
|
+
end
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def test_array_env_negative_search
|
|
499
|
+
@store.report(Logger::INFO, "test", "message ABCD", env: [{ cluster: "business5" }, { cluster: "standard3" }], count: 2)
|
|
500
|
+
@store.report(Logger::INFO, "test", "message WXYZ", env: [{ cluster: "business2" }, { cluster: "standard7" }], count: 2)
|
|
501
|
+
|
|
502
|
+
messages = @store.latest
|
|
503
|
+
assert_equal(2, messages.length)
|
|
504
|
+
|
|
505
|
+
messages = @store.latest(search: "-business")
|
|
506
|
+
assert_equal(2, messages.size)
|
|
507
|
+
|
|
508
|
+
assert_equal(["standard3"], messages[0].env.map { |env| env["cluster"] })
|
|
509
|
+
assert_equal(1, messages[0].count)
|
|
510
|
+
assert_equal(["standard7"], messages[1].env.map { |env| env["cluster"] })
|
|
511
|
+
assert_equal(1, messages[1].count)
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def test_negative_search_MUST_not_match_title_in_order_to_include_message
|
|
515
|
+
@store.report(Logger::INFO, "test", "message ABCD", env: [{ cluster: "business5" }, { cluster: "standard3" }], count: 2)
|
|
516
|
+
|
|
517
|
+
messages = @store.latest(search: "-ABCD")
|
|
518
|
+
assert_equal(0, messages.size) # cause title has ABCD
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def test_positive_search_looks_at_title_OR_env
|
|
522
|
+
@store.report(Logger::INFO, "test", "message", env: [{ cluster: "business5 ABCDEFG" }, { cluster: "standard3" }], count: 2)
|
|
523
|
+
|
|
524
|
+
messages = @store.latest(search: "ABCDEFG")
|
|
525
|
+
assert_equal(1, messages.size)
|
|
526
|
+
assert_equal(1, messages[0].env.size)
|
|
527
|
+
assert_equal("business5 ABCDEFG", messages[0].env[0]["cluster"])
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def test_backtrace
|
|
531
|
+
@store.report(Logger::INFO, "test", "pattern_1")
|
|
532
|
+
message = @store.latest(limit: 1).first
|
|
533
|
+
assert_match("test_backtrace", message.backtrace)
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def test_ignore
|
|
537
|
+
@store.ignore = [/^test/]
|
|
538
|
+
@store.report(Logger::INFO, "test", "test it")
|
|
539
|
+
@store.report(Logger::INFO, "test", " test it")
|
|
540
|
+
|
|
541
|
+
assert_equal(1, @store.latest.count)
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def test_solve
|
|
545
|
+
Logster.config.application_version = "abc"
|
|
546
|
+
|
|
547
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
548
|
+
m = @store.report(Logger::WARN, "application", "test error2", backtrace: "backtrace1")
|
|
549
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace2")
|
|
550
|
+
|
|
551
|
+
assert_equal(3, @store.latest.count)
|
|
552
|
+
|
|
553
|
+
@store.solve(m.key)
|
|
554
|
+
|
|
555
|
+
assert_equal(1, @store.latest.count)
|
|
556
|
+
|
|
557
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
558
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
559
|
+
|
|
560
|
+
assert_equal(2, @store.latest.count)
|
|
561
|
+
|
|
562
|
+
ensure
|
|
563
|
+
Logster.config.application_version = nil
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def test_solve_grouped
|
|
567
|
+
Logster.config.allow_grouping = true
|
|
568
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
569
|
+
m = @store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "efg" })
|
|
570
|
+
|
|
571
|
+
assert_equal(1, @store.latest.count)
|
|
572
|
+
|
|
573
|
+
@store.solve(m.key)
|
|
574
|
+
|
|
575
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
576
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "efg" })
|
|
577
|
+
|
|
578
|
+
assert_equal(0, @store.latest.count)
|
|
579
|
+
|
|
580
|
+
ensure
|
|
581
|
+
Logster.config.allow_grouping = false
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
def test_clears_solved
|
|
585
|
+
m = @store.report(Logger::WARN, "application", "test error2", backtrace: "backtrace1", env: { "application_version" => "abc" })
|
|
586
|
+
@store.solve(m.key)
|
|
587
|
+
|
|
588
|
+
assert_equal(1, @store.solved.length)
|
|
589
|
+
|
|
590
|
+
@store.clear
|
|
591
|
+
assert_equal(0, @store.solved.length)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def test_solving_with_some_missing_version
|
|
595
|
+
|
|
596
|
+
m = @store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1", env: { "application_version" => "xyz" })
|
|
597
|
+
@store.report(Logger::WARN, "application", "test error1", backtrace: "backtrace1")
|
|
598
|
+
|
|
599
|
+
@store.solve(m.key)
|
|
600
|
+
|
|
601
|
+
assert_equal(1, @store.latest.count)
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
def test_env
|
|
605
|
+
env = Rack::MockRequest.env_for("/test").merge(
|
|
606
|
+
"HTTP_HOST" => "www.site.com",
|
|
607
|
+
"HTTP_USER_AGENT" => "SOME WHERE"
|
|
608
|
+
)
|
|
609
|
+
orig = env.dup
|
|
610
|
+
orig["test"] = "tests"
|
|
611
|
+
orig["test1"] = "tests1"
|
|
612
|
+
Logster.add_to_env(env, "test", "tests")
|
|
613
|
+
Logster.add_to_env(env, "test1", "tests1")
|
|
614
|
+
|
|
615
|
+
orig.delete_if do |k, v|
|
|
616
|
+
!%w{
|
|
617
|
+
HTTP_HOST
|
|
618
|
+
REQUEST_METHOD
|
|
619
|
+
HTTP_USER_AGENT
|
|
620
|
+
test
|
|
621
|
+
test1
|
|
622
|
+
}.include? k
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
@store.report(Logger::INFO, "test", "test", env: env)
|
|
626
|
+
|
|
627
|
+
env = @store.latest.last.env
|
|
628
|
+
|
|
629
|
+
env.delete "hostname"
|
|
630
|
+
env.delete "process_id"
|
|
631
|
+
|
|
632
|
+
assert_equal(orig, env)
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def test_rate_limits
|
|
636
|
+
%w{minute hour}.each do |duration|
|
|
637
|
+
begin
|
|
638
|
+
called = false
|
|
639
|
+
|
|
640
|
+
assert_instance_of(
|
|
641
|
+
Logster::RedisRateLimiter,
|
|
642
|
+
@store.public_send("register_rate_limit_per_#{duration}", Logger::WARN, 0) do
|
|
643
|
+
called = true
|
|
644
|
+
end
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
@store.report(Logger::WARN, "test", "test")
|
|
648
|
+
assert called
|
|
649
|
+
ensure
|
|
650
|
+
reset_redis
|
|
651
|
+
end
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
def test_rate_limits_only_checks_when_message_is_bumped_or_saved
|
|
656
|
+
Logster.config.allow_grouping = true
|
|
657
|
+
Logster.config.application_version = 'abc'
|
|
658
|
+
|
|
659
|
+
@store.ignore = [/^ActiveRecord::RecordNotFound/]
|
|
660
|
+
rate_limit = @store.register_rate_limit_per_minute(Logger::WARN, 0)
|
|
661
|
+
|
|
662
|
+
message = @store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
663
|
+
assert_equal(1, rate_limit.retrieve_rate)
|
|
664
|
+
|
|
665
|
+
@store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
666
|
+
assert_equal(2, rate_limit.retrieve_rate)
|
|
667
|
+
|
|
668
|
+
@store.solve(message.key)
|
|
669
|
+
@store.report(Logger::WARN, 'message 1', "Error!", backtrace: 'here')
|
|
670
|
+
assert_equal(2, rate_limit.retrieve_rate)
|
|
671
|
+
|
|
672
|
+
@store.report(Logger::WARN, 'message 2', "Error!")
|
|
673
|
+
assert_equal(3, rate_limit.retrieve_rate)
|
|
674
|
+
|
|
675
|
+
@store.report(Logger::WARN, 'message 3', "ActiveRecord::RecordNotFound")
|
|
676
|
+
assert_equal(3, rate_limit.retrieve_rate)
|
|
677
|
+
ensure
|
|
678
|
+
Logster.config.allow_grouping = false
|
|
679
|
+
Logster.config.application_version = nil
|
|
680
|
+
reset_redis
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
def test_rate_limits_with_prefix
|
|
684
|
+
begin
|
|
685
|
+
time = Time.now
|
|
686
|
+
Timecop.freeze(time)
|
|
687
|
+
current_namespace = 'first'
|
|
688
|
+
@store.redis_prefix = Proc.new { current_namespace }
|
|
689
|
+
|
|
690
|
+
called_first = 0
|
|
691
|
+
called_second = 0
|
|
692
|
+
|
|
693
|
+
@store.register_rate_limit_per_minute(Logger::WARN, 0) { called_first += 1 }
|
|
694
|
+
@store.report(Logger::WARN, "test", "test")
|
|
695
|
+
assert_equal(1, called_first)
|
|
696
|
+
|
|
697
|
+
current_namespace = 'second'
|
|
698
|
+
@store.register_rate_limit_per_minute(Logger::WARN, 0) { called_second += 1 }
|
|
699
|
+
@store.report(Logger::WARN, "test", "test")
|
|
700
|
+
assert_equal(1, called_first)
|
|
701
|
+
assert_equal(1, called_second)
|
|
702
|
+
|
|
703
|
+
Timecop.freeze(time + 10) do
|
|
704
|
+
current_namespace = 'first'
|
|
705
|
+
@store.report(Logger::WARN, "test", "test")
|
|
706
|
+
|
|
707
|
+
assert_equal(2, called_first)
|
|
708
|
+
assert_equal(1, called_second)
|
|
709
|
+
end
|
|
710
|
+
ensure
|
|
711
|
+
reset_redis
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
private
|
|
716
|
+
|
|
717
|
+
def reset_redis
|
|
718
|
+
@store.redis.flushall
|
|
719
|
+
end
|
|
720
|
+
end
|