logster 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -0
- data/Guardfile +2 -0
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/assets/javascript/client-app.js +69 -53
- data/assets/javascript/vendor.js +580 -559
- data/assets/stylesheets/client-app.css +1 -1
- data/client-app/README.md +2 -2
- data/client-app/app/components/env-tab.js +16 -36
- data/client-app/app/components/message-row.js +1 -1
- data/client-app/app/components/page-nav.js +30 -0
- data/client-app/app/components/patterns-list.js +2 -1
- data/client-app/app/controllers/index.js +68 -92
- data/client-app/app/controllers/show.js +6 -0
- data/client-app/app/models/group.js +20 -0
- data/client-app/app/models/message-collection.js +159 -57
- data/client-app/app/routes/index.js +0 -2
- data/client-app/app/routes/settings.js +3 -1
- data/client-app/app/styles/app.css +17 -2
- data/client-app/app/templates/components/env-tab.hbs +5 -7
- data/client-app/app/templates/components/message-info.hbs +13 -8
- data/client-app/app/templates/components/page-nav.hbs +13 -0
- data/client-app/app/templates/components/patterns-list.hbs +6 -4
- data/client-app/app/templates/index.hbs +45 -11
- data/client-app/app/templates/settings.hbs +10 -1
- data/client-app/app/templates/show.hbs +2 -0
- data/client-app/package-lock.json +2817 -1215
- data/client-app/package.json +12 -12
- data/client-app/tests/integration/components/env-tab-test.js +29 -8
- data/client-app/tests/integration/components/message-info-test.js +10 -2
- data/lib/examples/sidekiq_logster_reporter.rb +2 -0
- data/lib/logster.rb +2 -2
- data/lib/logster/base_store.rb +40 -4
- data/lib/logster/cache.rb +9 -8
- data/lib/logster/defer_logger.rb +2 -0
- data/lib/logster/group.rb +124 -0
- data/lib/logster/grouping_pattern.rb +29 -0
- data/lib/logster/ignore_pattern.rb +2 -0
- data/lib/logster/logger.rb +2 -0
- data/lib/logster/message.rb +3 -1
- data/lib/logster/middleware/reporter.rb +2 -2
- data/lib/logster/middleware/viewer.rb +12 -1
- data/lib/logster/pattern.rb +13 -0
- data/lib/logster/redis_store.rb +99 -10
- data/lib/logster/scheduler.rb +2 -0
- data/lib/logster/suppression_pattern.rb +5 -2
- data/lib/logster/version.rb +1 -1
- data/lib/logster/web.rb +2 -0
- data/logster.gemspec +4 -1
- data/test/examples/test_sidekiq_reporter_example.rb +2 -0
- data/test/fake_data/Gemfile +2 -0
- data/test/fake_data/generate.rb +2 -0
- data/test/logster/middleware/test_viewer.rb +3 -1
- data/test/logster/test_base_store.rb +2 -0
- data/test/logster/test_cache.rb +19 -12
- data/test/logster/test_defer_logger.rb +2 -0
- data/test/logster/test_group.rb +92 -0
- data/test/logster/test_ignore_pattern.rb +2 -0
- data/test/logster/test_logger.rb +3 -1
- data/test/logster/test_message.rb +2 -0
- data/test/logster/test_pattern.rb +2 -2
- data/test/logster/test_redis_rate_limiter.rb +2 -0
- data/test/logster/test_redis_store.rb +253 -0
- data/test/test_helper.rb +6 -0
- metadata +26 -6
data/client-app/package.json
CHANGED
@@ -18,20 +18,19 @@
|
|
18
18
|
"test": "ember test"
|
19
19
|
},
|
20
20
|
"devDependencies": {
|
21
|
-
"jquery": "3.4.1",
|
22
21
|
"@ember/optional-features": "^0.6.3",
|
23
22
|
"broccoli-asset-rev": "^2.7.0",
|
24
23
|
"ember-ajax": "^5.0.0",
|
25
|
-
"ember-cli": "
|
24
|
+
"ember-cli": "^3.8.3",
|
26
25
|
"ember-cli-app-version": "^3.2.0",
|
27
|
-
"ember-cli-babel": "^7.
|
28
|
-
"ember-cli-dependency-checker": "^3.
|
26
|
+
"ember-cli-babel": "^7.12.0",
|
27
|
+
"ember-cli-dependency-checker": "^3.2.0",
|
29
28
|
"ember-cli-eslint": "^4.2.3",
|
30
|
-
"ember-cli-htmlbars": "^3.
|
29
|
+
"ember-cli-htmlbars": "^3.1.0",
|
31
30
|
"ember-cli-htmlbars-inline-precompile": "^1.0.3",
|
32
31
|
"ember-cli-inject-live-reload": "^1.8.2",
|
33
32
|
"ember-cli-sri": "^2.1.1",
|
34
|
-
"ember-cli-template-lint": "^1.0.0-beta.
|
33
|
+
"ember-cli-template-lint": "^1.0.0-beta.3",
|
35
34
|
"ember-cli-uglify": "^2.1.0",
|
36
35
|
"ember-data": "~3.8.0",
|
37
36
|
"ember-export-application-global": "^2.0.0",
|
@@ -39,19 +38,20 @@
|
|
39
38
|
"ember-load-initializers": "^1.1.0",
|
40
39
|
"ember-maybe-import-regenerator": "^0.1.6",
|
41
40
|
"ember-qunit": "^3.4.1",
|
42
|
-
"ember-resolver": "^5.0
|
43
|
-
"ember-source": "
|
41
|
+
"ember-resolver": "^5.3.0",
|
42
|
+
"ember-source": "^3.8.3",
|
44
43
|
"ember-welcome-page": "^3.2.0",
|
45
|
-
"eslint-plugin-ember": "^5.
|
44
|
+
"eslint-plugin-ember": "^5.4.0",
|
45
|
+
"jquery": "3.4.1",
|
46
46
|
"loader.js": "^4.7.0",
|
47
|
-
"prettier": "^1.
|
48
|
-
"qunit-dom": "^0.8.
|
47
|
+
"prettier": "^1.19.1",
|
48
|
+
"qunit-dom": "^0.8.5"
|
49
49
|
},
|
50
50
|
"engines": {
|
51
51
|
"node": "6.* || 8.* || >= 10.*"
|
52
52
|
},
|
53
53
|
"dependencies": {
|
54
|
-
"lodash": "
|
54
|
+
"lodash": "^4.17.15",
|
55
55
|
"moment": "~2.22.2"
|
56
56
|
}
|
57
57
|
}
|
@@ -35,11 +35,18 @@ module("Integration | Component | env-tab", function(hooks) {
|
|
35
35
|
setupRenderingTest(hooks);
|
36
36
|
|
37
37
|
test("it renders", async function(assert) {
|
38
|
-
this.set("
|
39
|
-
|
38
|
+
const callback = newPosition => this.set("envPosition", newPosition);
|
39
|
+
this.setProperties({
|
40
|
+
message,
|
41
|
+
callback,
|
42
|
+
envPosition: 0
|
43
|
+
});
|
44
|
+
await render(
|
45
|
+
hbs`{{env-tab message=message envChangedAction=callback currentEnvPosition=envPosition}}`
|
46
|
+
);
|
40
47
|
|
41
48
|
assert.equal(
|
42
|
-
find(".
|
49
|
+
find(".current-number").textContent,
|
43
50
|
"1/2",
|
44
51
|
"shows the current over the total number of env objects"
|
45
52
|
);
|
@@ -71,14 +78,21 @@ module("Integration | Component | env-tab", function(hooks) {
|
|
71
78
|
});
|
72
79
|
|
73
80
|
test("it works correctly", async function(assert) {
|
74
|
-
this.set("
|
75
|
-
|
81
|
+
const callback = newPosition => this.set("envPosition", newPosition);
|
82
|
+
this.setProperties({
|
83
|
+
message,
|
84
|
+
callback,
|
85
|
+
envPosition: 0
|
86
|
+
});
|
87
|
+
await render(
|
88
|
+
hbs`{{env-tab message=message envChangedAction=callback currentEnvPosition=envPosition}}`
|
89
|
+
);
|
76
90
|
|
77
91
|
const buttons = findAll("button.nav-btn");
|
78
92
|
await click(buttons[2]);
|
79
93
|
|
80
94
|
assert.equal(
|
81
|
-
find(".
|
95
|
+
find(".current-number").textContent,
|
82
96
|
"2/2",
|
83
97
|
"shows the current over the total number of env objects"
|
84
98
|
);
|
@@ -108,8 +122,15 @@ module("Integration | Component | env-tab", function(hooks) {
|
|
108
122
|
env_expandable_keys: ["env_key_2", "default_expanded"]
|
109
123
|
});
|
110
124
|
init();
|
111
|
-
this.set("
|
112
|
-
|
125
|
+
const callback = newPosition => this.set("envPosition", newPosition);
|
126
|
+
this.setProperties({
|
127
|
+
message: message3,
|
128
|
+
callback,
|
129
|
+
envPosition: 0
|
130
|
+
});
|
131
|
+
await render(
|
132
|
+
hbs`{{env-tab message=message envChangedAction=callback currentEnvPosition=envPosition}}`
|
133
|
+
);
|
113
134
|
|
114
135
|
const trs = findAll(".env-table tr");
|
115
136
|
const expandable = trs[0];
|
@@ -17,14 +17,22 @@ module("Integration | Component | message-info", function(hooks) {
|
|
17
17
|
setupRenderingTest(hooks);
|
18
18
|
|
19
19
|
test("it renders", async function(assert) {
|
20
|
+
const callback = newPosition => this.set("currentEnvPosition", newPosition);
|
20
21
|
this.setProperties({
|
21
22
|
actionsInMenu: true,
|
22
23
|
showTitle: false,
|
23
|
-
|
24
|
+
envPosition: 0,
|
25
|
+
message,
|
26
|
+
callback
|
24
27
|
});
|
25
28
|
|
26
29
|
await render(
|
27
|
-
hbs`{{message-info
|
30
|
+
hbs`{{message-info
|
31
|
+
currentMessage=message
|
32
|
+
showTitle=showTitle
|
33
|
+
currentEnvPosition=envPosition
|
34
|
+
envChangedAction=callback
|
35
|
+
actionsInMenu=actionsInMenu}}`
|
28
36
|
);
|
29
37
|
let activeTab = find(".message-info .content.active pre");
|
30
38
|
assert.equal(
|
data/lib/logster.rb
CHANGED
@@ -7,6 +7,8 @@ require 'logster/web'
|
|
7
7
|
require 'logster/ignore_pattern'
|
8
8
|
require 'logster/pattern'
|
9
9
|
require 'logster/suppression_pattern'
|
10
|
+
require 'logster/grouping_pattern'
|
11
|
+
require 'logster/group'
|
10
12
|
require 'logster/cache'
|
11
13
|
|
12
14
|
if defined? Redis
|
@@ -17,8 +19,6 @@ else
|
|
17
19
|
end
|
18
20
|
|
19
21
|
module Logster
|
20
|
-
PATTERNS = [SuppressionPattern]
|
21
|
-
|
22
22
|
def self.logger=(logger)
|
23
23
|
@logger = logger
|
24
24
|
end
|
data/lib/logster/base_store.rb
CHANGED
@@ -115,22 +115,39 @@ module Logster
|
|
115
115
|
|
116
116
|
# increments the number of messages that have been suppressed by a pattern
|
117
117
|
def increment_ignore_count(pattern)
|
118
|
+
not_implemented
|
118
119
|
end
|
119
120
|
|
120
121
|
# removes number of suppressed messages by a pattern
|
121
122
|
def remove_ignore_count(pattern)
|
123
|
+
not_implemented
|
122
124
|
end
|
123
125
|
|
124
126
|
# returns a hash that maps patterns to the number of messages they
|
125
127
|
# have suppressed
|
126
128
|
def get_all_ignore_count
|
127
|
-
|
129
|
+
not_implemented
|
128
130
|
end
|
129
131
|
|
130
132
|
def rate_limited?(ip_address, perform: false, limit: 60)
|
131
133
|
not_implemented
|
132
134
|
end
|
133
135
|
|
136
|
+
# find all pattern groups; returns an array of Logster::Group
|
137
|
+
def find_pattern_groups(load_messages: true)
|
138
|
+
not_implemented
|
139
|
+
end
|
140
|
+
|
141
|
+
# saves an instance of Logster::Group
|
142
|
+
def save_pattern_group(group)
|
143
|
+
not_implemented
|
144
|
+
end
|
145
|
+
|
146
|
+
# removes the Logster::Group instance associated with the given pattern
|
147
|
+
def remove_pattern_group(pattern)
|
148
|
+
not_implemented
|
149
|
+
end
|
150
|
+
|
134
151
|
def report(severity, progname, msg, opts = {})
|
135
152
|
return if (!msg || (String === msg && msg.empty?)) && skip_empty
|
136
153
|
return if level && severity < level
|
@@ -164,7 +181,7 @@ module Logster
|
|
164
181
|
end
|
165
182
|
|
166
183
|
if Logster.config.enable_custom_patterns_via_ui || allow_custom_patterns
|
167
|
-
custom_ignore = @patterns_cache.fetch do
|
184
|
+
custom_ignore = @patterns_cache.fetch(Logster::SuppressionPattern::CACHE_KEY) do
|
168
185
|
Logster::SuppressionPattern.find_all(store: self)
|
169
186
|
end
|
170
187
|
return if custom_ignore.any? do |pattern|
|
@@ -194,10 +211,29 @@ module Logster
|
|
194
211
|
save message
|
195
212
|
message
|
196
213
|
end
|
214
|
+
|
215
|
+
message = similar || message
|
216
|
+
|
217
|
+
if Logster.config.enable_custom_patterns_via_ui || allow_custom_patterns
|
218
|
+
grouping_patterns = @patterns_cache.fetch(Logster::GroupingPattern::CACHE_KEY) do
|
219
|
+
Logster::GroupingPattern.find_all(store: self)
|
220
|
+
end
|
221
|
+
|
222
|
+
grouping_patterns.each do |pattern|
|
223
|
+
if message =~ pattern
|
224
|
+
group = find_pattern_groups() { |pat| pat == pattern }[0]
|
225
|
+
group ||= Logster::Group.new(pattern.inspect)
|
226
|
+
group.add_message(message)
|
227
|
+
save_pattern_group(group) if group.changed?
|
228
|
+
break
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
message
|
197
233
|
end
|
198
234
|
|
199
|
-
def
|
200
|
-
@patterns_cache.clear
|
235
|
+
def clear_patterns_cache(key)
|
236
|
+
@patterns_cache.clear(key)
|
201
237
|
end
|
202
238
|
|
203
239
|
private
|
data/lib/logster/cache.rb
CHANGED
@@ -1,20 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Logster
|
2
4
|
class Cache
|
3
5
|
def initialize(age = 2)
|
4
6
|
@age = age
|
5
|
-
@hash = {
|
7
|
+
@hash = {}
|
6
8
|
end
|
7
9
|
|
8
|
-
def fetch
|
9
|
-
if !@hash.key?(
|
10
|
-
@hash[
|
11
|
-
@hash[:created_at] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
10
|
+
def fetch(key)
|
11
|
+
if !@hash.key?(key) || @hash[key][:created_at] + @age < Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
12
|
+
@hash[key] = { data: yield, created_at: Process.clock_gettime(Process::CLOCK_MONOTONIC) }
|
12
13
|
end
|
13
|
-
@hash[:data]
|
14
|
+
@hash[key][:data]
|
14
15
|
end
|
15
16
|
|
16
|
-
def clear
|
17
|
-
@hash.delete(
|
17
|
+
def clear(key)
|
18
|
+
@hash.delete(key)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
data/lib/logster/defer_logger.rb
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Logster
|
4
|
+
class Group
|
5
|
+
MAX_SIZE = 100
|
6
|
+
|
7
|
+
attr_reader :key, :messages_keys, :timestamp, :messages
|
8
|
+
attr_accessor :changed
|
9
|
+
|
10
|
+
def initialize(key, messages_keys = [], timestamp: 0)
|
11
|
+
@key = key
|
12
|
+
@messages_keys = messages_keys || []
|
13
|
+
@timestamp = timestamp
|
14
|
+
@changed = true
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_json(json)
|
18
|
+
hash = JSON.parse(json)
|
19
|
+
group = new(
|
20
|
+
hash["key"],
|
21
|
+
hash["messages_keys"],
|
22
|
+
timestamp: hash["timestamp"] || 0
|
23
|
+
)
|
24
|
+
group.changed = false
|
25
|
+
group
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.max_size
|
29
|
+
(defined?(@max_size) && @max_size) || MAX_SIZE
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_h
|
33
|
+
{
|
34
|
+
key: @key,
|
35
|
+
messages_keys: @messages_keys,
|
36
|
+
timestamp: @timestamp
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_h_web
|
41
|
+
{
|
42
|
+
regex: @key,
|
43
|
+
count: self.count,
|
44
|
+
timestamp: @timestamp,
|
45
|
+
messages: @messages,
|
46
|
+
severity: -1,
|
47
|
+
group: true
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_json(opts = nil)
|
52
|
+
JSON.fast_generate(self.to_h, opts)
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_message(message)
|
56
|
+
if !@messages_keys.include?(message.key)
|
57
|
+
@messages_keys.unshift(message.key)
|
58
|
+
@changed = true
|
59
|
+
end
|
60
|
+
if @timestamp < message.timestamp
|
61
|
+
@timestamp = message.timestamp
|
62
|
+
@messages_keys.unshift(@messages_keys.slice!(@messages_keys.index(message.key)))
|
63
|
+
@changed = true
|
64
|
+
end
|
65
|
+
if self.count > max_size
|
66
|
+
@messages_keys.slice!(max_size..-1)
|
67
|
+
@changed = true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def remove_message(message)
|
72
|
+
index = @messages_keys.index(message.key)
|
73
|
+
if index
|
74
|
+
@messages_keys.slice!(index)
|
75
|
+
@changed = true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def messages=(messages)
|
80
|
+
messages.compact!
|
81
|
+
messages.uniq!(&:key)
|
82
|
+
if messages.size > 0
|
83
|
+
messages.sort_by!(&:timestamp)
|
84
|
+
messages.reverse!
|
85
|
+
messages.slice!(max_size..-1) if messages.size > max_size
|
86
|
+
@messages = messages
|
87
|
+
before = @messages_keys.sort
|
88
|
+
@messages_keys = @messages.map(&:key)
|
89
|
+
@timestamp = @messages[0].timestamp
|
90
|
+
@changed = before != @messages_keys.sort
|
91
|
+
else
|
92
|
+
@messages_keys = []
|
93
|
+
@messages = []
|
94
|
+
@timestamp = 0
|
95
|
+
@changed = true
|
96
|
+
end
|
97
|
+
@messages
|
98
|
+
end
|
99
|
+
|
100
|
+
def changed?
|
101
|
+
@changed
|
102
|
+
end
|
103
|
+
|
104
|
+
def count
|
105
|
+
@messages_keys.size
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def max_size
|
111
|
+
self.class.max_size
|
112
|
+
end
|
113
|
+
|
114
|
+
GroupWeb = Struct.new(*%i[regex count timestamp messages row_id]) do
|
115
|
+
def to_json(opts = nil)
|
116
|
+
JSON.fast_generate(self.to_h.merge(severity: -1, group: true), opts)
|
117
|
+
end
|
118
|
+
|
119
|
+
def key
|
120
|
+
self.regex # alias for testing convenience
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Logster
|
4
|
+
class GroupingPattern < Pattern
|
5
|
+
CACHE_KEY = :grouping
|
6
|
+
def self.set_name
|
7
|
+
"__LOGSTER__grouping_patterns_set".freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
def save(args = {})
|
11
|
+
super
|
12
|
+
existing_groups = @store.find_pattern_groups
|
13
|
+
group = Logster::Group.new(self.to_s)
|
14
|
+
messages = @store.get_all_messages(with_env: false)
|
15
|
+
messages.select! do |m|
|
16
|
+
m.message =~ self.pattern && existing_groups.none? { |g| g.messages_keys.include?(m.key) }
|
17
|
+
end
|
18
|
+
group.messages = messages
|
19
|
+
@store.save_pattern_group(group) if group.changed?
|
20
|
+
@store.clear_patterns_cache(CACHE_KEY)
|
21
|
+
end
|
22
|
+
|
23
|
+
def destroy(clear_cache: true) # arg used in tests
|
24
|
+
super()
|
25
|
+
@store.remove_pattern_group(self.pattern)
|
26
|
+
@store.clear_patterns_cache(CACHE_KEY) if clear_cache
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|