Skip to content

Commit 5467167

Browse files
authored
app start control (#196)
1 parent 3759c46 commit 5467167

16 files changed

+259
-21
lines changed

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartHandler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ private static Span CreateAppStartSpan(string name, string category)
9898
return _spanFactory.CreateAutoAppStartSpan(name, category, category.Equals(APP_START_CATEGORY));
9999
}
100100

101+
internal Span GetAppStartSpan() => _rootSpan;
102+
101103
internal void SubsystemRegistration()
102104
{
103105
_rootSpan = CreateAppStartSpan(UNITY_RUNTIME_SPAN_NAME, APP_START_CATEGORY);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace BugsnagUnityPerformance
2+
{
3+
internal class AppStartSpanControl : IAppStartSpanControl
4+
{
5+
private const string Prefix = "[AppStart/UnityRuntime]";
6+
private readonly Span _span;
7+
8+
public AppStartSpanControl(Span span) => _span = span;
9+
10+
public void SetType(string type)
11+
{
12+
_span?.TryUpdateAppStartSpan(type, Prefix);
13+
}
14+
15+
public void ClearType()
16+
{
17+
_span?.TryUpdateAppStartSpan(null, Prefix);
18+
}
19+
}
20+
}

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartSpanControl.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace BugsnagUnityPerformance
2+
{
3+
internal class SpanControlRegistry
4+
{
5+
private readonly AppStartHandler _appStartHandler;
6+
7+
public SpanControlRegistry(AppStartHandler handler)
8+
{
9+
_appStartHandler = handler;
10+
}
11+
12+
public T GetSpanControl<T>(ISpanQuery<T> query) where T : class
13+
{
14+
if (query is SpanType.AppStartQuery)
15+
{
16+
var span = _appStartHandler.GetAppStartSpan();
17+
return span != null ? new AppStartSpanControl(span) as T : null;
18+
}
19+
20+
return null;
21+
}
22+
}
23+
}

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/SpanControlRegistry.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformance.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class BugsnagPerformance
3232
private SystemMetricsCollector _systemMetricsCollector;
3333
private static List<WeakReference<Span>> _potentiallyOpenSpans = new List<WeakReference<Span>>();
3434
private Func<BugsnagNetworkRequestInfo, BugsnagNetworkRequestInfo> _networkRequestCallback;
35+
private static SpanControlRegistry _spanControlRegistry;
3536

3637
private static Dictionary<WeakReference<BugsnagUnityWebRequest>, Span> _networkSpans = new Dictionary<WeakReference<BugsnagUnityWebRequest>, Span>();
3738

@@ -44,7 +45,6 @@ internal class SceneLoadSpanContainer
4445
{
4546
public List<Span> Spans = new List<Span>();
4647
}
47-
4848
public static void Start(PerformanceConfiguration configuration)
4949
{
5050
#if BUGSNAG_DEBUG
@@ -122,6 +122,11 @@ public static Span StartNetworkSpan(string url, HttpVerb httpVerb, SpanOptions s
122122
return _sharedInstance._spanFactory.CreateManualNetworkSpan(url, httpVerb, spanOptions);
123123
}
124124

125+
public static T GetSpanControl<T>(ISpanQuery<T> query) where T : class
126+
{
127+
return _spanControlRegistry?.GetSpanControl(query);
128+
}
129+
125130
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
126131
private static void SubsystemRegistration()
127132
{
@@ -141,6 +146,7 @@ private BugsnagPerformance()
141146
_tracer = new Tracer(_sampler, _delivery, _frameMetricsCollector, _systemMetricsCollector);
142147
_spanFactory = new SpanFactory(_tracer.OnSpanEnd, _frameMetricsCollector);
143148
_appStartHandler = new AppStartHandler(_spanFactory);
149+
_spanControlRegistry = new SpanControlRegistry(_appStartHandler);
144150
_pValueUpdater = new PValueUpdater(_delivery, _sampler);
145151
}
146152

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/Span.cs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class Span : ISpanContext
3131
private const string MEMORY_SPACES_ART_SIZE_KEY = "bugsnag.system.memory.spaces.art.size";
3232
private const string MEMORY_SPACES_ART_USED_KEY = "bugsnag.system.memory.spaces.art.used";
3333
private const string MEMORY_SPACES_ART_MEAN_KEY = "bugsnag.system.memory.spaces.art.mean";
34+
private const string APP_START_NAME_KEY = "bugsnag.app_start.name";
3435
private const double CPU_METRICS_MIN_THRESHOLD = 0.0001;
3536

3637
public string Name { get; internal set; }
@@ -42,7 +43,7 @@ public class Span : ISpanContext
4243
public DateTimeOffset EndTime { get; internal set; }
4344
internal double samplingProbability { get; private set; }
4445
internal bool Ended;
45-
private object _endLock = new object();
46+
private readonly object _endLock = new object();
4647
private OnSpanEnd _onSpanEnd;
4748
internal bool IsAppStartSpan;
4849
internal bool WasDiscarded;
@@ -52,6 +53,8 @@ public class Span : ISpanContext
5253
private int _customAttributeCount;
5354
private int _maxCustomAttributes;
5455
internal bool IsFrozenFrameSpan;
56+
private readonly object _attributesLock = new object();
57+
5558

5659
public Span(string name, SpanKind kind, string id,
5760
string traceId, string parentSpanId, DateTimeOffset startTime,
@@ -190,12 +193,15 @@ public void UpdateSamplingProbability(double value)
190193
internal void SetAttributeInternal(string key, bool value) => SetAttributeWithoutChecks(key, value);
191194
private void SetAttributeWithoutChecks(string key, object value)
192195
{
193-
if (value == null)
196+
lock (_attributesLock)
194197
{
195-
_attributes.Remove(key);
196-
return;
198+
if (value == null)
199+
{
200+
_attributes.Remove(key);
201+
return;
202+
}
203+
_attributes[key] = value;
197204
}
198-
_attributes[key] = value;
199205
}
200206

201207

@@ -215,31 +221,57 @@ private void SetAttributeWithChecks(string key, object value)
215221
MainThreadDispatchBehaviour.LogWarning($"Attempting to set attribute: {key} on span: {Name} after the span has ended.");
216222
return;
217223
}
218-
219-
if (_attributes.ContainsKey(key))
224+
lock (_attributesLock)
220225
{
221-
if (value == null)
226+
if (_attributes.ContainsKey(key))
222227
{
223-
_attributes.Remove(key);
224-
_customAttributeCount--;
228+
if (value == null)
229+
{
230+
_attributes.Remove(key);
231+
_customAttributeCount--;
232+
}
233+
else
234+
{
235+
_attributes[key] = value;
236+
}
237+
return;
225238
}
226-
else
239+
240+
if (_customAttributeCount >= _maxCustomAttributes)
227241
{
228-
_attributes[key] = value;
242+
DroppedAttributesCount++;
243+
return;
229244
}
230-
return;
245+
_attributes[key] = value;
246+
_customAttributeCount++;
231247
}
248+
}
232249

233-
if (_customAttributeCount >= _maxCustomAttributes)
250+
internal bool TryUpdateAppStartSpan(string? type, string namePrefix = "[AppStart/UnityRuntime]")
251+
{
252+
lock (_endLock)
234253
{
235-
DroppedAttributesCount++;
236-
return;
254+
if (Ended)
255+
{
256+
return false;
257+
}
258+
Name = type == null ? namePrefix : namePrefix + type;
259+
lock (_attributesLock)
260+
{
261+
if (type == null) _attributes.Remove(APP_START_NAME_KEY);
262+
else _attributes[APP_START_NAME_KEY] = type;
263+
}
264+
return true;
237265
}
238-
_attributes[key] = value;
239-
_customAttributeCount++;
240266
}
241267

242-
internal Dictionary<string, object> GetAttributes() => new Dictionary<string, object>(_attributes);
268+
internal Dictionary<string, object> GetAttributes()
269+
{
270+
lock (_attributesLock)
271+
{
272+
return new Dictionary<string, object>(_attributes);
273+
}
274+
}
243275

244276
internal void SetCallbackComplete()
245277
{
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace BugsnagUnityPerformance
2+
{
3+
public interface IAppStartSpanControl
4+
{
5+
void SetType(string type);
6+
void ClearType();
7+
}
8+
9+
public interface ISpanQuery<T> { }
10+
11+
public static class SpanType
12+
{
13+
public static readonly ISpanQuery<IAppStartSpanControl> AppStart = new AppStartQuery();
14+
internal sealed class AppStartQuery : ISpanQuery<IAppStartSpanControl> { }
15+
}
16+
}

BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/SpanControl.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
## TBD
44

5+
### Additions
6+
7+
- Allow app start span customisation. [#196](https://github.com/bugsnag/bugsnag-unity-performance/pull/196)
8+
59
### Bug Fixes
610

7-
- Fix issue where CPU metrics where reported when no valid CPU data was avaliable. [#193](https://github.com/bugsnag/bugsnag-unity-performance/pull/193)
11+
- Fix issue where CPU metrics were reported when no valid CPU data was available. [#193](https://github.com/bugsnag/bugsnag-unity-performance/pull/193)
812

913
## v1.10.0 (2025-06-03)
1014

0 commit comments

Comments
 (0)