Skip to content

Commit 8bb0fa9

Browse files
Merge branch 'master' into smi/quick-start/react-router
2 parents 0bb8fc6 + 6d53857 commit 8bb0fa9

File tree

3 files changed

+213
-0
lines changed
  • docs/platforms/unity/tracing/trace-propagation/custom-instrumentation
  • platform-includes/distributed-tracing

3 files changed

+213
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
title: Custom Instrumentation
3+
sidebar_order: 40
4+
---
5+
6+
<PlatformContent includePath="distributed-tracing/custom-instrumentation/" />
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
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.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In order to use distributed tracing, follow the <PlatformLink to="/tracing/trace-propagation/custom-instrumentation/">custom instrumentation</PlatformLink> steps.

0 commit comments

Comments
 (0)