|
| 1 | +On this page you will learn how to manually propagate trace information into and out of your Unity application. |
| 2 | + |
| 3 | +To set it up you have to make sure your game extracts incoming headers and to set those headers again when making an outgoing request. |
| 4 | + |
| 5 | +## Choosing Between HttpClient and UnityWebRequest |
| 6 | + |
| 7 | +Unity supports two approaches for making HTTP requests out of the box: |
| 8 | + |
| 9 | +- **HttpClient**: Use .NET's `HttpClient` with `SentryHttpMessageHandler` for automatic trace propagation. This is the simplest approach and works on all platforms except WebGL. It supports modern async/await patterns. |
| 10 | +- **UnityWebRequest (Required for WebGL)**: Use Unity's `UnityWebRequest`, as `HttpClient` is not supported in WebGL due to browser security restrictions. This approach also works well if you prefer Unity's coroutine-based patterns or need consistent behavior across all platforms. |
| 11 | + |
| 12 | +## Step 1) Extract Incoming Tracing Information |
| 13 | + |
| 14 | +Incoming tracing information has to be extracted and stored in memory for later use. Sentry provides the `ContinueTrace()` function to help you with this. Tracing information can come from incoming headers, for example, by another Sentry SDK used in your backend service. |
| 15 | + |
| 16 | +### Using HttpClient |
| 17 | + |
| 18 | +If you're using .NET's `HttpClient`, you can extract trace headers from the response: |
| 19 | + |
| 20 | +```csharp |
| 21 | +using System.Linq; |
| 22 | +using System.Net.Http; |
| 23 | +using System.Threading.Tasks; |
| 24 | +using UnityEngine; |
| 25 | + |
| 26 | +public class TraceReceiver : MonoBehaviour |
| 27 | +{ |
| 28 | + private static readonly HttpClient httpClient = new HttpClient(); |
| 29 | + |
| 30 | + async Task MakeRequest() |
| 31 | + { |
| 32 | + try |
| 33 | + { |
| 34 | + var response = await httpClient.GetAsync("https://example.com/api/data"); |
| 35 | + |
| 36 | + if (response.IsSuccessStatusCode) |
| 37 | + { |
| 38 | + // Extract Sentry trace headers from the response |
| 39 | + var sentryTraceHeader = string.Empty; |
| 40 | + var sentryBaggageHeader = string.Empty; |
| 41 | + |
| 42 | + if (response.Headers.TryGetValues("sentry-trace", out var traceValues)) |
| 43 | + { |
| 44 | + sentryTraceHeader = traceValues.FirstOrDefault() ?? string.Empty; |
| 45 | + } |
| 46 | + |
| 47 | + if (response.Headers.TryGetValues("baggage", out var baggageValues)) |
| 48 | + { |
| 49 | + sentryBaggageHeader = baggageValues.FirstOrDefault() ?? string.Empty; |
| 50 | + } |
| 51 | + |
| 52 | + // Continue the trace from the backend service |
| 53 | + var transactionContext = SentrySdk.ContinueTrace(sentryTraceHeader, sentryBaggageHeader); |
| 54 | + var transaction = SentrySdk.StartTransaction(transactionContext); |
| 55 | + |
| 56 | + // Process your data here... |
| 57 | + var content = await response.Content.ReadAsStringAsync(); |
| 58 | + |
| 59 | + transaction.Finish(); |
| 60 | + } |
| 61 | + } |
| 62 | + catch (HttpRequestException e) |
| 63 | + { |
| 64 | + Debug.LogError($"Request failed: {e.Message}"); |
| 65 | + } |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +### Using UnityWebRequest (Required for WebGL) |
| 71 | + |
| 72 | +For WebGL builds or if you prefer Unity's coroutine-based approach, use `UnityWebRequest`: |
| 73 | + |
| 74 | +```csharp |
| 75 | +using System.Collections; |
| 76 | +using UnityEngine; |
| 77 | +using UnityEngine.Networking; |
| 78 | + |
| 79 | +public class TraceReceiver : MonoBehaviour |
| 80 | +{ |
| 81 | + IEnumerator MakeRequest() |
| 82 | + { |
| 83 | + using var www = UnityWebRequest.Get("https://example.com/api/data"); |
| 84 | + yield return www.SendWebRequest(); |
| 85 | + |
| 86 | + if (www.result == UnityWebRequest.Result.Success) |
| 87 | + { |
| 88 | + // Extract headers from the incoming response |
| 89 | + var responseHeaders = www.GetResponseHeaders(); |
| 90 | + if (responseHeaders != null) |
| 91 | + { |
| 92 | + var sentryTraceHeader = string.Empty; |
| 93 | + var sentryBaggageHeader = string.Empty; |
| 94 | + |
| 95 | + if (responseHeaders.TryGetValue("sentry-trace", out var traceHeader)) |
| 96 | + { |
| 97 | + sentryTraceHeader = traceHeader; |
| 98 | + } |
| 99 | + |
| 100 | + if (responseHeaders.TryGetValue("baggage", out var baggageHeader)) |
| 101 | + { |
| 102 | + sentryBaggageHeader = baggageHeader; |
| 103 | + } |
| 104 | + |
| 105 | + // Continue the trace from the backend service |
| 106 | + var transactionContext = SentrySdk.ContinueTrace(sentryTraceHeader, sentryBaggageHeader); |
| 107 | + var transaction = SentrySdk.StartTransaction(transactionContext); |
| 108 | + |
| 109 | + // Process your data here... |
| 110 | +
|
| 111 | + transaction.Finish(); |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +If you pass these headers to Sentry's `ContinueTrace()` function it will store them in memory for later use. |
| 119 | + |
| 120 | +## Step 2) Inject Tracing Information to Outgoing Requests |
| 121 | + |
| 122 | +For distributed tracing to work, the two headers `sentry-trace` and `baggage`, must now also be added to outgoing requests. |
| 123 | + |
| 124 | +### Using HttpClient with SentryHttpMessageHandler (Recommended for non-WebGL) |
| 125 | + |
| 126 | +The easiest way to propagate traces is to use .NET's `HttpClient` with `SentryHttpMessageHandler`. This automatically adds tracing headers to all outgoing requests: |
| 127 | + |
| 128 | +```csharp |
| 129 | +using System.Net.Http; |
| 130 | +using System.Threading.Tasks; |
| 131 | +using Sentry.Http; |
| 132 | +using UnityEngine; |
| 133 | + |
| 134 | +public class TraceSender : MonoBehaviour |
| 135 | +{ |
| 136 | + private static readonly HttpClient httpClient = new HttpClient(new SentryHttpMessageHandler()); |
| 137 | + |
| 138 | + async Task SendRequest() |
| 139 | + { |
| 140 | + try |
| 141 | + { |
| 142 | + var response = await httpClient.PostAsync( |
| 143 | + "https://example.com/api/action", |
| 144 | + new StringContent("{}", System.Text.Encoding.UTF8, "application/json")); |
| 145 | + |
| 146 | + if (response.IsSuccessStatusCode) |
| 147 | + { |
| 148 | + Debug.Log("Request sent with automatic trace headers"); |
| 149 | + } |
| 150 | + } |
| 151 | + catch (HttpRequestException e) |
| 152 | + { |
| 153 | + Debug.LogError($"Request failed: {e.Message}"); |
| 154 | + } |
| 155 | + } |
| 156 | +} |
| 157 | +``` |
| 158 | + |
| 159 | +Note that `SentryHttpMessageHandler` automatically adds the `sentry-trace` and `baggage` headers, so you don't need to do anything manually. |
| 160 | + |
| 161 | +### Using UnityWebRequest (Required for WebGL) |
| 162 | + |
| 163 | +For WebGL builds or if you prefer Unity's coroutine-based approach, you can manually add trace headers using Unity's `UnityWebRequest`: |
| 164 | + |
| 165 | +```csharp |
| 166 | +using System.Collections; |
| 167 | +using UnityEngine; |
| 168 | +using UnityEngine.Networking; |
| 169 | + |
| 170 | +public class TraceSender : MonoBehaviour |
| 171 | +{ |
| 172 | + IEnumerator SendRequest() |
| 173 | + { |
| 174 | + var jsonData = "{}"; |
| 175 | + using var www = UnityWebRequest.Post("https://example.com/api/action", jsonData, "application/json"); |
| 176 | + |
| 177 | + // Add Sentry trace headers to propagate the trace |
| 178 | + var traceHeader = SentrySdk.GetTraceHeader(); |
| 179 | + if (traceHeader != null) |
| 180 | + { |
| 181 | + www.SetRequestHeader("sentry-trace", traceHeader.ToString()); |
| 182 | + } |
| 183 | + |
| 184 | + var baggageHeader = SentrySdk.GetBaggage(); |
| 185 | + if (baggageHeader != null) |
| 186 | + { |
| 187 | + www.SetRequestHeader("baggage", baggageHeader.ToString()); |
| 188 | + } |
| 189 | + |
| 190 | + yield return www.SendWebRequest(); |
| 191 | + |
| 192 | + if (www.result == UnityWebRequest.Result.Success) |
| 193 | + { |
| 194 | + Debug.Log("Request sent with trace headers"); |
| 195 | + } |
| 196 | + } |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +This way, tracing information is propagated to the project receiving the message. If this project uses the Sentry .NET SDK, it will extract and save the tracing information for later use. |
| 201 | + |
| 202 | +The two services are now connected with your custom distributed tracing implementation. |
| 203 | + |
| 204 | +## Verification |
| 205 | + |
| 206 | +If you make outgoing requests from your project to other services, check if the headers `sentry-trace` and `baggage` are present in the request. If so, distributed tracing is working. |
0 commit comments