diff --git a/go.mod b/go.mod index d0472c5..7a70409 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/go-playground/universal-translator v0.18.0 github.com/go-playground/validator/v10 v10.9.0 github.com/go-redis/redis/v8 v8.8.3 + github.com/gofrs/uuid v4.2.0+incompatible github.com/iamolegga/enviper v1.2.1 github.com/jackc/pgx/v4 v4.10.1 github.com/jmoiron/sqlx v1.3.3 diff --git a/go.sum b/go.sum index b5f2971..fdf5c3f 100644 --- a/go.sum +++ b/go.sum @@ -545,8 +545,9 @@ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= diff --git a/logging/correlation.go b/logging/correlation.go new file mode 100644 index 0000000..f13e556 --- /dev/null +++ b/logging/correlation.go @@ -0,0 +1,48 @@ +package logging + +import ( + "context" + + "github.com/gin-gonic/gin" + "github.com/gofrs/uuid" + "go.uber.org/zap" +) + +type ctxKey string + +const ( + CorrelationIDName ctxKey = "correlation_id" + IntCorrelationIDName ctxKey = "int_correlation_id" + ExternalCorrelationIDName string = "X-Correlation-Id" +) + +// CorrelationIDMiddleware adds correlationID if it's not specified in HTTP request +func CorrelationIDMiddleware(l *zap.SugaredLogger) gin.HandlerFunc { + return func(c *gin.Context) { + addCorrelationID(c, l) + } +} + +func addCorrelationID(c *gin.Context, l *zap.SugaredLogger) { + ctx := c.Request.Context() + + correlationID := c.Request.Header.Get(ExternalCorrelationIDName) + + if correlationID != "" { + ctx = context.WithValue(ctx, CorrelationIDName, correlationID) + c.Writer.Header().Set(ExternalCorrelationIDName, correlationID) + l = l.With(CorrelationIDName, correlationID) + } + + id, err := uuid.NewV4() + l.Errorf("Error while creating new internal correlation id error: %w", err) + + ctx = context.WithValue(ctx, IntCorrelationIDName, id.String()) + l = l.With(IntCorrelationIDName, id) + + c.Set("logger", l) + + c.Request = c.Request.WithContext(ctx) + + c.Next() +} diff --git a/logging/rest.go b/logging/rest.go index 2262e49..51d7f09 100644 --- a/logging/rest.go +++ b/logging/rest.go @@ -1,6 +1,7 @@ package logging import ( + "fmt" "time" "github.com/gin-gonic/gin" @@ -17,6 +18,9 @@ func LogRequest(logger *zap.Logger) gin.HandlerFunc { func log(c *gin.Context) { start := time.Now() + + c.Next() + // some evil middlewares modify this values path := c.Request.URL.Path query := c.Request.URL.RawQuery @@ -30,6 +34,18 @@ func log(c *gin.Context) { zap.String("user-agent", c.Request.UserAgent()), zap.String("time", start.Format(time.RFC3339)), ) +} - c.Next() +func GetLoggerFromContext(c *gin.Context) (*zap.SugaredLogger, error) { + value, ok := c.Get("logger") + if !ok { + return nil, fmt.Errorf("logger does not exists in context") + } + + l, ok := value.(*zap.SugaredLogger) + if !ok { + return nil, fmt.Errorf("invalid logger format in context") + } + + return l, nil }