78 lines
2.8 KiB
Go
78 lines
2.8 KiB
Go
// nolint:revive
|
|
package util
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const (
|
|
CTXKeyUser contextKey = "user"
|
|
CTXKeyAccessToken contextKey = "access_token"
|
|
CTXKeyCacheControl contextKey = "cache_control"
|
|
CTXKeyRequestID contextKey = "request_id"
|
|
CTXKeyDisableLogger contextKey = "disable_logger"
|
|
)
|
|
|
|
//nolint:containedctx
|
|
type detachedContext struct {
|
|
parent context.Context
|
|
}
|
|
|
|
func (c detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
|
func (c detachedContext) Done() <-chan struct{} { return nil }
|
|
func (c detachedContext) Err() error { return nil }
|
|
func (c detachedContext) Value(key interface{}) interface{} { return c.parent.Value(key) }
|
|
|
|
// DetachContext detaches a context by returning a wrapped struct implementing the context interface, but omitting the deadline, done and error functionality.
|
|
// Mainly used to pass context information to go routines that should not be cancelled by the context.
|
|
// ! USE THIS DETACHED CONTEXT SPARINGLY, ONLY IF ABSOLUTELY NEEDED. DO *NOT* KEEP USING A DETACHED CONTEXT FOR A PROLONGED TIME OUT OF CHAIN
|
|
func DetachContext(ctx context.Context) context.Context {
|
|
return detachedContext{ctx}
|
|
}
|
|
|
|
// RequestIDFromContext returns the ID of the (HTTP) request, returning an error if it is not present.
|
|
func RequestIDFromContext(ctx context.Context) (string, error) {
|
|
val := ctx.Value(CTXKeyRequestID)
|
|
if val == nil {
|
|
return "", errors.New("no request id present in context")
|
|
}
|
|
|
|
id, ok := val.(string)
|
|
if !ok {
|
|
return "", errors.New("request id in context is not a string")
|
|
}
|
|
|
|
return id, nil
|
|
}
|
|
|
|
// ShouldDisableLogger checks whether the logger instance should be disabled for the provided context.
|
|
// `util.LogFromContext` will use this function to check whether it should return a default logger if
|
|
// none has been set by our logging middleware before, or fall back to the disabled logger, suppressing
|
|
// all output. Use `ctx = util.DisableLogger(ctx, true)` to disable logging for the given context.
|
|
func ShouldDisableLogger(ctx context.Context) bool {
|
|
s := ctx.Value(CTXKeyDisableLogger)
|
|
if s == nil {
|
|
return false
|
|
}
|
|
|
|
shouldDisable, ok := s.(bool)
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
return shouldDisable
|
|
}
|
|
|
|
// DisableLogger toggles the indication whether `util.LogFromContext` should return a disabled logger
|
|
// for a context if none has been set by our logging middleware before. Whilst the usecase for a disabled
|
|
// logger are relatively minimal (we almost always want to have some log output, even if the context
|
|
// was not directly derived from a HTTP request), this functionality was provideds so you can switch back
|
|
// to the old zerolog behavior if so desired.
|
|
func DisableLogger(ctx context.Context, shouldDisable bool) context.Context {
|
|
return context.WithValue(ctx, CTXKeyDisableLogger, shouldDisable)
|
|
}
|