github.com/newrelic/go-agent@v3.26.0+incompatible/transaction.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package newrelic 5 6 import ( 7 "net/http" 8 "net/url" 9 ) 10 11 // Transaction instruments one logical unit of work: either an inbound web 12 // request or background task. Start a new Transaction with the 13 // Application.StartTransaction() method. 14 type Transaction interface { 15 // The transaction's http.ResponseWriter methods delegate to the 16 // http.ResponseWriter provided as a parameter to 17 // Application.StartTransaction or Transaction.SetWebResponse. This 18 // allows instrumentation of the response code and response headers. 19 // These methods may be called safely if the transaction does not have a 20 // http.ResponseWriter. 21 http.ResponseWriter 22 23 // End finishes the Transaction. After that, subsequent calls to End or 24 // other Transaction methods have no effect. All segments and 25 // instrumentation must be completed before End is called. 26 End() error 27 28 // Ignore prevents this transaction's data from being recorded. 29 Ignore() error 30 31 // SetName names the transaction. Use a limited set of unique names to 32 // ensure that Transactions are grouped usefully. 33 SetName(name string) error 34 35 // NoticeError records an error. The Transaction saves the first five 36 // errors. For more control over the recorded error fields, see the 37 // newrelic.Error type. In certain situations, using this method may 38 // result in an error being recorded twice: Errors are automatically 39 // recorded when Transaction.WriteHeader receives a status code above 40 // 400 or below 100 that is not in the IgnoreStatusCodes configuration 41 // list. This method is unaffected by the IgnoreStatusCodes 42 // configuration list. 43 NoticeError(err error) error 44 45 // AddAttribute adds a key value pair to the transaction event, errors, 46 // and traces. 47 // 48 // The key must contain fewer than than 255 bytes. The value must be a 49 // number, string, or boolean. 50 // 51 // For more information, see: 52 // https://docs.newrelic.com/docs/agents/manage-apm-agents/agent-metrics/collect-custom-attributes 53 AddAttribute(key string, value interface{}) error 54 55 // SetWebRequest marks the transaction as a web transaction. If 56 // WebRequest is non-nil, SetWebRequest will additionally collect 57 // details on request attributes, url, and method. If headers are 58 // present, the agent will look for a distributed tracing header. Use 59 // NewWebRequest to transform a *http.Request into a WebRequest. 60 SetWebRequest(WebRequest) error 61 62 // SetWebResponse sets transaction's http.ResponseWriter. After calling 63 // this method, the transaction may be used in place of the 64 // ResponseWriter to intercept the response code. This method is useful 65 // when the ResponseWriter is not available at the beginning of the 66 // transaction (if so, it can be given as a parameter to 67 // Application.StartTransaction). This method will return a reference 68 // to the transaction which implements the combination of 69 // http.CloseNotifier, http.Flusher, http.Hijacker, and io.ReaderFrom 70 // implemented by the ResponseWriter. 71 SetWebResponse(http.ResponseWriter) Transaction 72 73 // StartSegmentNow starts timing a segment. The SegmentStartTime 74 // returned can be used as the StartTime field in Segment, 75 // DatastoreSegment, or ExternalSegment. We recommend using the 76 // StartSegmentNow function instead of this method since it checks if 77 // the Transaction is nil. 78 StartSegmentNow() SegmentStartTime 79 80 // CreateDistributedTracePayload creates a payload used to link 81 // transactions. CreateDistributedTracePayload should be called every 82 // time an outbound call is made since the payload contains a timestamp. 83 // 84 // StartExternalSegment calls CreateDistributedTracePayload, so you 85 // don't need to use it for outbound HTTP calls: Just use 86 // StartExternalSegment! 87 // 88 // This method never returns nil. If the application is disabled or not 89 // yet connected then this method returns a shim implementation whose 90 // methods return empty strings. 91 CreateDistributedTracePayload() DistributedTracePayload 92 93 // AcceptDistributedTracePayload links transactions by accepting a 94 // distributed trace payload from another transaction. 95 // 96 // Application.StartTransaction calls this method automatically if a 97 // payload is present in the request headers. Therefore, this method 98 // does not need to be used for typical HTTP transactions. 99 // 100 // AcceptDistributedTracePayload should be used as early in the 101 // transaction as possible. It may not be called after a call to 102 // CreateDistributedTracePayload. 103 // 104 // The payload parameter may be a DistributedTracePayload, a string, or 105 // a []byte. 106 AcceptDistributedTracePayload(t TransportType, payload interface{}) error 107 108 // Application returns the Application which started the transaction. 109 Application() Application 110 111 // BrowserTimingHeader generates the JavaScript required to enable New 112 // Relic's Browser product. This code should be placed into your pages 113 // as close to the top of the <head> element as possible, but after any 114 // position-sensitive <meta> tags (for example, X-UA-Compatible or 115 // charset information). 116 // 117 // This function freezes the transaction name: any calls to SetName() 118 // after BrowserTimingHeader() will be ignored. 119 // 120 // The *BrowserTimingHeader return value will be nil if browser 121 // monitoring is disabled, the application is not connected, or an error 122 // occurred. It is safe to call the pointer's methods if it is nil. 123 BrowserTimingHeader() (*BrowserTimingHeader, error) 124 125 // NewGoroutine allows you to use the Transaction in multiple 126 // goroutines. 127 // 128 // Each goroutine must have its own Transaction reference returned by 129 // NewGoroutine. You must call NewGoroutine to get a new Transaction 130 // reference every time you wish to pass the Transaction to another 131 // goroutine. It does not matter if you call this before or after the 132 // other goroutine has started. 133 // 134 // All Transaction methods can be used in any Transaction reference. 135 // The Transaction will end when End() is called in any goroutine. 136 // 137 // Example passing a new Transaction reference directly to another 138 // goroutine: 139 // 140 // go func(txn newrelic.Transaction) { 141 // defer newrelic.StartSegment(txn, "async").End() 142 // time.Sleep(100 * time.Millisecond) 143 // }(txn.NewGoroutine()) 144 // 145 // Example passing a new Transaction reference on a channel to another 146 // goroutine: 147 // 148 // ch := make(chan newrelic.Transaction) 149 // go func() { 150 // txn := <-ch 151 // defer newrelic.StartSegment(txn, "async").End() 152 // time.Sleep(100 * time.Millisecond) 153 // }() 154 // ch <- txn.NewGoroutine() 155 // 156 NewGoroutine() Transaction 157 158 // GetTraceMetadata returns distributed tracing identifiers. Empty 159 // string identifiers are returned if the transaction has finished. 160 GetTraceMetadata() TraceMetadata 161 162 // GetLinkingMetadata returns the fields needed to link data to a trace or 163 // entity. 164 GetLinkingMetadata() LinkingMetadata 165 166 // IsSampled indicates if the Transaction is sampled. A sampled 167 // Transaction records a span event for each segment. Distributed tracing 168 // must be enabled for transactions to be sampled. False is returned if 169 // the transaction has finished. 170 IsSampled() bool 171 } 172 173 // DistributedTracePayload traces requests between applications or processes. 174 // DistributedTracePayloads are automatically added to HTTP requests by 175 // StartExternalSegment, so you only need to use this if you are tracing through 176 // a message queue or another non-HTTP communication library. The 177 // DistributedTracePayload may be marshalled in one of two formats: HTTPSafe or 178 // Text. All New Relic agents can accept payloads in either format. 179 type DistributedTracePayload interface { 180 // HTTPSafe serializes the payload into a string containing http safe 181 // characters. 182 HTTPSafe() string 183 // Text serializes the payload into a string. The format is slightly 184 // more compact than HTTPSafe. 185 Text() string 186 } 187 188 const ( 189 // DistributedTracePayloadHeader is the header used by New Relic agents 190 // for automatic trace payload instrumentation. 191 DistributedTracePayloadHeader = "Newrelic" 192 ) 193 194 // TransportType is used in Transaction.AcceptDistributedTracePayload() to 195 // represent the type of connection that the trace payload was transported over. 196 type TransportType struct{ name string } 197 198 // TransportType names used across New Relic agents: 199 var ( 200 TransportUnknown = TransportType{name: "Unknown"} 201 TransportHTTP = TransportType{name: "HTTP"} 202 TransportHTTPS = TransportType{name: "HTTPS"} 203 TransportKafka = TransportType{name: "Kafka"} 204 TransportJMS = TransportType{name: "JMS"} 205 TransportIronMQ = TransportType{name: "IronMQ"} 206 TransportAMQP = TransportType{name: "AMQP"} 207 TransportQueue = TransportType{name: "Queue"} 208 TransportOther = TransportType{name: "Other"} 209 ) 210 211 // WebRequest may be implemented to provide request information to 212 // Transaction.SetWebRequest. 213 type WebRequest interface { 214 // Header may return nil if you don't have any headers or don't want to 215 // transform them to http.Header format. 216 Header() http.Header 217 // URL may return nil if you don't have a URL or don't want to transform 218 // it to *url.URL. 219 URL() *url.URL 220 Method() string 221 // If a distributed tracing header is found in the headers returned by 222 // Header(), this TransportType will be used in the distributed tracing 223 // metrics. 224 Transport() TransportType 225 } 226 227 // NewWebRequest turns a *http.Request into a WebRequest for input into 228 // Transaction.SetWebRequest. 229 func NewWebRequest(request *http.Request) WebRequest { 230 if nil == request { 231 return nil 232 } 233 return requestWrap{request: request} 234 } 235 236 // NewStaticWebRequest takes the minimum necessary information and creates a static WebRequest out of it 237 func NewStaticWebRequest(hdrs http.Header, url *url.URL, method string, transport TransportType) WebRequest { 238 return staticWebRequest{hdrs, url, method, transport} 239 } 240 241 // LinkingMetadata is returned by Transaction.GetLinkingMetadata. It contains 242 // identifiers needed link data to a trace or entity. 243 type LinkingMetadata struct { 244 // TraceID identifies the entire distributed trace. This field is empty 245 // if distributed tracing is disabled. 246 TraceID string 247 // SpanID identifies the currently active segment. This field is empty 248 // if distributed tracing is disabled or the transaction is not sampled. 249 SpanID string 250 // EntityName is the Application name as set on the newrelic.Config. If 251 // multiple application names are specified, only the first is returned. 252 EntityName string 253 // EntityType is the type of this entity and is always the string 254 // "SERVICE". 255 EntityType string 256 // EntityGUID is the unique identifier for this entity. 257 EntityGUID string 258 // Hostname is the hostname this entity is running on. 259 Hostname string 260 } 261 262 // TraceMetadata is returned by Transaction.GetTraceMetadata. It contains 263 // distributed tracing identifiers. 264 type TraceMetadata struct { 265 // TraceID identifies the entire distributed trace. This field is empty 266 // if distributed tracing is disabled. 267 TraceID string 268 // SpanID identifies the currently active segment. This field is empty 269 // if distributed tracing is disabled or the transaction is not sampled. 270 SpanID string 271 }