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