const Logger = @This(); query: bool, // Must define an `init` method, which will accept your Config // Alternatively, you can define a init(config: Config, mc: httpz.MiddlewareConfig) // here mc will give you access to the server's allocator and arena pub fn init(config: Config) !Logger { return .{ .query = config.query, }; } // optionally you can define an "deinit" method // pub fn deinit(self: *Logger) void { // } // Must define an `execute` method. `self` doesn't have to be `const`, but // you're responsible for making your middleware thread-safe. pub fn execute(self: *const Logger, req: *httpz.Request, res: *httpz.Response, executor: anytype) !void { const start = std.time.microTimestamp(); defer { const elapsed = std.time.microTimestamp() - start; var logger = logz.logger().multiuse() .stringSafe("@l", "REQ") .stringSafe("method", @tagName(req.method)) .int("status", res.status) .string("path", req.url.path); if (self.query) { _ = logger.string("query", req.url.query); } logger.int("us", elapsed).log(); } // If you don't call executor.next(), there will be no further processing of // the request and we'll go straight to writing the response. return executor.next(); } // Must defined a pub config structure, even if it's empty pub const Config = struct { query: bool, }; const std = @import("std"); const httpz = @import("httpz"); const logz = @import("logz");