errlog 0.2.3 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65181ee001218bc27b39fad26a4d7ae78dbcd476
4
- data.tar.gz: a8e2ad45e7a803b646c0dd373121bae6993330ac
3
+ metadata.gz: 742e90a6c45ef372d95f07e88a6842095748d109
4
+ data.tar.gz: 515ee1ca2103aee10a0fec3036dba273f62f9bd3
5
5
  SHA512:
6
- metadata.gz: b08bb5fd56db25996b049920aa008179bbf4aa19483797d0cdc46d80d02426be77bf7c29401fa603ad301de9cf1b13e355ffe61c3a1bf3da418ffd98b28e7ebd
7
- data.tar.gz: 4973a36a2aa8f8ef7ead6f0520cb901721d31081e4cf841f1b46492579fba7e5eb2cc0d3d1cda852bf16d249aa8bbe4e128e9e85500f397799f7a06849c7be6e
6
+ metadata.gz: 5e7ed76719a32f26a44ba923c456e100203c3b772d9f66fb423c92b59d65a19498920c50399302e0af96b857869c351f691552543447ccfbaff2432b26ca6219
7
+ data.tar.gz: 12be1679456863fa78013bdf145e3bafe0394e1b27f94ec2abfaa48200669d0c124fafc90e4127a62a613562221e01b31e5bbdab8af0086d0c1bbc6e220f5eae
data/bin/errlogr CHANGED
@@ -66,7 +66,7 @@ begin
66
66
  id = ARGV[n]
67
67
  n += 1
68
68
  when /^--local/
69
- host = "http://localhost:3000"
69
+ host = "http://localhost:8080"
70
70
  when /^--warn/
71
71
  severity = Errlog::WARNING
72
72
  when /^--trace/
data/errlog.gemspec CHANGED
@@ -22,7 +22,8 @@ Gem::Specification.new do |gem|
22
22
 
23
23
  gem.add_dependency 'boss-protocol', '>= 0.1.3'
24
24
  gem.add_dependency 'hashie', '>= 1.2.0'
25
- gem.add_dependency 'httpclient', '>= 2.3'
25
+ gem.add_dependency 'httpclient', '>= 2.3.3'
26
+ gem.add_dependency 'httpclient-uploadio', '>=1.0'
26
27
  gem.add_dependency 'colorize'
27
28
  gem.add_development_dependency "rspec"
28
29
  end
data/lib/errlog.rb CHANGED
@@ -8,6 +8,8 @@ require 'hashie'
8
8
  require 'thread'
9
9
  require 'httpclient'
10
10
  require 'weakref'
11
+ require 'stringio'
12
+ require 'httpclient/uploadio'
11
13
 
12
14
  if defined?(Rails)
13
15
  require 'errlog/rails_controller_extensions'
@@ -32,21 +34,53 @@ module Errlog
32
34
  return Packager.new id, key
33
35
  end
34
36
 
37
+ @@configured = false
38
+
35
39
  def self.configure id, key, opts={}
40
+ @@configured = true
36
41
  @@app_id, @@app_secret, @options = id, key, opts
37
- @@app_name = opts[:app_name]
42
+ @@application = opts[:application] || ''
38
43
  @@packager = packager @@app_id, @@app_secret
39
44
  @@host = opts[:host] || "http://errorlog.co"
40
45
  @@client = HTTPClient.new
41
- @@rails = defined?(Rails)
46
+ @@opts = opts
47
+ @@rails = defined?(Rails)
48
+ @@loggers_ready = false
49
+ @@component = nil
50
+
51
+ if @@rails && !opts[:no_catch_logs]
52
+ @@logger = Rails.logger = ChainLogger.new Rails.logger
53
+ ActionController::Base.logger = ChainLogger.new ActionController::Base.logger
54
+ if defined?(ActiveRecord)
55
+ ActiveRecord::Base.logger = ChainLogger.new ActiveRecord::Base.logger
56
+ end
57
+ @@loggers_ready = true
58
+
59
+ # Delayed job
60
+ if defined?(Delayed)
61
+ require 'errlog/dj'
62
+ end
63
+ end
42
64
  end
43
65
 
44
- def self.app_name
45
- @@app_name #rescue nil
66
+ def self.logger
67
+ @@logger ||= ChainLogger.new
68
+ end
69
+
70
+ def self.use_logging?
71
+ !@@opts[:no_logs]
72
+ end
73
+
74
+ def self.application
75
+ @@application #rescue nil
46
76
  end
47
77
 
48
78
  def self.configured?
