1// Package timer adds HTTP request and response timing information to a 2// context. 3package timer 4 5import ( 6 "fmt" 7 "time" 8 9 "golang.org/x/net/context" 10) 11 12// Timer collects request and response timing information 13type Timer struct { 14 // When the request headers have been received - earliest timing point can get 15 // right now. 16 tsRequestHeaders int64 17 // When the response headers have been received 18 tsResponseHeaders int64 19 // When the response is completely written 20 tsResponseDone int64 21} 22 23func (t Timer) String() string { 24 if t.tsRequestHeaders == 0 { 25 return "timer" 26 } 27 return fmt.Sprintf( 28 "%.2fms total, %.2fms to response headers, %.2fms sending response body", 29 float64(t.tsResponseDone-t.tsRequestHeaders)/1000000.0, 30 float64(t.tsResponseHeaders-t.tsRequestHeaders)/1000000.0, 31 float64(t.tsResponseDone-t.tsResponseHeaders)/1000000.0, 32 ) 33} 34 35// RequestHeaders sets the time at which request headers were received 36func (t *Timer) RequestHeaders() { 37 t.tsRequestHeaders = time.Now().UnixNano() 38} 39 40// ResponseHeaders sets the time at which request headers were received 41func (t *Timer) ResponseHeaders() { 42 t.tsResponseHeaders = time.Now().UnixNano() 43} 44 45// ResponseDone sets the time at which request headers were received 46func (t *Timer) ResponseDone() { 47 t.tsResponseDone = time.Now().UnixNano() 48} 49 50// NewContext creates a new context with the timer included 51func (t *Timer) NewContext(ctx context.Context) context.Context { 52 return context.WithValue(ctx, "timer", t) 53} 54 55// FromContext creates a new context with the timer included 56func FromContext(ctx context.Context) *Timer { 57 timer, ok := ctx.Value("timer").(*Timer) 58 if !ok { 59 // Return a dummy timer 60 return &Timer{} 61 } 62 return timer 63} 64