FEATURE: All 500 errors now show up in Logster

Added Discourse.handle_request_exception()
This commit is contained in:
riking 2015-02-09 12:48:33 -08:00
parent 5657006aca
commit 68ccd2d664
4 changed files with 24 additions and 153 deletions

View File

@ -65,7 +65,7 @@ class ApplicationController < ActionController::Base
ActionController::UnknownController,
AbstractController::ActionNotFound].include? exception.class
begin
ErrorLog.report_async!(exception, self, request, current_user)
Discourse.handle_request_exception(exception, self, request, current_user)
rescue
# dont care give up
end

View File

@ -1,94 +0,0 @@
# TODO:
# a mechanism to iterate through errors in reverse
# async logging should queue, if dupe stack traces are found in batch error should be merged into prev one
class ErrorLog
@lock = Mutex.new
def self.filename
"#{Rails.root}/log/#{Rails.env}_errors.log"
end
def self.clear!(_guid)
raise NotImplementedError
end
def self.clear_all!()
File.delete(ErrorLog.filename) if File.exists?(ErrorLog.filename)
end
def self.report_async!(exception, controller, request, user)
Thread.new do
report!(exception, controller, request, user)
end
end
def self.report!(exception, controller, request, user)
add_row!(
date: DateTime.now,
guid: SecureRandom.uuid,
user_id: user && user.id,
parameters: request && request.filtered_parameters.to_json,
action: controller.action_name,
controller: controller.controller_name,
backtrace: sanitize_backtrace(exception.backtrace).join("\n"),
message: exception.message,
url: "#{request.protocol}#{request.env["HTTP_X_FORWARDED_HOST"] || request.env["HTTP_HOST"]}#{request.fullpath}",
exception_class: exception.class.to_s
)
end
def self.add_row!(hash)
data = hash.to_xml(skip_instruct: true)
# use background thread to write the log cause it may block if it gets backed up
@lock.synchronize do
File.open(filename, "a") do |f|
f.flock(File::LOCK_EX)
f.write(data)
f.close
end
end
end
def self.each(&blk)
skip(0, &blk)
end
def self.skip(skip=0)
pos = 0
return [] unless File.exists?(filename)
loop do
lines = ""
File.open(self.filename, "r") do |f|
f.flock(File::LOCK_SH)
f.pos = pos
while !f.eof?
line = f.readline
lines << line
break if line.starts_with? "</hash>"
end
pos = f.pos
end
if lines != "" && skip == 0
h = {}
e = Nokogiri.parse(lines).children[0]
e.children.each do |inner|
h[inner.name] = inner.text
end
yield h
end
skip-=1 if skip > 0
break if lines == ""
end
end
def self.sanitize_backtrace(trace)
re = Regexp.new(/^#{Regexp.escape(Rails.root.to_s)}/)
trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s }
end
private_class_method :sanitize_backtrace
end

View File

@ -26,6 +26,29 @@ module Discourse
}.merge(context))
end
def self.handle_request_exception(ex, controller, request, current_user)
cm = RailsMultisite::ConnectionManagement
context = {
current_db: cm.current_db,
current_hostname: cm.current_hostname,
rails_action: controller.action_name,
rails_controller: controller.controller_name,
}
env = request.env.dup
context.each do |key, value|
Logster.add_to_env(env, key, value)
end
begin
Thread.current[Logster::Logger::LOGSTER_ENV] = env
Logster.logger.fatal("#{ex.class.to_s}: #{ex.message} in #{controller.controller_name}##{controller.action_name}")
ensure
Thread.current[Logster::Logger::LOGSTER_ENV] = nil
end
end
# Expected less matches than what we got in a find
class TooManyMatches < Exception; end

View File

@ -1,58 +0,0 @@
require 'spec_helper'
describe ErrorLog do
def boom
raise "boom"
end
def exception
begin
boom
rescue => e
return e
end
end
def controller
DraftController.new
end
def request
ActionController::TestRequest.new(host: 'test')
end
describe "add_row!" do
it "creates a non empty file on first call" do
ErrorLog.clear_all!
ErrorLog.add_row!(hello: "world")
expect(File.exists?(ErrorLog.filename)).to eq true
end
end
describe "logging data" do
it "is able to read the data it writes" do
ErrorLog.clear_all!
ErrorLog.report!(exception, controller, request, nil)
ErrorLog.report!(exception, controller, request, nil)
i = 0
ErrorLog.each do |h|
i += 1
end
expect(i).to eq 2
end
it "is able to skip rows" do
ErrorLog.clear_all!
ErrorLog.report!(exception, controller, request, nil)
ErrorLog.report!(exception, controller, request, nil)
ErrorLog.report!(exception, controller, request, nil)
ErrorLog.report!(exception, controller, request, nil)
i = 0
ErrorLog.skip(3) do |h|
i += 1
end
expect(i).to eq 1
end
end
end