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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2cfda323f9ee2749181b885b462d4e6b6398f03b
4
- data.tar.gz: d9cf1b6ce77e9c7d74745c253047d39c992a1855
3
+ metadata.gz: 817153c3885fd064575528496f299e302802edff
4
+ data.tar.gz: 2adf2a219859d1d5a1b7163fa98714a3e0d353fc
5
5
  SHA512:
6
- metadata.gz: bef73cfac1f6232793744b1fcb1807da74088a271bba04b0ad7ad6bca95de46a9d39ed73e23371970afd0c7e045a93c8d538c056b4434fddbed44946fb37064f
7
- data.tar.gz: 8bcab70e33821609e020ad951e2453394eafbe2fb11607d3cdb63563898656e0b48aa8227b1edb97e0eef471ef09f4f93a6c802db745676bffd714d7ca6eb2ac
6
+ metadata.gz: 40a5c76579e0f5145e3cdb490daab9550dd30e12d3e6be4609774aa045f46d33f3465ba20bcd0a1fe350de3000f92a9bff54c94cdb7032cbc1eccabb88765ea4
7
+ data.tar.gz: 33401bae4031a18e2d0e40f22679acfc1ebf0cb8515df2ea9084ca06e0eccb82a781ee34abeadf5dc4a5592c3327c77f246623b7724a40959ea330a6f4768df8
@@ -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
- _.each(env, function(v,k){
100
- if(k !== "params"){
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
- buffer.push("");
106
- if(_.size(env.params) > 0){
107
- buffer.push("Params:");
108
- buffer.push("");
109
- _.each(env.params, function(v,k){
110
- buffer.push(" " + k + ": " + v);
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
@@ -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 :level, :redis, :max_backlog,
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) > @max_backlog
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
@@ -1,3 +1,3 @@
1
1
  module Logster
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -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::TestStore.new
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
- error = Logster.store.reported[0]
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
- assert(error.backtrace != nil)
27
- assert_equal("Job exception: TypeError\n", error.message)
28
- assert_equal("Test", error.env[:code])
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
@@ -14,7 +14,7 @@ class TestReporter < Minitest::Test
14
14
  status, = reporter.call(env)
15
15
 
16
16
  assert_equal(200, status)
17
- assert_equal(1, Logster.store.reported.length)
17
+ assert_equal(1, Logster.store.count)
18
18
  end
19
19
 
20
20
  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
@@ -6,7 +6,7 @@ class TestRedisStore < Minitest::Test
6
6
 
7
7
  def setup
8
8
  @store = Logster::RedisStore.new(Redis.new)
9
- @store.clear
9
+ @store.clear_all
10
10
  end
11
11
 
12
12
  def teardown
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 report(severity, progname, message, opts = nil)
16
- opts ||= {}
17
- env = opts[:env]
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
- if env
32
- message.populate_from_env(env)
33
- end
19
+ def count
20
+ @reported.count
21
+ end
34
22
 
35
- @reported << message
23
+ def clear
24
+ @reported = []
25
+ end
36
26
 
37
- message
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.0
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