github.com/lulzWill/go-agent@v2.1.2+incompatible/segments.go (about)

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