Attention: Cloud Diagnostics Advanced is officially deprecated. On October 31, 2024, all existing customers will be able to migrate to Backtrace. You will be able to complete the migration process by clicking a link in the Unity Cloud Dashboard. Migration instructions have been emailed to existing customers. After this date, you will no longer be able to access your Backtrace dashboard in the Unity Cloud Dashboard. Unity and Backtrace will support existing customers through the migration and end of their current annual subscription. Contact us if you are interested in a crash and error reporting tool.
C# configuration
Minimal usage
After you've set up the Backtrace client and database configuration, you can retrieve database and client instances by using GameObject, then use a try/catch statement to throw an exception and send reports.
//Read from manager BacktraceClient instance
var backtraceClient = GameObject.Find("_Manager").GetComponent<BacktraceClient>();
try
{
//throw exception here
}
catch(Exception exception)
{
var report = new BacktraceReport(exception);
backtraceClient.Send(report);
}
Initialization
You can use BacktraceClient.Initialize
to initialize the Backtrace Unity SDK directly in the C# code of your Unity project.
var backtraceClient = BacktraceClient.Initialize(
url: serverUrl,
databasePath: "${Application.persistentDataPath}/sample/backtrace/path",
gameObjectName: "game-object-name",
attributes: attributes);
If you need to use more advanced configuration settings, the Initialize
method accepts a BacktraceConfiguration
scriptable object. For example:
var configuration = ScriptableObject.CreateInstance<BacktraceConfiguration>();
configuration.ServerUrl = serverUrl;
configuration.Enabled = true;
configuration.DatabasePath = "${Application.persistentDataPath}/sample/backtrace/path";
configuration.CreateDatabase = true;
configuration.Sampling = 0.002;
configuration.ClientSideUnwinding = true;
_backtraceClient = BacktraceClient.Initialize(
configuration,
gameObjectName: "game-object-name",
attributes: attributes);
Note: If you change the configuration dynamically in the C# code of your project, make sure to use backtraceClient.Refresh
to apply to configuration settings for backtraceClient
. For example:
//Read from manager BacktraceClient instance
var backtraceClient = GameObject.Find("manager name").GetComponent<BacktraceClient>();
//Set custom client attribute
backtraceClient["attribute"] = "attribute value";
//Change configuration value
backtraceClient.configuration.DeduplicationStrategy = deduplicationStrategy;
//Refresh configuration
backtraceClient.Refresh();
Crash-free metrics
You can enable crash free metrics at runtime with backtraceClient.EnableMetrics()
.
Custom metrics groups
You can use backtraceClient.Instance.Metrics.AddSummedEvent
to add custom metrics groups and attributes to capture your game or apps' stability.
For example, if you want to know details about the levels that a user has played in your game, you can add a "LevelsPlayed" event with the application.version
and score
attributes.
BacktraceClient.Instance.Metrics.AddSummedEvent("levels_played", new Dictionary<string, string>() {
{"application.version", BacktraceClient.Instance["application.version"]},
{"score", "" + score}
}
);
As another example, if you want to know how many minutes a user has played your game, you can add a "MinutesPlayed" event with the application.version
and uname.sysname
attributes.
private void Update()
{
timeElapsedSeconds += Time.deltaTime;
// Every second, add an event for this metric group
if (timeElapsedSeconds >= 60)
{
timeElapsedSeconds = 0;
// Generate your attribute values for the attributes you want linked
Dictionary<string,string> attributes = new Dictionary<string, string>()
{
{ "application.version", BacktraceClient.Instance["application.version"] },
{ "uname.sysname", BacktraceClient.Instance["uname.sysname"] },
{ "custom.field", "custom.value" },
};
// Add the summed event using the metric group name and attributes
BacktraceClient.Instance.Metrics.AddSummedEvent("MinutesPlayed", attributes);
}
}
The example above adds an event for this metric group to a queue, which will be sent based on the Auto send interval setting in the Backtrace Configuration in Unity.
You can adjust the frequency of that send process to suit your needs and/or manually send the events with BacktraceClient.Instance.Metrics.Send()
.
Caution: Adding multiple events with many linked attributes or sending the metrics events too frequently may affect the performance of your game or app and contribute a lot of data towards your Backtrace data storage limits.
Breadcrumbs
You can also add custom breadcrumb events, with information like "player completed a level" and sub attributes:
GetComponent<BacktraceClient>().Breadcrumbs.Info("Player Base Upgraded", new Dictionary<string, string>() {
{"base.name", "MtGox"},
{"base.level", "15"}
});
Sending reports
You can use backtraceClient.Send
to send error reports. For example:
try
{
//throw exception here
}
catch (Exception exception)
{
var report = new BacktraceReport(
exception: exception,
attributes: new Dictionary<string, string>() { { "key", "value" } },
attachmentPaths: new List<string>() { @"file_path_1", @"file_path_2" }
);
backtraceClient.Send(report);
}
Custom event handlers
You can also add custom event handlers to the client. For example, you can use BeforeSend
to trigger actions before the Send
method:
//Add a custom event handler
backtraceClient.BeforeSend =
(Model.BacktraceData model) =>
{
var data = model;
//do something with the data, for example:
data.Attributes.Attributes.Add("eventAttribute", "EventAttributeValue");
if(data.Classifier == null || !data.Classifier.Any())
{
data.Attachments.Add("path to attachment");
}
return data;
};
BacktraceClient
currently supports the following events:
BeforeSend
OnClientReportLimitReached
OnServerResponse
OnServerError
You can also use the backtraceReport
class to customize the data included in the error reports sent by the backtraceClient
.
Using BacktraceReport
The BacktraceReport
class represents a single error report. You can also submit custom attributes using the attributes parameter, or attach files by supplying an array of file paths in the attachmentPaths
parameter. For example:
try
{
//throw exception here
}
catch (Exception exception)
{
var report = new BacktraceReport(
exception: exception,
attributes: new Dictionary<string, string>() { { "key", "value" } },
attachmentPaths: new List<string>() { @"file_path_1", @"file_path_2" }
);
backtraceClient.Send(report);
}
You can use the Fingerprint
and Factor
properties to modify the client side deduplication strategy. The Fingerprint
property changes the hash that is generated, while the Factor
property changes how duplicated reports are aggregated. For example:
try
{
//throw exception here
}
catch (Exception exception)
{
var report = new BacktraceReport(...){
Fingerprint = "sha256 string",
Factor = exception.GetType().Name
};
...
}
Note: Fingerprint values must be a valid SHA-256 string.
The Backtrace client will send a single report when an exception occurs and maintain a count for every other time it occurs, which reduces the volume of reports that are generated and sent.
The count is reset when the offline database is cleared (usually when the reports are sent to the server) or if the game is closed before the reports are sent. A new single report is created the next time the exception occurs.
Information about aggregate reports is stored in backtraceDatabaseRecord
. You can use the Hash
property to verify the generated hash for the diagnostic data, and the Counter
property to verify the count of duplicate reports.
Filter reports
If you want to ignore specific types of error reports, we recommend that you use the Filter reports settings of the Backtrace Configuration asset in the Unity Editor.
However, for more advanced use cases, you can use BacktraceClient.SkipReport
to set the ReportFilterType
. For example:
// Return 'true' to ignore a report,
// Return 'false' to handle the report and generate it for the error.
BacktraceClient.SkipReport = (ReportFilterType type, Exception e, string msg) =>
{
// ReportFilterType is one of None, Message, Exception, UnhandledException or Hang.
// It is also possible to filter based on the exception and exception message.
// Report hangs and crashes only.
return type != ReportFilterType.Hang && type != ReportFilterType.UnhandledException;
};
Database management
backtraceDatabase.Clear
You can use backtraceDatabase.Clear();
to clear all reports from the database without sending them to the Backtrace server.
backtraceDatabase.Count
You can use backtraceDatabase.Count();
to return the number of reports stored in the database, including deduplicated reports.
backtraceDatabase.Delete
You can use backtraceDatabase.Delete();
to remove a report stored in the database, including deduplicated reports.
backtraceDatabase.Flush
You can use backtraceDatabase.Flush();
to send all reports to the Backtrace server then delete them from the database. This method is only needed to support the offline database when the Auto send mode is disabled.
Note: The Flush
method ignores client side deduplication and retry settings.
Caution: If the Send
method fails, the database will no longer store any data.
backtraceDatabase.Send
You can use backtraceDatabase.Send();
to send all reports to the Backtrace server, as defined by the client side deduplication and database retry settings. This method is only needed to support the offline database when the Auto send mode is disabled.
Data management
Use the Backtrace Unity SDK to modify and remove data that the library collects when an exception occurs using the following methods.
backtraceClient.BeforeSend
Triggers an event every time an exception in the managed environment occurs, so you can skip the report (by returning a null value) or to modify data that library collected before sending the report.
You can use BeforeSend
to extend attributes or JSON object data based on data the application has at the time of exception.
//Read from manager BacktraceClient instance
var backtraceClient = GameObject.Find("manager name").GetComponent<BacktraceClient>();
// set beforeSend event
_backtraceClient.BeforeSend = (BacktraceData data) =>
{
data.Attributes.Attributes["my-dynamic-attribute"] = "value";
return data;
};
Annotation.EnvironmentVariables
The Annotation
class exposes the EnvironmentVariablesCache
dictionary, which stores environment variables collected by the library. You can manipulate the data in this cache before the report is sent.
For example, you can use an annotation to replace the USERNAME
environment variable with a random string, which will be used to create reports.
Annotations.EnvironmentVariablesCache["USERNAME"] = "%USERNAME%";
}
You can also use BeforeSend
with annotations for environment variables to edit collected diagnostic data.
client.BeforeSend = (BacktraceData data) =>
{
data.Annotation.EnvironmentVariables["USERNAME"] = "%USERNAME%";
return data;
}
Architecture
backtraceApi
Class used to send diagnostic data in JSON format to the Backtrace endpoint, including asynchronous reports. backtraceApi
is instantiated when the backtraceClient awake method is called.
backtraceClient
Class used to send backtraceReport
to the Backtrace server by using backtraceApi
. backtraceClient
requires a Backtrace Configuration window. This class inherits MonoBehaviour
functions.
backtraceData
Serializable class that holds the diagnostic data in JSON format to be sent to the Backtrace endpoint via backtraceApi.
backtraceDatabase
Class that stores error report data in your local hard drive when reports fail to send due to network outages or server unavailability. backtraceDatabase
will periodically try to resend reports cached in the database.
backtraceReport
Class that defines a single error report.
reportWatcher
Class that validates send requests from backtraceApi
to the Backtrace endpoint. If ReportPerMin
is set in the backtraceClient
constructor call, ReportWatcher
will not send error reports that go over the limit.