49
- defined?(@@app_id) && @@app_id && @@app_secret
79
+ if @@configured
80
+ (@@rails && Rails.env == 'test') || defined?(@@app_id) && @@app_id && @@app_secret
81
+ else
82
+ false
83
+ end
50
84
  end
51
85
 
52
86
  def self.default_platform
@@ -61,20 +95,28 @@ module Errlog
61
95
  @@packager.pack(data)
62
96
  end
63
97
 
64
- def self.create_logger with_logger=nil
65
- self.context.create_logger with_logger
66
- end
67
-
68
98
  def self.protect component_name=nil, options={}, &block
69
- context.protect component_name, options, &block
99
+ context.protect component_name, options, &block
70
100
  end
71
101
 
72
102
  def self.protect_rethrow component_name=nil, &block
73
103
  context.protect_rethrow component_name, &block
74
104
  end
75
105
 
76
- def self.report_exception e, &block
77
- self.context.report_exception e, &block
106
+ def self.exception e, &block
107
+ self.context.exception e, &block
108
+ end
109
+
110
+ def self.trace text, details=nil, severity=Errlog::TRACE, &block
111
+ self.context.trace text, details, severity, &block
112
+ end
113
+
114
+ def self.error text, details=nil, severity=Errlog::TRACE, &block
115
+ self.context.error text, details, severity, &block
116
+ end
117
+
118
+ def self.warning text, details=nil, severity=Errlog::TRACE, &block
119
+ self.context.warning text, details, severity, &block
78
120
  end
79
121
 
80
122
  def self.report text, severity = Errlog::ERROR, &block
@@ -82,7 +124,7 @@ module Errlog
82
124
  end
83
125
 
84
126
  def self.clear_context
85
- ctx = Errlog::Context.new
127
+ ctx = Errlog::Context.new
86
128
  Thread.current[:errlog_context] = ctx
87
129
  ctx
88
130
  end
@@ -94,18 +136,24 @@ module Errlog
94
136
  private
95
137
 
96
138
  def self.post src
97
- data = pack(src)
139
+ if @@rails && Rails.env == 'test'
140
+ Rails.logger.info "Errlog: sending: #{src[:text]}"
141
+ return
142
+ end
143
+ data = pack(src)
98
144
  @@send_threads ||= []
99
145
 
100
146
  t = Thread.start {
101
- #puts "sending to #{@@host}"
102
147
  error = nil
103
148
  begin
104
- res = @@client.post "#{@@host}/reports/log", app_id: @@app_id, data: Base64::encode64(data)
149
+ fio = HTTPClient::UploadIO.new(StringIO.new(data), "data.bin")
150
+ res = @@client.post "#{@@host}/reports/log", app_id: @@app_id, :file => fio
105
151
  error = "report refused: #{res.status}" if res.status != 200
106
152
  rescue Exception => e
107
153
  error = e
108
154
  end
155
+ STDERR.puts "Error sending errlog: #{error}" if error
156
+ #puts "sent" unless error
109
157
  yield error if block_given?
110
158
  }
111
159
  @@send_threads << WeakRef.new(t)
@@ -117,3 +165,7 @@ module Errlog
117
165
  end
118
166
 
119
167
  end
168
+
169
+ if defined?(Rails) && Rails.env == 'test'
170
+ Errlog.configure 'test id', 'test key', application: 'test app'
171
+ end
@@ -4,26 +4,25 @@ module Errlog
4
4
 
5
5
  class ChainLogger < Logger
6
6
 
7
- attr_reader :buffer, :prev_logger
7
+ attr_reader :prev_logger
8
8
 
9
- def initialize prev
10
- @buffer = []
9
+ def initialize prev=nil
11
10
  @prev_logger = prev
12
11
  super(nil)
13
12
  end
14
13
 
15
14
  def level= l
16
- @prev_logger.level = l
15
+ @prev_logger and @prev_logger.level = l
17
16
  end
18
17
 
19
18
  def level
20
- @prev_logger.level
19
+ @prev_logger and @prev_logger.level
21
20
  end
22
21
 
23
22
  def add severity, message = nil, progname = nil
24
23
  message = yield if block_given?
25
24
  @prev_logger and @prev_logger.add(severity, message, progname)
26
- @buffer << [severity, Time.now, message, progname]
25
+ Errlog.context.add_log_record [severity, Time.now, message, progname]
27
26
  end
28
27
 
29
28
  end
@@ -8,7 +8,7 @@ module Errlog
8
8
  begin
9
9
  yield self
10
10
  rescue Exception => e
