...

Source file src/edge-infra.dev/pkg/sds/emergencyaccess/middleware/middleware.go

Documentation: edge-infra.dev/pkg/sds/emergencyaccess/middleware

     1  package middleware
     2  
     3  import (
     4  	"context"
     5  
     6  	"edge-infra.dev/pkg/lib/fog"
     7  
     8  	"github.com/gin-contrib/requestid"
     9  	"github.com/gin-gonic/gin"
    10  	"github.com/go-logr/logr"
    11  )
    12  
    13  type correlationIDKey struct{}
    14  
    15  const (
    16  	CorrelationIDKey   = "X-Correlation-ID"
    17  	correlationIDLabel = "correlationID"
    18  )
    19  
    20  // Sets the input logger with Operation ID and Correlation ID values in the server context, where
    21  // Operation ID refers to each request that the component receives and Correlation ID refers to a
    22  // request made by a user as it travels through the system.
    23  //
    24  // Expects the use of [pkg/edge-infra.dev/pkg/edge/api/middleware.SetRequestContext] middleware
    25  // to set the Correlation ID value in the context. Please include WithCustomHeaderStrKey(CorrelationIDLabel)
    26  // as an option in requestid.New().
    27  //
    28  // Expects the gin engine's ContextWithFallback field to be set to true to allow request
    29  // context values to fallback to the parent context. By default it is false.
    30  //
    31  // The Correlation ID value is set from the incoming `X-Correlation-ID` header
    32  // if present. It is possible to use the [GetCorrelationID] function to extract
    33  // the incoming correlation ID from a context to be used to propagate to any
    34  // further services used for a particular request
    35  func SetLoggerInContext(log logr.Logger) gin.HandlerFunc {
    36  	return func(c *gin.Context) {
    37  		correlationID := requestid.Get(c)
    38  		operationID := fog.OperationID(c.Request.Context())
    39  
    40  		log := log.WithValues(correlationIDLabel, correlationID)
    41  		log = log.WithValues(fog.OperationFields(operationID)...)
    42  
    43  		ctxWithID := context.WithValue(c.Request.Context(), correlationIDKey{}, correlationID)
    44  		c.Request = c.Request.Clone(fog.IntoContext(ctxWithID, log))
    45  
    46  		c.Next()
    47  	}
    48  }
    49  
    50  // Writes an initial log message before a request is processed and a final log after a request is finished (success OR fail).
    51  // Should be set in a router after correlation and operation IDs are set, and before any middleware that could end the request.
    52  func RequestBookendLogs() gin.HandlerFunc {
    53  	return func(c *gin.Context) {
    54  		// before request
    55  		url := c.Request.URL.Path
    56  		log := fog.FromContext(c, "endpoint", url)
    57  		c.Request = c.Request.Clone(fog.IntoContext(c.Request.Context(), log))
    58  		log.Info("Request received")
    59  
    60  		c.Next()
    61  
    62  		// after request
    63  		status := c.Writer.Status()
    64  		log = fog.FromContext(c, "statusCode", status)
    65  		if status < 400 {
    66  			log = log.WithValues("isSuccessful", true)
    67  		} else {
    68  			log = log.WithValues("isSuccessful", false)
    69  		}
    70  		log.Info("Request completed")
    71  	}
    72  }
    73  
    74  func GetCorrelationID(ctx context.Context) string {
    75  	correlationID := ctx.Value(correlationIDKey{})
    76  	if correlationID == nil { // Avoid panic if correlationID has not been set
    77  		return ""
    78  	}
    79  	return correlationID.(string)
    80  }
    81  

View as plain text