From 345723fa597785088503f8b300714e0cfe8e097c Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Sat, 9 Mar 2024 09:24:03 +0100 Subject: [PATCH 1/8] feat: migrate to slog.Logger This commit removes the ServerLogger interface and updates the recover and logging middlewares. Signed-off-by: Marek Cermak --- README.md | 20 +++++++++----- http/config.go | 5 ++-- http/middleware.go | 55 ++++++++++++++++++++++++++------------ http/server.go | 20 +++++++------- internal/logger.go | 34 ++++++++++++++++------- internal/responsewriter.go | 11 ++++---- logger/logger.go | 35 ------------------------ 7 files changed, 93 insertions(+), 87 deletions(-) delete mode 100644 logger/logger.go diff --git a/README.md b/README.md index a57664a..08881a0 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,13 @@ Go package facilitating writing API applications in a fast and easy manner. ### errors Definition of common errors. -### logger -Interface `ServerLogger` implements common logging methods. - ### net Common functionality that comes in handy regardless of the used API architecture. `net` currently supports generating request IDs with some helper methods. ### http Wrapper around the Go native http server. `http` defines the `Server` that can be configured by the `ServerConfig`. Implemented features: - Started http server can be easily stopped by cancelling the context that is passed by the `Run` method. -- The `Server` can be configured with a logger for logging important information during starting/ending of the server. +- The `Server` can be configured with a slog.Logger for logging important information during starting/ending of the server. - The `Server` listens for `SIGINT` and `SIGTERM` signals so it can be stopped by firing the signal. - By the `ServerConfig` can be configured functions to be called before the `Server` ends. @@ -46,7 +43,16 @@ import ( func main() { ... - + h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ + Level: level, + ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { + if a.Key == slog.TimeKey { + a.Value = slog.StringValue(a.Value.Time().Format("2006-01-02T15:04:05.000Z")) + } + return a + }, + }) + l := slog.New(h) serverConfig := httpx.ServerConfig{ Addr: ":8080", Handler: handler(), // define your http handler @@ -58,11 +64,11 @@ func main() { }, }, Limits: nil, - Logger: util.NewServerLogger("httpx.Server"), // wrapper around zap logger to implement httpx logging interface + Logger: l.WithGroup("httpx.Server"), // the server expects *slog.Logger } server := httpx.NewServer(&serverConfig) if err = server.Start(ctx); err != nil { - logger.Fatal("HTTP server unexpectedly ended", zap.Error(err)) + l.Error("HTTP server unexpectedly ended", slog.Any("error", err)) } } ``` diff --git a/http/config.go b/http/config.go index cf4eb0d..a7c0aae 100644 --- a/http/config.go +++ b/http/config.go @@ -1,10 +1,9 @@ package http import ( + "log/slog" "net/http" - "go.strv.io/net/logger" - "go.strv.io/time" ) @@ -23,7 +22,7 @@ type ServerConfig struct { Limits *Limits `json:"limits,omitempty"` // Logger is server logger. - Logger logger.ServerLogger + Logger *slog.Logger } // Limits define timeouts and header restrictions. diff --git a/http/middleware.go b/http/middleware.go index 41f2d30..b7712b5 100644 --- a/http/middleware.go +++ b/http/middleware.go @@ -1,12 +1,13 @@ package http import ( + "log/slog" "net/http" + "runtime/debug" "time" "go.strv.io/net" "go.strv.io/net/internal" - "go.strv.io/net/logger" ) const ( @@ -40,10 +41,26 @@ func RequestIDMiddleware(f RequestIDFunc) func(http.Handler) http.Handler { } } +type RecoverMiddlewareOptions struct { + enableStackTrace bool +} + +type RecoverMiddlewareOption func(*RecoverMiddlewareOptions) + +func WithStackTrace() RecoverMiddlewareOption { + return func(opts *RecoverMiddlewareOptions) { + opts.enableStackTrace = true + } +} + // RecoverMiddleware calls next handler and recovers from a panic. // If a panic occurs, log this event, set http.StatusInternalServerError as a status code // and save a panic object into the response writer. -func RecoverMiddleware(l logger.ServerLogger) func(http.Handler) http.Handler { +func RecoverMiddleware(l *slog.Logger, opts ...RecoverMiddlewareOption) func(http.Handler) http.Handler { + options := RecoverMiddlewareOptions{} + for _, o := range opts { + o(&options) + } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { @@ -56,10 +73,14 @@ func RecoverMiddleware(l logger.ServerLogger) func(http.Handler) http.Handler { rw.SetPanicObject(re) rw.WriteHeader(http.StatusInternalServerError) - l.With( - logger.Any("err", re), - logger.Any(requestIDLogFieldName, net.RequestIDFromCtx(r.Context())), - ).Error("panic recover", nil) + logAttributes := []slog.Attr{ + slog.Any(requestIDLogFieldName, net.RequestIDFromCtx(r.Context())), + slog.Any("error", re), + } + if options.enableStackTrace { + logAttributes = append(logAttributes, slog.String("trace", string(debug.Stack()))) + } + l.LogAttrs(r.Context(), slog.LevelError, "panic recover", logAttributes...) } }() next.ServeHTTP(w, r) @@ -77,7 +98,7 @@ func RecoverMiddleware(l logger.ServerLogger) func(http.Handler) http.Handler { // - Panic object if exists // // If the status code >= http.StatusInternalServerError, logs with error level, info otherwise. -func LoggingMiddleware(l logger.ServerLogger) func(http.Handler) http.Handler { +func LoggingMiddleware(l *slog.Logger) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { rw, ok := w.(*internal.ResponseWriter) @@ -101,7 +122,7 @@ func LoggingMiddleware(l logger.ServerLogger) func(http.Handler) http.Handler { } if statusCode >= http.StatusInternalServerError { - WithData(l, ld).Error("request processed", nil) + WithData(l, ld).Error("request processed") } else { WithData(l, ld).Info("request processed") } @@ -127,20 +148,20 @@ type LogData struct { Panic any } -// WithData returns logger with filled fields. -func WithData(l logger.ServerLogger, ld LogData) logger.ServerLogger { +// WithData returns slog with filled fields. +func WithData(l *slog.Logger, ld LogData) *slog.Logger { l = l.With( - logger.Any("method", ld.Method), - logger.Any("path", ld.Path), - logger.Any("status_code", ld.ResponseStatusCode), - logger.Any("request_id", ld.RequestID), - logger.Any("duration_ms", ld.Duration.Milliseconds()), + slog.Any("method", ld.Method), + slog.String("path", ld.Path), + slog.Int("status_code", ld.ResponseStatusCode), + slog.String("request_id", ld.RequestID), + slog.Duration("duration_ms", ld.Duration), ) if ld.Err != nil { - l = l.With(logger.Any("err", ld.Err.Error())) + l = l.With(slog.Any("error", ld.Err)) } if ld.Panic != nil { - l = l.With(logger.Any("panic", ld.Panic)) + l = l.With(slog.Any("panic", ld.Panic)) } return l } diff --git a/http/server.go b/http/server.go index c46db08..275ed26 100644 --- a/http/server.go +++ b/http/server.go @@ -3,6 +3,7 @@ package http import ( "context" "errors" + "log/slog" "net" "net/http" "os" @@ -13,7 +14,6 @@ import ( neterrors "go.strv.io/net/errors" "go.strv.io/net/internal" - "go.strv.io/net/logger" ) func NewServer(config *ServerConfig) *Server { @@ -22,7 +22,7 @@ func NewServer(config *ServerConfig) *Server { } if config.Logger == nil { - config.Logger = &internal.NopLogger{} + config.Logger = internal.NewNopLogger() } s := &Server{ @@ -55,7 +55,7 @@ func NewServer(config *ServerConfig) *Server { } type Server struct { - logger logger.ServerLogger + logger *slog.Logger server *http.Server signalsListener chan os.Signal @@ -69,7 +69,7 @@ type Server struct { // Passed context is used as base context of all http requests and to shutdown server gracefully. func (s *Server) Run(ctx context.Context) error { if s.logger == nil { - s.logger = &internal.NopLogger{} + s.logger = internal.NewNopLogger() } cCtx, cancel := context.WithCancel(ctx) @@ -92,22 +92,22 @@ func (s *Server) Run(ctx context.Context) error { if errors.Is(err, http.ErrServerClosed) { s.logger.Debug("server stopped: server closed") } else { - s.logger.Error("server stopped: error received", err) + s.logger.Error("server stopped: error received", slog.Any("error", err)) } case <-ctx.Done(): - s.logger.Error("server stopped: context closed", ctx.Err()) + s.logger.Error("server stopped: context closed", slog.Any("error", ctx.Err())) case sig := <-s.signalsListener: s.logger.With( - logger.Any("signal", sig), - ).Error("server stopped: signal received", neterrors.ErrServerInterrupted) + slog.Any("signal", sig), + ).Error("server stopped: signal received", slog.Any("error", neterrors.ErrServerInterrupted)) } s.logger.With( - logger.Any("timeout", s.shutdownTimeout.String()), + slog.Duration("timeout", *s.shutdownTimeout), ).Debug("waiting for server shutdown...") if err := s.server.Shutdown(context.Background()); err != nil { - s.logger.Error("server shutdown", err) + s.logger.Error("server shutdown", slog.Any("error", err)) return err } defer s.logger.Debug("server shutdown complete") diff --git a/internal/logger.go b/internal/logger.go index 84796a4..a824a6b 100644 --- a/internal/logger.go +++ b/internal/logger.go @@ -1,18 +1,34 @@ package internal -import "go.strv.io/net/logger" +import ( + "context" + "log/slog" +) -// NopLogger is a no-op logger that is used if no logger is present. -type NopLogger struct{} +func NewNopLogger() *slog.Logger { + return slog.New(nopHandler{}) +} -func (l *NopLogger) With(...logger.Field) logger.ServerLogger { - return l +// NopLogger is a no-op logger that discards all of the log messages. +// This logger is used in the case no other logger is provided to the server. +type NopLogger struct { + slog.Logger } -func (*NopLogger) Info(string) {} +type nopHandler struct{} + +func (nopHandler) Enabled(context.Context, slog.Level) bool { + return false +} -func (*NopLogger) Debug(string) {} +func (nopHandler) Handle(context.Context, slog.Record) error { + return nil +} -func (*NopLogger) Warn(string) {} +func (n nopHandler) WithAttrs([]slog.Attr) slog.Handler { + return n +} -func (*NopLogger) Error(string, error) {} +func (n nopHandler) WithGroup(string) slog.Handler { + return n +} diff --git a/internal/responsewriter.go b/internal/responsewriter.go index 5952e45..64fbd2c 100644 --- a/internal/responsewriter.go +++ b/internal/responsewriter.go @@ -3,23 +3,22 @@ package internal import ( "bufio" "errors" + "log/slog" "net" "net/http" "sync/atomic" - - "go.strv.io/net/logger" ) type ResponseWriter struct { http.ResponseWriter statusCode int calledWriteHeader int32 - logger logger.ServerLogger + logger *slog.Logger err error panic any } -func NewResponseWriter(w http.ResponseWriter, l logger.ServerLogger) *ResponseWriter { +func NewResponseWriter(w http.ResponseWriter, l *slog.Logger) *ResponseWriter { return &ResponseWriter{ ResponseWriter: w, statusCode: http.StatusOK, @@ -39,8 +38,8 @@ func (r *ResponseWriter) WriteHeader(statusCode int) { return } r.logger.With( - logger.Any("current_status_code", r.statusCode), - logger.Any("ignored_status_code", statusCode), + slog.Int("current_status_code", r.statusCode), + slog.Int("ignored_status_code", statusCode), ).Warn("WriteHeader multiple call") } diff --git a/logger/logger.go b/logger/logger.go deleted file mode 100644 index ca4d5a9..0000000 --- a/logger/logger.go +++ /dev/null @@ -1,35 +0,0 @@ -package logger - -// ServerLogger is an interface for logging server messages. -type ServerLogger interface { - // With creates a child logger and adds structured context to it. Fields added - // to the child don't affect the parent, and vice versa. - With(fields ...Field) ServerLogger - - // Info logs a message at InfoLevel. The message includes any fields passed - // at the log site, as well as any fields accumulated on the logger. - Info(msg string) - - // Debug logs a message at DebugLevel. The message includes any fields passed - // at the log site, as well as any fields accumulated on the logger. - Debug(msg string) - - // Warn logs a message at WarnLevel. The message includes any fields passed - // at the log site, as well as any fields accumulated on the logger. - Warn(msg string) - - // Error logs a message at ErrorLevel. The message includes any fields passed - // at the log site, as well as any fields accumulated on the logger. - Error(msg string, err error) -} - -// Field contains logging context passed to logging functions. -// It is inspired by zapcore.Field. See https://godoc.org/go.uber.org/zap#Field for details. -type Field struct { - Key string - Value any -} - -func Any(key string, value any) Field { - return Field{Key: key, Value: value} -} From 42a4756fd75149732ef858e2c35e1bcc5cf1dc0d Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Sat, 9 Mar 2024 09:31:40 +0100 Subject: [PATCH 2/8] ci: update setup-go workflow Signed-off-by: Marek Cermak --- .github/actions/setup-go/action.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml index 03ce258..bd4d978 100644 --- a/.github/actions/setup-go/action.yml +++ b/.github/actions/setup-go/action.yml @@ -3,9 +3,10 @@ description: | Setup Go inputs: - go-version: - description: Used Go version - default: '1.20' + cache: + description: Cache + required: false + default: "true" runs: using: "composite" @@ -15,10 +16,11 @@ runs: echo "Go version is set to ${{ inputs.go-version }}" echo "GO_VERSION=${{ inputs.go-version }}" >> $GITHUB_ENV shell: bash + name: Setup Go - id: go-setup - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: - go-version: ${{ env.GO_VERSION }} - - run: | - go mod download - shell: bash + go-version-file: go.mod + check-latest: true + cache: ${{ inputs.cache }} + From 9e1101d75958123dc152e966f856f43fddaf01bb Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Sat, 9 Mar 2024 09:33:12 +0100 Subject: [PATCH 3/8] build: update to go 1.22 Signed-off-by: Marek Cermak --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index b978113..4c35490 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module go.strv.io/net -go 1.20 +go 1.22 require ( github.com/go-chi/chi/v5 v5.0.8 From ee52e4acee7beef4f4984f5c1f32da7705eadd97 Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Sat, 9 Mar 2024 09:36:08 +0100 Subject: [PATCH 4/8] ci: update golangci-lint version Signed-off-by: Marek Cermak --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 79c4266..cebd54a 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -23,4 +23,4 @@ jobs: - name: Run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.51.1 + version: v1.56.1 From 4ec0ac5965b24bd6ef6781e0ba654f88177b04c1 Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Mon, 11 Mar 2024 06:35:32 +0100 Subject: [PATCH 5/8] chore: refactor log data in to log valuer This commit also removes the error and panic objects from the log data and renames it to request data. The fields are then nested under a group called "request" and as such, "request_" prefix was removed from the fields. Signed-off-by: Marek Cermak --- http/middleware.go | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/http/middleware.go b/http/middleware.go index b7712b5..41ae5ea 100644 --- a/http/middleware.go +++ b/http/middleware.go @@ -111,26 +111,24 @@ func LoggingMiddleware(l *slog.Logger) func(http.Handler) http.Handler { statusCode := rw.StatusCode() requestID := net.RequestIDFromCtx(r.Context()) - ld := LogData{ + ld := RequestData{ Path: r.URL.EscapedPath(), Method: r.Method, RequestID: requestID, Duration: time.Since(requestStart), ResponseStatusCode: statusCode, - Err: rw.ErrorObject(), - Panic: rw.PanicObject(), } if statusCode >= http.StatusInternalServerError { - WithData(l, ld).Error("request processed") + withRequestData(l, rw, ld).Error("request processed") } else { - WithData(l, ld).Info("request processed") + withRequestData(l, rw, ld).Info("request processed") } }) } } -// LogData contains processed request data for logging purposes. +// RequestData contains processed request data for logging purposes. // Path is path from URL of the request. // Method is HTTP request method. // Duration is how long it took to process whole request. @@ -138,30 +136,34 @@ func LoggingMiddleware(l *slog.Logger) func(http.Handler) http.Handler { // RequestID is unique identifier of request. // Err is error object containing error message. // Panic is panic object containing error message. -type LogData struct { +type RequestData struct { Path string Method string Duration time.Duration ResponseStatusCode int RequestID string - Err error - Panic any } -// WithData returns slog with filled fields. -func WithData(l *slog.Logger, ld LogData) *slog.Logger { - l = l.With( - slog.Any("method", ld.Method), - slog.String("path", ld.Path), - slog.Int("status_code", ld.ResponseStatusCode), - slog.String("request_id", ld.RequestID), - slog.Duration("duration_ms", ld.Duration), - ) - if ld.Err != nil { - l = l.With(slog.Any("error", ld.Err)) +func (r RequestData) LogValue() slog.Value { + attr := []slog.Attr{ + slog.String("id", r.RequestID), + slog.String("method", r.Method), + slog.String("path", r.Path), + slog.Int("status_code", r.ResponseStatusCode), + slog.Duration("duration_ms", r.Duration), } - if ld.Panic != nil { - l = l.With(slog.Any("panic", ld.Panic)) + return slog.GroupValue(attr...) +} + +// withRequestData returns slog with filled fields. +func withRequestData(l *slog.Logger, rw *internal.ResponseWriter, rd RequestData) *slog.Logger { + errorObject := rw.ErrorObject() + panicObject := rw.PanicObject() + if errorObject != nil { + l = l.With("error", errorObject) + } + if panicObject != nil { + l = l.With("panic", panicObject) } - return l + return l.With("request", rd) } From 00fd34e17425dd75ee08065288e60529eea6c249 Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Mon, 11 Mar 2024 07:07:43 +0100 Subject: [PATCH 6/8] chore: refactor to account for review comments Signed-off-by: Marek Cermak --- http/middleware.go | 4 ++-- http/server.go | 4 ---- http/server_test.go | 3 +++ internal/logger.go | 8 ++++---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/http/middleware.go b/http/middleware.go index 41ae5ea..1eb3849 100644 --- a/http/middleware.go +++ b/http/middleware.go @@ -74,11 +74,11 @@ func RecoverMiddleware(l *slog.Logger, opts ...RecoverMiddlewareOption) func(htt rw.WriteHeader(http.StatusInternalServerError) logAttributes := []slog.Attr{ - slog.Any(requestIDLogFieldName, net.RequestIDFromCtx(r.Context())), + slog.String(requestIDLogFieldName, net.RequestIDFromCtx(r.Context())), slog.Any("error", re), } if options.enableStackTrace { - logAttributes = append(logAttributes, slog.String("trace", string(debug.Stack()))) + logAttributes = append(logAttributes, slog.String("stack_trace", string(debug.Stack()))) } l.LogAttrs(r.Context(), slog.LevelError, "panic recover", logAttributes...) } diff --git a/http/server.go b/http/server.go index 275ed26..7785ca3 100644 --- a/http/server.go +++ b/http/server.go @@ -68,10 +68,6 @@ type Server struct { // Run calls ListenAndServe but returns error only if err != http.ErrServerClosed. // Passed context is used as base context of all http requests and to shutdown server gracefully. func (s *Server) Run(ctx context.Context) error { - if s.logger == nil { - s.logger = internal.NewNopLogger() - } - cCtx, cancel := context.WithCancel(ctx) defer cancel() diff --git a/http/server_test.go b/http/server_test.go index 1eed812..7188184 100644 --- a/http/server_test.go +++ b/http/server_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "go.strv.io/net/internal" ) type cancellableContext struct { @@ -66,6 +67,7 @@ func TestNewServer(t *testing.T) { want: func() *Server { //nolint:gosec s := &Server{ + logger: internal.NewNopLogger(), server: &http.Server{}, shutdownTimeout: &defaultShutdownTimeout, doBeforeShutdown: []ServerHookFunc(nil), @@ -173,6 +175,7 @@ func TestServer_Start(t *testing.T) { } s := &Server{ + logger: internal.NewNopLogger(), server: tt.fields.server, signalsListener: tt.fields.signalsListener, shutdownTimeout: tt.fields.shutdownTimeout, diff --git a/internal/logger.go b/internal/logger.go index a824a6b..fe49b61 100644 --- a/internal/logger.go +++ b/internal/logger.go @@ -5,16 +5,16 @@ import ( "log/slog" ) -func NewNopLogger() *slog.Logger { - return slog.New(nopHandler{}) -} - // NopLogger is a no-op logger that discards all of the log messages. // This logger is used in the case no other logger is provided to the server. type NopLogger struct { slog.Logger } +func NewNopLogger() *slog.Logger { + return slog.New(nopHandler{}) +} + type nopHandler struct{} func (nopHandler) Enabled(context.Context, slog.Level) bool { From 5c09c41c8ff091fc4da6c7408186e5e59df0d848 Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Mon, 11 Mar 2024 07:11:49 +0100 Subject: [PATCH 7/8] build: upgrade Go dependencies Signed-off-by: Marek Cermak --- go.mod | 10 +++++----- go.sum | 30 +++++++++++------------------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 4c35490..f9ceb67 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,17 @@ module go.strv.io/net go 1.22 require ( - github.com/go-chi/chi/v5 v5.0.8 - github.com/google/uuid v1.3.0 - github.com/stretchr/testify v1.8.0 + github.com/go-chi/chi/v5 v5.0.12 + github.com/google/uuid v1.6.0 + github.com/stretchr/testify v1.9.0 go.strv.io/time v0.2.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index db22115..b64c081 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,13 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= -github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= +github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -17,21 +15,15 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.strv.io/time v0.2.0 h1:RgCpABq+temfp8+DLM2zqsdimnKpktOSPduUghM8ZIk= go.strv.io/time v0.2.0/go.mod h1:B/lByAO3oACN3uLOXQaB64cKhkVIMoZjnZBhADFNbFY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 13501ff980d7171a7e768ce5ac27205e36dec4c1 Mon Sep 17 00:00:00 2001 From: Marek Cermak Date: Mon, 11 Mar 2024 07:23:39 +0100 Subject: [PATCH 8/8] docs: update CHANGELOG Signed-off-by: Marek Cermak --- CHANGELOG.md | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06be892..f39e0c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,28 @@ How to release a new version: ## [Unreleased] -## [0.6.2] - 2022-06-27 +## [0.7.0] - 2024-03-11 +### Changed +- Logging interface changes to `log/slog`. + + NOTE: This is version presents a BREAKING CHANGE in the server's logger interface. The server now accepts a `slog.Logger` instead of a custom `ServerLogger`. +- Change in the logging middleware. The middleware now nests request specific data under the "request" group. +- Updated from Go 1.20 to Go 1.22. +- Updated packages: + ```diff + - github.com/go-chi/chi/v5 v5.0.8 + - github.com/google/uuid v1.3.0 + - github.com/stretchr/testify v1.8.0 + + github.com/go-chi/chi/v5 v5.0.12 + + github.com/google/uuid v1.6.0 + + github.com/stretchr/testify v1.9.0 + ``` + +## [0.6.2] - 2023-06-27 ### Fixed - Error logging when terminating HTTP server. -## [0.6.1] - 2022-03-28 +## [0.6.1] - 2023-03-28 ### Changed - package `http/param` does not zero the field if not tagged with any relevant tags @@ -18,7 +35,7 @@ How to release a new version: - package `http/signature` to simplify defining http handler functions - package `http/param` to simplify parsing http path and query parameters -## [0.5.0] - 2022-01-20 +## [0.5.0] - 2023-01-20 ### Added - `ErrorResponseOptions` contains public error message. - `ErrorResponseOptions` contains request ID. @@ -26,7 +43,7 @@ How to release a new version: - `WithErrorMessage` - `WithRequestID` -## [0.4.0] - 2022-01-12 +## [0.4.0] - 2023-01-12 ### Changed - JSON tags in `ErrorResponseOptions`. @@ -53,7 +70,8 @@ How to release a new version: ### Added - Added Changelog. -[Unreleased]: https://github.com/strvcom/strv-backend-go-net/compare/v0.6.2...HEAD +[Unreleased]: https://github.com/strvcom/strv-backend-go-net/compare/v0.7.0...HEAD +[0.7.0]: https://github.com/strvcom/strv-backend-go-net/compare/v0.6.2...v0.7.0 [0.6.2]: https://github.com/strvcom/strv-backend-go-net/compare/v0.6.1...v0.6.2 [0.6.1]: https://github.com/strvcom/strv-backend-go-net/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/strvcom/strv-backend-go-net/compare/v0.5.0...v0.6.0