logster 0.1.0 → 0.1.1
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/assets/javascript/app.js +26 -21
- data/lib/logster/base_store.rb +80 -0
- data/lib/logster/redis_store.rb +6 -28
- data/lib/logster/version.rb +1 -1
- data/test/examples/test_sidekiq_reporter_example.rb +21 -6
- data/test/logster/middleware/test_reporter.rb +1 -1
- data/test/logster/test_base_store.rb +94 -0
- data/test/logster/test_redis_store.rb +1 -1
- data/test/test_helper.rb +15 -22
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 817153c3885fd064575528496f299e302802edff
|
4
|
+
data.tar.gz: 2adf2a219859d1d5a1b7163fa98714a3e0d353fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40a5c76579e0f5145e3cdb490daab9550dd30e12d3e6be4609774aa045f46d33f3465ba20bcd0a1fe350de3000f92a9bff54c94cdb7032cbc1eccabb88765ea4
|
7
|
+
data.tar.gz: 33401bae4031a18e2d0e40f22679acfc1ebf0cb8515df2ea9084ca06e0eccb82a781ee34abeadf5dc4a5592c3327c77f246623b7724a40959ea330a6f4768df8
|
data/assets/javascript/app.js
CHANGED
@@ -45,7 +45,7 @@ App.preloadOrAjax = function(url, settings) {
|
|
45
45
|
}
|
46
46
|
};
|
47
47
|
|
48
|
-
App.Router.map(function(){
|
48
|
+
App.Router.map(function() {
|
49
49
|
this.route("index", { path: "/" });
|
50
50
|
this.route("show", { path: "/show/:id" });
|
51
51
|
});
|
@@ -67,7 +67,7 @@ App.Message = Ember.Object.extend({
|
|
67
67
|
return App.ajax("/unprotect/" + this.get('key'), { type: "DELETE" });
|
68
68
|
},
|
69
69
|
|
70
|
-
hasMore: function(){
|
70
|
+
hasMore: function() {
|
71
71
|
var message = this.get("message");
|
72
72
|
var expanded = this.get("expanded");
|
73
73
|
|
@@ -82,32 +82,37 @@ App.Message = Ember.Object.extend({
|
|
82
82
|
return Logger.rootPath + (this.get('protected') ? '/unprotect/' : '/protect/') + this.get('key');
|
83
83
|
}.property("key"),
|
84
84
|
|
85
|
-
displayMessage: function(){
|
85
|
+
displayMessage: function() {
|
86
86
|
var message = this.get("message");
|
87
87
|
var expanded = this.get("expanded");
|
88
88
|
|
89
|
-
if(!expanded && message.length > this.MAX_LEN){
|
90
|
-
message = message.substr(0,this.MAX_LEN);
|
89
|
+
if (!expanded && message.length > this.MAX_LEN) {
|
90
|
+
message = message.substr(0, this.MAX_LEN);
|
91
91
|
}
|
92
92
|
return message;
|
93
|
-
}.property("message","expanded"),
|
93
|
+
}.property("message", "expanded"),
|
94
94
|
|
95
|
-
envDebug: function(){
|
95
|
+
envDebug: function() {
|
96
96
|
var env = this.get("env");
|
97
|
-
if(env){
|
98
|
-
var buffer = []
|
99
|
-
|
100
|
-
|
97
|
+
if (env) {
|
98
|
+
var buffer = [],
|
99
|
+
hashes = [];
|
100
|
+
_.each(env, function(v, k) {
|
101
|
+
if (typeof v === "object") {
|
102
|
+
hashes.push(k);
|
103
|
+
} else {
|
101
104
|
buffer.push(k + ": " + v);
|
102
105
|
}
|
103
106
|
});
|
104
107
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
if (_.size(hashes) > 0) {
|
109
|
+
_.each(hashes, function(k1) {
|
110
|
+
v1 = env[k1];
|
111
|
+
buffer.push("");
|
112
|
+
buffer.push(k1 + ":");
|
113
|
+
_.each(v1, function(v2, k2) {
|
114
|
+
buffer.push(" " + k2 + ": " + v2);
|
115
|
+
})
|
111
116
|
});
|
112
117
|
}
|
113
118
|
return buffer.join("\n");
|
@@ -116,7 +121,7 @@ App.Message = Ember.Object.extend({
|
|
116
121
|
}.property("env"),
|
117
122
|
|
118
123
|
rowClass: function() {
|
119
|
-
switch(this.get("severity")){
|
124
|
+
switch (this.get("severity")) {
|
120
125
|
case 0:
|
121
126
|
return "debug";
|
122
127
|
case 1:
|
@@ -130,8 +135,8 @@ App.Message = Ember.Object.extend({
|
|
130
135
|
}
|
131
136
|
}.property("severity"),
|
132
137
|
|
133
|
-
glyph: function(){
|
134
|
-
switch(this.get("severity")){
|
138
|
+
glyph: function() {
|
139
|
+
switch (this.get("severity")) {
|
135
140
|
case 0:
|
136
141
|
return "";
|
137
142
|
case 1:
|
@@ -151,7 +156,7 @@ App.MessageCollection = Em.Object.extend({
|
|
151
156
|
messages: Em.A(),
|
152
157
|
total: 0,
|
153
158
|
|
154
|
-
load: function(opts){
|
159
|
+
load: function(opts) {
|
155
160
|
var self = this;
|
156
161
|
opts = opts || {};
|
157
162
|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
module Logster
|
3
|
+
class BaseStore
|
4
|
+
|
5
|
+
attr_accessor :level, :max_retention, :skip_empty, :ignore
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@dedup = false
|
9
|
+
@max_retention = 60 * 60 * 24 * 7
|
10
|
+
@skip_empty = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def save(message)
|
14
|
+
not_implemented
|
15
|
+
end
|
16
|
+
|
17
|
+
def count
|
18
|
+
not_implemented
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear
|
22
|
+
not_implemented
|
23
|
+
end
|
24
|
+
|
25
|
+
def clear_all
|
26
|
+
not_implemented
|
27
|
+
end
|
28
|
+
|
29
|
+
def get(message_key)
|
30
|
+
not_implemented
|
31
|
+
end
|
32
|
+
|
33
|
+
def protect(message_key)
|
34
|
+
not_implemented
|
35
|
+
end
|
36
|
+
|
37
|
+
def unprotect(message_key)
|
38
|
+
not_implemented
|
39
|
+
end
|
40
|
+
|
41
|
+
def report(severity, progname, message, opts = {})
|
42
|
+
return if (!message || (String === message && message.empty?)) && skip_empty
|
43
|
+
return if level && severity < level
|
44
|
+
return if ignore && ignore.any? { |pattern| message =~ pattern}
|
45
|
+
|
46
|
+
message = Logster::Message.new(severity, progname, message, opts[:timestamp])
|
47
|
+
|
48
|
+
env = opts[:env]
|
49
|
+
backtrace = opts[:backtrace]
|
50
|
+
|
51
|
+
if env
|
52
|
+
if env[:backtrace]
|
53
|
+
# Special - passing backtrace through env
|
54
|
+
backtrace = env.delete(:backtrace)
|
55
|
+
end
|
56
|
+
|
57
|
+
message.populate_from_env(env)
|
58
|
+
end
|
59
|
+
|
60
|
+
if backtrace
|
61
|
+
if backtrace.respond_to? :join
|
62
|
+
backtrace = backtrace.join("\n")
|
63
|
+
end
|
64
|
+
message.backtrace = backtrace
|
65
|
+
else
|
66
|
+
message.backtrace = caller.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
save message
|
70
|
+
|
71
|
+
message
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def not_implemented
|
77
|
+
raise "Not Implemented"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/logster/redis_store.rb
CHANGED
@@ -1,38 +1,18 @@
|
|
1
1
|
require 'json'
|
2
|
+
require 'logster/base_store'
|
2
3
|
|
3
4
|
module Logster
|
4
|
-
class RedisStore
|
5
|
+
class RedisStore < BaseStore
|
5
6
|
|
6
|
-
attr_accessor :
|
7
|
-
:dedup, :max_retention, :skip_empty,
|
8
|
-
:ignore
|
7
|
+
attr_accessor :redis, :max_backlog
|
9
8
|
|
10
9
|
def initialize(redis = nil)
|
10
|
+
super()
|
11
11
|
@redis = redis || Redis.new
|
12
12
|
@max_backlog = 1000
|
13
|
-
@dedup = false
|
14
|
-
@max_retention = 60 * 60 * 24 * 7
|
15
|
-
@skip_empty = true
|
16
13
|
end
|
17
14
|
|
18
|
-
|
19
|
-
def report(severity, progname, message, opts = nil)
|
20
|
-
return if (!message || (String === message && message.empty?)) && skip_empty
|
21
|
-
return if level && severity < level
|
22
|
-
return if @ignore && @ignore.any?{|pattern| message =~ pattern}
|
23
|
-
|
24
|
-
message = Logster::Message.new(severity, progname, message, (opts && opts[:timestamp]))
|
25
|
-
|
26
|
-
if opts && backtrace = opts[:backtrace]
|
27
|
-
message.backtrace = backtrace
|
28
|
-
else
|
29
|
-
message.backtrace = caller.join("\n")
|
30
|
-
end
|
31
|
-
|
32
|
-
if opts && env = opts[:env]
|
33
|
-
message.populate_from_env(env)
|
34
|
-
end
|
35
|
-
|
15
|
+
def save(message)
|
36
16
|
# multi for integrity
|
37
17
|
@redis.multi do
|
38
18
|
@redis.hset(hash_key, message.key, message.to_json)
|
@@ -40,14 +20,12 @@ module Logster
|
|
40
20
|
end
|
41
21
|
|
42
22
|
# TODO make it atomic
|
43
|
-
if @redis.llen(list_key) >
|
23
|
+
if @redis.llen(list_key) > max_backlog
|
44
24
|
removed_key = @redis.lpop(list_key)
|
45
25
|
if removed_key && !@redis.sismember(protected_key, removed_key)
|
46
26
|
@redis.hdel(hash_key, removed_key)
|
47
27
|
end
|
48
28
|
end
|
49
|
-
|
50
|
-
message
|
51
29
|
end
|
52
30
|
|
53
31
|
def count
|
data/lib/logster/version.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
2
|
require 'logster/logger'
|
3
|
+
require 'logster/redis_store'
|
3
4
|
require 'logger'
|
4
5
|
require 'examples/sidekiq_logster_reporter'
|
5
6
|
|
6
7
|
class TestSidekiqReporter < MiniTest::Test
|
7
8
|
|
8
9
|
def setup
|
9
|
-
Logster.store = @store = Logster::
|
10
|
+
Logster.store = @store = Logster::RedisStore.new(Redis.new)
|
10
11
|
Logster.logger = @logger = Logster::Logger.new(Logster.store)
|
12
|
+
@store.clear_all
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@store.clear_all
|
11
17
|
end
|
12
18
|
|
13
19
|
def test_sidekiq_handler_example
|
@@ -18,14 +24,23 @@ class TestSidekiqReporter < MiniTest::Test
|
|
18
24
|
rescue => e
|
19
25
|
error = e
|
20
26
|
end
|
27
|
+
trace = error.backtrace
|
21
28
|
|
22
29
|
handler.call(error, code: "Test", something_important: "Foo", params: { article_id: 20 })
|
23
30
|
|
24
|
-
|
31
|
+
report = @store.latest[0]
|
32
|
+
|
33
|
+
# Message is right format
|
34
|
+
assert_equal("Job exception: TypeError\n", report.message)
|
35
|
+
|
36
|
+
# A backtrace is joined()
|
37
|
+
assert_equal(trace.join("\n"), report.backtrace)
|
38
|
+
# The backtrace is deleted from the env
|
39
|
+
assert_nil(report.env['backtrace'])
|
40
|
+
assert_nil(report.env[:backtrace])
|
25
41
|
|
26
|
-
|
27
|
-
assert_equal("
|
28
|
-
assert_equal(
|
29
|
-
assert_equal(20, error.env[:params][:article_id])
|
42
|
+
# The env is in the report
|
43
|
+
assert_equal("Test", report.env['code'])
|
44
|
+
assert_equal(20, report.env['params']['article_id'])
|
30
45
|
end
|
31
46
|
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require 'logster/base_store'
|
3
|
+
|
4
|
+
class TestBaseStore < Minitest::Test
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@store = Logster::TestStore.new
|
8
|
+
@store.clear_all
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
@store.clear_all
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_report_skip_empty
|
16
|
+
@store.skip_empty = true
|
17
|
+
@store.report(Logger::WARN, "test", nil)
|
18
|
+
@store.report(Logger::WARN, "test", '')
|
19
|
+
@store.report(Logger::WARN, "test", "foo") #
|
20
|
+
@store.skip_empty = false
|
21
|
+
@store.report(Logger::WARN, "test", nil) #
|
22
|
+
|
23
|
+
assert_equal(2, @store.count)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_report_skip_level
|
27
|
+
@store.level = nil
|
28
|
+
@store.report(Logger::DEBUG, "test", "A") #
|
29
|
+
@store.level = Logger::WARN
|
30
|
+
@store.report(Logger::DEBUG, "test", "A")
|
31
|
+
@store.report(Logger::INFO, "test", "B")
|
32
|
+
@store.report(Logger::WARN, "test", "C") #
|
33
|
+
@store.report(Logger::ERROR, "test", "D") #
|
34
|
+
assert_equal(3, @store.count)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_report_skip_ignore
|
38
|
+
@store.report(Logger::WARN, "test", "Can't verify CSRF token authenticity")
|
39
|
+
@store.report(Logger::FATAL, "test", "ActiveRecord::RecordNotFound (Couldn't find Upload with 'id'=9947)")
|
40
|
+
@store.report(Logger::WARN, "test", "B")
|
41
|
+
@store.ignore = [
|
42
|
+
/^ActiveRecord::RecordNotFound \(Couldn't find Upload/,
|
43
|
+
/^Can't verify CSRF token authenticity/
|
44
|
+
]
|
45
|
+
@store.report(Logger::WARN, "test", "Can't verify CSRF token authenticity")
|
46
|
+
@store.report(Logger::FATAL, "test", "ActiveRecord::RecordNotFound (Couldn't find Upload with 'id'=9947)")
|
47
|
+
@store.report(Logger::FATAL, "test", "ActiveRecord::RecordNotFound (Couldn't find Upload with 'id'=9489+78946947)")
|
48
|
+
@store.report(Logger::WARN, "test", "B")
|
49
|
+
|
50
|
+
assert_equal(4, @store.count)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_timestamp
|
54
|
+
time = Time.now - 24*60*60
|
55
|
+
message = @store.report(Logger::WARN, "test", "B", timestamp: time)
|
56
|
+
|
57
|
+
assert_equal(time, message.timestamp)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_backtrace
|
61
|
+
# Create an error with a backtrace
|
62
|
+
error = TypeError.new
|
63
|
+
begin
|
64
|
+
raise error
|
65
|
+
rescue => e
|
66
|
+
error = e
|
67
|
+
end
|
68
|
+
|
69
|
+
# Backtrace can be passed via backtrace param or env
|
70
|
+
message = @store.report(Logger::WARN, "test", "A", backtrace: error.backtrace)
|
71
|
+
assert_equal(error.backtrace.join("\n"), message.backtrace)
|
72
|
+
message = @store.report(Logger::WARN, "test", "B", env: {backtrace: error.backtrace})
|
73
|
+
assert_equal(error.backtrace.join("\n"), message.backtrace)
|
74
|
+
|
75
|
+
# Via env takes priority
|
76
|
+
message = @store.report(Logger::WARN, "test", "C", backtrace: "Garbage", env: {backtrace: error.backtrace})
|
77
|
+
assert_equal(error.backtrace.join("\n"), message.backtrace)
|
78
|
+
|
79
|
+
# Backtrace is always a string
|
80
|
+
# Cannot do an equal assert here, because it uses `caller` when not provided
|
81
|
+
message = @store.report(Logger::WARN, "test", "D", backtrace: nil)
|
82
|
+
assert_kind_of(String, message.backtrace)
|
83
|
+
message = @store.report(Logger::WARN, "test", "E", env: {backtrace: nil})
|
84
|
+
assert_kind_of(String, message.backtrace)
|
85
|
+
message = @store.report(Logger::WARN, "test", "F", backtrace: nil, env: {backtrace: nil})
|
86
|
+
assert_kind_of(String, message.backtrace)
|
87
|
+
message = @store.report(Logger::WARN, "test", "G")
|
88
|
+
assert_kind_of(String, message.backtrace)
|
89
|
+
|
90
|
+
# Arrays are turned into strings via join \n
|
91
|
+
message = @store.report(Logger::WARN, "test", "H", backtrace: ["Foo", "Bar"])
|
92
|
+
assert_equal("Foo\nBar", message.backtrace)
|
93
|
+
end
|
94
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -4,36 +4,29 @@ require 'minitest/autorun'
|
|
4
4
|
require 'minitest/pride'
|
5
5
|
require 'logster'
|
6
6
|
require 'redis'
|
7
|
+
require 'logster/base_store'
|
7
8
|
|
8
|
-
|
9
|
-
class Logster::TestStore
|
9
|
+
class Logster::TestStore < Logster::BaseStore
|
10
10
|
attr_accessor :reported
|
11
11
|
def initialize
|
12
12
|
@reported = []
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
backtrace = opts[:backtrace]
|
19
|
-
if env && !backtrace
|
20
|
-
backtrace = env[:backtrace]
|
21
|
-
end
|
22
|
-
|
23
|
-
message = Logster::Message.new(severity, progname, message)
|
24
|
-
|
25
|
-
if backtrace
|
26
|
-
message.backtrace = backtrace
|
27
|
-
else
|
28
|
-
message.backtrace = caller.join("\n")
|
29
|
-
end
|
15
|
+
def save(message)
|
16
|
+
@reported << message
|
17
|
+
end
|
30
18
|
|
31
|
-
|
32
|
-
|
33
|
-
|
19
|
+
def count
|
20
|
+
@reported.count
|
21
|
+
end
|
34
22
|
|
35
|
-
|
23
|
+
def clear
|
24
|
+
@reported = []
|
25
|
+
end
|
36
26
|
|
37
|
-
|
27
|
+
def clear_all
|
28
|
+
@reported = []
|
38
29
|
end
|
30
|
+
|
31
|
+
# get, protect, unprotect: unimplemented
|
39
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- UI for viewing logs in Rack
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- bower.json
|
127
127
|
- lib/examples/sidekiq_logster_reporter.rb
|
128
128
|
- lib/logster.rb
|
129
|
+
- lib/logster/base_store.rb
|
129
130
|
- lib/logster/configuration.rb
|
130
131
|
- lib/logster/logger.rb
|
131
132
|
- lib/logster/message.rb
|
@@ -140,6 +141,7 @@ files:
|
|
140
141
|
- test/examples/test_sidekiq_reporter_example.rb
|
141
142
|
- test/logster/middleware/test_reporter.rb
|
142
143
|
- test/logster/middleware/test_viewer.rb
|
144
|
+
- test/logster/test_base_store.rb
|
143
145
|
- test/logster/test_logger.rb
|
144
146
|
- test/logster/test_redis_store.rb
|
145
147
|
- test/test_helper.rb
|
@@ -172,6 +174,7 @@ test_files:
|
|
172
174
|
- test/examples/test_sidekiq_reporter_example.rb
|
173
175
|
- test/logster/middleware/test_reporter.rb
|
174
176
|
- test/logster/middleware/test_viewer.rb
|
177
|
+
- test/logster/test_base_store.rb
|
175
178
|
- test/logster/test_logger.rb
|
176
179
|
- test/logster/test_redis_store.rb
|
177
180
|
- test/test_helper.rb
|