11
- report_exception e
11
+ exception e
12
12
  options[:retrhow] and raise
13
13
  end
14
14
  end
@@ -17,36 +17,62 @@ module Errlog
17
17
  self.protect component_name, retrhow: true, &block
18
18
  end
19
19
 
20
- def report_exception e, &block
20
+ def exception e, severity=Errlog::ERROR, &block
21
+ raise unless Errlog.configured?
21
22
  self.stack = e.backtrace
22
- report "#{e.class.name}: #{e.to_s}", Errlog::ERROR
23
+ self.exception_class = e.class.name
24
+ report e.to_s, severity
23
25
  end
24
26
 
25
- def report_warning text, &block
26
- report text, Errlog::WARNING, &block
27
+ def trace text, details=nil, severity=Errlog::TRACE, &block
28
+ details and self.details = details
29
+ report text, severity
27
30
  end
28
31
 
29
- def report_trace text, &block
30
- report text, Errlog::TRACE, &block
32
+ def warning text, details=nil, severity=Errlog::WARNING, &block
33
+ details and self.details = details
34
+ report text, severity
35
+ end
36
+
37
+ def error text, details=nil, severity=Errlog::ERROR, &block
38
+ details and self.details = details
39
+ report text, severity
40
+ end
41
+
42
+ def before_report &block
43
+ (@before_handlers ||= []) << block
31
44
  end
32
45
 
33
46
  def report text, severity = Errlog::ERROR, &block
34
47
  raise 'Errlog is not configured. Use Errlog.config' unless Errlog.configured?
35
- !self.app_name and self.app_name = Errlog.app_name
48
+ self.application ||= Errlog.application
36
49
  self.time = Time.now
37
50
  self.severity = severity
38
51
  self.platform ||= Errlog.default_platform
39
52
  self.stack ||= caller
40
53
  self.text = text
41
- @loggers and self.log = @loggers.reduce([]){ |all,x| all + x.buffer }.sort { |x,y| x[1] <=> y[1] }
54
+
55
+ if @before_handlers
56
+ @before_handlers.each { |h|
57
+ h.call self
58
+ }
59
+ end
60
+
61
+ @log_records and self.log = @log_records.inject([]){ |all,x| all << x; all}.sort { |x,y| x[1] <=> y[1] }
42
62
  Errlog.rails? and self.rails_root = Rails.root.to_s
43
63
  Errlog.post(self.to_hash, &block)
44
64
  end
45
65
 
46
- def create_logger with_logger=nil
47
- l = Errlog::ChainLogger.new(with_logger)
48
- (@loggers ||= []) << l
49
- l
66
+ MAX_LOG_LINES = 100
67
+
68
+ def add_log_record record
69
+ @log_records ||= []
70
+ @log_records << record
71
+ if @log_records.length > MAX_LOG_LINES
72
+ @log_records.delete_at(0)
73
+ self.log_truncated = true
74
+ end
50
75
  end
76
+
51
77
  end
52
78
  end
data/lib/errlog/dj.rb ADDED
@@ -0,0 +1,22 @@
1
+
2
+ begin
3
+ class Delayed::Worker
4
+ def handle_failed_job_with_errlog(job, error)
5
+ Errlog.context.component = 'DJ'
6
+ Errlog.exception error
7
+ Errlog.clear_context
8
+ handle_failed_job_without_errlog(job, error)
9
+ end
10
+ alias_method_chain :handle_failed_job, :errlog
11
+
12
+ def run_with_errlog job
13
+ Errlog.clear_context
14
+ run_without_errlog job
15
+ end
16
+ alias_method_chain :run, :errlog
17
+ end
18
+ rescue => e
19
+ STDERR.puts "Problem starting Exceptional for Delayed-Job. Your app will run as normal\n#{e}"
20
+ Errlog.context.component = 'DJ'
21
+ Errlog.exception e
22
+ end
@@ -2,61 +2,85 @@ module Errlog
2
2
  module ControllerFilter
3
3
 
4
4
  def self.included base
5
- base.send :prepend_around_filter, :errlog_exceptions_trap
5
+ base.send :prepend_before_filter, :errlog_connect_context
6
+ base.send :rescue_from, Exception, :with => :errlog_report_exceptons
6
7
  base.send :helper_method, :errlog_context
7
- base.send :helper_method, :errlog_report
8
- base.send :helper_method, :errlog_collect_context
9
- base.send :helper_method, :errlog_exception
10
- true
11
- end
12
-
13
- def errlog_context
14
- @errlog_context || Errlog.clear_context
8
+ base.send :helper_method, :errlog_not_found
15
9
  end
