Skip to content
Merged
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
Binary file modified Android/lib/arm64-v8a/libbacktrace-native.so
Binary file not shown.
Binary file modified Android/lib/arm64-v8a/libcrashpad_handler.so
Binary file not shown.
Binary file modified Android/lib/armeabi-v7a/libbacktrace-native.so
Binary file not shown.
Binary file modified Android/lib/armeabi-v7a/libcrashpad_handler.so
Binary file not shown.
Binary file modified Android/lib/x86/libbacktrace-native.so
Binary file not shown.
8 changes: 7 additions & 1 deletion Editor/BacktraceConfigurationEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ public override void OnInspectorGUI()
serializedObject.FindProperty("SendUnhandledGameCrashesOnGameStartup"),
new GUIContent(BacktraceConfigurationLabels.LABEL_SEND_UNHANDLED_GAME_CRASHES_ON_STARTUP));
#endif

EditorGUILayout.PropertyField(
serializedObject.FindProperty("ReportFilterType"),
new GUIContent(BacktraceConfigurationLabels.LABEL_REPORT_FILTER));
Expand Down Expand Up @@ -93,6 +92,13 @@ public override void OnInspectorGUI()
EditorGUILayout.HelpBox("Please insert value greater or equal -1", MessageType.Error);
}
}

#if UNITY_ANDROID || UNITY_IOS
EditorGUILayout.PropertyField(
serializedObject.FindProperty("AttachmentPaths"),
new GUIContent(BacktraceConfigurationLabels.LABEL_REPORT_ATTACHMENTS));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@konraddysput does this end up exposing the array as we discussed in the editor? (The default foldout arrow thing?) If so, this is good for now! Side note - as a part of the work I am doing, I am going to try to come up with some custom property drawers to make these easier to use

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it does - I hope we can make it prettier soon!

#endif

#if !UNITY_SWITCH
SerializedProperty enabled = serializedObject.FindProperty("Enabled");
EditorGUILayout.PropertyField(enabled, new GUIContent(BacktraceConfigurationLabels.LABEL_ENABLE_DATABASE));
Expand Down
1 change: 1 addition & 0 deletions Editor/BacktraceConfigurationLabels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal static class BacktraceConfigurationLabels
"(Early access) Send Out of memory exceptions to Backtrace";
#endif
#endif
internal static string LABEL_REPORT_ATTACHMENTS = "Report attachment paths";
internal static string CAPTURE_NATIVE_CRASHES = "Capture native crashes";
internal static string LABEL_REPORT_FILTER = "Filter reports";
internal static string LABEL_NUMBER_OF_LOGS = "Collect last n game logs";
Expand Down
58 changes: 57 additions & 1 deletion Runtime/BacktraceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ public class BacktraceClient : MonoBehaviour, IBacktraceClient

internal readonly Stack<BacktraceReport> BackgroundExceptions = new Stack<BacktraceReport>();

/// <summary>
/// Client report attachments
/// </summary>
private List<string> _clientReportAttachments;

/// <summary>
/// Attribute object accessor
/// </summary>
Expand All @@ -50,6 +55,26 @@ public string this[string index]
}
}

/// <summary>
/// Add attachment to managed reports.
/// Note: this option won't add attachment to your native reports. You can add attachments to
/// native reports only on BacktraceClient initialization.
/// </summary>
/// <param name="pathToAttachment">Path to attachment</param>
public void AddAttachment(string pathToAttachment)
{
_clientReportAttachments.Add(pathToAttachment);
}

/// <summary>
/// Returns list of defined path to attachments stored by Backtrace client.
/// </summary>
/// <returns>List of client attachments</returns>
public List<string> GetAttachments()
{
return _clientReportAttachments;
}

