From bdb813c521819bfa2d7a50a6be546f2dddb1bc2b Mon Sep 17 00:00:00 2001 From: Bob Farrell Date: Thu, 15 Feb 2024 21:40:21 +0000 Subject: [PATCH] Dump stack trace on internal server error Provide stack trace for debugging runtime errors in debug builds --- README.md | 6 +++++- src/jetzig/http/Server.zig | 20 +++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 25e347a..1fee1ba 100644 --- a/README.md +++ b/README.md @@ -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: Static content from /public directory. * :white_check_mark: Headers (available but not yet wrapped). +* :white_check_mark: Stack trace output on error. * :x: Static content generation (nearly there!). * :x: Param/JSON payload parsing/abstracting. -* :x: Development-mode responses for debugging. * :x: Environment configurations (develompent/production/etc.) * :x: Middleware extensions (for e.g. authentication). * :x: Email delivery. @@ -45,3 +45,7 @@ If you are interested in _Jetzig_ you will probably find these tools interesting ## LICENSE [MIT](LICENSE) + +## Contributors + +* [Bob Farrell](https://github.com/bobf) diff --git a/src/jetzig/http/Server.zig b/src/jetzig/http/Server.zig index 3d93bd9..8a85c2e 100644 --- a/src/jetzig/http/Server.zig +++ b/src/jetzig/http/Server.zig @@ -292,16 +292,34 @@ fn isUnhandledError(err: anyerror) bool { } fn internalServerError(self: *Self, request: *jetzig.http.Request, err: anyerror) !RenderedView { - _ = self; request.response_data.reset(); + var object = try request.response_data.object(); try object.put("error", request.response_data.string(@errorName(err))); + const stack = @errorReturnTrace(); + if (stack) |capture| try self.logStackTrace(capture, request, object); + return .{ .view = jetzig.views.View{ .data = request.response_data, .status_code = .internal_server_error }, .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 { const status: jetzig.http.status_codes.TaggedStatusCode = switch (result.value.status_code) {