Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): update .NET SDK to v4.0.2 #89

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
- Bump Cocoa SDK from v8.8.0 to v8.9.4 ([#1397](https://github.com/getsentry/sentry-unity/pull/1397), [#1399](https://github.com/getsentry/sentry-unity/pull/1399), [#1404](https://github.com/getsentry/sentry-unity/pull/1404), [#1406](https://github.com/getsentry/sentry-unity/pull/1406), [#1413](https://github.com/getsentry/sentry-unity/pull/1413))
- [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#894)
- [diff](https://github.com/getsentry/sentry-cocoa/compare/8.8.0...8.9.4)
- Bump .NET SDK from v3.33.1 to v3.34.0 ([#1398](https://github.com/getsentry/sentry-unity/pull/1398))
- [changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md#3340)
- [diff](https://github.com/getsentry/sentry-dotnet/compare/3.33.1...3.34.0)
- Bump .NET SDK from v3.33.1 to v4.0.2 ([#1398](https://github.com/getsentry/sentry-unity/pull/1398), [#89](https://github.com/demelev/sentry-unity/pull/89))
- [changelog](https://github.com/getsentry/sentry-dotnet/blob/main/CHANGELOG.md#402)
- [diff](https://github.com/getsentry/sentry-dotnet/compare/3.33.1...4.0.2)

## 1.5.0

Expand Down
10 changes: 10 additions & 0 deletions src/Sentry.Unity.Editor/ConfigurationWindow/CoreTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ internal static void Display(ScriptableSentryUnityOptions options)
options.CaptureInEditor = EditorGUILayout.Toggle(
new GUIContent("Capture In Editor", "Capture errors while running in the Editor."),
options.CaptureInEditor);

options.TreatExceptionsAsHandled = EditorGUILayout.Toggle(
new GUIContent("Exceptions as handled", "The SDK marks all exceptions as handled "
+ "to not mark sessions as crashed because unity survives and do not crash."),
options.TreatExceptionsAsHandled);
}

EditorGUILayout.Space();
Expand Down Expand Up @@ -59,6 +64,11 @@ internal static void Display(ScriptableSentryUnityOptions options)
"same type if they are more frequent than once per second."),
options.EnableLogDebouncing);

options.UseExperimentalDebouncer = EditorGUILayout.Toggle(
new GUIContent("Use Flashback Debouncer", "The SDK will use experimental debouncer instead of plain TimeDebounce" +
" debouncing repeating messages by message and LogType instead of only LogType."),
options.UseExperimentalDebouncer);

options.DebounceTimeLog = EditorGUILayout.IntField(
new GUIContent("Log Debounce [ms]", "The time that has to pass between events of " +
"LogType.Log before the SDK sends it again."),
Expand Down
73 changes: 73 additions & 0 deletions src/Sentry.Unity/FlashbackDebouncer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;

namespace Sentry.Unity
{
public class FlashbackDebouncer
{
record LogEntry
{
#region Properties
public string? Message;
public LogType LogType;
public int Count;
public DateTime Timestamp;
#endregion

#region Methods
public override string ToString() => $"{Message} ({Count} times)";
public static implicit operator string(LogEntry entry) => entry.ToString();
#endregion
}

readonly Dictionary<int, LogEntry?> entries = new ();
TimeSpan offset = TimeSpan.FromSeconds(1);

public async void Debounce(string message, LogType logType, DebouncerCaptureCallback capture)
{
void FlushTails()
{
// TODO: sort by timestemps to order breadcrumbs
foreach (int key in entries.Keys.ToArray())
{
if (entries[key] is LogEntry tailEntry)
{
capture?.Invoke(tailEntry, tailEntry.LogType, AsBreadcrumbsOnly: true);
entries[key] = null;
}
}
}

int hash = message.GetHashCode() + logType.GetHashCode();

if (!entries.TryGetValue(hash, out LogEntry? entry))
{
FlushTails();

entries[hash] = null;
capture?.Invoke(message, logType, AsBreadcrumbsOnly: false);

await Task.Delay(offset);

while (entries[hash] is LogEntry tailEntry && (tailEntry.Timestamp - DateTime.Now) is {} time && (time.TotalMilliseconds > 100))
await Task.Delay(time);

if (entries[hash] is LogEntry tailEntryCapture)
capture?.Invoke(tailEntryCapture, tailEntryCapture.LogType, AsBreadcrumbsOnly: true);

entries.Remove(hash);
}
else
{
// TODO: var textDistance = GetTextDistance(firstMessage, currentMessage);
// if textDistance > threshold then add message to breadcrumbs
entries[hash] = entry ??= new() { Message = message, LogType = logType, Count = 0 };
entry.Count++;
entry.Timestamp = DateTime.Now.Add(offset);
}
}
}
}
101 changes: 70 additions & 31 deletions src/Sentry.Unity/Integrations/UnityLogHandlerIntegration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Sentry.Extensibility;
using Sentry.Integrations;
using Sentry.Protocol;
Expand Down Expand Up @@ -45,6 +46,14 @@ public void Register(IHub hub, SentryOptions sentryOptions)
return;
}

if (_sentryOptions != null)
{
if (_sentryOptions.UseExperimentalDebouncer)
_sentryOptions.Debouncer = new FlashbackDebouncer().Debounce;
else
_sentryOptions.Debouncer = DefaultDebouncer;
}

_unityLogHandler = Debug.unityLogger.logHandler;
Debug.unityLogger.logHandler = this;

Expand All @@ -71,20 +80,7 @@ internal void CaptureException(Exception exception, UnityEngine.Object? context)
return;
}

// TODO: Capture the context (i.e. grab the name if != null and set it as context)

// NOTE: This might not be entirely true, as a user could as well call `Debug.LogException`
// and expect a handled exception but it is not possible for us to differentiate
// https://docs.sentry.io/platforms/unity/troubleshooting/#unhandled-exceptions---debuglogexception
exception.Data[Mechanism.HandledKey] = false;
exception.Data[Mechanism.MechanismKey] = "Unity.LogException";
_ = _hub.CaptureException(exception);

if (_sentryOptions?.AddBreadcrumbsForLogType[LogType.Exception] is true)
{
// So the next event includes this error as a breadcrumb
_hub.AddBreadcrumb(message: $"{exception.GetType()}: {exception.Message}", category: "unity.logger", level: BreadcrumbLevel.Error);
}
CaptureLogFormat(LogType.Exception, context, "{0}", $"{exception.GetType()}: {exception.Message}", exception);
}

public void LogFormat(LogType logType, UnityEngine.Object? context, string format, params object[] args)
Expand Down Expand Up @@ -113,34 +109,61 @@ internal void CaptureLogFormat(LogType logType, UnityEngine.Object? context, str
return;
}

if (_sentryOptions?.EnableLogDebouncing is true)
// if (args[0] is not string logMessage)
// {
// return;
// }

// if (logType == LogType.Exception && args.Length < 2)
// {
// return;
// }
// // We're not capturing SDK internal logs
// if (logMessage.StartsWith(UnityLogger.LogTag, StringComparison.Ordinal))
// {
// // TODO: Maybe color Sentry internal logs (highlight 'Sentry'?)
// return;
// }

void Capture(string logMessage, LogType logType, bool OnlyBreadcrumbs = false)
{
var debounced = logType switch
if (logType is LogType.Exception && !OnlyBreadcrumbs)
{
if (args[1] is Exception exception)
{
// TODO: Capture the context (i.e. grab the name if != null and set it as context)

// NOTE: This might not be entirely true, as a user could as well call `Debug.LogException`
// and expect a handled exception but it is not possible for us to differentiate
// https://docs.sentry.io/platforms/unity/troubleshooting/#unhandled-exceptions---debuglogexception

exception.Data[Mechanism.HandledKey] = _sentryOptions?.IsExceptionHandled(exception) ?? false;
exception.Data[Mechanism.MechanismKey] = "Unity.LogException";

_ = _hub.CaptureException(exception);
}
}

if (logType is LogType.Error or LogType.Assert && !OnlyBreadcrumbs)
{
LogType.Error or LogType.Exception or LogType.Assert => ErrorTimeDebounce.Debounced(),
LogType.Log => LogTimeDebounce.Debounced(),
LogType.Warning => WarningTimeDebounce.Debounced(),
_ => true
};
_hub.CaptureMessage(logMessage, ToEventTagType(logType));
}

if (!debounced)
if (_sentryOptions?.AddBreadcrumbsForLogType[logType] is true)
{
return;
// So the next event includes this as a breadcrumb
_hub.AddBreadcrumb(message: logMessage, category: "unity.logger", level: ToBreadcrumbLevel(logType));
}
}

var logMessage = args.Length == 0 ? format : string.Format(format, args);

if (logType is LogType.Error or LogType.Assert)
if (_sentryOptions?.EnableLogDebouncing is true && _sentryOptions?.Debouncer != null)
{
// TODO: Capture the context (i.e. grab the name if != null and set it as context)
_hub.CaptureMessage(logMessage, ToEventTagType(logType));
_sentryOptions.Debouncer(logMessage, logType, Capture);
}

if (_sentryOptions?.AddBreadcrumbsForLogType[logType] is true)
else
{
// So the next event includes this as a breadcrumb
_hub.AddBreadcrumb(message: logMessage, category: "unity.logger", level: ToBreadcrumbLevel(logType));
Capture(logMessage, logType);
}
}

Expand Down Expand Up @@ -181,5 +204,21 @@ private static BreadcrumbLevel ToBreadcrumbLevel(LogType logType)
LogType.Warning => BreadcrumbLevel.Warning,
_ => BreadcrumbLevel.Info
};

internal void DefaultDebouncer(string message, LogType logType, DebouncerCaptureCallback capture)
{
var debounced = logType switch
{
LogType.Error or LogType.Exception or LogType.Assert => ErrorTimeDebounce.Debounced(),
LogType.Log => LogTimeDebounce.Debounced(),
LogType.Warning => WarningTimeDebounce.Debounced(),
_ => true
};

if (debounced)
{
capture(message, logType, AsBreadcrumbsOnly: false);
}
}
}
}
5 changes: 4 additions & 1 deletion src/Sentry.Unity/ScriptableSentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public static string GetConfigPath(string? notDefaultConfigName = null)

[field: SerializeField] public string? Dsn { get; set; }
[field: SerializeField] public bool CaptureInEditor { get; set; } = true;

[field: SerializeField] public bool TreatExceptionsAsHandled { get; set; } = false;
[field: SerializeField] public bool UseExperimentalDebouncer { get; set; } = false;
[field: SerializeField] public bool EnableLogDebouncing { get; set; } = false;
[field: SerializeField] public int DebounceTimeLog { get; set; } = (int)TimeSpan.FromSeconds(1).TotalMilliseconds;
[field: SerializeField] public int DebounceTimeWarning { get; set; } = (int)TimeSpan.FromSeconds(1).TotalMilliseconds;
Expand Down Expand Up @@ -133,6 +134,8 @@ internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, ISentryUnityIn
DebounceTimeLog = TimeSpan.FromMilliseconds(DebounceTimeLog),
DebounceTimeWarning = TimeSpan.FromMilliseconds(DebounceTimeWarning),
DebounceTimeError = TimeSpan.FromMilliseconds(DebounceTimeError),
UseExperimentalDebouncer = UseExperimentalDebouncer,
TreatExceptionsAsHandled = TreatExceptionsAsHandled,
TracesSampleRate = TracesSampleRate,
AutoStartupTraces = AutoStartupTraces,
AutoSceneLoadTraces = AutoSceneLoadTraces,
Expand Down
24 changes: 24 additions & 0 deletions src/Sentry.Unity/SentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

namespace Sentry.Unity
{
public delegate void DebouncerCaptureCallback(string logMessage, LogType logType, bool AsBreadcrumbsOnly);
public delegate void DebouncerFunction(string logMessage, LogType logType, DebouncerCaptureCallback capture);

/// <summary>
/// Sentry Unity Options.
/// </summary>
Expand Down Expand Up @@ -46,6 +49,11 @@ public sealed class SentryUnityOptions : SentryOptions
// Lower entry barrier, likely set to false after initial setup.
public bool CaptureInEditor { get; set; } = true;

/// <summary>
/// Whether Sentry should mark all exceptions as handled.
/// </summary>
public bool TreatExceptionsAsHandled { get; set; } = false;

/// <summary>
/// Whether Sentry events should be debounced it too frequent.
/// </summary>
Expand All @@ -66,6 +74,22 @@ public sealed class SentryUnityOptions : SentryOptions
/// </summary>
public TimeSpan DebounceTimeError { get; set; } = TimeSpan.FromSeconds(1);

/// <summary>
/// Custom function determines whether an exception should be makerd as handled.
/// </summary>
public Func<Exception, bool>? IsExceptionHandledCheck { get; set; }

/// <summary>
/// Whether Sentry should use experimental FlashbackDebouncer instead of
/// plain TimeDebounce.
/// </summary>
public bool UseExperimentalDebouncer { get; set; } = false;

/// <summary>
/// Assing a custom debouncer if you need, otherwise the default one
/// will be used.
/// </summary>
public DebouncerFunction? Debouncer { get; set; }

private CompressionLevelWithAuto _requestBodyCompressionLevel = CompressionLevelWithAuto.Auto;

Expand Down
3 changes: 3 additions & 0 deletions src/Sentry.Unity/SentryUnityOptionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Sentry.Extensibility;
using Sentry.Unity.Integrations;

Expand Down Expand Up @@ -75,6 +76,8 @@ internal static void AddIl2CppExceptionProcessor(this SentryUnityOptions options
}
}

public static bool IsExceptionHandled(this SentryUnityOptions options, Exception ex) => options.IsExceptionHandledCheck?.Invoke(ex) ?? options.TreatExceptionsAsHandled;

/// <summary>
/// Disables the capture of errors through <see cref="UnityLogHandlerIntegration"/>.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/sentry-dotnet
Submodule sentry-dotnet updated 954 files