From c707c2f21f6c0cee8addff156a4723314bd84023 Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 9 Sep 2024 11:33:08 +0100 Subject: [PATCH 1/8] Use the latest v9 Maze Runner --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 8923b55..49b1142 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ gem 'cocoapods' unless Gem.win_platform? # Use official Maze Runner release - gem 'bugsnag-maze-runner', '~> 9.13.0' + gem 'bugsnag-maze-runner', '~> 9.0' # Use a specific Maze Runner branch #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'master' From e7e2f8e8e548a257df51b4fe69bde84230b9656a Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Fri, 13 Sep 2024 15:45:47 +0200 Subject: [PATCH 2/8] add TracePropagationUrls to the configuration window (#136) --- .../Editor/BugsnagPerformanceEditor.cs | 3 +- .../BugsnagPerformanceSettingsObject.cs | 41 ++++++++++++++++--- CHANGELOG.md | 6 +++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs index 2ded04b..bd4b52a 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs @@ -101,10 +101,9 @@ private void DrawSettingsEditorWindow() EditorGUIUtility.labelWidth = 200; EditorGUILayout.PropertyField(so.FindProperty("Endpoint")); - EditorGUILayout.PropertyField(so.FindProperty("AutoInstrumentAppStart")); EditorGUILayout.PropertyField(so.FindProperty("ServiceName")); - + EditorGUILayout.PropertyField(so.FindProperty("TracePropagationUrls")); EditorGUI.indentLevel--; so.ApplyModifiedProperties(); EditorUtility.SetDirty(settings); diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs index a5b646a..9384858 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text.RegularExpressions; using UnityEngine; namespace BugsnagUnityPerformance @@ -26,6 +27,7 @@ public class BugsnagPerformanceSettingsObject : ScriptableObject public int VersionCode = -1; public string BundleVersion; public string ServiceName; + public string[] TracePropagationUrls; public bool GenerateAnonymousId = true; @@ -45,8 +47,7 @@ public static PerformanceConfiguration LoadConfiguration() internal PerformanceConfiguration GetConfig() { - PerformanceConfiguration config = null; - + PerformanceConfiguration config; if (UseNotifierSettings && NotifierConfigAvaliable()) { config = GetSettingsFromNotifier(out StartAutomaticallyAtLaunch); @@ -56,15 +57,43 @@ internal PerformanceConfiguration GetConfig() config = GetStandaloneConfig(); } - config.AutoInstrumentAppStart = AutoInstrumentAppStart; + GetCommonConfigValues(config); + + return config; + } + private void GetCommonConfigValues(PerformanceConfiguration config) + { + config.AutoInstrumentAppStart = AutoInstrumentAppStart; config.Endpoint = Endpoint; + if(TracePropagationUrls != null && TracePropagationUrls.Length > 0) + { + config.TracePropagationUrls = ConvertTracePropagationUrls(TracePropagationUrls); + } + config.ServiceName = ServiceName; + } - config.GenerateAnonymousId = GenerateAnonymousId; + private Regex[] ConvertTracePropagationUrls(string[] urls) + { + if (urls == null) + { + return null; + } - config.ServiceName = ServiceName; + var regexes = new Regex[urls.Length]; + for (int i = 0; i < urls.Length; i++) + { + try + { + regexes[i] = new Regex(urls[i]); + } + catch (Exception e) + { + Debug.LogWarning("Error converting TracePropagationUrl " + urls[i] + " into a regex pattern in settings object: " + e.Message); + } + } - return config; + return regexes; } private PerformanceConfiguration GetStandaloneConfig() diff --git a/CHANGELOG.md b/CHANGELOG.md index e31d55a..136f8dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## TBD + +### Additions + +- Add TracePropagationUrls to the configuration window. [#136](https://github.com/bugsnag/bugsnag-unity-performance/pull/136) + ## v1.5.1 (2024-09-09) ### Bug Fixes From a85615eb42a53a3851a81f7587443141f66fd9e2 Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Fri, 13 Sep 2024 15:46:00 +0200 Subject: [PATCH 3/8] wait for sampling request to finish (#135) --- .../Scripts/Scenarios/Spans/ConfiguredSamplingRate1.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Spans/ConfiguredSamplingRate1.cs b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Spans/ConfiguredSamplingRate1.cs index c06c736..0d776bc 100644 --- a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Spans/ConfiguredSamplingRate1.cs +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Spans/ConfiguredSamplingRate1.cs @@ -14,6 +14,12 @@ public override void PreparePerformanceConfig(string apiKey, string host) public override void Run() { base.Run(); + StartCoroutine(DoSpans()); + } + + private IEnumerator DoSpans() + { + yield return new WaitForSeconds(4); BugsnagPerformance.StartSpan("ManualSpan1").End(); BugsnagPerformance.StartSpan("ManualSpan2").End(); BugsnagPerformance.StartSpan("ManualSpan3").End(); From 817c308adee8d22fbb754b355c6879cec7c760b1 Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Mon, 23 Sep 2024 13:42:45 +0200 Subject: [PATCH 4/8] configurable limits on custom attributes (#137) --- .../Editor/BugsnagPerformanceEditor.cs | 19 ++- .../Scripts/Internal/AppStartHandler.cs | 10 +- .../Scripts/Internal/CacheManager.cs | 11 +- .../Scripts/Internal/Delivery.cs | 16 +- .../Internal/MainThreadDispatchBehaviour.cs | 8 + .../Scripts/Internal/PValueUpdater.cs | 10 +- .../Scripts/Internal/PersistentState.cs | 6 +- .../Scripts/Internal/SpanFactory.cs | 18 ++- .../Scripts/Internal/TracePayload.cs | 9 +- .../Scripts/Internal/Tracer.cs | 36 ++--- .../Scripts/Models/SpanModel.cs | 150 ++++++++++++------ .../Scripts/Public/BugsnagPerformance.cs | 4 +- .../BugsnagPerformanceSettingsObject.cs | 22 ++- .../Public/PerformanceConfiguration.cs | 60 ++++++- .../BugsnagPerformance/Scripts/Public/Span.cs | 29 +++- .../Assets/UnitTests/ConfigurationTests.cs | 74 ++++++++- .../Assets/UnitTests/SamplerTests.cs | 24 ++- .../Assets/UnitTests/TracePayloadTests.cs | 7 +- features/custom_attributes.feature | 41 +++++ .../mazerunner/Assets/Scenes/MainScene.unity | 27 ++++ .../Attributes/CustomAttributeLimits.cs | 54 +++++++ .../Attributes/CustomAttributeLimits.cs.meta | 11 ++ .../Attributes/DefaultAttributeLimits.cs | 51 ++++++ .../Attributes/DefaultAttributeLimits.cs.meta | 11 ++ 24 files changed, 571 insertions(+), 137 deletions(-) create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs.meta create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs create mode 100644 features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs.meta diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs index bd4b52a..85a1bf5 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Editor/BugsnagPerformanceEditor.cs @@ -100,8 +100,11 @@ private void DrawSettingsEditorWindow() } EditorGUIUtility.labelWidth = 200; - EditorGUILayout.PropertyField(so.FindProperty("Endpoint")); + DrawIntPropertyWithDefault(so, "AttributeArrayLengthLimit", "AttributeArrayLengthLimit", PerformanceConfiguration.DEFAULT_ATTRIBUTE_ARRAY_LENGTH_LIMIT); + DrawIntPropertyWithDefault(so, "AttributeCountLimit", "AttributeCountLimit", PerformanceConfiguration.DEFAULT_ATTRIBUTE_COUNT_LIMIT); + DrawIntPropertyWithDefault(so, "AttributeStringValueLimit", "AttributeStringValueLimit", PerformanceConfiguration.DEFAULT_ATTRIBUTE_STRING_VALUE_LIMIT); EditorGUILayout.PropertyField(so.FindProperty("AutoInstrumentAppStart")); + EditorGUILayout.PropertyField(so.FindProperty("Endpoint")); EditorGUILayout.PropertyField(so.FindProperty("ServiceName")); EditorGUILayout.PropertyField(so.FindProperty("TracePropagationUrls")); EditorGUI.indentLevel--; @@ -109,6 +112,20 @@ private void DrawSettingsEditorWindow() EditorUtility.SetDirty(settings); } + private void DrawIntPropertyWithDefault(SerializedObject so, string propertyName, string label, int defaultValue) + { + var property = so.FindProperty(propertyName); + var isValueSet = property.intValue > 0; + if (!isValueSet) + { + property.intValue = EditorGUILayout.IntField(label, isValueSet ? property.intValue : defaultValue); + } + else + { + EditorGUILayout.PropertyField(property); + } + } + private void DrawStandaloneSettings(SerializedObject so, BugsnagPerformanceSettingsObject settings) { EditorGUIUtility.labelWidth = 70; diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartHandler.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartHandler.cs index 3078ddd..cbbb4b6 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartHandler.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/AppStartHandler.cs @@ -11,12 +11,10 @@ public class AppStartHandler : IPhasedStartup private static Span _loadAssembliesSpan; private static Span _splashScreenSpan; private static Span _firstSceneSpan; - + private PerformanceConfiguration _config; private static bool _appStartComplete; private static DateTimeOffset? _defaultAppStartEndTime = null; - private static AutoInstrumentAppStartSetting _appStartSetting; - private static SpanFactory _spanFactory; internal AppStartHandler(SpanFactory spanFactory) @@ -26,8 +24,8 @@ internal AppStartHandler(SpanFactory spanFactory) public void Configure(PerformanceConfiguration config) { - _appStartSetting = config.AutoInstrumentAppStart; - if (_appStartSetting == AutoInstrumentAppStartSetting.OFF) + _config = config; + if (_config.AutoInstrumentAppStart == AutoInstrumentAppStartSetting.OFF) { AbortAppStartSpans(); } @@ -55,7 +53,7 @@ private void AbortAppStartSpans() public void Start() { - if (_appStartSetting == AutoInstrumentAppStartSetting.FULL) + if (_config.AutoInstrumentAppStart == AutoInstrumentAppStartSetting.FULL) { MainThreadDispatchBehaviour.Instance().Enqueue(CheckForAppStartCompletion()); } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/CacheManager.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/CacheManager.cs index e02d258..5af893a 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/CacheManager.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/CacheManager.cs @@ -7,8 +7,7 @@ namespace BugsnagUnityPerformance { public class CacheManager : IPhasedStartup { - private int _maxPersistedBatchAgeSeconds; - private bool _deviceAutoGenerateId; + private PerformanceConfiguration _config; private string _cacheDirectory; private string _deviceidFilePath; private string _persistentStateFilePath; @@ -32,9 +31,7 @@ public CacheManager(string basePath) public void Configure(PerformanceConfiguration config) { - _maxPersistedBatchAgeSeconds = config.MaxPersistedBatchAgeSeconds; - _deviceAutoGenerateId = config.GenerateAnonymousId; - + _config = config; } public void Start() @@ -50,7 +47,7 @@ public string GetDeviceId() try { //if generateAnonymousId is true then store/report/generate else don't - if (_deviceAutoGenerateId) + if (_config.GenerateAnonymousId) { if (File.Exists(_deviceidFilePath)) { @@ -138,7 +135,7 @@ private void RemoveExpiredPayloads() { var creationTime = File.GetCreationTimeUtc(path); var timeSinceCreation = DateTimeOffset.UtcNow - creationTime; - if (timeSinceCreation.TotalSeconds > _maxPersistedBatchAgeSeconds) + if (timeSinceCreation.TotalSeconds > _config.MaxPersistedBatchAgeSeconds) { DeleteFile(path); } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Delivery.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Delivery.cs index 3181cda..f87f2f2 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Delivery.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Delivery.cs @@ -14,13 +14,11 @@ namespace BugsnagUnityPerformance internal class Delivery : IPhasedStartup { - private string _endpoint; - private string _apiKey; - private bool _isFixedSamplingProbability = false; private OnProbabilityChanged _onProbabilityChanged; private bool _flushingCache; private ResourceModel _resourceModel; private CacheManager _cacheManager; + private PerformanceConfiguration _config; private enum RequestResult { @@ -57,9 +55,7 @@ public Delivery(ResourceModel resourceModel, CacheManager cacheManager, OnProbab public void Configure(PerformanceConfiguration config) { - _endpoint = config.GetEndpoint(); - _apiKey = config.ApiKey; - _isFixedSamplingProbability = config.IsFixedSamplingProbability; + _config = config; } public void Start() @@ -69,7 +65,7 @@ public void Start() public void Deliver(List batch) { - var payload = new TracePayload(_resourceModel, batch, _isFixedSamplingProbability); + var payload = new TracePayload(_resourceModel, batch, _config.IsFixedSamplingProbability, _config.AttributeArrayLengthLimit, _config.AttributeStringValueLimit); MainThreadDispatchBehaviour.Instance().Enqueue(PushToServer(payload, OnTraceDeliveryCompleted)); } @@ -99,7 +95,7 @@ public void DeliverPValueRequest(OnServerResponse onResponse = null) { onResponse = OnPValueRequestCompleted; } - var payload = new TracePayload(_resourceModel, null, false); + var payload = TracePayload.GetTracePayloadForPValueRequest(_resourceModel); MainThreadDispatchBehaviour.Instance().Enqueue(PushToServer(payload, onResponse)); } @@ -134,13 +130,13 @@ private IEnumerator PushToServer(TracePayload payload, OnServerResponse onServer yield break; } - using (var req = new UnityWebRequest(_endpoint)) + using (var req = new UnityWebRequest(_config.Endpoint)) { foreach (var header in payload.Headers) { req.SetRequestHeader(header.Key, header.Value); } - req.SetRequestHeader("Bugsnag-Api-Key", _apiKey); + req.SetRequestHeader("Bugsnag-Api-Key", _config.ApiKey); req.SetRequestHeader("Content-Type", "application/json"); req.SetRequestHeader("Bugsnag-Integrity", "sha1 " + Hash(body)); req.SetRequestHeader("Bugsnag-Sent-At", DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)); diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/MainThreadDispatchBehaviour.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/MainThreadDispatchBehaviour.cs index 87a810a..701da41 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/MainThreadDispatchBehaviour.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/MainThreadDispatchBehaviour.cs @@ -72,6 +72,14 @@ public void Enqueue(IEnumerator action) } } + public void LogWarning(string msg) + { + Enqueue(() => + { + Debug.LogWarning(msg); + }); + } + /// /// Locks the queue and adds the Action to the queue /// diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PValueUpdater.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PValueUpdater.cs index dd65218..a6e5b8e 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PValueUpdater.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PValueUpdater.cs @@ -7,11 +7,10 @@ namespace BugsnagUnityPerformance { internal class PValueUpdater : IPhasedStartup { + private PerformanceConfiguration _config; private Delivery _delivery; private Sampler _sampler; private DateTime _pValueTimeout; - private float _pValueTimeoutSeconds; - private float _pValueCheckIntervalSeconds; public bool IsConfigured { get; private set; } public PValueUpdater(Delivery delivery, Sampler sampler) @@ -23,8 +22,7 @@ public PValueUpdater(Delivery delivery, Sampler sampler) public void Configure(PerformanceConfiguration config) { - _pValueTimeoutSeconds = config.PValueTimeoutSeconds; - _pValueCheckIntervalSeconds = config.PValueCheckIntervalSeconds; + _config = config; IsConfigured = true; } @@ -45,13 +43,13 @@ private IEnumerator CheckPValue() _delivery.DeliverPValueRequest(OnPValueRequestCompleted); } - yield return new WaitForSeconds(_pValueCheckIntervalSeconds); + yield return new WaitForSeconds(_config.PValueCheckIntervalSeconds); } } private void markPValueUpdated() { - _pValueTimeout = DateTime.Now.AddSeconds(_pValueTimeoutSeconds); + _pValueTimeout = DateTime.Now.AddSeconds(_config.PValueTimeoutSeconds); } private void OnPValueRequestCompleted(TracePayload payload, UnityWebRequest req, double newProbability) diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PersistentState.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PersistentState.cs index ee54ae6..33f25e6 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PersistentState.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/PersistentState.cs @@ -1,5 +1,5 @@ -using System; -using System.IO; +using System; +using System.IO; using System.Threading; using Newtonsoft.Json; using UnityEngine; @@ -94,7 +94,7 @@ private void Save() } catch (Exception e) { - Debug.Log("Failed to save persistent state: " + e); + MainThreadDispatchBehaviour.Instance().LogWarning("Failed to save persistent state: " + e); } finally { diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/SpanFactory.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/SpanFactory.cs index 2beb13f..8083289 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/SpanFactory.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/SpanFactory.cs @@ -7,7 +7,7 @@ namespace BugsnagUnityPerformance { - internal class SpanFactory + internal class SpanFactory : IPhasedStartup { [ThreadStatic] @@ -25,12 +25,24 @@ internal class SpanFactory private WaitForSeconds _connectionPollRate = new WaitForSeconds(1); + private int _maxCustomAttributes = PerformanceConfiguration.DEFAULT_ATTRIBUTE_COUNT_LIMIT; + public SpanFactory(OnSpanEnd onSpanEnd) { _onSpanEnd = onSpanEnd; MainThreadDispatchBehaviour.Instance().StartCoroutine(GetConnectionType()); } + public void Configure(PerformanceConfiguration config) + { + // private property used here as this factory can be accessed before configure is called + _maxCustomAttributes = config.AttributeCountLimit; + } + + public void Start() + { + } + private string GetNewTraceId() { byte[] byteArray = new byte[16]; @@ -95,7 +107,7 @@ private Span CreateSpan(string name, SpanKind kind, SpanOptions spanOptions) } } - var newSpan = new Span(name, kind, spanId, traceId, parentSpanId, spanOptions.StartTime, spanOptions.IsFirstClass, _onSpanEnd); + var newSpan = new Span(name, kind, spanId, traceId, parentSpanId, spanOptions.StartTime, spanOptions.IsFirstClass, _onSpanEnd, _maxCustomAttributes); if (spanOptions.MakeCurrentContext) { AddToContextStack(newSpan); @@ -240,5 +252,7 @@ internal Span CreateAutoAppStartSpan(string name, string category) span.IsAppStartSpan = true; return span; } + + } } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/TracePayload.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/TracePayload.cs index 4944619..c68a5e9 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/TracePayload.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/TracePayload.cs @@ -20,7 +20,7 @@ public class TracePayload private string _jsonbody; - public TracePayload(ResourceModel resourceModel, List spans, bool isFixedSamplingProbability) + public TracePayload(ResourceModel resourceModel, List spans, bool isFixedSamplingProbability, int attributeArrayLengthLimit, int attributeStringValueLimit ) { _resourceModel = resourceModel; if (spans != null && spans.Count > 0) @@ -29,7 +29,7 @@ public TracePayload(ResourceModel resourceModel, List spans, bool isFixedS PayloadId = Guid.NewGuid().ToString(); foreach (var span in spans) { - _spans.Add(new SpanModel(span)); + _spans.Add(new SpanModel(span, attributeArrayLengthLimit, attributeStringValueLimit)); } SamplingHistogram = CalculateSamplingHistorgram(spans); if(!isFixedSamplingProbability) @@ -46,6 +46,11 @@ public TracePayload(ResourceModel resourceModel, List spans, bool isFixedS } } + internal static TracePayload GetTracePayloadForPValueRequest(ResourceModel resourceModel) + { + return new TracePayload(resourceModel, null, false, 0, 0); + } + private TracePayload(Dictionary headers, string cachedJson, string payloadId) { PayloadId = payloadId; diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Tracer.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Tracer.cs index 8acb229..03ae9f1 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Tracer.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Tracer.cs @@ -8,33 +8,17 @@ namespace BugsnagUnityPerformance { internal class Tracer : IPhasedStartup { - private int _maxBatchSize = 100; - - private float _maxBatchAgeSeconds = 30f; - + private PerformanceConfiguration _config; private List _finishedSpanQueue = new List(); - private List> _preStartSpans = new List>(); - private object _queueLock = new object(); - private object _prestartLock = new object(); - private WaitForSeconds _workerPollFrequency = new WaitForSeconds(1); - private DateTimeOffset _lastBatchSendTime = DateTimeOffset.UtcNow; - private Sampler _sampler; - private Delivery _delivery; - private bool _started; - private static AutoInstrumentAppStartSetting _appStartSetting; - - private List> _onSpanEndCallbacks; - - public Tracer(Sampler sampler, Delivery delivery) { _sampler = sampler; @@ -43,10 +27,7 @@ public Tracer(Sampler sampler, Delivery delivery) public void Configure(PerformanceConfiguration config) { - _onSpanEndCallbacks = config.GetOnSpanEndCallbacks(); - _maxBatchSize = config.MaxBatchSize; - _maxBatchAgeSeconds = config.MaxBatchAgeSeconds; - _appStartSetting = config.AutoInstrumentAppStart; + _config = config; } public void Start() @@ -75,7 +56,7 @@ private void FlushPreStartSpans() { if (weakRef.TryGetTarget(out var span)) { - if (span.IsAppStartSpan && _appStartSetting == AutoInstrumentAppStartSetting.OFF) + if (span.IsAppStartSpan && _config.AutoInstrumentAppStart == AutoInstrumentAppStartSetting.OFF) { continue; } @@ -114,10 +95,11 @@ public void OnSpanEnd(Span span) public void RunOnEndCallbacks(Span span) { - if (!span.WasDiscarded && _onSpanEndCallbacks != null && _onSpanEndCallbacks.Count > 0) + var callbacks = _config.GetOnSpanEndCallbacks(); + if (!span.WasDiscarded && callbacks != null && callbacks.Count > 0) { var startTime = DateTimeOffset.UtcNow; - foreach (var callback in _onSpanEndCallbacks) + foreach (var callback in callbacks) { try { @@ -129,7 +111,7 @@ public void RunOnEndCallbacks(Span span) } catch (Exception e) { - Debug.LogError("Error running OnSpanEndCallback: " + e.Message); + MainThreadDispatchBehaviour.Instance().LogWarning("Error running OnSpanEndCallback: " + e.Message); } } var duration = DateTimeOffset.UtcNow - startTime; @@ -203,12 +185,12 @@ private void DeliverBatch() private bool BatchSizeLimitReached() { - return _finishedSpanQueue.Count >= _maxBatchSize; + return _finishedSpanQueue.Count >= _config.MaxBatchSize; } private bool BatchDue() { - return (DateTimeOffset.UtcNow - _lastBatchSendTime).TotalSeconds > _maxBatchAgeSeconds; + return (DateTimeOffset.UtcNow - _lastBatchSendTime).TotalSeconds > _config.MaxBatchAgeSeconds; } } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Models/SpanModel.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Models/SpanModel.cs index 7779d4f..f1e6eb4 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Models/SpanModel.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Models/SpanModel.cs @@ -3,71 +3,117 @@ namespace BugsnagUnityPerformance { - internal class SpanModel -{ - static readonly DateTimeOffset _unixStart = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); - - public string name; - public int kind; - public string spanId; - public string traceId; - public string startTimeUnixNano; - public string endTimeUnixNano; - public string parentSpanId; - public List attributes = new List(); - - public SpanModel(Span span) + internal class SpanModel { - name = span.Name; - kind = (int)span.Kind; - spanId = span.SpanId; - traceId = span.TraceId.Replace("-", string.Empty); - parentSpanId = span.ParentSpanId; - startTimeUnixNano = GetNanoSeconds(span.StartTime); - endTimeUnixNano = GetNanoSeconds(span.EndTime); + private const int MAXIMUM_ATTRIBUTE_KEY_LENGTH_LIMIT = 128; + static readonly DateTimeOffset _unixStart = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero); + public string name; + public int kind; + public string spanId; + public string traceId; + public string startTimeUnixNano; + public string endTimeUnixNano; + public string parentSpanId; + public List attributes = new List(); - foreach (var attr in span.GetAttributes()) + public SpanModel(Span span, int attributeArrayLengthLimit, int attributeStringValueLimit) { - if (attr.Value is string[] stringArray) - { - attributes.Add(new AttributeModel(attr.Key, new AttributeStringArrayValueModel(stringArray))); - } - else if (attr.Value is long[] intArray) - { - attributes.Add(new AttributeModel(attr.Key, new AttributeIntArrayValueModel(intArray))); - } - else if (attr.Value is bool[] boolArray) - { - attributes.Add(new AttributeModel(attr.Key, new AttributeBoolArrayValueModel(boolArray))); - } - else if (attr.Value is double[] doubleArray) - { - attributes.Add(new AttributeModel(attr.Key, new AttributeDoubleArrayValueModel(doubleArray))); - } - else if (attr.Value is string strValue) + name = span.Name; + kind = (int)span.Kind; + spanId = span.SpanId; + traceId = span.TraceId.Replace("-", string.Empty); + parentSpanId = span.ParentSpanId; + startTimeUnixNano = GetNanoSeconds(span.StartTime); + endTimeUnixNano = GetNanoSeconds(span.EndTime); + + foreach (var attr in span.GetAttributes()) { - attributes.Add(new AttributeModel(attr.Key, new AttributeStringValueModel(strValue))); + if (string.IsNullOrEmpty(attr.Key) || attr.Value == null) + { + continue; + } + + if (attr.Key.Length > MAXIMUM_ATTRIBUTE_KEY_LENGTH_LIMIT) + { + span.DroppedAttributesCount++; + continue; + } + + if (attr.Value is string[] stringArray) + { + var truncatedStringArray = TruncateArrayIfNeeded(stringArray, attributeArrayLengthLimit, attr.Key, span.Name); + var valueLengthCheckedStringArray = new string[truncatedStringArray.Length]; + for (int i = 0; i < truncatedStringArray.Length; i++) + { + valueLengthCheckedStringArray[i] = TruncateStringIfNeeded(truncatedStringArray[i], attributeStringValueLimit); + } + attributes.Add(new AttributeModel(attr.Key, new AttributeStringArrayValueModel(valueLengthCheckedStringArray))); + } + else if (attr.Value is long[] intArray) + { + var truncatedIntArray = TruncateArrayIfNeeded(intArray, attributeArrayLengthLimit, attr.Key, span.Name); + attributes.Add(new AttributeModel(attr.Key, new AttributeIntArrayValueModel(truncatedIntArray))); + } + else if (attr.Value is bool[] boolArray) + { + var truncatedBoolArray = TruncateArrayIfNeeded(boolArray, attributeArrayLengthLimit, attr.Key, span.Name); + attributes.Add(new AttributeModel(attr.Key, new AttributeBoolArrayValueModel(truncatedBoolArray))); + } + else if (attr.Value is double[] doubleArray) + { + var truncatedDoubleArray = TruncateArrayIfNeeded(doubleArray, attributeArrayLengthLimit, attr.Key, span.Name); + attributes.Add(new AttributeModel(attr.Key, new AttributeDoubleArrayValueModel(truncatedDoubleArray))); + } + else if (attr.Value is string strValue) + { + attributes.Add(new AttributeModel(attr.Key, new AttributeStringValueModel(TruncateStringIfNeeded(strValue, attributeStringValueLimit)))); + } + else if (attr.Value is long longValue) + { + attributes.Add(new AttributeModel(attr.Key, new AttributeIntValueModel(longValue))); + } + else if (attr.Value is bool boolValue) + { + attributes.Add(new AttributeModel(attr.Key, new AttributeBoolValueModel(boolValue))); + } + else if (attr.Value is double doubleValue) + { + attributes.Add(new AttributeModel(attr.Key, new AttributeDoubleValueModel(doubleValue))); + } } - else if (attr.Value is long intValue) + + if (span.DroppedAttributesCount > 0) { - attributes.Add(new AttributeModel(attr.Key, new AttributeIntValueModel(intValue))); + attributes.Add(new AttributeModel("dropped_attributes_count", new AttributeIntValueModel(span.DroppedAttributesCount))); } - else if (attr.Value is bool boolValue) + } + + private T[] TruncateArrayIfNeeded(T[] array, int limit, string key, string spanName) + { + if (array.Length > limit) { - attributes.Add(new AttributeModel(attr.Key, new AttributeBoolValueModel(boolValue))); + var truncatedArray = new T[limit]; + Array.Copy(array, truncatedArray, limit); + return truncatedArray; } - else if (attr.Value is double doubleValue) + return array; + } + + private string TruncateStringIfNeeded(string strValue, int limit) + { + if (strValue.Length > limit) { - attributes.Add(new AttributeModel(attr.Key, new AttributeDoubleValueModel(doubleValue))); + int truncatedLength = strValue.Length - limit; + return strValue.Substring(0, limit) + $"*** {truncatedLength} CHARS TRUNCATED"; } + return strValue; } - } - private string GetNanoSeconds(DateTimeOffset time) - { - var duration = time - _unixStart; - return (duration.Ticks * 100).ToString(); + private string GetNanoSeconds(DateTimeOffset time) + { + var duration = time - _unixStart; + return (duration.Ticks * 100).ToString(); + } } -} } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformance.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformance.cs index f0d9c22..21bc747 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformance.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformance.cs @@ -51,7 +51,7 @@ public static void Start(PerformanceConfiguration configuration) { if (IsStarted) { - Debug.LogWarning(ALREADY_STARTED_WARNING); + MainThreadDispatchBehaviour.Instance().LogWarning(ALREADY_STARTED_WARNING); return; } IsStarted = true; @@ -141,6 +141,7 @@ private BugsnagPerformance() private void Configure(PerformanceConfiguration config) { + _spanFactory.Configure(config); _networkRequestCallback = config.NetworkRequestCallback; _cacheManager.Configure(config); _persistentState.Configure(config); @@ -158,6 +159,7 @@ private void Configure(PerformanceConfiguration config) private void Start() { // The ordering of Start() must be carefully curated. + _spanFactory.Start(); _cacheManager.Start(); _persistentState.Start(); _delivery.Start(); diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs index 9384858..0604693 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/BugsnagPerformanceSettingsObject.cs @@ -28,6 +28,11 @@ public class BugsnagPerformanceSettingsObject : ScriptableObject public string BundleVersion; public string ServiceName; public string[] TracePropagationUrls; + public int AttributeStringValueLimit; + public int AttributeArrayLengthLimit; + public int AttributeCountLimit; + + public bool GenerateAnonymousId = true; @@ -66,11 +71,24 @@ private void GetCommonConfigValues(PerformanceConfiguration config) { config.AutoInstrumentAppStart = AutoInstrumentAppStart; config.Endpoint = Endpoint; - if(TracePropagationUrls != null && TracePropagationUrls.Length > 0) + if (TracePropagationUrls != null && TracePropagationUrls.Length > 0) { config.TracePropagationUrls = ConvertTracePropagationUrls(TracePropagationUrls); } config.ServiceName = ServiceName; + if (AttributeStringValueLimit > 0) + { + config.AttributeStringValueLimit = AttributeStringValueLimit; + } + if (AttributeArrayLengthLimit > 0) + { + config.AttributeArrayLengthLimit = AttributeArrayLengthLimit; + } + if (AttributeCountLimit > 0) + { + config.AttributeCountLimit = AttributeCountLimit; + } + } private Regex[] ConvertTracePropagationUrls(string[] urls) @@ -89,7 +107,7 @@ private Regex[] ConvertTracePropagationUrls(string[] urls) } catch (Exception e) { - Debug.LogWarning("Error converting TracePropagationUrl " + urls[i] + " into a regex pattern in settings object: " + e.Message); + MainThreadDispatchBehaviour.Instance().LogWarning("Error converting TracePropagationUrl " + urls[i] + " into a regex pattern in settings object: " + e.Message); } } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/PerformanceConfiguration.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/PerformanceConfiguration.cs index 3996ea2..9cba1dd 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/PerformanceConfiguration.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/PerformanceConfiguration.cs @@ -4,6 +4,7 @@ using UnityEngine; [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Tests")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BugsnagPerformanceEditor")] namespace BugsnagUnityPerformance { @@ -12,6 +13,12 @@ public class PerformanceConfiguration private const string LEGACY_DEFAULT_ENDPOINT = "https://otlp.bugsnag.com/v1/traces"; private const string DEFAULT_ENDPOINT = "https://{0}.otlp.bugsnag.com/v1/traces"; + internal const int DEFAULT_ATTRIBUTE_STRING_VALUE_LIMIT = 1024; + private const int MAXIMUM_ATTRIBUTE_STRING_VALUE_LIMIT = 10000; + internal const int DEFAULT_ATTRIBUTE_ARRAY_LENGTH_LIMIT = 1000; + private const int MAXIMUM_ATTRIBUTE_ARRAY_LENGTH_LIMIT = 10000; + internal const int DEFAULT_ATTRIBUTE_COUNT_LIMIT = 128; + private const int MAXIMUM_ATTRIBUTE_COUNT_LIMIT = 1000; public PerformanceConfiguration(string apiKey) { @@ -27,6 +34,57 @@ public PerformanceConfiguration(string apiKey) internal float PValueCheckIntervalSeconds = 30f; //Public config + private int _attributeStringValueLimit = DEFAULT_ATTRIBUTE_STRING_VALUE_LIMIT; + public int AttributeStringValueLimit + { + get => _attributeStringValueLimit; + set + { + if (value > 0 && value <= MAXIMUM_ATTRIBUTE_STRING_VALUE_LIMIT) + { + _attributeStringValueLimit = value; + } + else + { + MainThreadDispatchBehaviour.Instance().LogWarning("AttributeStringValueLimit must be greater than 0 and no larger than " + MAXIMUM_ATTRIBUTE_STRING_VALUE_LIMIT); + } + } + } + + private int _attributeArrayLengthLimit = DEFAULT_ATTRIBUTE_ARRAY_LENGTH_LIMIT; + public int AttributeArrayLengthLimit + { + get => _attributeArrayLengthLimit; + set + { + if (value > 0 && value <= MAXIMUM_ATTRIBUTE_ARRAY_LENGTH_LIMIT) + { + _attributeArrayLengthLimit = value; + } + else + { + MainThreadDispatchBehaviour.Instance().LogWarning("AttributeArrayLengthLimit must be greater than 0 and no larger than " + MAXIMUM_ATTRIBUTE_ARRAY_LENGTH_LIMIT); + + } + } + } + + private int _attributeCountLimit = DEFAULT_ATTRIBUTE_COUNT_LIMIT; + public int AttributeCountLimit + { + get => _attributeCountLimit; + set + { + if (value > 0 && value <= MAXIMUM_ATTRIBUTE_COUNT_LIMIT) + { + _attributeCountLimit = value; + } + else + { + MainThreadDispatchBehaviour.Instance().LogWarning("AttributeCountLimit must be greater than 0 and no larger than " + MAXIMUM_ATTRIBUTE_COUNT_LIMIT); + } + } + } public string ApiKey; @@ -74,7 +132,7 @@ internal List> GetOnSpanEndCallbacks() public string GetEndpoint() { - if(string.IsNullOrEmpty(Endpoint) || Endpoint == LEGACY_DEFAULT_ENDPOINT) + if (string.IsNullOrEmpty(Endpoint) || Endpoint == LEGACY_DEFAULT_ENDPOINT) { return string.Format(DEFAULT_ENDPOINT, ApiKey); } diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/Span.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/Span.cs index 05244d8..ca01177 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/Span.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Public/Span.cs @@ -23,8 +23,11 @@ public class Span : ISpanContext internal bool WasDiscarded; private bool _callbackComplete; private Dictionary _attributes = new Dictionary(); + internal int DroppedAttributesCount; + private int _customAttributeCount; + private int _maxCustomAttributes; - public Span(string name, SpanKind kind, string id, string traceId, string parentSpanId, DateTimeOffset startTime, bool? isFirstClass, OnSpanEnd onSpanEnd) + public Span(string name, SpanKind kind, string id, string traceId, string parentSpanId, DateTimeOffset startTime, bool? isFirstClass, OnSpanEnd onSpanEnd, int maxCustomAttributes) { Name = name; Kind = kind; @@ -33,6 +36,7 @@ public Span(string name, SpanKind kind, string id, string traceId, string parent StartTime = startTime; ParentSpanId = parentSpanId; samplingProbability = 1; + _maxCustomAttributes = maxCustomAttributes; if (isFirstClass != null) { SetAttributeInternal("bugsnag.span.first_class", isFirstClass.Value); @@ -42,9 +46,9 @@ public Span(string name, SpanKind kind, string id, string traceId, string parent void LogSpanEndingWarning() { - UnityEngine.Debug.LogWarning($"Attempting to call End on span: {Name} after the span has already ended."); + MainThreadDispatchBehaviour.Instance().LogWarning($"Attempting to call End on span: {Name} after the span has already ended."); } - + public void End(DateTimeOffset? endTime = null) { lock (_endLock) @@ -177,18 +181,31 @@ private void SetAttributeWithChecks(string key, object value) { if (_callbackComplete) { - UnityEngine.Debug.LogWarning($"Attempting to set attribute: {key} on span: {Name} after the span has ended."); + MainThreadDispatchBehaviour.Instance().LogWarning($"Attempting to set attribute: {key} on span: {Name} after the span has ended."); return; } - if (value == null) + + if (_attributes.ContainsKey(key)) { - if (_attributes.ContainsKey(key)) + if (value == null) { _attributes.Remove(key); + _customAttributeCount--; + } + else + { + _attributes[key] = value; } return; } + + if (_customAttributeCount >= _maxCustomAttributes) + { + DroppedAttributesCount++; + return; + } _attributes[key] = value; + _customAttributeCount++; } internal Dictionary GetAttributes() => new Dictionary(_attributes); diff --git a/BugsnagPerformance/Assets/UnitTests/ConfigurationTests.cs b/BugsnagPerformance/Assets/UnitTests/ConfigurationTests.cs index bdeecd5..724f1d7 100644 --- a/BugsnagPerformance/Assets/UnitTests/ConfigurationTests.cs +++ b/BugsnagPerformance/Assets/UnitTests/ConfigurationTests.cs @@ -81,7 +81,8 @@ public void TestCustomSpanTimes() "", CustomStartTime, true, - OnSpanEnd); + OnSpanEnd, + 128); span.End(CustomEndTime); Assert.AreEqual(span.StartTime, CustomStartTime); Assert.AreEqual(span.EndTime, CustomEndTime); @@ -121,5 +122,76 @@ public void CustomSamplingValue() Assert.IsTrue(config.IsFixedSamplingProbability); } + [Test] + public void TestAttributeStringValueLimit() + { + var config = new PerformanceConfiguration(VALID_API_KEY); + + Assert.AreEqual(PerformanceConfiguration.DEFAULT_ATTRIBUTE_STRING_VALUE_LIMIT, config.AttributeStringValueLimit); + + config.AttributeStringValueLimit = 5000; + Assert.AreEqual(5000, config.AttributeStringValueLimit); + + config.AttributeStringValueLimit = 10000; + Assert.AreEqual(10000, config.AttributeStringValueLimit); + + config.AttributeStringValueLimit = -1; + Assert.AreEqual(10000, config.AttributeStringValueLimit, "Value should not change if it's less than 0"); + + config.AttributeStringValueLimit = 0; + Assert.AreEqual(10000, config.AttributeStringValueLimit, "Value should not change if it's 0"); + + config.AttributeStringValueLimit = 15000; + Assert.AreEqual(10000, config.AttributeStringValueLimit, "Value should not exceed the maximum of 10000"); + } + + [Test] + public void TestAttributeArrayLengthLimit() + { + var config = new PerformanceConfiguration(VALID_API_KEY); + + Assert.AreEqual(PerformanceConfiguration.DEFAULT_ATTRIBUTE_ARRAY_LENGTH_LIMIT, config.AttributeArrayLengthLimit); + + config.AttributeArrayLengthLimit = 500; + Assert.AreEqual(500, config.AttributeArrayLengthLimit); + + config.AttributeArrayLengthLimit = 10000; + Assert.AreEqual(10000, config.AttributeArrayLengthLimit); + + config.AttributeArrayLengthLimit = 0; + Assert.AreEqual(10000, config.AttributeArrayLengthLimit, "Value should not change if it's 0"); + + config.AttributeArrayLengthLimit = -1; + Assert.AreEqual(10000, config.AttributeArrayLengthLimit, "Value should not change if it's less than 0"); + + config.AttributeArrayLengthLimit = 15000; + Assert.AreEqual(10000, config.AttributeArrayLengthLimit, "Value should not exceed the maximum of 10000"); + } + + [Test] + public void TestAttributeCountLimit() + { + var config = new PerformanceConfiguration(VALID_API_KEY); + + Assert.AreEqual(PerformanceConfiguration.DEFAULT_ATTRIBUTE_COUNT_LIMIT, config.AttributeCountLimit); + + config.AttributeCountLimit = 500; + Assert.AreEqual(500, config.AttributeCountLimit); + + config.AttributeCountLimit = 1000; + Assert.AreEqual(1000, config.AttributeCountLimit); + + config.AttributeCountLimit = -1; + Assert.AreEqual(1000, config.AttributeCountLimit, "Value should not change if it's less than 0"); + + config.AttributeCountLimit = 0; + Assert.AreEqual(1000, config.AttributeCountLimit, "Value should not change if it's 0"); + + config.AttributeCountLimit = 1500; + Assert.AreEqual(1000, config.AttributeCountLimit, "Value should not exceed the maximum of 1000"); + } + + + } } diff --git a/BugsnagPerformance/Assets/UnitTests/SamplerTests.cs b/BugsnagPerformance/Assets/UnitTests/SamplerTests.cs index fa90f0f..c2cb21b 100644 --- a/BugsnagPerformance/Assets/UnitTests/SamplerTests.cs +++ b/BugsnagPerformance/Assets/UnitTests/SamplerTests.cs @@ -51,7 +51,8 @@ public void TestDefaultConfig() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.AreEqual(1.0, sampler.Probability); Assert.IsTrue(sampler.Sampled(span)); @@ -89,7 +90,8 @@ public void TestProbability1_0() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsTrue(sampler.Sampled(span)); } @@ -108,7 +110,8 @@ public void TestProbability0_0() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsFalse(sampler.Sampled(span)); } @@ -127,7 +130,8 @@ public void TestProbability0_1() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsFalse(sampler.Sampled(span)); @@ -138,7 +142,8 @@ public void TestProbability0_1() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsTrue(sampler.Sampled(span)); } @@ -157,7 +162,8 @@ public void TestProbability0_9() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsTrue(sampler.Sampled(span)); @@ -168,7 +174,8 @@ public void TestProbability0_9() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsTrue(sampler.Sampled(span)); span = new Span("test", @@ -178,7 +185,8 @@ public void TestProbability0_9() "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); Assert.IsFalse(sampler.Sampled(span)); } diff --git a/BugsnagPerformance/Assets/UnitTests/TracePayloadTests.cs b/BugsnagPerformance/Assets/UnitTests/TracePayloadTests.cs index 97b141e..f596ea7 100644 --- a/BugsnagPerformance/Assets/UnitTests/TracePayloadTests.cs +++ b/BugsnagPerformance/Assets/UnitTests/TracePayloadTests.cs @@ -12,6 +12,8 @@ namespace Tests public class TracePayloadTests { + private const string VALID_API_KEY = "227df1042bc7772c321dbde3b31a03c2"; + [Test] public void TestPersistenceNoHeaders() { @@ -90,7 +92,7 @@ private TracePayload PayloadWithPValues(List pValues) { var cacheManager = new CacheManager(Application.temporaryCachePath); var resourceModel = new ResourceModel(cacheManager); - return new TracePayload(resourceModel, SpansWithProbabilities(pValues), false); + return new TracePayload(resourceModel, SpansWithProbabilities(pValues),false,1,1); } private void AssertSpanSamplingHistogram(List pValues, string expectedHistogram) @@ -123,7 +125,8 @@ private Span SpanWithProbability(double probability) "", DateTimeOffset.Now, true, - OnSpanEnd); + OnSpanEnd, + 128); span.UpdateSamplingProbability(probability); return span; } diff --git a/features/custom_attributes.feature b/features/custom_attributes.feature index 414e523..1ec2b71 100644 --- a/features/custom_attributes.feature +++ b/features/custom_attributes.feature @@ -42,3 +42,44 @@ Feature: Custom Attributes * the trace "Bugsnag-Span-Sampling" header equals "1:1" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "AddAttributesInCallbacks" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" boolean attribute "config-callback" is true + + Scenario: Default AttributeLimits + When I run the game in the "DefaultAttributeLimits" state + And I wait for 1 span + Then the trace Bugsnag-Integrity header is valid + And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" + * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "DefaultAttributeLimits" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.3.key" equals "control" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" string attribute "too long string" equals "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*** 1 CHARS TRUNCATED" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.3.key" equals "control" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.5.value.arrayValue.values" is an array with 1000 elements + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.5.value.arrayValue.values.0.stringValue" equals "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa*** 1 CHARS TRUNCATED" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" integer attribute "int1" equals 999 + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" integer attribute "dropped_attributes_count" equals 77 + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes" is an array with 132 elements + + + Scenario: Custom AttributeLimits + When I run the game in the "CustomAttributeLimits" state + And I wait for 1 span + Then the trace Bugsnag-Integrity header is valid + And the trace "Bugsnag-Api-Key" header equals "a35a2a72bd230ac0aa0f52715bbdc6aa" + * the trace "Bugsnag-Sent-At" header matches the regex "^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d\d\dZ$" + * the trace "Bugsnag-Span-Sampling" header equals "1:1" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.name" equals "CustomAttributeLimits" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.3.key" equals "control" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" string attribute "too long string" equals "aaaaaaaaaa*** 1015 CHARS TRUNCATED" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.3.key" equals "control" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.5.value.arrayValue.values" is an array with 2 elements + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes.5.value.arrayValue.values.0.stringValue" equals "aaaaaaaaaa*** 1015 CHARS TRUNCATED" + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" integer attribute "int1" equals 999 + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0" integer attribute "dropped_attributes_count" equals 197 + * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.attributes" is an array with 12 elements + + + + + + diff --git a/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity b/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity index a808334..2762674 100644 --- a/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity +++ b/features/fixtures/mazerunner/Assets/Scenes/MainScene.unity @@ -502,6 +502,8 @@ GameObject: - component: {fileID: 323187831} - component: {fileID: 323187832} - component: {fileID: 323187833} + - component: {fileID: 323187835} + - component: {fileID: 323187834} m_Layer: 0 m_Name: Attributes m_TagString: Untagged @@ -550,6 +552,30 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: ShouldStartNotifier: 0 +--- !u!114 &323187834 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323187830} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 552d75942a8b04b0cb4df3695b068649, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!114 &323187835 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 323187830} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cbb1313beb8e2452eb405afc7461767c, type: 3} + m_Name: + m_EditorClassIdentifier: --- !u!1 &368414949 GameObject: m_ObjectHideFlags: 0 @@ -1165,6 +1191,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 60784bd8dd5b64233afa1f365ad01f71, type: 3} m_Name: m_EditorClassIdentifier: + ShouldStartNotifier: 0 --- !u!1 &1513513349 GameObject: m_ObjectHideFlags: 0 diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs new file mode 100644 index 0000000..8bd0715 --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs @@ -0,0 +1,54 @@ +using System.Collections; +using System.Collections.Generic; +using BugsnagUnityPerformance; +using UnityEngine; + +public class CustomAttributeLimits : Scenario +{ + public override void PreparePerformanceConfig(string apiKey, string host) + { + base.PreparePerformanceConfig(apiKey, host); + SetMaxBatchSize(1); + Configuration.AttributeStringValueLimit = 10; + Configuration.AttributeArrayLengthLimit = 2; + Configuration.AttributeCountLimit = 8; + } + + public override void Run() + { + base.Run(); + var span = BugsnagPerformance.StartSpan("CustomAttributeLimits"); + + var tooLongKey = string.Empty; + for (int i = 0; i < 129; i++) + { + tooLongKey += "a"; + } + span.SetAttribute(tooLongKey, "1234"); + span.SetAttribute("control", "1234"); + + var tooLongString = string.Empty; + for (int i = 0; i < 1025; i++) + { + tooLongString += "a"; + } + span.SetAttribute("too long string", tooLongString); + + var tooLongArray = new string[20000]; + for (int i = 0; i < 20000; i++) + { + tooLongArray[i] = "a"; + } + tooLongArray[0] = tooLongString; + span.SetAttribute("tooLongArray", tooLongArray); + + for (int i = 0; i < 200; i++) + { + span.SetAttribute("int" + i, i); + } + span.SetAttribute("int1", 999); + + span.End(); + } + +} diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs.meta b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs.meta new file mode 100644 index 0000000..7c34b0b --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/CustomAttributeLimits.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbb1313beb8e2452eb405afc7461767c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs new file mode 100644 index 0000000..58d77ff --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using BugsnagUnityPerformance; +using UnityEngine; + +public class DefaultAttributeLimits : Scenario +{ + public override void PreparePerformanceConfig(string apiKey, string host) + { + base.PreparePerformanceConfig(apiKey, host); + SetMaxBatchSize(1); + } + + public override void Run() + { + base.Run(); + var span = BugsnagPerformance.StartSpan("DefaultAttributeLimits"); + + var tooLongKey = string.Empty; + for (int i = 0; i < 129; i++) + { + tooLongKey += "a"; + } + span.SetAttribute(tooLongKey, "1234"); + span.SetAttribute("control", "1234"); + + var tooLongString = string.Empty; + for (int i = 0; i < 1025; i++) + { + tooLongString += "a"; + } + span.SetAttribute("too long string", tooLongString); + + var tooLongArray = new string[20000]; + for (int i = 0; i < 20000; i++) + { + tooLongArray[i] = "a"; + } + tooLongArray[0] = tooLongString; + span.SetAttribute("tooLongArray", tooLongArray); + + for (int i = 0; i < 200; i++) + { + span.SetAttribute("int" + i, i); + } + span.SetAttribute("int1", 999); + + span.End(); + } + +} diff --git a/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs.meta b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs.meta new file mode 100644 index 0000000..ec1ef32 --- /dev/null +++ b/features/fixtures/mazerunner/Assets/Scripts/Scenarios/Attributes/DefaultAttributeLimits.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 552d75942a8b04b0cb4df3695b068649 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 63677884cccf0b678526ef56784a8e5926761a28 Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Tue, 24 Sep 2024 11:35:50 +0200 Subject: [PATCH 5/8] finalise error correlation tests (#119) --- .buildkite/pipeline.full.yml | 6 +- .buildkite/pipeline.yml | 2 +- features/correlation.feature | 12 ++-- .../mazerunner/Packages/manifest.json | 45 ------------- .../ProjectSettings/ProjectSettings.asset | 14 +++-- features/scripts/import_package.sh | 63 ++++++++++++++++++- 6 files changed, 79 insertions(+), 63 deletions(-) delete mode 100644 features/fixtures/mazerunner/Packages/manifest.json diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index 7d034aa..2d9a710 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -99,7 +99,7 @@ steps: - features/fixtures/mazerunner/build/Windows-2020.zip - features/fixtures/build_windows.log commands: - - features/scripts/import_package.sh + - features/scripts/import_package.sh --windows - features/scripts/build_windows.sh release retry: automatic: @@ -141,7 +141,7 @@ steps: - features/fixtures/mazerunner/build/Windows-2022.zip - features/fixtures/build_windows.log commands: - - features/scripts/import_package.sh + - features/scripts/import_package.sh --windows - features/scripts/build_windows.sh release retry: automatic: @@ -464,7 +464,7 @@ steps: - features/fixtures/mazerunner/build/Windows-dev-2021.zip - features/fixtures/build_windows.log commands: - - features/scripts/import_package.sh + - features/scripts/import_package.sh --windows - features/scripts/build_windows.sh dev retry: automatic: diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 226c879..3fbfdee 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -89,7 +89,7 @@ steps: - features/fixtures/mazerunner/build/Windows-2021.zip - features/fixtures/build_windows.log commands: - - features/scripts/import_package.sh + - features/scripts/import_package.sh --windows - features/scripts/build_windows.sh release retry: automatic: diff --git a/features/correlation.feature b/features/correlation.feature index 0693488..2673e5f 100644 --- a/features/correlation.feature +++ b/features/correlation.feature @@ -15,8 +15,8 @@ Feature: Manual creation of spans * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.spanId" is stored as the value "context_span_id" * the trace payload field "resourceSpans.0.scopeSpans.0.spans.0.traceId" is stored as the value "context_trace_id" - * the error payload field "events.0.correlation.spanid" equals the stored value "context_span_id" - * the error payload field "events.0.correlation.traceid" equals the stored value "context_trace_id" + * the error payload field "events.0.correlation.spanId" equals the stored value "context_span_id" + * the error payload field "events.0.correlation.traceId" equals the stored value "context_trace_id" Scenario: Correlation Should be null @@ -45,15 +45,15 @@ Feature: Manual creation of spans * I sort the errors by the payload field "events.0.exceptions.0.message" * the exception "message" equals "Event From Background Thread" - * the error payload field "events.0.correlation.spanid" equals the stored value "background_span_id" - * the error payload field "events.0.correlation.traceid" equals the stored value "background_trace_id" + * the error payload field "events.0.correlation.spanId" equals the stored value "background_span_id" + * the error payload field "events.0.correlation.traceId" equals the stored value "background_trace_id" And I discard the oldest error * the exception "message" equals "Event From Main Thread" - * the error payload field "events.0.correlation.spanid" equals the stored value "main_span_id" - * the error payload field "events.0.correlation.traceid" equals the stored value "main_trace_id" + * the error payload field "events.0.correlation.spanId" equals the stored value "main_span_id" + * the error payload field "events.0.correlation.traceId" equals the stored value "main_trace_id" diff --git a/features/fixtures/mazerunner/Packages/manifest.json b/features/fixtures/mazerunner/Packages/manifest.json deleted file mode 100644 index 12c4dd4..0000000 --- a/features/fixtures/mazerunner/Packages/manifest.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "dependencies": { - "com.unity.collab-proxy": "2.0.5", - "com.unity.ide.rider": "1.2.1", - "com.unity.ide.visualstudio": "2.0.12", - "com.unity.ide.vscode": "1.2.4", - "com.bugsnag.unitynotifier": "https://github.com/bugsnag/bugsnag-unity-upm.git#v7.8.0-rc1", - "com.unity.nuget.newtonsoft-json": "3.2.1", - "com.unity.test-framework": "1.1.29", - "com.unity.textmeshpro": "2.1.6", - "com.unity.timeline": "1.2.18", - "com.unity.ugui": "1.0.0", - "com.unity.modules.ai": "1.0.0", - "com.unity.modules.androidjni": "1.0.0", - "com.unity.modules.animation": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.cloth": "1.0.0", - "com.unity.modules.director": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.particlesystem": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.physics2d": "1.0.0", - "com.unity.modules.screencapture": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.terrainphysics": "1.0.0", - "com.unity.modules.tilemap": "1.0.0", - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.uielements": "1.0.0", - "com.unity.modules.umbra": "1.0.0", - "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.unitywebrequesttexture": "1.0.0", - "com.unity.modules.unitywebrequestwww": "1.0.0", - "com.unity.modules.vehicles": "1.0.0", - "com.unity.modules.video": "1.0.0", - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.wind": "1.0.0", - "com.unity.modules.xr": "1.0.0" - } -} diff --git a/features/fixtures/mazerunner/ProjectSettings/ProjectSettings.asset b/features/fixtures/mazerunner/ProjectSettings/ProjectSettings.asset index 3b14fba..a7f20d2 100644 --- a/features/fixtures/mazerunner/ProjectSettings/ProjectSettings.asset +++ b/features/fixtures/mazerunner/ProjectSettings/ProjectSettings.asset @@ -768,11 +768,15 @@ PlayerSettings: webGLThreadsSupport: 0 webGLDecompressionFallback: 0 scriptingDefineSymbols: - 0: BUGSNAG_PERFORMANCE - 1: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG - 4: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG - 7: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG - 13: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG + 0: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + 1: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + 13: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + 4: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + 7: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + Android: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + Standalone: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + WebGL: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST + iPhone: BUGSNAG_PERFORMANCE;BUGSNAG_DEBUG;BUGSNAG_UNITY_WEB_REQUEST additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: diff --git a/features/scripts/import_package.sh b/features/scripts/import_package.sh index 5e470aa..b6f42cd 100755 --- a/features/scripts/import_package.sh +++ b/features/scripts/import_package.sh @@ -1,11 +1,68 @@ #!/usr/bin/env bash -root_path=`pwd` +if [ -z "$UNITY_PERFORMANCE_VERSION" ]; then + echo "UNITY_PERFORMANCE_VERSION must be set" + exit 1 +fi -destination="features/fixtures/mazerunner/Packages" +# Parse arguments +BUILD_WINDOWS=false +while [[ "$#" -gt 0 ]]; do + case $1 in + --windows) BUILD_WINDOWS=true ;; + *) echo "Unknown option: $1" ;; + esac + shift +done + +# Set Unity path based on the platform +if [ "$BUILD_WINDOWS" = true ]; then + UNITY_PATH="/mnt/c/Program Files/Unity/Hub/Editor/$UNITY_PERFORMANCE_VERSION/Editor/Unity.exe" + PACKAGE_DOWNLOAD_PATH="features/fixtures/mazerunner/Bugsnag.unitypackage" +else + UNITY_PATH="/Applications/Unity/Hub/Editor/$UNITY_PERFORMANCE_VERSION/Unity.app/Contents/MacOS/Unity" + PACKAGE_DOWNLOAD_PATH="features/fixtures/mazerunner/Bugsnag.unitypackage" +fi + +FIXTURE_PATH="features/fixtures/mazerunner" +DEFAULT_CLI_ARGS="-batchmode -nographics -quit" +BUGSNAG_RELEASE_URL="https://github.com/bugsnag/bugsnag-unity/releases/latest/download/Bugsnag.unitypackage" + +# Download the latest Bugsnag Unity package if it doesn't exist or override it +echo "Downloading Bugsnag.unitypackage from $BUGSNAG_RELEASE_URL" +curl -L "$BUGSNAG_RELEASE_URL" -o "$PACKAGE_DOWNLOAD_PATH" +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo "Failed to download Bugsnag.unitypackage" + exit $RESULT +fi + +# Check if Unity path exists +if [ ! -f "$UNITY_PATH" ]; then + echo "Unity executable not found at $UNITY_PATH" + exit 1 +fi +# Importing the Bugsnag package into Unity project +echo "Importing Bugsnag.unitypackage into $FIXTURE_PATH" +"$UNITY_PATH" $DEFAULT_CLI_ARGS \ + -projectPath $FIXTURE_PATH \ + -ignoreCompilerErrors \ + -importPackage "Bugsnag.unitypackage" +RESULT=$? +if [ $RESULT -ne 0 ]; then + echo "Failed to import Bugsnag.unitypackage" + exit $RESULT +fi + +echo "Bugsnag package imported successfully" + +# Proceed with unzipping the main package +root_path=$(pwd) +destination="features/fixtures/mazerunner/Packages" package="$root_path/upm-package.zip" rm -rf "$destination/package" - unzip -q "$package" -d "$destination" + +echo "Package unzipped successfully" From 9d8f13695f03fda3330c6c3ba801c86e53aac53c Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Tue, 24 Sep 2024 11:45:22 +0200 Subject: [PATCH 6/8] Release v1.6.0 --- .../Assets/BugsnagPerformance/Scripts/Internal/Version.cs | 2 +- CHANGELOG.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Version.cs b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Version.cs index e8a7171..f751e52 100644 --- a/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Version.cs +++ b/BugsnagPerformance/Assets/BugsnagPerformance/Scripts/Internal/Version.cs @@ -3,6 +3,6 @@ internal static class Version { //TODO set this using sed or something in the release automation task - public const string VersionString = "1.5.1"; + public const string VersionString = "1.6.0"; } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 136f8dd..1eb2915 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ # Changelog -## TBD +## v1.6.0 (2024-09-24) ### Additions +- Add configurable limits to custom attributes. [#137](https://github.com/bugsnag/bugsnag-unity-performance/pull/137) + - Add TracePropagationUrls to the configuration window. [#136](https://github.com/bugsnag/bugsnag-unity-performance/pull/136) ## v1.5.1 (2024-09-09) From 2a2939cd4a9daacf35771aacf44860688aa90128 Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Tue, 24 Sep 2024 13:14:50 +0200 Subject: [PATCH 7/8] add manifest with TMP --- .../mazerunner/Packages/manifest.json | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 features/fixtures/mazerunner/Packages/manifest.json diff --git a/features/fixtures/mazerunner/Packages/manifest.json b/features/fixtures/mazerunner/Packages/manifest.json new file mode 100644 index 0000000..912ee12 --- /dev/null +++ b/features/fixtures/mazerunner/Packages/manifest.json @@ -0,0 +1,44 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "2.2.0", + "com.unity.ide.rider": "3.0.27", + "com.unity.ide.visualstudio": "2.0.22", + "com.unity.ide.vscode": "1.2.5", + "com.unity.test-framework": "1.1.33", + "com.unity.textmeshpro": "3.0.9", + "com.unity.timeline": "1.6.5", + "com.unity.ugui": "1.0.0", + "com.unity.visualscripting": "1.9.1", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} From 53d2017d866618384ff4a22855098a826828a4d1 Mon Sep 17 00:00:00 2001 From: Richard Elms Date: Tue, 24 Sep 2024 15:30:05 +0200 Subject: [PATCH 8/8] package manifest fix [full ci] (#139) * package manifest fix [full ci] * newtonsoft fix * [full ci] * final manifest [full ci] --- .gitignore | 1 + .../mazerunner/Packages/manifest.json | 87 ++++++++++--------- 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index d09dd55..1481fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ features/fixtures/minimalapp/minimal_with_xcode features/fixtures/minimalapp/minimal_without_xcode features/fixtures/mazerunner/mazerunner_macos_BackUpThisFolder_ButDontShipItWithYourGame BugsnagPerformance/.vscode +features/fixtures/mazerunner/Assets/Bugsnag diff --git a/features/fixtures/mazerunner/Packages/manifest.json b/features/fixtures/mazerunner/Packages/manifest.json index 912ee12..fec24d0 100644 --- a/features/fixtures/mazerunner/Packages/manifest.json +++ b/features/fixtures/mazerunner/Packages/manifest.json @@ -1,44 +1,45 @@ { - "dependencies": { - "com.unity.collab-proxy": "2.2.0", - "com.unity.ide.rider": "3.0.27", - "com.unity.ide.visualstudio": "2.0.22", - "com.unity.ide.vscode": "1.2.5", - "com.unity.test-framework": "1.1.33", - "com.unity.textmeshpro": "3.0.9", - "com.unity.timeline": "1.6.5", - "com.unity.ugui": "1.0.0", - "com.unity.visualscripting": "1.9.1", - "com.unity.modules.ai": "1.0.0", - "com.unity.modules.androidjni": "1.0.0", - "com.unity.modules.animation": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.cloth": "1.0.0", - "com.unity.modules.director": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0", - "com.unity.modules.particlesystem": "1.0.0", - "com.unity.modules.physics": "1.0.0", - "com.unity.modules.physics2d": "1.0.0", - "com.unity.modules.screencapture": "1.0.0", - "com.unity.modules.terrain": "1.0.0", - "com.unity.modules.terrainphysics": "1.0.0", - "com.unity.modules.tilemap": "1.0.0", - "com.unity.modules.ui": "1.0.0", - "com.unity.modules.uielements": "1.0.0", - "com.unity.modules.umbra": "1.0.0", - "com.unity.modules.unityanalytics": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.unitywebrequesttexture": "1.0.0", - "com.unity.modules.unitywebrequestwww": "1.0.0", - "com.unity.modules.vehicles": "1.0.0", - "com.unity.modules.video": "1.0.0", - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.wind": "1.0.0", - "com.unity.modules.xr": "1.0.0" - } -} + "dependencies": + { + "com.unity.collab-proxy": "2.0.5", + "com.unity.ide.rider": "1.2.1", + "com.unity.ide.visualstudio": "2.0.12", + "com.unity.ide.vscode": "1.2.4", + "com.unity.nuget.newtonsoft-json": "3.2.1", + "com.unity.test-framework": "1.1.29", + "com.unity.textmeshpro": "2.1.6", + "com.unity.timeline": "1.2.18", + "com.unity.ugui": "1.0.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} \ No newline at end of file