### Start Transaction with Options Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Start a transaction with additional options, such as specifying the parent trace context or the transaction's start time. ```go opts := apm.TransactionOptions{ Start: time.Now(), TraceContext: parentTraceContext, } transaction := apm.DefaultTracer().StartTransactionOptions("GET /", "request", opts) ``` -------------------------------- ### Tracer.StartTransactionOptions Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new transaction with options, allowing specification of start time and parent trace context. ```APIDOC ## Tracer.StartTransactionOptions ### Description Starts a new transaction with the specified name, type, and options. This allows for setting a custom start time and a parent trace context. ### Method `func (*Tracer) StartTransactionOptions(name, type string, opts TransactionOptions) *Transaction` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go opts := apm.TransactionOptions{ Start: time.Now(), TraceContext: parentTraceContext, } transaction := apm.DefaultTracer().StartTransactionOptions("GET /", "request", opts) ``` ### Response #### Success Response Returns a pointer to a `Transaction` object. #### Response Example (No specific response example provided in source, returns *Transaction) ``` -------------------------------- ### Set Global Tracer and Start Spans Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentracing-api.md Set the global OpenTracing tracer and demonstrate starting parent and child spans from context. ```go import ( "context" "go.elastic.co/apm/module/apmot/v2" "github.com/opentracing/opentracing-go" ) func main() { opentracing.SetGlobalTracer(apmot.New()) parent, ctx := opentracing.StartSpanFromContext(context.Background(), "parent") child, _ := opentracing.StartSpanFromContext(ctx, "child") child.Finish() parent.Finish() } ``` -------------------------------- ### Start a Span with Options Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md This method is similar to StartSpan but allows specifying the parent trace context and/or the span's start time. If no parent is specified, the span becomes a direct child of the transaction. ```go opts := apm.SpanOptions{ Start: time.Now(), Parent: parentSpan.TraceContext(), } span := tx.StartSpanOptions("SELECT FROM foo", "db.mysql.query", opts) ``` -------------------------------- ### Install Elastic APM Go Agent Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/set-up-apm-go-agent.md Install the Elastic APM Go agent package within a Go module using the go get command. ```bash go get -u go.elastic.co/apm/v2 ``` -------------------------------- ### Start a Span from Context Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new span within the sampled transaction and parent span found in the context. If the span is not dropped, it's included in the resulting context. ```go span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query") ``` -------------------------------- ### Start and End a Transaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/custom-instrumentation.md Start a new transaction with a name and type, customize it with context, and end it. Use defer tx.End() to ensure the transaction is always ended. ```go tx := apm.DefaultTracer().StartTransaction("GET /api/v1", "request") defer tx.End() ... tx.Result = "HTTP 2xx" tx.Context.SetLabel("region", "us-east-1") ``` -------------------------------- ### Transaction.StartSpanOptions Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new Span with additional options, allowing specification of the parent trace context and start time. If no parent is specified, the span becomes a direct child of the transaction. ```APIDOC ## Transaction.StartSpanOptions ### Description StartSpanOptions is essentially the same as StartSpan, but also accepts an options struct. This struct allows you to specify the parent trace context and/or the spans’s start time. If the parent trace context is not specified in the options, then the span will be a direct child of the transaction. Otherwise, the parent trace context should belong to some span descended from the transaction. ### Method Signature `func (*Transaction) StartSpanOptions(name, spanType string, opts SpanOptions) *Span` ### Parameters - **name** (string) - The name of the span. - **spanType** (string) - The type of the span. - **opts** (SpanOptions) - A struct containing options like Start time and Parent trace context. - **Start** (time.Time) - The start time of the span. - **Parent** (TraceContext) - The parent trace context. ### Example ```go opts := apm.SpanOptions{ Start: time.Now(), Parent: parentSpan.TraceContext(), } span := tx.StartSpanOptions("SELECT FROM foo", "db.mysql.query", opts) ``` ``` -------------------------------- ### Start a new Span within a Transaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Use this method to start a new span with a name, type, and optional parent. The span's start time is set to the current time. If the transaction is not sampled, the span will be discarded. ```go span := tx.StartSpan("SELECT FROM foo", "db.mysql.query", nil) ``` -------------------------------- ### Example Log Message with Trace IDs Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/log-correlation.md An example of an unstructured log message that includes trace, transaction, and span IDs, formatted for easy parsing. ```text 2019/09/17 14:48:02 ERROR [trace.id=cd04f33b9c0c35ae8abe77e799f126b7 transaction.id=cd04f33b9c0c35ae span.id=960834f4538880a4] an error occurred ``` -------------------------------- ### Tracer.StartTransaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new transaction with a given name and type. This is the primary method to begin tracking a request or operation. ```APIDOC ## Tracer.StartTransaction ### Description Starts a new transaction with the specified name and type. The transaction's start time is set to the current time. Use `StartTransactionOptions` for custom timestamps or parent trace contexts. ### Method `func (*Tracer) StartTransaction(name, type string) *Transaction` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go transaction := apm.DefaultTracer().StartTransaction("GET /", "request") ``` ### Response #### Success Response Returns a pointer to a `Transaction` object. #### Response Example (No specific response example provided in source, returns *Transaction) ``` -------------------------------- ### Wrap SQL Drivers with apmsql Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Register and open SQL drivers using apmsql to trace queries as spans. This example shows registration for PostgreSQL and SQLite. ```go import ( "go.elastic.co/apm/module/apmsql/v2" _ "go.elastic.co/apm/module/apmsql/v2/pq" _ "go.elastic.co/apm/module/apmsql/v2/sqlite3" ) func main() { db, err := apmsql.Open("postgres", "postgres://...") db, err := apmsql.Open("sqlite3", ":memory:") } ``` -------------------------------- ### Start a Transaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Start a new transaction with a given name and type. This should be called at the beginning of a request or operation. Transactions are grouped by type and name in the Elastic APM app. ```go transaction := apm.DefaultTracer().StartTransaction("GET /", "request") ``` -------------------------------- ### Example of apmslog Handler Usage Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Demonstrates how to create and use the apmslog Handler with slog. It shows how to configure the handler to send logs to Elastic APM and how trace context is automatically attached to log messages when using context-aware logging methods. ```go import ( "context" "log/slog" "go.elastic.co/apm/module/apmslog/v2" ) func ExampleHandler() { // Report slog "ERROR" level messages to Elastic APM using // apm.DefaultTracer() while utilizing some specific slog handler // to format logging messages apmHandler = apmslog.NewApmHandler( apmslog.WithHandler( slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{ Level: slog.LevelInfo, }), ), ) logger = slog.New(apmHandler) // while using slog context aware methods, any existing trace, // transaction, or span ID are added from the given context tx := apm.DefaultTracer().StartTransaction("name", "type") defer tx.End() ctx := apm.ContextWithTransaction(context.Background(), tx) span, ctx := apm.StartSpan(ctx, "name", "type") defer span.End() // log msg will have a trace, transaction, and a span attached logger.InfoContext(ctx, "I should have a trace, transaction, and span id attached!") // the log msg will be reported to apm logger.ErrorContext(ctx, "I want this to be reported, but have no error to attach") // the log msg with its error will be reported to apm logger.ErrorContext(ctx, "I will report this error to apm", "error", errors.New("new error")) // BOTH errors with the log msg will be reported to apm. [ error, err ] slog attribute keys are by default reported logger.ErrorContext(ctx, "I will report this error to apm", "error", errors.New("new error"), "err", errors.New("new err")) } ``` -------------------------------- ### apm.StartSpan Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new Span within the sampled transaction and parent span found in the context. If the span is not dropped, it is included in the resulting context. ```APIDOC ## apm.StartSpan ### Description StartSpan starts and returns a new Span within the sampled transaction and parent span in the context, if any. If the span isn’t dropped, it will be included in the resulting context. ### Method Signature `func StartSpan(ctx context.Context, name, spanType string) (*Span, context.Context)` ### Parameters - **ctx** (context.Context) - The current context. - **name** (string) - The name of the span. - **spanType** (string) - The type of the span. ### Returns - **(*Span, context.Context)** - The created span and the updated context. ### Example ```go span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query") ``` ``` -------------------------------- ### Transaction.StartSpan Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Starts a new Span within the current transaction. It takes a name, type, and an optional parent span. The span's start time is set to the current time. If the transaction is not sampled, the span will be discarded. ```APIDOC ## Transaction.StartSpan ### Description Starts and returns a new Span within the transaction, with the specified name, type, and optional parent span, and with the start time set to the current time. If you need to set the timestamp or parent trace context, use Transaction.StartSpanOptions. If the span type contains two dots, they are assumed to separate the span type, subtype, and action; a single dot separates span type and subtype, and the action will not be set. If the transaction is sampled, then the span’s ID will be set, and its stacktrace will be set if the tracer is configured accordingly. If the transaction is not sampled, then the returned span will be silently discarded when its End method is called. To avoid any unnecessary computation for these dropped spans, call the Dropped method. As a convenience, it is valid to create a span on a nil Transaction; the resulting span will be non-nil and safe for use, but will not be reported to the APM server. ### Method Signature `func (*Transaction) StartSpan(name, spanType string, parent *Span) *Span` ### Parameters - **name** (string) - The name of the span. - **spanType** (string) - The type of the span (e.g., "db.mysql.query"). - **parent** (*Span) - Optional parent span. ### Example ```go span := tx.StartSpan("SELECT FROM foo", "db.mysql.query", nil) ``` ``` -------------------------------- ### Beego Middleware and Span Creation Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Provides middleware for the Beego web framework and demonstrates starting a span within a controller. The apmbeego middleware handles request transactions and panics. ```go import ( "github.com/astaxie/beego" "go.elastic.co/apm/v2" "go.elastic.co/apm/module/apmbeego/v2" ) type thingController struct{beego.Controller} func (c *thingController) Get() { span, _ := apm.StartSpan(c.Ctx.Request.Context(), "thingController.Get", "controller") span.End() ... } func main() { beego.Router("/", &thingController{}) beego.Router("/thing/:id:int", &thingController{}, "get:Get") beego.RunWithMiddleWares("localhost:8080", apmbeego.Middleware()) } ``` -------------------------------- ### Start and End a Span Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/custom-instrumentation.md Start a span within a transaction to represent a sub-operation. Use defer span.End() to ensure the span is always ended. The span can be associated with a parent span if one exists in the context. ```go span, ctx := apm.StartSpan(ctx, "SELECT FROM foo", "db.mysql.query") defer span.End() ``` -------------------------------- ### Instrumenting HTTP Handlers and Database Queries Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/custom-instrumentation-propagation.md This example demonstrates how to instrument an HTTP handler to create a transaction and how to create child spans for database queries using apmsql. The transaction is automatically added to the request context by apmhttp.Wrap, and this context is passed down to functions like getList to create child spans. ```go import ( "context" "database/sql" "net/http" "go.elastic.co/apm/v2" "go.elastic.co/apm/module/apmhttp/v2" "go.elastic.co/apm/module/apmsql/v2" _ "go.elastic.co/apm/module/apmsql/v2/pq" ) var db *sql.DB func init() { // apmsql.Open wraps sql.Open, // in order to add tracing to database operations. db, _ = apmsql.Open("postgres", "") } func main() { mux := http.NewServeMux() mux.HandleFunc("/", handleList) // apmhttp.Wrap instruments an http.Handler, in order // to report any request to this handler as a transaction, // and to store the transaction in the request's context. handler := apmhttp.Wrap(mux) http.ListenAndServe(":8080", handler) } func handleList(w http.ResponseWriter, req *http.Request) { // By passing the request context down to getList, getList can add spans to it. ctx := req.Context() getList(ctx) // ... } func getList(ctx context.Context) ( // When getList is called with a context containing a transaction or span, // StartSpan creates a child span. In this example, getList is always called // with a context containing a transaction for the handler, so we should // expect to see something like: // // Transaction: handleList // Span: getList // Span: SELECT FROM items // span, ctx := apm.StartSpan(ctx, "getList", "custom") defer span.End() // NOTE: The context object ctx returned by StartSpan above contains // the current span now, so subsequent calls to StartSpan create new // child spans. // db was opened with apmsql, so queries will be reported as // spans when using the context methods. rows, err := db.QueryContext(ctx, "SELECT * FROM items") // ... rows.Close() ) ``` -------------------------------- ### Get Default Tracer Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Obtain the default APM tracer. The tracer is initialized on the first call to DefaultTracer() and configured via environment variables. ```go import ( "go.elastic.co/apm/v2" ) func main() { tracer := apm.DefaultTracer() ... ``` -------------------------------- ### Inject Trace Context for RUM Initialization Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Example of injecting trace and parent span IDs into an HTML template to initialize the JavaScript RUM agent. This ensures the page load appears as the root of the trace. ```go var initialPageTemplate = template.Must(template.New("").Parse(` ... `)) func initialPageHandler(w http.ResponseWriter, req *http.Request) { err := initialPageTemplate.Execute(w, apm.TransactionFromContext(req.Context())) if err != nil { ... } } ``` -------------------------------- ### Get Span Trace Context Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Returns the span's trace context, which can be used to set the parent for new spans. ```go span.TraceContext() ``` -------------------------------- ### apm.ContextWithSpan Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Adds a span to the provided context and returns the updated context. This span can later be retrieved using SpanFromContext or used as a parent for new spans started with apm.StartSpan. ```APIDOC ## apm.ContextWithSpan ### Description ContextWithSpan adds the span to the context and returns the resulting context. The span can be retrieved using apm.SpanFromContext. The context may also be passed into apm.StartSpan, which uses SpanFromContext under the covers to create another span as a child of the span. ### Method Signature `func ContextWithSpan(context.Context, *Span) context.Context` ### Parameters - **ctx** (context.Context) - The original context. - **span** (*Span) - The span to add to the context. ### Returns - **context.Context** - The context with the span added. ``` -------------------------------- ### Run Go Test Suite Source: https://github.com/elastic/apm-agent-go/blob/main/CONTRIBUTING.md Execute the entire test suite for the project. This command should be run to ensure no existing functionality is broken by your changes. ```bash go test ./... ``` -------------------------------- ### Initialize and Configure OpenTelemetry Tracing Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Set up the OpenTelemetry Tracer Provider and create a span. Spans created here will be sent to the Elastic APM tracer. ```go import ( "go.elastic.co/apm/v2" "go.elastic.co/apm/module/apmotel/v2" "go.opentelemetry.io/otel" ) func main() { provider, err := apmotel.NewTracerProvider() if err != nil { log.Fatal(err) } otel.SetTracerProvider(provider) racer := otel.GetTracerProvider().Tracer("example") // Start a new span to track some work, which will be sent to the Elastic APM tracer ctx, span := tracer.Start(context.Background(), "my_work") // Do something span.End() } ``` -------------------------------- ### Initialize and Configure OpenTelemetry Metrics Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Set up the OpenTelemetry MeterProvider with the custom exporter and register the exporter with the Elastic APM agent. Metrics recorded via OpenTelemetry will be exported to the Elastic Agent. ```go import ( "go.elastic.co/apm" "go.elastic.co/apm/module/apmotel" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/sdk/metric" ) func main() { exporter := apmotel.NewGatherer() // Configure OpenTelemetry provider := metric.NewMeterProvider(metric.WithReader(exporter)) otel.SetMeterProvider(provider) // Configure the Elastic APM apm.DefaultTracer().RegisterMetricsGatherer(exporter) // Record a metric with OpenTelemetry which will be exported to the Elastic Agent meter := provider.Meter("my_application") counter, _ := meter.Float64Counter("metric_called") counter.Add(context.TODO(), 1) } ``` -------------------------------- ### Initialize OpenTracing Tracer Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentracing-api.md Initialize the OpenTracing tracer using apmot.New(). It wraps apm.DefaultTracer() by default, or a custom tracer can be provided. ```go otTracer := apmot.New() ``` -------------------------------- ### Create OpenTelemetry Tracer Provider Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Instantiate the OpenTelemetry Tracer Provider using apmotel.NewTracerProvider. ```go provider, err := apmotel.NewTracerProvider() ``` -------------------------------- ### Initialize GORM v2 with Elastic APM Tracing Source: https://github.com/elastic/apm-agent-go/blob/main/module/apmgormv2/README.md Replace the standard GORM driver import with the Elastic APM driver for MySQL. This enables automatic tracing of database operations. ```go import ( mysql "go.elastic.co/apm/module/apmgormv2/driver/mysql" "gorm.io/gorm" ) db, err := gorm.Open(mysql.Open("dsn"), &gorm.Config{}) ``` -------------------------------- ### Import OpenTelemetry Tracing Bridge Package Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Import the apmotel package to use the OpenTelemetry tracing bridge. ```go import ( "go.elastic.co/apm/module/apmotel/v2" ) ``` -------------------------------- ### Mixing Native and OpenTracing APIs Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentracing-api.md Demonstrates creating a transaction with the native API and then a child span using the OpenTracing API, followed by another native API span as a child of the OpenTracing span. ```go // Transaction created through native API. transaction := apm.DefaultTracer().StartTransaction("GET /", "request") ctx := apm.ContextWithTransaction(context.Background(), transaction) // Span created through OpenTracing API will be a child of the transaction. otSpan, ctx := opentracing.StartSpanFromContext(ctx, "ot-span") // Span created through the native API will be a child of the span created // above via the OpenTracing API. apmSpan, ctx := apm.StartSpan(ctx, "apm-span", "apm-span") ``` -------------------------------- ### Set Transaction on Error Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Associates an error with an active transaction. Ensure the transaction is started before creating the error. ```go tx := apm.DefaultTracer().StartTransaction("GET /foo", "request") defer tx.End() e := apm.DefaultTracer().NewError(err) e.SetTransaction(tx) e.Send() ``` -------------------------------- ### Get Span Parent ID Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Returns the ID of the span's parent. This is useful for understanding the span hierarchy. ```go span.ParentID() ``` -------------------------------- ### Get Transaction Trace Context Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Retrieve the transaction's trace context, which includes trace and span IDs. ```go transaction.TraceContext() ``` -------------------------------- ### Import apmot package Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentracing-api.md Import the apmot package to use the OpenTracing API implementation. ```go import ( "go.elastic.co/apm/module/apmot/v2" ) ``` -------------------------------- ### Import OpenTelemetry Metrics Exporter Package Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Import the apmotel package to use the OpenTelemetry metrics exporter. ```go import ( "go.elastic.co/apm/module/apmotel" ) ``` -------------------------------- ### Get Transaction Parent ID Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Retrieve the ID of the transaction's parent span. Returns a zero (invalid) SpanID if the transaction has no parent. ```go transaction.ParentID() ``` -------------------------------- ### Create GitHub Release Source: https://github.com/elastic/apm-agent-go/blob/main/CONTRIBUTING.md Creates a new release on GitHub using the GitHub CLI. This is a step in the release procedure after creating tags. ```bash gh release create vN.N.N ``` -------------------------------- ### Span.End Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Marks the span as complete. The span's duration is calculated from its start time to this call. The duration can be overridden by setting the Duration field before calling End. ```APIDOC ## Span.End ### Description End marks the span as complete. The Span must not be modified after this, but may still be used as the parent of a span. The span’s duration will be calculated as the amount of time elapsed since the span was started until this call. To override this behaviour, the span’s Duration field may be set before calling End. ### Method Signature `func (*Span) End()` ``` -------------------------------- ### End a Span Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Marks the span as complete. The span's duration is calculated from its start time to this call. The duration can be overridden by setting the Duration field before calling End. ```go span.End() ``` -------------------------------- ### Import apmlambda for AWS Lambda Tracing Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Importing this package is sufficient to automatically report AWS Lambda function invocations. Future versions may require explicit calls to apmlambda.Start. ```go import ( _ "go.elastic.co/apm/module/apmlambda/v2" ) ``` -------------------------------- ### Check Test Coverage Source: https://github.com/elastic/apm-agent-go/blob/main/CONTRIBUTING.md Run the test suite and report code coverage. This helps ensure that your new or modified code is adequately tested. ```bash go test -cover ``` -------------------------------- ### Ensure Parent Span ID for RUM Integration Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Get the transaction's parent span ID, generating one if it doesn't exist. This is useful for correlating backend traces with frontend JavaScript RUM agent data. ```go transaction.EnsureParent() ``` -------------------------------- ### Update Go Modules Source: https://github.com/elastic/apm-agent-go/blob/main/CONTRIBUTING.md Synchronizes dependencies and updates module information. This command is part of the release procedure. ```bash make update-modules ``` -------------------------------- ### Instrument GORM Database Operations Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Import apmgorm/dialects and use apmgorm.Open and apmgorm.WithContext to instrument GORM operations. This creates spans for database queries. ```go import ( "go.elastic.co/apm/module/apmgorm/v2" _ "go.elastic.co/apm/module/apmgorm/v2/dialects/postgres" ) func main() { db, err := apmgorm.Open("postgres", "") ... db = apmgorm.WithContext(ctx, db) db.Find(...) // creates a "SELECT FROM " span } ``` -------------------------------- ### Propagating Trace Context with Detached Context Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/custom-instrumentation-propagation.md This example shows how to use apm.DetachedContext to propagate trace context to a goroutine without propagating the parent context's cancellation. This is useful for fire-and-forget operations that should still be associated with the original transaction. ```go func handleRequest(w http.ResponseWriter, req *http.Request) { go fireAndForget(apm.DetachedContext(req.Context())) // After handleRequest returns, req.Context() will be canceled, // but the "detached context" passed into fireAndForget will not. // Any spans created by fireAndForget will still be joined to // the handleRequest transaction. } ``` -------------------------------- ### Create OpenTelemetry Metrics Gatherer Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/opentelemetry-api.md Instantiate the OpenTelemetry Metrics Gatherer using apmotel.NewGatherer. This acts as both a MetricsGatherer for the Elastic APM Agent and a metric.Reader for OpenTelemetry. ```go exporter := apmotel.NewGatherer() ``` -------------------------------- ### Gin Middleware Integration Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Integrates Elastic APM tracing into a Gin web framework application using the apmgin middleware. This middleware automatically creates transactions for each request and recovers panics. ```go import ( "go.elastic.co/apm/module/apmgin/v2" ) func main() { engine := gin.New() engine.Use(apmgin.Middleware(engine)) ... } ``` -------------------------------- ### Instrument GORM v2 Database Operations Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Import the apmgormv2/driver package and use its dialects with gorm.Open to instrument GORM database operations. Use db.WithContext to propagate a transaction context. ```go import ( "gorm.io/gorm" postgres "go.elastic.co/apm/module/apmgormv2/v2/driver/postgres" ) func main() { db, err := gorm.Open(postgres.Open("dsn"), &gorm.Config{}) ... db = db.WithContext(ctx) db.Find(...) // creates a "SELECT FROM " span } ``` -------------------------------- ### Use TraceFormatter for Unstructured Logging Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/log-correlation.md Utilize the apm.TraceFormatter function to easily include trace context information in unstructured log messages, such as with log.Printf. ```go log.Printf("ERROR [%+v] an error occurred", apm.TraceFormatter(ctx)) ``` -------------------------------- ### Instrument go-pg Database Operations Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Call apmgopg.Instrument with your database instance and a context containing an APM transaction to trace go-pg statements. ```go import ( "github.com/go-pg/pg" "go.elastic.co/apm/module/apmgopg/v2" ) func main() { db := pg.Connect(&pg.Options{}) apmgopg.Instrument(db) db.WithContext(ctx).Model(...) } ``` -------------------------------- ### Use apmhttprouter.Router for Automatic Route Instrumentation Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Replace httprouter.New with apmhttprouter.New to use the apmhttprouter.Router type. This wrapper automatically instruments added routes without requiring explicit route passing. ```go import "go.elastic.co/apm/module/apmhttprouter/v2" func main() { router := apmhttprouter.New() router.GET(route, h) ... } ``` -------------------------------- ### Tag Release Version Source: https://github.com/elastic/apm-agent-go/blob/main/CONTRIBUTING.md Creates Git tags for a new release, including version tags and module-specific tags. This script is executed manually during the release process. ```bash scripts/tagversion.sh ``` -------------------------------- ### Instrument MongoDB Go Driver with apmmongo Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Instrument the MongoDB Go Driver by passing apmmongo.CommandMonitor to client options. Ensure commands are executed within a transaction context. ```go import ( "context" "net/http" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.elastic.co/apm/module/apmmongo/v2" ) var client, _ = mongo.Connect( context.Background(), options.Client().SetMonitor(apmmongo.CommandMonitor()), ) func handleRequest(w http.ResponseWriter, req *http.Request) { collection := client.Database("db").Collection("coll") cur, err := collection.Find(req.Context(), bson.D{}) ... } ``` -------------------------------- ### Wrap HTTP Handler with APM Tracing Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Wrap an existing http.Handler with apmhttp.Wrap to automatically trace incoming requests. A transaction is stored in the request context for use in handlers. ```go import ( "go.elastic.co/apm/module/apmhttp/v2" ) func main() { var myHandler http.Handler = ... tracedHandler := apmhttp.Wrap(myHandler) } ``` -------------------------------- ### Instrument Gorilla Mux Router Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Integrates the apmgorilla middleware with a Gorilla Mux router to automatically instrument incoming requests. ```go import ( "github.com/gorilla/mux" "go.elastic.co/apm/module/apmgorilla/v2" ) func main() { router := mux.NewRouter() apmgorilla.Instrument(router) // ... } ``` -------------------------------- ### Recover and Report Panics Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/custom-instrumentation.md Use Tracer.Recovered in a deferred recovery function to catch panics, associate them with the current transaction or span, and send them as errors. ```go defer func() { if v := recover(); v != nil { e := apm.DefaultTracer().Recovered() e.SetTransaction(tx) // or e.SetSpan(span) e.Send() } }() ``` -------------------------------- ### Instrument AWS SDK Go with apmawssdkgo Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Wrap your AWS SDK Go session with apmawssdkgo.WrapSession to report AWS requests as spans. This is supported for S3, DynamoDB, SQS, and SNS services. ```go import ( "context" "net/http" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3/s3manager" "go.elastic.co/apm/module/apmawssdkgo/v2" ) func main() { session := session.Must(session.NewSession()) session = apmawssdkgo.WrapSession(session) uploader := s3manager.NewUploader(session) s := &server{uploader} ... } func (s *server) handleRequest(w http.ResponseWriter, req *http.Request) { ctx := req.Context() out, err := s.uploader.UploadWithContext(ctx, &s3manager.UploadInput{ Bucket: aws.String("your-bucket"), Key: aws.String("your-key"), Body: bytes.NewBuffer([]byte("your-body")), }) ... } ``` -------------------------------- ### Instrument HTTP Client for APM Tracing Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Instrument an http.Client using apmhttp.WrapClient to trace outgoing requests as spans. Ensure the response body is fully consumed or closed to finalize the span. ```go import ( "net/http" "golang.org/x/net/context/ctxhttp" "go.elastic.co/apm/v2" "go.elastic.co/apm/module/apmhttp/v2" ) var tracingClient = apmhttp.WrapClient(http.DefaultClient) func serverHandler(w http.ResponseWriter, req *http.Request) { // Propagate the transaction context contained in req.Context(). resp, err := ctxhttp.Get(req.Context(), tracingClient, "http://backend.local/foo") if err != nil { apm.CaptureError(req.Context(), err).Send() http.Error(w, "failed to query backend", 500) return } body, err := ioutil.ReadAll(resp.Body) ... } func main() { http.ListenAndServe(":8080", apmhttp.Wrap(http.HandlerFunc(serverHandler))) } ``` -------------------------------- ### Tracer Config API Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Many configuration attributes for the APM tracer can be updated dynamically using `apm.Tracer` method calls. Configuration methods are typically prefixed with `Set`. ```APIDOC ## Tracer Config API Many configuration attributes can be be updated dynamically via `apm.Tracer` method calls. Please refer to the documentation at [pkg.go.dev/go.elastic.co/apm/v2#Tracer](https://pkg.go.dev/go.elastic.co/apm/v2#Tracer) for details. The configuration methods are primarily prefixed with `Set`, such as [apm#Tracer.SetLogger](https://pkg.go.dev/go.elastic.co/apm/v2#Tracer.SetLogger). ``` -------------------------------- ### TraceFormatter Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Returns a fmt.Formatter for formatting trace, transaction, and span IDs from the context. Supports various format verbs for different output styles. ```APIDOC ## func TraceFormatter(context.Context) fmt.Formatter [apm-traceformatter] TraceFormatter returns an implementation of [fmt.Formatter](https://golang.org/pkg/fmt/#Formatter) that can be used to format the IDs of the transaction and span stored in the provided context. The formatter understands the following formats: * %v: trace ID, transaction ID, and (if in the context of a span) span ID, space separated * %t: trace ID only * %x: transaction ID only * %s: span ID only The "+" option can be used to format the values in "key=value" style, with the field names `trace.id`, `transaction.id`, and `span.id`. For example, using "%+v" as the format would yield "trace.id=… transaction.id=… span.id=…". For a more in-depth example, see [Manual log correlation (unstructured)](/reference/log-correlation.md#log-correlation-manual-unstructured). ``` -------------------------------- ### Wrap go-redis Client for APM Spans (v2) Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Wrap a go-redis client to report Redis commands as spans within the current APM transaction. The wrapped client can be associated with a specific request context. ```go import ( "net/http" "github.com/go-redis/redis" "go.elastic.co/apm/module/apmgoredis/v2" ) var redisClient *redis.Client // initialized at program startup func handleRequest(w http.ResponseWriter, req *http.Request) { // Wrap and bind redisClient to the request context. If the HTTP // server is instrumented with Elastic APM (e.g. with apmhttp), // Redis commands will be reported as spans within the request's // transaction. client := apmgoredis.Wrap(redisClient).WithContext(req.Context()) ... } ``` -------------------------------- ### Instrument go-pg v10 Database Operations Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Use apmgopgv10.Instrument for tracing database operations with v10 of the go-pg library. Ensure the context includes an APM transaction. ```go import ( "github.com/go-pg/pg/v10" "go.elastic.co/apm/module/apmgopgv10/v2" ) func main() { db := pg.Connect(&pg.Options{}) apmgopg.Instrument(db) db.WithContext(ctx).Model(...) } ``` -------------------------------- ### Integrate Zerolog with Elastic APM Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Use apmzerolog.Writer to send error-level logs to Elastic APM. Configure zerolog.ErrorStackMarshaler to include stack traces from github.com/pkg/errors. ```go import ( "net/http" "github.com/rs/zerolog" "go.elastic.co/apm/module/apmzerolog/v2" ) // apmzerolog.Writer will send log records with the level error or greater to Elastic APM. var logger = zerolog.New(zerolog.MultiLevelWriter(os.Stdout, &apmzerolog.Writer{})) func init() { // apmzerolog.MarshalErrorStack will extract stack traces from // errors produced by github.com/pkg/errors. The main difference // with github.com/rs/zerolog/pkgerrors.MarshalStack is that // the apmzerolog implementation records fully-qualified function // names, enabling errors reported to Elastic APM to be attributed // to the correct package. zerolog.ErrorStackMarshaler = apmzerolog.MarshalErrorStack } func traceLoggingMiddleware(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() logger := zerolog.Ctx(ctx).Hook(apmzerolog.TraceContextHook(ctx)) req = req.WithContext(logger.WithContext(ctx)) h.ServeHTTP(w, req) }) } ``` -------------------------------- ### Wrap httprouter Handler with Route Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Use apmhttprouter.Wrap to instrument a httprouter handler, passing the route explicitly. This is necessary because httprouter does not provide a way to obtain the matched route. ```go import ( "github.com/julienschmidt/httprouter" "go.elastic.co/apm/module/apmhttprouter/v2" ) func main() { router := httprouter.New() const route = "/my/route" router.GET(route, apmhttprouter.Wrap(h, route)) ... } ``` -------------------------------- ### Set User Email for Transaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Use SetUserEmail to record the email address of the user associated with the transaction. ```go ctx.SetUserEmail("john.doe@example.com") ``` -------------------------------- ### Wrap fasthttp RequestHandler with APM Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Integrates APM transaction tracking into a fasthttp RequestHandler. The APM transaction is stored in the request context and can be accessed using apm.TransactionFromContext. ```go import ( "github.com/valyala/fasthttp" "go.elastic.co/apm/module/apmfasthttp/v2" ) func main() { var myHandler fasthttp.RequestHandler = func(ctx *fasthttp.RequestCtx) { apmCtx := apm.TransactionFromContext(ctx) // ... } tracedHandler := apmfasthttp.Wrap(myHandler) } ``` -------------------------------- ### Instrument gRPC Server and Client Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/builtin-modules.md Provides server and client interceptors for gRPC-Go to report transactions and spans for RPCs. Server interceptors capture incoming requests, while client interceptors capture outgoing requests. ```go import ( "go.elastic.co/apm/module/apmgrpc/v2" ) func main() { server := grpc.NewServer( grpc.UnaryInterceptor(apmgrpc.NewUnaryServerInterceptor()), grpc.StreamInterceptor(apmgrpc.NewStreamServerInterceptor()), ) // ... conn, err := grpc.Dial(addr, grpc.WithUnaryInterceptor(apmgrpc.NewUnaryClientInterceptor()), grpc.WithStreamInterceptor(apmgrpc.NewStreamClientInterceptor()), ) // ... } ``` -------------------------------- ### Set Username for Transaction Source: https://github.com/elastic/apm-agent-go/blob/main/docs/reference/api-documentation.md Use SetUsername to record the username of the user associated with the transaction. ```go ctx.SetUsername("john.doe") ```