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.

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.