github.com/shoshinnikita/budget-manager@v0.7.1-0.20220131195411-8c46ff1c6778/internal/pkg/reqid/request_id.go (about)

     1  package reqid
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"encoding/hex"
     7  
     8  	"github.com/ShoshinNikita/budget-manager/internal/logger"
     9  )
    10  
    11  // RequestID is a random hex string. It doesn't correspond to UUID RFC 4122 format because it would be
    12  // an overkill for such small project. Also it can be easily modified to match RFC 4122
    13  type RequestID string
    14  
    15  func (r RequestID) ToString() string {
    16  	return string(r)
    17  }
    18  
    19  const requestIDLength = 8
    20  
    21  // New creates a new request id
    22  func New() RequestID {
    23  	data := make([]byte, requestIDLength/2)
    24  	rand.Read(data) //nolint:errcheck
    25  	return RequestID(hex.EncodeToString(data))
    26  }
    27  
    28  type requestIDContextKey struct{}
    29  
    30  // FromContext extracts request id from context.
    31  // If request id doesn't exist, it generates a new one
    32  func FromContext(ctx context.Context) RequestID {
    33  	if reqID, ok := ctx.Value(requestIDContextKey{}).(RequestID); ok {
    34  		return reqID
    35  	}
    36  	return New()
    37  }
    38  
    39  // ToContext returns a context based on passed one with injected request id
    40  func ToContext(ctx context.Context, reqID RequestID) context.Context {
    41  	return context.WithValue(ctx, requestIDContextKey{}, reqID)
    42  }
    43  
    44  const loggerFieldKey = "request_id"
    45  
    46  // FromContextToLogger extracts request id from context and returns logger with added field
    47  func FromContextToLogger(ctx context.Context, log logger.Logger) logger.Logger {
    48  	reqID := FromContext(ctx)
    49  	return log.WithField(loggerFieldKey, reqID)
    50  }