Skip to content

Commit

Permalink
Merge pull request #9 from mittwald/feat/logging
Browse files Browse the repository at this point in the history
feat: add option to log all executed requests
  • Loading branch information
martin-helmich authored Feb 5, 2025
2 parents b89a4c5 + b5e2ce5 commit 9eea9b1
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
21 changes: 21 additions & 0 deletions mittwaldv2/client_opt_logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package mittwaldv2

import (
"context"
"log/slog"

"github.com/mittwald/api-client-go/pkg/httpclient"
)

// WithRequestLogging adds a logging middleware to the request runner chain
// allowing you to log all executed HTTP requests in a slog.Logger of your
// choice.
//
// Be mindful of the log{Request,Response}Bodies parameters; these will cause
// the logger to print the full request bodies without redaction, which may
// easily leak sensitive data.
func WithRequestLogging(logger *slog.Logger, logRequestBodies, logResponseBodies bool) ClientOption {
return func(ctx context.Context, runner httpclient.RequestRunner) (httpclient.RequestRunner, error) {
return httpclient.NewLoggingClient(runner, logger, logRequestBodies, logResponseBodies), nil
}
}
59 changes: 59 additions & 0 deletions pkg/httpclient/client_logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package httpclient

import (
"bytes"
"io"
"log/slog"
"net/http"
)

type loggingClient struct {
inner RequestRunner
logger *slog.Logger
logRequestBodies bool
logResponseBodies bool
}

func NewLoggingClient(inner RequestRunner, logger *slog.Logger, logRequestBodies, logResponseBodies bool) RequestRunner {
return &loggingClient{
inner: inner,
logger: logger,
logRequestBodies: logRequestBodies,
logResponseBodies: logResponseBodies,
}
}

func (c *loggingClient) Do(request *http.Request) (*http.Response, error) {
l := c.logger.With("req.method", request.Method, "req.url", request.URL.String())

if c.logRequestBodies && request.Body != nil {
body, err := io.ReadAll(request.Body)
if err != nil {
return nil, err
}

request.Body = io.NopCloser(bytes.NewBuffer(body))
l = l.With("req.body", string(body))
}

l.Debug("executing request")

response, err := c.inner.Do(request)

if response != nil {
l = l.With("res.status", response.StatusCode)
if c.logResponseBodies && response.Body != nil {
body, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
}

response.Body = io.NopCloser(bytes.NewBuffer(body))
l = l.With("res.body", string(body))
}
}

l.Debug("received response")

return response, err
}

0 comments on commit 9eea9b1

Please sign in to comment.