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 }