github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/net/http/reqid/reqid.go (about)

     1  // Package reqid creates request IDs and stores them in Contexts.
     2  package reqid
     3  
     4  import (
     5  	"context"
     6  	"crypto/rand"
     7  	"encoding/hex"
     8  	"net/http"
     9  
    10  	log "github.com/sirupsen/logrus"
    11  )
    12  
    13  // key is an unexported type for keys defined in this package.
    14  // This prevents collisions with keys defined in other packages.
    15  type key int
    16  
    17  const (
    18  	// reqIDKey is the key for request IDs in Contexts.  It is
    19  	// unexported; clients use NewContext and FromContext
    20  	// instead of using this key directly.
    21  	reqIDKey key = iota
    22  	// subReqIDKey is the key for sub-request IDs in Contexts.  It is
    23  	// unexported; clients use NewSubContext and FromSubContext
    24  	// instead of using this key directly.
    25  	subReqIDKey
    26  	// coreIDKey is the key for Chain-Core-ID request header field values.
    27  	// It is only for statistics; don't use it for authorization.
    28  	coreIDKey
    29  	// pathKey is the key for the request path being handled.
    30  	pathKey
    31  	logModule = "reqid"
    32  )
    33  
    34  // New generates a random request ID.
    35  func New() string {
    36  	// Given n IDs of length b bits, the probability that there will be a collision is bounded by
    37  	// the number of pairs of IDs multiplied by the probability that any pair might collide:
    38  	// p ≤ n(n - 1)/2 * 1/(2^b)
    39  	//
    40  	// We assume an upper bound of 1000 req/sec, which means that in a week there will be
    41  	// n = 1000 * 604800 requests. If l = 10, b = 8*10, then p ≤ 1.512e-7, which is a suitably
    42  	// low probability.
    43  	l := 10
    44  	b := make([]byte, l)
    45  	_, err := rand.Read(b)
    46  	if err != nil {
    47  		log.WithFields(log.Fields{"module": logModule, "error": err}).Info("error making reqID")
    48  	}
    49  	return hex.EncodeToString(b)
    50  }
    51  
    52  // NewContext returns a new Context that carries reqid.
    53  // It also adds a log prefix to print the request ID using
    54  // package bytom/log.
    55  func NewContext(ctx context.Context, reqid string) context.Context {
    56  	ctx = context.WithValue(ctx, reqIDKey, reqid)
    57  	return ctx
    58  }
    59  
    60  // FromContext returns the request ID stored in ctx,
    61  // if any.
    62  func FromContext(ctx context.Context) string {
    63  	reqID, _ := ctx.Value(reqIDKey).(string)
    64  	return reqID
    65  }
    66  
    67  // CoreIDFromContext returns the Chain-Core-ID stored in ctx,
    68  // or the empty string.
    69  func CoreIDFromContext(ctx context.Context) string {
    70  	id, _ := ctx.Value(coreIDKey).(string)
    71  	return id
    72  }
    73  
    74  // PathFromContext returns the HTTP path stored in ctx,
    75  // or the empty string.
    76  func PathFromContext(ctx context.Context) string {
    77  	path, _ := ctx.Value(pathKey).(string)
    78  	return path
    79  }
    80  
    81  func NewSubContext(ctx context.Context, reqid string) context.Context {
    82  	ctx = context.WithValue(ctx, subReqIDKey, reqid)
    83  	return ctx
    84  }
    85  
    86  // FromSubContext returns the sub-request ID stored in ctx,
    87  // if any.
    88  func FromSubContext(ctx context.Context) string {
    89  	subReqID, _ := ctx.Value(subReqIDKey).(string)
    90  	return subReqID
    91  }
    92  
    93  func Handler(handler http.Handler) http.Handler {
    94  	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    95  	})
    96  }