/// <summary>
/// Set client attributes that will be included in every report
/// </summary>
Expand Down Expand Up @@ -271,6 +296,7 @@ internal ReportLimitWatcher ReportLimitWatcher
/// </summary>
/// <param name="configuration">Backtrace configuration scriptable object</param>
/// <param name="attributes">Client side attributes</param>
/// param name="attachments">List of attachments </param>
/// <param name="gameObjectName">game object name</param>
/// <returns>Backtrace client</returns>
public static BacktraceClient Initialize(BacktraceConfiguration configuration, Dictionary<string, string> attributes = null, string gameObjectName = "BacktraceClient")
Expand Down Expand Up @@ -313,9 +339,24 @@ public static BacktraceClient Initialize(BacktraceConfiguration configuration, D
/// <param name="gameObjectName">game object name</param>
/// <returns>Backtrace client</returns>
public static BacktraceClient Initialize(string url, string databasePath, Dictionary<string, string> attributes = null, string gameObjectName = "BacktraceClient")
{
return Initialize(url, databasePath, attributes, null, gameObjectName);
}

/// <summary>
/// Initialize new Backtrace integration with database path. Note - database path will be auto created by Backtrace Unity plugin
/// </summary>
/// <param name="url">Server url</param>
/// <param name="databasePath">Database path</param>
/// <param name="attributes">Client side attributes</param>
/// <param name="attachments">Paths to attachments that Backtrace client will include in managed/native reports</param>
/// <param name="gameObjectName">game object name</param>
/// <returns>Backtrace client</returns>
public static BacktraceClient Initialize(string url, string databasePath, Dictionary<string, string> attributes = null, string[] attachments = null, string gameObjectName = "BacktraceClient")
{
var configuration = ScriptableObject.CreateInstance<BacktraceConfiguration>();
configuration.ServerUrl = url;
configuration.AttachmentPaths = attachments;
configuration.Enabled = true;
configuration.DatabasePath = databasePath;
configuration.CreateDatabase = true;
Expand All @@ -330,9 +371,23 @@ public static BacktraceClient Initialize(string url, string databasePath, Dictio
/// <param name="gameObjectName">game object name</param>
/// <returns>Backtrace client</returns>
public static BacktraceClient Initialize(string url, Dictionary<string, string> attributes = null, string gameObjectName = "BacktraceClient")
{
return Initialize(url, attributes, new string[0], gameObjectName);
}

/// <summary>
/// Initialize new Backtrace integration
/// </summary>
/// <param name="url">Server url</param>
/// <param name="attributes">Client side attributes</param>
/// <param name="attachments">Paths to attachments that Backtrace client will include in managed/native reports</param>
/// <param name="gameObjectName">game object name</param>
/// <returns>Backtrace client</returns>
public static BacktraceClient Initialize(string url, Dictionary<string, string> attributes = null, string[] attachments = null, string gameObjectName = "BacktraceClient")
{
var configuration = ScriptableObject.CreateInstance<BacktraceConfiguration>();
configuration.ServerUrl = url;
configuration.AttachmentPaths = attachments;
configuration.Enabled = false;
return Initialize(configuration, attributes, gameObjectName);
}
Expand All @@ -358,7 +413,7 @@ public void Refresh()
_current = Thread.CurrentThread;
CaptureUnityMessages();
_reportLimitWatcher = new ReportLimitWatcher(Convert.ToUInt32(Configuration.ReportPerMin));

_clientReportAttachments = Configuration.GetAttachmentPaths();

BacktraceApi = new BacktraceApi(
credentials: new BacktraceCredentials(Configuration.GetValidServerUrl()),
Expand Down Expand Up @@ -668,6 +723,7 @@ private BacktraceData SetupBacktraceData(BacktraceReport report)
: _backtraceLogManager.ToSourceCode();

report.AssignSourceCodeToReport(sourceCode);
report.AttachmentPaths.AddRange(_clientReportAttachments);

// pass copy of dictionary to prevent overriding client attributes
var result = report.ToBacktraceData(null, GameObjectDepth);
Expand Down
66 changes: 66 additions & 0 deletions Runtime/Common/ClientPathHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.IO;
using UnityEngine;

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Backtrace.Unity.Tests.Runtime")]
namespace Backtrace.Unity.Common
{
internal static class ClientPathHelper
{
/// <summary>
/// Parse Backtrace client path string to full path
/// </summary>
/// <param name="path">Backtrace path with interpolated string and other Backtrace's improvements</param>
/// <returns>Full path to Backtrace file/directory</returns>
internal static string GetFulLPath(string path)
{
if (string.IsNullOrEmpty(path))
{
return string.Empty;
}

return path.ParseInterpolatedString().GetFullPath();
}

private static string ParseInterpolatedString(this string path)
{
// check if string has any interpolated substring
var interpolationStart = path.IndexOf("${");
if (interpolationStart == -1)
{
return path;
}
var interpolationEnd = path.IndexOf('}', interpolationStart);
if (interpolationEnd == -1)
{
return path;
}
var interpolationValue = path.Substring(interpolationStart, interpolationEnd - interpolationStart + 1);
if (string.IsNullOrEmpty(interpolationValue))
{
return path;
}

switch (interpolationValue.ToLower())
{
case "${application.persistentdatapath}":
return path.Replace(interpolationValue, Application.persistentDataPath);
case "${application.datapath}":
return path.Replace(interpolationValue, Application.dataPath);
default:
return path;
}

}

private static string GetFullPath(this string path)
{
if (!Path.IsPathRooted(path))
{
path = Path.Combine(Application.persistentDataPath, path);
}
return Path.GetFullPath(path);

}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 0 additions & 66 deletions Runtime/Common/DatabasePathHelper.cs

This file was deleted.

32 changes: 29 additions & 3 deletions Runtime/Model/BacktraceConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Backtrace.Unity.Common;
using Backtrace.Unity.Types;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

Expand Down Expand Up @@ -161,7 +162,13 @@ public class BacktraceConfiguration : ScriptableObject
/// Generate game screen shot when exception happen
/// </summary>
[Tooltip("Generate and attach screenshot of frame as exception occurs")]
public bool GenerateScreenshotOnException = false;
public bool GenerateScreenshotOnException = false;

/// <summary>
/// List of path to attachments that Backtrace client will include in the native and managed reports.
/// </summary>
[Tooltip("List of path to attachments that Backtrace client will include in the native and managed reports.")]
public string[] AttachmentPaths;

/// <summary>
/// Directory path where reports and minidumps are stored
Expand Down Expand Up @@ -213,7 +220,7 @@ public class BacktraceConfiguration : ScriptableObject

/// <summary>
/// Maximum number of retries
[Tooltip("If the database is unable to send its record, this setting specifies the maximum number of retries before the system gives up")]
[Tooltip("If the database is unable to send its record, this setting specifies the maximum number of retries before the system gives up.")]
public int RetryLimit = 3;

/// <summary>
Expand All @@ -222,9 +229,28 @@ public class BacktraceConfiguration : ScriptableObject
[Tooltip("This specifies in which order records are sent to the Backtrace server.")]
public RetryOrder RetryOrder;

/// <summary>
/// Get full paths to attachments added by client
/// </summary>
/// <returns>List of absolute path to attachments</returns>
public List<string> GetAttachmentPaths()
{
var result = new List<string>();
if (AttachmentPaths == null || AttachmentPaths.Length == 0)
{
return result;
}

foreach (var path in AttachmentPaths)
{
result.Add(ClientPathHelper.GetFulLPath(path));
}
return result;
}

public string GetFullDatabasePath()
{
return DatabasePathHelper.GetFullDatabasePath(DatabasePath);
return ClientPathHelper.GetFulLPath(DatabasePath);
}
public string CrashpadDatabasePath
{
Expand Down
15 changes: 9 additions & 6 deletions Runtime/Native/Android/NativeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ internal class NativeClient : INativeClient
private Thread _anrThread;

[DllImport("backtrace-native")]
private static extern bool Initialize(IntPtr submissionUrl, IntPtr databasePath, IntPtr handlerPath, IntPtr keys, IntPtr values);
private static extern bool Initialize(IntPtr submissionUrl, IntPtr databasePath, IntPtr handlerPath, IntPtr keys, IntPtr values, IntPtr attachments);

[DllImport("backtrace-native")]
private static extern bool AddAttribute(IntPtr key, IntPtr value);

[DllImport("backtrace-native", EntryPoint = "DumpWithoutCrash")]
private static extern bool NativeReport(IntPtr message);
private static extern bool NativeReport(IntPtr message, bool setMainThreadAsFaultingThread);

/// <summary>
/// Native client built-in specific attributes
Expand Down Expand Up @@ -206,9 +206,10 @@ private void HandleNativeCrashes()
return;
}
// get default built-in Backtrace-Unity attributes
var backtraceAttributes = new BacktraceAttributes(null, null, true);
var backtraceAttributes = new BacktraceAttributes(null, null, true).Attributes;

var minidumpUrl = new BacktraceCredentials(_configuration.GetValidServerUrl()).GetMinidumpSubmissionUrl().ToString();
var attachments = _configuration.GetAttachmentPaths().ToArray();

// reassign to captureNativeCrashes
// to avoid doing anything on crashpad binary, when crashpad
Expand All @@ -217,12 +218,14 @@ private void HandleNativeCrashes()
AndroidJNI.NewStringUTF(minidumpUrl),
AndroidJNI.NewStringUTF(databasePath),
AndroidJNI.NewStringUTF(crashpadHandlerPath),
AndroidJNIHelper.ConvertToJNIArray(backtraceAttributes.Attributes.Keys.ToArray()),
AndroidJNIHelper.ConvertToJNIArray(backtraceAttributes.Attributes.Values.ToArray()));
AndroidJNIHelper.ConvertToJNIArray(backtraceAttributes.Keys.ToArray()),
AndroidJNIHelper.ConvertToJNIArray(backtraceAttributes.Values.ToArray()),
AndroidJNIHelper.ConvertToJNIArray(attachments));
if (!_captureNativeCrashes)
{
Debug.LogWarning("Backtrace native integration status: Cannot initialize Crashpad client");
}

// add exception type to crashes handled by crashpad - all exception handled by crashpad
// by default we setting this option here, to set error.type when unexpected crash happen (so attribute will present)
// otherwise in other methods - ANR detection, OOM handler, we're overriding it and setting it back to "crash"
Expand Down Expand Up @@ -335,7 +338,7 @@ public void HandleAnr(string gameObjectName, string callbackName)
AndroidJNI.NewStringUTF("error.type"),
AndroidJNI.NewStringUTF("Hang"));

NativeReport(AndroidJNI.NewStringUTF("ANRException: Blocked thread detected."));
NativeReport(AndroidJNI.NewStringUTF("ANRException: Blocked thread detected."), true);
// update error.type attribute in case when crash happen
SetAttribute("error.type", "Crash");
}
Expand Down
Loading