segments.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package newrelic
  2. import "net/http"
  3. // SegmentStartTime is created by Transaction.StartSegmentNow and marks the
  4. // beginning of a segment. A segment with a zero-valued SegmentStartTime may
  5. // safely be ended.
  6. type SegmentStartTime struct{ segment }
  7. // Segment is used to instrument functions, methods, and blocks of code. The
  8. // easiest way use Segment is the StartSegment function.
  9. type Segment struct {
  10. StartTime SegmentStartTime
  11. Name string
  12. }
  13. // DatastoreSegment is used to instrument calls to databases and object stores.
  14. // Here is an example:
  15. //
  16. // ds := &newrelic.DatastoreSegment{
  17. // StartTime: newrelic.StartSegmentNow(txn),
  18. // Product: newrelic.DatastoreMySQL,
  19. // Collection: "my_table",
  20. // Operation: "SELECT",
  21. // }
  22. // defer ds.End()
  23. //
  24. type DatastoreSegment struct {
  25. StartTime SegmentStartTime
  26. // Product is the datastore type. See the constants in datastore.go.
  27. Product DatastoreProduct
  28. // Collection is the table or group.
  29. Collection string
  30. // Operation is the relevant action, e.g. "SELECT" or "GET".
  31. Operation string
  32. // ParameterizedQuery may be set to the query being performed. It must
  33. // not contain any raw parameters, only placeholders.
  34. ParameterizedQuery string
  35. // QueryParameters may be used to provide query parameters. Care should
  36. // be taken to only provide parameters which are not sensitive.
  37. // QueryParameters are ignored in high security mode.
  38. QueryParameters map[string]interface{}
  39. // Host is the name of the server hosting the datastore.
  40. Host string
  41. // PortPathOrID can represent either the port, path, or id of the
  42. // datastore being connected to.
  43. PortPathOrID string
  44. // DatabaseName is name of database where the current query is being
  45. // executed.
  46. DatabaseName string
  47. }
  48. // ExternalSegment is used to instrument external calls. StartExternalSegment
  49. // is recommended when you have access to an http.Request.
  50. type ExternalSegment struct {
  51. StartTime SegmentStartTime
  52. Request *http.Request
  53. Response *http.Response
  54. // If you do not have access to the request, this URL field should be
  55. // used to indicate the endpoint. NOTE: If non-empty, this field
  56. // is parsed using url.Parse and therefore it MUST include the protocol
  57. // (eg. "http://").
  58. URL string
  59. }
  60. // End finishes the segment.
  61. func (s *Segment) End() error { return endSegment(s) }
  62. // End finishes the datastore segment.
  63. func (s *DatastoreSegment) End() error { return endDatastore(s) }
  64. // End finishes the external segment.
  65. func (s *ExternalSegment) End() error { return endExternal(s) }
  66. // OutboundHeaders returns the headers that should be attached to the external
  67. // request.
  68. func (s *ExternalSegment) OutboundHeaders() http.Header {
  69. return outboundHeaders(s)
  70. }
  71. // StartSegmentNow helps avoid Transaction nil checks.
  72. func StartSegmentNow(txn Transaction) SegmentStartTime {
  73. if nil != txn {
  74. return txn.StartSegmentNow()
  75. }
  76. return SegmentStartTime{}
  77. }
  78. // StartSegment makes it easy to instrument segments. To time a function, do
  79. // the following:
  80. //
  81. // func timeMe(txn newrelic.Transaction) {
  82. // defer newrelic.StartSegment(txn, "timeMe").End()
  83. // // ... function code here ...
  84. // }
  85. //
  86. // To time a block of code, do the following:
  87. //
  88. // segment := StartSegment(txn, "myBlock")
  89. // // ... code you want to time here ...
  90. // segment.End()
  91. //
  92. func StartSegment(txn Transaction, name string) *Segment {
  93. return &Segment{
  94. StartTime: StartSegmentNow(txn),
  95. Name: name,
  96. }
  97. }
  98. // StartExternalSegment makes it easier to instrument external calls.
  99. //
  100. // segment := newrelic.StartExternalSegment(txn, request)
  101. // resp, err := client.Do(request)
  102. // segment.Response = resp
  103. // segment.End()
  104. //
  105. func StartExternalSegment(txn Transaction, request *http.Request) *ExternalSegment {
  106. s := &ExternalSegment{
  107. StartTime: StartSegmentNow(txn),
  108. Request: request,
  109. }
  110. for key, values := range s.OutboundHeaders() {
  111. for _, value := range values {
  112. request.Header.Add(key, value)
  113. }
  114. }
  115. return s
  116. }