instrumentation.go 2.4 KB

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