Custom Instrumentation

Learn how to capture performance data on any action in your app.

To capture transactions and spans customized to your organization's needs, you must first set up performance monitoring.

To instrument certain regions of your code, you can create transactions to capture them.

The following example creates a transaction based on an incoming request:

Copied
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	hub := sentry.GetHubFromContext(ctx)
	if hub == nil {
		// Check the concurrency guide for more details: https://docs.sentry.io/platforms/go/concurrency/
		hub = sentry.CurrentHub().Clone()
		ctx = sentry.SetHubOnContext(ctx, hub)
	}

	options := []sentry.SpanOption{
		// Set the OP based on values from https://develop.sentry.dev/sdk/performance/span-operations/
		sentry.WithOpName("http.server"),
		sentry.ContinueFromRequest(r),
		sentry.WithTransactionSource(sentry.SourceURL),
	}

	transaction := sentry.StartTransaction(ctx,
		fmt.Sprintf("%s %s", r.Method, r.URL.Path),
		options...,
	)
	defer transaction.Finish()

	doWork(transaction.Context());
})

The next example contains the implementation of the hypothetical doWork function called from the code snippet in the previous section. Our SDK can determine if there is currently an open transaction in the current context and add all newly created spans as child operations to that transaction. Keep in mind that each individual span also needs to be manually finished. Otherwise, spans will not show up on the transaction.

Copied
func doWork(ctx context.Context) {
	// Set the OP based on values from https://develop.sentry.dev/sdk/performance/span-operations/
	span := sentry.StartSpan(ctx, "function")
	span.Description = "suboperation1"
	// omitted code ...
	span.Finish()

	// Set the OP based on values from https://develop.sentry.dev/sdk/performance/span-operations/
	span := sentry.StartSpan(ctx, "function")
	span.Description = "suboperation2"
	// omitted code ...
	span.Finish()
}

All finished spans are sent together as a transaction when the root span is finished. Make sure to call Finish() appropriately. Often times defer span.Finish() is handy.

In cases where you want to access the current transaction but don't have a direct reference to it, use sentry.TransactionFromContext. This function returns the root span of the current transaction, or nil if no transaction is started.

Copied
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    transaction := sentry.TransactionFromContext(ctx)
    cookie, _ := r.Cookie("secret")
    transaction.SetTag("secret-cookie", cookie.Value)
    // ...
})
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").