github.com/lulzWill/go-agent@v2.1.2+incompatible/instrumentation.go (about) 1 package newrelic 2 3 import "net/http" 4 5 // instrumentation.go contains helpers built on the lower level api. 6 7 // WrapHandle facilitates instrumentation of handlers registered with an 8 // http.ServeMux. For example, to instrument this code: 9 // 10 // http.Handle("/foo", fooHandler) 11 // 12 // Perform this replacement: 13 // 14 // http.Handle(newrelic.WrapHandle(app, "/foo", fooHandler)) 15 // 16 // The Transaction is passed to the handler in place of the original 17 // http.ResponseWriter, so it can be accessed using type assertion. 18 // For example, to rename the transaction: 19 // 20 // // 'w' is the variable name of the http.ResponseWriter. 21 // if txn, ok := w.(newrelic.Transaction); ok { 22 // txn.SetName("other-name") 23 // } 24 // 25 func WrapHandle(app Application, pattern string, handler http.Handler) (string, http.Handler) { 26 return pattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 27 txn := app.StartTransaction(pattern, w, r) 28 defer txn.End() 29 30 handler.ServeHTTP(txn, r) 31 }) 32 } 33 34 // WrapHandleFunc serves the same purpose as WrapHandle for functions registered 35 // with ServeMux.HandleFunc. 36 func WrapHandleFunc(app Application, pattern string, handler func(http.ResponseWriter, *http.Request)) (string, func(http.ResponseWriter, *http.Request)) { 37 p, h := WrapHandle(app, pattern, http.HandlerFunc(handler)) 38 return p, func(w http.ResponseWriter, r *http.Request) { h.ServeHTTP(w, r) } 39 } 40 41 // NewRoundTripper creates an http.RoundTripper to instrument external requests. 42 // This RoundTripper must be used in same the goroutine as the other uses of the 43 // Transaction's SegmentTracer methods. http.DefaultTransport is used if an 44 // http.RoundTripper is not provided. 45 // 46 // client := &http.Client{} 47 // client.Transport = newrelic.NewRoundTripper(txn, nil) 48 // resp, err := client.Get("http://example.com/") 49 // 50 func NewRoundTripper(txn Transaction, original http.RoundTripper) http.RoundTripper { 51 return roundTripperFunc(func(request *http.Request) (*http.Response, error) { 52 segment := StartExternalSegment(txn, request) 53 54 if nil == original { 55 original = http.DefaultTransport 56 } 57 response, err := original.RoundTrip(request) 58 59 segment.Response = response 60 segment.End() 61 62 return response, err 63 }) 64 } 65 66 type roundTripperFunc func(*http.Request) (*http.Response, error) 67 68 func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }