Skip to content

Commit f1b4396

Browse files
committed
Better error logging/handling.
1 parent 8061ecf commit f1b4396

File tree

2 files changed

+20
-55
lines changed

2 files changed

+20
-55
lines changed

lib/utopia/exceptions/handler.rb

Lines changed: 19 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Released under the MIT License.
44
# Copyright, 2014-2025, by Samuel Williams.
55

6+
require 'console'
7+
68
module Utopia
79
module Exceptions
810
# A middleware which catches exceptions and performs an internal redirect.
@@ -22,68 +24,31 @@ def freeze
2224
super
2325
end
2426

25-
# Generate a very simple fatal error response. This function should be unlikely to fail. Additionally, it generates a lowest common denominator response which should be suitable as a response to any kind of request. Ideally, this response is also not good or useful for any kind of higher level browser or API client, as this is not a normal error path but one that represents broken behaviour.
26-
def fatal_error(env, exception)
27-
body = StringIO.new
28-
29-
write_exception_to_stream(body, env, exception)
30-
body.rewind
31-
32-
return [500, {HTTP::CONTENT_TYPE => "text/plain"}, body]
33-
end
34-
35-
def log_exception(env, exception)
36-
# An error has occurred, log it:
37-
output = env["rack.errors"] || $stderr
38-
write_exception_to_stream(output, env, exception, true)
39-
end
40-
4127
def call(env)
4228
begin
4329
return @app.call(env)
4430
rescue Exception => exception
45-
log_exception(env, exception)
31+
Console.warn(self, "An error occurred while processing the request.", error: exception)
4632

47-
# If the error occurred while accessing the error handler, we finish with a fatal error:
48-
if env[Rack::PATH_INFO] == @location
49-
return fatal_error(env, exception)
50-
else
51-
begin
52-
# We do an internal redirection to the error location:
53-
error_request = env.merge(Rack::PATH_INFO => @location, Rack::REQUEST_METHOD => Rack::GET)
54-
error_response = @app.call(error_request)
55-
56-
return [500, error_response[1], error_response[2]]
57-
rescue Exception
58-
# If redirection fails, we also finish with a fatal error:
59-
return fatal_error(env, exception)
60-
end
33+
begin
34+
# We do an internal redirection to the error location:
35+
error_request = env.merge(
36+
Rack::PATH_INFO => @location,
37+
Rack::REQUEST_METHOD => Rack::GET,
38+
"utopia.exception" => exception,
39+
)
40+
41+
error_response = @app.call(error_request)
42+
error_response[0] = 500
43+
44+
return error_response
45+
rescue Exception => exception
46+
# If redirection fails, we also finish with a fatal error:
47+
Console.error(self, "An error occurred while invoking the error handler.", error: exception)
48+
return [500, {"content-type" => "text/plain"}, ["An error occurred while processing the request."]]
6149
end
6250
end
6351
end
64-
65-
private
66-
67-
def write_exception_to_stream(stream, env, exception, include_backtrace = false)
68-
buffer = []
69-
70-
buffer << "While requesting resource #{env[Rack::PATH_INFO].inspect}, a fatal error occurred:"
71-
72-
while exception != nil
73-
buffer << "\t#{exception.class.name}: #{exception.to_s}"
74-
75-
if include_backtrace
76-
exception.backtrace.each do |line|
77-
buffer << "\t\t#{line}"
78-
end
79-
end
80-
81-
exception = exception.cause
82-
end
83-
84-
# We do this in one go so that lines don't get mixed up.
85-
stream.puts buffer.join("\n")
86-
end
8752
end
8853
end
8954
end

test/utopia/exceptions/handler.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
expect(last_response.status).to be == 500
1919
expect(last_response.headers["content-type"]).to be == "text/plain"
20-
expect(last_response.body).to be(:include?, "fatal error")
20+
expect(last_response.body).to be(:include?, "error")
2121
end
2222

2323
it "should fail with a 500 error" do

0 commit comments

Comments
 (0)