16
10
 
17
- def errlog_exceptions_trap
18
- ctx = @errlog_context = Errlog.clear_context
19
11
 
20
- rl = Rails.logger = ctx.create_logger Rails.logger
21
- acl = ActionController::Base.logger = ctx.create_logger ActionController::Base.logger
22
- arl = nil
23
- if defined?(ActiveRecord)
24
- arl = ActiveRecord::Base.logger = ctx.create_logger ActiveRecord::Base.logger
12
+ # Get the context that is linked to the current request and will
13
+ # pass all its data if reporting will be called.
14
+ # Dafault Loggerr.context might not always be connected to the request.
15
+ #
16
+ def errlog_context
17
+ unless @errlog_context
18
+ errlog_connect_context
25
19
  end
20
+ @errlog_context
21
+ end
26
22
 
27
- yield
23
+ # Helper for 404's or like. Can be used as the trap.
24
+ #
25
+ # The argument may be either an Exception object or a text message.
26
+ # Can be used as the rescue_from catcher:
27
+ #
28
+ # rescue_from :ActiveRecord::NotFound, :with => :errlog_not_found
29
+ #
30
+ # or manually:
31
+ #
32
+ # def load_item
33
+ # item = Item.find_by_id(params[:id]) or errlog_not_found
34
+ #
35
+ # Reports and rethrows rails standard ActionController::RoutingError to
36
+ # activate default 404 processing
37
+ def errlog_not_found text = 'Resource not found'
38
+ ex = ActionController::RoutingError.new text
39
+ errlog_context.exception ex
40
+ raise ex
41
+ end
28
42
 
29
- rescue Exception => e
30
- if Errlog.configured?
31
- errlog_collect_context ctx
32
- ctx.report_exception e
33
- else
34
- rl.prev_logger.error 'Errlog is not configured, can not report an exception'
35
- end
36
- raise
43
+ private
37
44
 
38
- ensure
39
- Rails.logger = rl.prev_logger
40
- ActionController::Base.logger = acl.prev_logger
41
- arl and ActiveRecord::Base.logger = arl.prev_logger
45
+ def errlog_connect_context
46
+ @errlog_context = Errlog.context
47
+ @errlog_context.before_report {
48
+ errlog_collect_context
49
+ }
42
50
  true
43
51
  end
44
52
 
45
- def errlog_exception e, context = nil
46
- errlog_collect_context(context).report_exception e
53
+ def errlog_report_exceptons e
54
+ errlog_context.exception e, e.is_a?(ActionController::RoutingError) ? Errlog::ERROR : Errlog::WARNING
55
+ raise
47
56
  end
48
57
 
49
- def errlog_report text, severity = Errlog::ERROR, context=nil
50
- errlog_collect_context(context).report text, severity
58
+ def parametrize obj
59
+ case obj
60
+ when String
61
+ obj
62
+ when Array
63
+ obj.map { |x| parametrize(x) }
64
+ when ActionDispatch::Http::UploadedFile
65
+ obj.inspect
66
+ when Hash
67
+ obj.inject({}) { |all, kv| all[kv[0].to_s] = parametrize(kv[1]); all }
68
+ else
69
+ obj.to_s
70
+ end
51
71
  end
52
72
 
73
+ @@headers_exclusion_keys = %w|async. action_dispatch. cookie rack. rack-cache. warden action_controller.|
74
+
75
+ public
76
+
53
77
  def errlog_collect_context ctx=nil
54
- ctx ||= errlog_context
55
- ctx.component = request.path
56
- ctx.params = params
78
+ ctx ||= errlog_context
79
+ ctx.component = "#{self.class.name}##{params[:action]}"
80
+ ctx.params = parametrize(params)
57
81
  headers = {}
