From 0480e066a3f1ae97dbab8fcb6303589eb0fa724c Mon Sep 17 00:00:00 2001 From: tjpcc Date: Mon, 23 Jan 2023 22:15:16 -0700 Subject: logging library up to top level --- logging/middleware.go | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 logging/middleware.go (limited to 'logging/middleware.go') diff --git a/logging/middleware.go b/logging/middleware.go new file mode 100644 index 0000000..cbb345a --- /dev/null +++ b/logging/middleware.go @@ -0,0 +1,107 @@ +package logging + +import ( + "context" + "errors" + "io" + "time" + + "tildegit.org/tjp/gus" +) + +func LogRequests(logger Logger) gus.Middleware { + return func(inner gus.Handler) gus.Handler { + return func(ctx context.Context, request *gus.Request) *gus.Response { + start := time.Now() + + response := inner(ctx, request) + if response != nil { + body := loggedResponseBody{ + request: request, + response: response, + body: response.Body, + start: start, + logger: logger, + } + response.Body = &body + } + + return response + } + } +} + +type loggedResponseBody struct { + request *gus.Request + response *gus.Response + body io.Reader + + start time.Time + + written int + logger Logger +} + +func loggingBody(logger Logger, request *gus.Request, response *gus.Response) io.Reader { + body := &loggedResponseBody{ + request: request, + response: response, + body: response.Body, + start: time.Now(), + written: 0, + logger: logger, + } + + if _, ok := response.Body.(io.WriterTo); ok { + return loggedWriteToResponseBody{body} + } + + return body +} + +func (lr *loggedResponseBody) log() { + end := time.Now() + _ = lr.logger.Log( + "msg", "request", + "ts", end, + "dur", end.Sub(lr.start), + "url", lr.request.URL, + "status", lr.response.Status, + "bodylen", lr.written, + ) +} + +func (lr *loggedResponseBody) Read(b []byte) (int, error) { + if lr.body == nil { + return 0, io.EOF + } + + wr, err := lr.body.Read(b) + lr.written += wr + + if errors.Is(err, io.EOF) { + lr.log() + } + + return wr, err +} + +func (lr *loggedResponseBody) Close() error { + if cl, ok := lr.body.(io.Closer); ok { + return cl.Close() + } + return nil +} + +type loggedWriteToResponseBody struct { + *loggedResponseBody +} + +func (lwtr loggedWriteToResponseBody) WriteTo(dst io.Writer) (int64, error) { + n, err := lwtr.body.(io.WriterTo).WriteTo(dst) + if err == nil { + lwtr.written += int(n) + lwtr.log() + } + return n, err +} -- cgit v1.2.3