Dump stack trace on internal server error

Provide stack trace for debugging runtime errors in debug builds
This commit is contained in:
Bob Farrell 2024-02-15 21:40:21 +00:00
parent 7958480ff7
commit bdb813c521
2 changed files with 24 additions and 2 deletions

View File

@ -28,9 +28,9 @@ If you are interested in _Jetzig_ you will probably find these tools interesting
* :white_check_mark: Error handling. * :white_check_mark: Error handling.
* :white_check_mark: Static content from /public directory. * :white_check_mark: Static content from /public directory.
* :white_check_mark: Headers (available but not yet wrapped). * :white_check_mark: Headers (available but not yet wrapped).
* :white_check_mark: Stack trace output on error.
* :x: Static content generation (nearly there!). * :x: Static content generation (nearly there!).
* :x: Param/JSON payload parsing/abstracting. * :x: Param/JSON payload parsing/abstracting.
* :x: Development-mode responses for debugging.
* :x: Environment configurations (develompent/production/etc.) * :x: Environment configurations (develompent/production/etc.)
* :x: Middleware extensions (for e.g. authentication). * :x: Middleware extensions (for e.g. authentication).
* :x: Email delivery. * :x: Email delivery.
@ -45,3 +45,7 @@ If you are interested in _Jetzig_ you will probably find these tools interesting
## LICENSE ## LICENSE
[MIT](LICENSE) [MIT](LICENSE)
## Contributors
* [Bob Farrell](https://github.com/bobf)

View File

@ -292,16 +292,34 @@ fn isUnhandledError(err: anyerror) bool {
} }
fn internalServerError(self: *Self, request: *jetzig.http.Request, err: anyerror) !RenderedView { fn internalServerError(self: *Self, request: *jetzig.http.Request, err: anyerror) !RenderedView {
_ = self;
request.response_data.reset(); request.response_data.reset();
var object = try request.response_data.object(); var object = try request.response_data.object();
try object.put("error", request.response_data.string(@errorName(err))); try object.put("error", request.response_data.string(@errorName(err)));
const stack = @errorReturnTrace();
if (stack) |capture| try self.logStackTrace(capture, request, object);
return .{ return .{
.view = jetzig.views.View{ .data = request.response_data, .status_code = .internal_server_error }, .view = jetzig.views.View{ .data = request.response_data, .status_code = .internal_server_error },
.content = "Internal Server Error\n", .content = "Internal Server Error\n",
}; };
} }
fn logStackTrace(
self: *Self,
stack: *std.builtin.StackTrace,
request: *jetzig.http.Request,
object: *jetzig.data.Value,
) !void {
_ = self;
std.debug.print("\nStack Trace:\n{}", .{stack});
var array = std.ArrayList(u8).init(request.allocator);
const writer = array.writer();
try stack.format("", .{}, writer);
// TODO: Generate an array of objects with stack trace in useful data structure instead of
// dumping the whole formatted backtrace as a JSON string:
try object.put("backtrace", request.response_data.string(array.items));
}
fn requestLogMessage(self: *Self, request: *jetzig.http.Request, result: jetzig.caches.Result) ![]const u8 { fn requestLogMessage(self: *Self, request: *jetzig.http.Request, result: jetzig.caches.Result) ![]const u8 {
const status: jetzig.http.status_codes.TaggedStatusCode = switch (result.value.status_code) { const status: jetzig.http.status_codes.TaggedStatusCode = switch (result.value.status_code) {