github.com/waldiirawan/apm-agent-go/v2@v2.2.2/docs/api.asciidoc (about) 1 [[api]] 2 == API Documentation 3 4 This section describes the most commonly used parts of the API. 5 6 The Go agent is documented using standard godoc. For complete documentation, 7 refer to the documentation at https://pkg.go.dev/github.com/waldiirawan/apm-agent-go/v2[pkg.go.dev/github.com/waldiirawan/apm-agent-go/v2], 8 or by using the "godoc" tool. 9 10 [float] 11 [[tracer-api]] 12 === Tracer API 13 14 The initial point of contact your application will have with the Go agent 15 is the `apm.Tracer` type, which provides methods for reporting 16 transactions and errors. 17 18 To make instrumentation simpler, the Go agent provides an initialization 19 function, `apm.DefaultTracer()`. This tracer is initialized the first time 20 `apm.DefaultTracer()` is called, and returned on subsequent calls. The tracer 21 returned by this function can be modified using `apm.SetDefaultTracer(tracer)`. 22 Calling this will close the previous default tracer, if any exists. This 23 tracer is configured with environment variables; see <<configuration>> for 24 details. 25 26 [source,go] 27 ---- 28 import ( 29 "github.com/waldiirawan/apm-agent-go/v2" 30 ) 31 32 func main() { 33 tracer := apm.DefaultTracer() 34 ... 35 } 36 ---- 37 38 // ------------------------------------------------------------------------------------------------- 39 40 [float] 41 [[transaction-api]] 42 === Transactions 43 44 [float] 45 [[tracer-api-start-transaction]] 46 ==== `func (*Tracer) StartTransaction(name, type string) *Transaction` 47 48 StartTransaction returns a new Transaction with the specified name and type, 49 and with the start time set to the current time. If you need to set the 50 timestamp or the parent <<trace-context, trace context>>, use 51 <<tracer-api-start-transaction-options, Tracer.StartTransactionOptions>>. 52 53 This method should be called at the beginning of a transaction such as a web 54 or RPC request. e.g.: 55 56 [source,go] 57 ---- 58 transaction := apm.DefaultTracer().StartTransaction("GET /", "request") 59 ---- 60 61 Transactions will be grouped by type and name in the Elastic APM app. 62 63 After starting a transaction, you can record a result and add context to 64 further describe the transaction. 65 66 [source,go] 67 ---- 68 transaction.Result = "Success" 69 transaction.Context.SetLabel("region", "us-east-1") 70 ---- 71 72 See <<context-api>> for more details on setting transaction context. 73 74 [float] 75 [[tracer-api-start-transaction-options]] 76 ==== `func (*Tracer) StartTransactionOptions(name, type string, opts TransactionOptions) *Transaction` 77 78 StartTransactionOptions is essentially the same as StartTransaction, but 79 also accepts an options struct. This struct allows you to specify the 80 parent <<trace-context, trace context>> and/or the transaction's start time. 81 82 [source,go] 83 ---- 84 opts := apm.TransactionOptions{ 85 Start: time.Now(), 86 TraceContext: parentTraceContext, 87 } 88 transaction := apm.DefaultTracer().StartTransactionOptions("GET /", "request", opts) 89 ---- 90 91 [float] 92 [[transaction-end]] 93 ==== `func (*Transaction) End()` 94 95 End enqueues the transaction for sending to the Elastic APM server. 96 The transaction must not be modified after this, but it may still 97 be used for starting spans. 98 99 The transaction's duration is calculated as the amount of time 100 elapsed between the start of the transaction and this call. To override 101 this behavior, the transaction's `Duration` field may be set before 102 calling End. 103 104 [source,go] 105 ---- 106 transaction.End() 107 ---- 108 109 [float] 110 [[transaction-tracecontext]] 111 ==== `func (*Transaction) TraceContext() TraceContext` 112 113 TraceContext returns the transaction's <<trace-context, trace context>>. 114 115 [float] 116 [[transaction-ensureparent]] 117 ==== `func (*Transaction) EnsureParent() SpanID` 118 119 EnsureParent returns the transaction's parent span ID--generating and recording one if 120 it did not previously have one. 121 122 EnsureParent enables correlation with spans created by the JavaScript Real User Monitoring 123 (RUM) agent for the initial page load. If your backend service generates the HTML page 124 dynamically, you can inject the trace and parent span ID into the page in order to initialize 125 the JavaScript RUM agent, such that the web browser's page load appears as the root of the 126 trace. 127 128 [source,go] 129 ---- 130 var initialPageTemplate = template.Must(template.New("").Parse(` 131 <html> 132 <head> 133 <script src="elastic-apm-js-base/dist/bundles/elastic-apm-js-base.umd.min.js"></script> 134 <script> 135 elasticApm.init({ 136 serviceName: '', 137 serverUrl: 'http://localhost:8200', 138 pageLoadTraceId: {{.TraceContext.Trace}}, 139 pageLoadSpanId: {{.EnsureParent}}, 140 pageLoadSampled: {{.Sampled}}, 141 }) 142 </script> 143 </head> 144 <body>...</body> 145 </html> 146 `)) 147 148 func initialPageHandler(w http.ResponseWriter, req *http.Request) { 149 err := initialPageTemplate.Execute(w, apm.TransactionFromContext(req.Context())) 150 if err != nil { 151 ... 152 } 153 } 154 ---- 155 156 See the {apm-rum-ref}/index.html[JavaScript RUM agent documentation] for more information. 157 158 [float] 159 [[transaction-parentid]] 160 ==== `func (*Transaction) ParentID() SpanID` 161 162 ParentID returns the ID of the transaction's parent, or a zero (invalid) SpanID if the transaction has no parent. 163 164 [float] 165 [[apm-context-with-transaction]] 166 ==== `func ContextWithTransaction(context.Context, *Transaction) context.Context` 167 168 ContextWithTransaction adds the transaction to the context, and returns the resulting context. 169 170 The transaction can be retrieved using <<apm-transaction-from-context, apm.TransactionFromContext>>. 171 The context may also be passed into <<apm-start-span, apm.StartSpan>>, which uses 172 TransactionFromContext under the covers to create a span as a child of the transaction. 173 174 [float] 175 [[apm-transaction-from-context]] 176 ==== `func TransactionFromContext(context.Context) *Transaction` 177 178 TransactionFromContext returns a transaction previously stored in the context using 179 <<apm-context-with-transaction, apm.ContextWithTransaction>>, or nil if the context 180 does not contain a transaction. 181 182 [float] 183 [[apm-detached-context]] 184 ==== `func DetachedContext(context.Context) context.Context` 185 186 DetachedContext returns a new context detached from the lifetime of the input, but 187 which still returns the same values as the input. 188 189 DetachedContext can be used to maintain trace context required to correlate events, 190 but where the operation is "fire-and-forget" and should not be affected by the 191 deadline or cancellation of the surrounding context. 192 193 [float] 194 [[apm-traceformatter]] 195 ==== `func TraceFormatter(context.Context) fmt.Formatter` 196 197 TraceFormatter returns an implementation of https://golang.org/pkg/fmt/#Formatter[fmt.Formatter] 198 that can be used to format the IDs of the transaction and span stored in the provided context. 199 200 The formatter understands the following formats: 201 202 - %v: trace ID, transaction ID, and (if in the context of a span) span ID, space separated 203 - %t: trace ID only 204 - %x: transaction ID only 205 - %s: span ID only 206 207 The "+" option can be used to format the values in "key=value" style, with the field 208 names `trace.id`, `transaction.id`, and `span.id`. For example, using "%+v" as the format 209 would yield "trace.id=... transaction.id=... span.id=...". 210 211 For a more in-depth example, see <<log-correlation-manual-unstructured>>. 212 213 // ------------------------------------------------------------------------------------------------- 214 215 [float] 216 [[span-api]] 217 === Spans 218 219 To describe an activity within a transaction, we create spans. The Go agent 220 has built-in support for generating spans for some activities, such as 221 database queries. You can use the API to report spans specific to your 222 application. 223 224 [float] 225 [[transaction-start-span]] 226 ==== `func (*Transaction) StartSpan(name, spanType string, parent *Span) *Span` 227 228 StartSpan starts and returns a new Span within the transaction, with the specified name, 229 type, and optional parent span, and with the start time set to the current time. 230 If you need to set the timestamp or parent <<trace-context, trace context>>, 231 use <<transaction-start-span-options, Transaction.StartSpanOptions>>. 232 233 If the span type contains two dots, they are assumed to separate the span type, subtype, 234 and action; a single dot separates span type and subtype, and the action will not be set. 235 236 If the transaction is sampled, then the span's ID will be set, and its stacktrace will 237 be set if the tracer is configured accordingly. If the transaction is not sampled, then 238 the returned span will be silently discarded when its End method is called. To avoid any unnecessary computation for these dropped spans, call the <<span-dropped, Dropped>> 239 method. 240 241 As a convenience, it is valid to create a span on a nil Transaction; the resulting span 242 will be non-nil and safe for use, but will not be reported to the APM server. 243 244 [source,go] 245 ---- 246 span := tx.StartSpan("SELECT FROM foo", "db.mysql.query", nil) 247 ---- 248 249 [float] 250 [[transaction-start-span-options]] 251 ==== `func (*Transaction) StartSpanOptions(name, spanType string, opts SpanOptions) *Span` 252 253 StartSpanOptions is essentially the same as StartSpan, but also accepts an options struct. 254 This struct allows you to specify the parent <<trace-context, trace context>> and/or the 255 spans's start time. If the parent trace context is not specified in the options, then the 256 span will be a direct child of the transaction. Otherwise, the parent trace context should 257 belong to some span descended from the transaction. 258 259 [source,go] 260 ---- 261 opts := apm.SpanOptions{ 262 Start: time.Now(), 263 Parent: parentSpan.TraceContext(), 264 } 265 span := tx.StartSpanOptions("SELECT FROM foo", "db.mysql.query", opts) 266 ---- 267 268 [float] 269 [[apm-start-span]] 270 ==== `func StartSpan(ctx context.Context, name, spanType string) (*Span, context.Context)` 271 272 StartSpan starts and returns a new Span within the sampled transaction and parent span 273 in the context, if any. If the span isn't dropped, it will be included in the resulting 274 context. 275 276 [source,go] 277 ---- 278 span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query") 279 ---- 280 281 [float] 282 [[span-end]] 283 ==== `func (*Span) End()` 284 285 End marks the span as complete. The Span must not be modified after this, 286 but may still be used as the parent of a span. 287 288 The span's duration will be calculated as the amount of time elapsed 289 since the span was started until this call. To override this behaviour, 290 the span's Duration field may be set before calling End. 291 292 [float] 293 [[span-dropped]] 294 ==== `func (*Span) Dropped() bool` 295 296 Dropped indicates whether or not the span is dropped, meaning it will not be reported to 297 the APM server. Spans are dropped when the created with a nil, or non-sampled transaction, 298 or one whose max spans limit has been reached. 299 300 [float] 301 [[span-tracecontext]] 302 ==== `func (*Span) TraceContext() TraceContext` 303 304 TraceContext returns the span's <<trace-context, trace context>>. 305 306 [float] 307 [[apm-context-with-span]] 308 ==== `func ContextWithSpan(context.Context, *Span) context.Context` 309 310 ContextWithSpan adds the span to the context and returns the resulting context. 311 312 The span can be retrieved using <<apm-span-from-context, apm.SpanFromContext>>. 313 The context may also be passed into <<apm-start-span, apm.StartSpan>>, which uses 314 SpanFromContext under the covers to create another span as a child of the span. 315 316 [float] 317 [[apm-span-from-context]] 318 ==== `func SpanFromContext(context.Context) *Span` 319 320 SpanFromContext returns a span previously stored in the context using 321 <<apm-context-with-span, apm.ContextWithSpan>>, or nil if the context 322 does not contain a span. 323 324 [float] 325 [[span-parentid]] 326 ==== `func (*Span) ParentID() SpanID` 327 328 ParentID returns the ID of the span's parent. 329 330 // ------------------------------------------------------------------------------------------------- 331 332 [float] 333 [[context-api]] 334 === Context 335 336 When reporting transactions and errors you can provide context to describe 337 those events. Built-in instrumentation will typically provide some context, 338 e.g. the URL and remote address for an HTTP request. You can also provide 339 custom context and tags. 340 341 [float] 342 [[context-set-label]] 343 ==== `func (*Context) SetLabel(key string, value interface{})` 344 345 SetLabel labels the transaction or error with the given key and value. 346 If the key contains any special characters (`.`, `*`, `"`), they will be 347 replaced with underscores. 348 349 If the value is numerical or boolean, then it will be sent to the server 350 as a JSON number or boolean; otherwise it will converted to a string, using 351 `fmt.Sprint` if necessary. Numerical and boolean values are supported by 352 the server from version 6.7 onwards. 353 354 String values longer than 1024 characters will be truncated. Labels are 355 indexed in Elasticsearch as keyword fields. 356 357 TIP: Before using labels, ensure you understand the different types of 358 {apm-guide-ref}/data-model-metadata.html[metadata] that are available. 359 360 WARNING: Avoid defining too many user-specified labels. 361 Defining too many unique fields in an index is a condition that can lead to a 362 {ref}/mapping.html#mapping-limit-settings[mapping explosion]. 363 364 [float] 365 [[context-set-custom]] 366 ==== `func (*Context) SetCustom(key string, value interface{})` 367 368 SetCustom is used to add custom, non-indexed, contextual information to 369 transactions or errors. If the key contains any special characters 370 (`.`, `*`, `"`), they will be replaced with underscores. 371 372 Non-indexed means the data is not searchable or aggregatable in Elasticsearch, 373 and you cannot build dashboards on top of the data. However, non-indexed 374 information is useful for other reasons, like providing contextual information 375 to help you quickly debug performance issues or errors. 376 377 The value can be of any type that can be encoded using `encoding/json`. 378 379 TIP: Before using custom context, ensure you understand the different types of 380 {apm-guide-ref}/data-model-metadata.html[metadata] that are available. 381 382 [float] 383 [[context-set-username]] 384 ==== `func (*Context) SetUsername(username string)` 385 386 SetUsername records the username of the user associated with the transaction. 387 388 [float] 389 [[context-set-user-id]] 390 ==== `func (*Context) SetUserID(id string)` 391 392 SetUserID records the ID of the user associated with the transaction. 393 394 [float] 395 [[context-set-user-email]] 396 ==== `func (*Context) SetUserEmail(email string)` 397 398 SetUserEmail records the email address of the user associated with the transaction. 399 400 // ------------------------------------------------------------------------------------------------- 401 402 [float] 403 [[error-api]] 404 === Errors 405 406 Elastic APM provides two methods of capturing an error event: reporting an error log record, 407 and reporting an "exception" (either a panic or an error in Go parlance). 408 409 [float] 410 [[tracer-new-error]] 411 ==== `func (*Tracer) NewError(error) *Error` 412 413 NewError returns a new Error with details taken from err. 414 415 The exception message will be set to `err.Error()`. The exception module and type will be set 416 to the package and type name of the cause of the error, respectively, where the cause has the 417 same definition as given by https://github.com/pkg/errors[github.com/pkg/errors]. 418 419 [source,go] 420 ---- 421 e := apm.DefaultTracer().NewError(err) 422 ... 423 e.Send() 424 ---- 425 426 The provided error can implement any of several interfaces to provide additional information: 427 428 [source,go] 429 ---- 430 // Errors implementing ErrorsStacktracer will have their stacktrace 431 // set based on the result of the StackTrace method. 432 type ErrorsStacktracer interface { 433 StackTrace() github.com/pkg/errors.StackTrace 434 } 435 436 // Errors implementing Stacktracer will have their stacktrace 437 // set based on the result of the StackTrace method. 438 type Stacktracer interface { 439 StackTrace() []github.com/waldiirawan/apm-agent-go/v2/stacktrace.Frame 440 } 441 442 // Errors implementing Typer will have a "type" field set to the 443 // result of the Type method. 444 type Typer interface { 445 Type() string 446 } 447 448 // Errors implementing StringCoder will have a "code" field set to the 449 // result of the Code method. 450 type StringCoder interface { 451 Code() string 452 } 453 454 // Errors implementing NumberCoder will have a "code" field set to the 455 // result of the Code method. 456 type NumberCoder interface { 457 Code() float64 458 } 459 ---- 460 461 Errors created by with NewError will have their ID field populated with a unique ID. 462 This can be used in your application for correlation. 463 464 [float] 465 [[tracer-new-error-log]] 466 ==== `func (*Tracer) NewErrorLog(ErrorLogRecord) *Error` 467 468 NewErrorLog returns a new Error for the given ErrorLogRecord: 469 470 [source,go] 471 ---- 472 type ErrorLogRecord struct { 473 // Message holds the message for the log record, 474 // e.g. "failed to connect to %s". 475 // 476 // If this is empty, "[EMPTY]" will be used. 477 Message string 478 479 // MessageFormat holds the non-interpolated format 480 // of the log record, e.g. "failed to connect to %s". 481 // 482 // This is optional. 483 MessageFormat string 484 485 // Level holds the severity level of the log record. 486 // 487 // This is optional. 488 Level string 489 490 // LoggerName holds the name of the logger used. 491 // 492 // This is optional. 493 LoggerName string 494 495 // Error is an error associated with the log record. 496 // 497 // This is optional. 498 Error error 499 } 500 ---- 501 502 The resulting Error's log stacktrace will not be set. Call the SetStacktrace method to set it. 503 504 [source,go] 505 ---- 506 e := apm.DefaultTracer().NewErrorLog(apm.ErrorLogRecord{ 507 Message: "Somebody set up us the bomb.", 508 }) 509 ... 510 e.Send() 511 ---- 512 513 [float] 514 [[error-set-transaction]] 515 ==== `func (*Error) SetTransaction(*Transaction)` 516 517 SetTransaction associates the error with the given transaction. 518 519 [float] 520 [[error-set-span]] 521 ==== `func (*Error) SetSpan(*Span)` 522 523 SetSpan associates the error with the given span and the span's transaction. When calling SetSpan, 524 it is not necessary to also call SetTransaction. 525 526 [float] 527 [[error-send]] 528 ==== `func (*Error) Send()` 529 530 Send enqueues the error for sending to the Elastic APM server. 531 532 [float] 533 [[tracer-recovered]] 534 ==== `func (*Tracer) Recovered(interface{}) *Error` 535 536 Recovered returns an Error from the recovered value, optionally associating it with a transaction. 537 The error is not sent; it is the caller's responsibility to set the error's context, 538 and then call its `Send` method. 539 540 [source,go] 541 ---- 542 tx := apm.DefaultTracer().StartTransaction(...) 543 defer tx.End() 544 defer func() { 545 if v := recover(); v != nil { 546 e := apm.DefaultTracer().Recovered(v) 547 e.SetTransaction(tx) 548 e.Send() 549 } 550 }() 551 ---- 552 553 [float] 554 [[apm-captureerror]] 555 ==== `func CaptureError(context.Context, error) *Error` 556 557 CaptureError returns a new error related to the sampled transaction and span present in the context, 558 if any, and sets its exception details using the given error. The Error.Handled field will be set to 559 true, and a stacktrace set. 560 561 If there is no transaction in the context, or it is not being sampled, CaptureError returns nil. 562 As a convenience, if the provided error is nil, then CaptureError will also return nil. 563 564 [source,go] 565 ---- 566 if err != nil { 567 e := apm.CaptureError(ctx, err) 568 e.Send() 569 } 570 ---- 571 572 [float] 573 [[trace-context]] 574 ==== Trace Context 575 576 Trace context contains the ID for a transaction or span, the ID of the end-to-end trace to which the 577 transaction or span belongs, and trace options such as flags relating to sampling. Trace context is 578 propagated between processes, e.g. in HTTP headers, in order to correlate events originating from 579 related services. 580 581 Elastic APM's trace context is based on the https://w3c.github.io/trace-context/[W3C Trace Context] draft. 582 583 [float] 584 [[error-context]] 585 ==== Error Context 586 587 Errors can be associated with context just like transactions. See <<context-api>> for details. 588 In addition, errors can be associated with an active transaction or span using 589 <<error-set-transaction, SetTransaction>> or <<error-set-span, SetSpan>>, respectively. 590 591 [source,go] 592 ---- 593 tx := apm.DefaultTracer().StartTransaction("GET /foo", "request") 594 defer tx.End() 595 e := apm.DefaultTracer().NewError(err) 596 e.SetTransaction(tx) 597 e.Send() 598 ---- 599 600 [float] 601 [[tracer-config-api]] 602 ==== Tracer Config 603 604 Many configuration attributes can be be updated dynamically via `apm.Tracer` method calls. 605 Please refer to the documentation at https://pkg.go.dev/github.com/waldiirawan/apm-agent-go/v2#Tracer[pkg.go.dev/github.com/waldiirawan/apm-agent-go/v2#Tracer] 606 for details. The configuration methods are primarily prefixed with `Set`, such as 607 https://pkg.go.dev/github.com/waldiirawan/apm-agent-go/v2#Tracer.SetLogger[apm#Tracer.SetLogger].