---
title: "Custom Instrumentation"
url: https://docs.sentry.io/platforms/unreal/tracing/trace-propagation/custom-instrumentation/
---

# Custom Instrumentation for Distributed Tracing for Unreal Engine

On this page you will learn how to manually propagate trace information into and out of your Unreal Engine game.

To set it up, make sure your game extracts incoming tracing information and attaches it again when making an outgoing request.

## [Step 1) Extract Incoming Tracing Information](https://docs.sentry.io/platforms/unreal/tracing/trace-propagation/custom-instrumentation.md#step-1-extract-incoming-tracing-information)

To continue a trace from another service, for example a backend that uses another Sentry SDK, pass its `sentry-trace` and `baggage` headers to `ContinueTrace()`. It returns a transaction context that continues the upstream trace, including its sampling decision:

```cpp
void OnResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bSucceeded)
{
    USentrySubsystem* SentrySubsystem = GEngine->GetEngineSubsystem<USentrySubsystem>();

    const FString SentryTrace = Response->GetHeader(TEXT("sentry-trace"));

    TArray<FString> BaggageHeaders;
    const FString Baggage = Response->GetHeader(TEXT("baggage"));
    if (!Baggage.IsEmpty())
    {
        BaggageHeaders.Add(Baggage);
    }

    if (USentryTransactionContext* TransactionContext = SentrySubsystem->ContinueTrace(SentryTrace, BaggageHeaders))
    {
        USentryTransaction* Transaction = SentrySubsystem->StartTransactionWithContext(TransactionContext);

        // Process the response here...

        Transaction->Finish();
    }
}
```

The `sentry-trace` header must follow the format defined in [the telemetry docs](https://develop.sentry.dev/sdk/telemetry/traces/#header-sentry-trace): a 32-character hexadecimal `traceId`, followed by a 16-character hexadecimal `spanId`, and an optional `sampled` flag.

Always check the result of `ContinueTrace()`. It returns `nullptr` if the SDK isn't initialized. On Android, it also returns `nullptr` if tracing is disabled, and on macOS and iOS, if the `sentry-trace` header is malformed.

On macOS and iOS, only the sample rate and sample rand are taken from the incoming `baggage`, and only when the `sentry-trace` header includes a sampling decision (`-1` or `-0`). Other values, such as release and environment, aren't carried over yet.

## [Step 2) Inject Tracing Information to Outgoing Requests](https://docs.sentry.io/platforms/unreal/tracing/trace-propagation/custom-instrumentation.md#step-2-inject-tracing-information-to-outgoing-requests)

For distributed tracing to work, the two headers `sentry-trace` and `baggage` must also be added to outgoing requests. Get them from the current transaction or span with `GetTraceHeaders()`:

```cpp
TSharedRef<IHttpRequest, ESPMode::ThreadSafe> HttpRequest = FHttpModule::Get().CreateRequest();
HttpRequest->SetURL(TEXT("https://example.com/api/action"));

for (const TPair<FString, FString>& Header : Transaction->GetTraceHeaders())
{
    HttpRequest->SetHeader(Header.Key, Header.Value);
}

HttpRequest->ProcessRequest();
```

`GetTrace()` is still available, but it only returns the `sentry-trace` header.

The two services are now connected with your custom distributed tracing implementation.

## [Verification](https://docs.sentry.io/platforms/unreal/tracing/trace-propagation/custom-instrumentation.md#verification)

If you make outgoing requests from your game to other services, check if the headers `sentry-trace` and `baggage` are present in the request. If so, distributed tracing is working.