58
82
  request.headers.to_hash.each { |k, v|
59
- next if k =~ /cookie/i || v.class.name =~ /cookie/i
83
+ next if @@headers_exclusion_keys.any? { |s| k.starts_with?(s) }
60
84
  res = nil
61
85
  case v
62
86
  when Hash
@@ -82,15 +106,33 @@ module Errlog
82
106
  "not logged in"
83
107
  end
84
108
  end
85
- ctx.url = request.url
86
- ctx.remote_ip = request.remote_ip
87
- if request.url =~ %r|^https?://(.+?)[/:]|
109
+ ctx.url = request.url
110
+ ctx.remote_ip = request.remote_ip
111
+ ctx.application = Errlog.application
112
+ if ctx.application.blank? && request.url =~ %r|^https?://(.+?)[/:]|
88
113
  ctx.application = $1
89
114
  end
90
115
  ctx
91
116
  end
117
+ end
118
+
119
+ class ContextMiddleware
120
+ def initialize(app)
121
+ @app = app
122
+ end
92
123
 
124
+ def call(env)
125
+ Errlog.clear_context
126
+ status, headers, body = @app.call(env)
127
+ [status, headers, body]
128
+ end
129
+ end
130
+
131
+ class Railtie < Rails::Railtie
132
+ initializer "Errlog.insert_middleware" do |app|
133
+ app.config.middleware.use 'Errlog::ContextMiddleware'
134
+ end
93
135
  end
94
136
  end
95
137
 
96
- ActionController::Base.send :include, Errlog::ControllerFilter
138
+ ActionController::Base.send :include, Errlog::ControllerFilter
@@ -1,3 +1,3 @@
1
1
  module Errlog
2
- VERSION = "0.2.3"
2
+ VERSION = "0.3.2"
3
3
  end
data/spec/errlog_spec.rb CHANGED
@@ -7,6 +7,7 @@ require 'stringio'
7
7
 
8
8
  describe Errlog do
9
9
 
10
+ context 'configured' do
10
11
  before :each do
11
12
  Errlog.configure 'TheTestId', '1234567890123456'
12
13
  @packager = Errlog.packager 'TheTestId', '1234567890123456'
@@ -19,13 +20,13 @@ describe Errlog do
19
20
  Errlog.context.value.should == nil
20
21
  end
21
22
 
22
- # This spec checks the whole chain - protect, report_exception, report, but does not check post
23
+ # This spec checks the whole chain - protect, exception, report, but does not check post
23
24
  it 'should provide protection' do
24
25
  Errlog.should_receive(:post).exactly(3).times do |payload|
25
26
  payload = Hashie::Mash.new payload
26
27
  payload.should_not be_nil
27
28
  payload.stack[0].should =~ /errlog_spec/
28
- payload.text.should == 'RuntimeError: TestError'
29
+ payload.text.should == 'TestError'
29
30
  payload.time.should be_within(5000).of(Time.now)
30
31
  payload.component_name.should == 'test'
31
32
  payload.test.should == '123'
@@ -45,7 +46,7 @@ describe Errlog do
45
46
  }.should raise_error
46
47
 
47
48
  Errlog.context.test = '123'
48
- Errlog.report 'RuntimeError: TestError'
49
+ Errlog.report 'TestError'
49
50
  end
50
51
 
51
52
  it 'should provide logs' do
@@ -57,8 +58,8 @@ describe Errlog do
57
58
  payload.log[1][3].should == 'test warning'
58
59
  end
59
60
  sio = StringIO.new
60
- l1 = Errlog.create_logger
61
- l2 = Errlog.create_logger Logger.new(sio)
61
+ l1 = Errlog::ChainLogger.new
62
+ l2 = Errlog::ChainLogger.new Logger.new(sio)
62
63
  l1.info 'test info'
63
64
  l2.warn 'test warning'
64
65
  Errlog.report 'LogTest', Errlog::TRACE
@@ -86,4 +87,15 @@ describe Errlog do
86
87
  Errlog.severity_name(Errlog::TRACE).should == 'trace'
87
88
  end
88
89
 
90
+ end
91
+
92
+ it 'should work fine when not configured' do
93
+ expect { Errlog.error "Some error" }.to raise_error(StandardError, 'Errlog is not configured. Use Errlog.config')
94
+ expect {
95
+ Errlog.protect_rethrow {
96
+ raise "test"
97
+ }
98
+ }.to raise_error(StandardError, "test")
99
+ end
100
+
89
101
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: errlog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergeych
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-01 00:00:00.000000000 Z
11
+ date: 2013-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: boss-protocol
@@ -44,14 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - '>='
46
46
  - !ruby/object:Gem::Version
47
- version: '2.3'
47
+ version: 2.3.3
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
- version: '2.3'
54
+ version: 2.3.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: httpclient-uploadio
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: colorize
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -101,6 +115,7 @@ files:
101
115
  - lib/errlog/chain_loggger.rb
102
116
  - lib/errlog/constants.rb
103
117
  - lib/errlog/context.rb
118
+ - lib/errlog/dj.rb
104
119
  - lib/errlog/packager.rb
105
120
  - lib/errlog/rails_controller_extensions.rb
106
121
  - lib/errlog/version.rb