diff --git a/CHANGELOG.md b/CHANGELOG.md index 06dbc949..af9b239f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,77 +1,87 @@ # Backtrace Unity Release Notes -## Version 3.4.0-rc1 +## Version 3.4.0-rc2 + - native/managed attachment support - user can add path to attachments via BacktraceClient Initialize method or via Unity Editor in the BacktraceClient's inspector. Once user add them on the initialization method/game object - it will be available in every report that BacktraceClient will send to Backtrace. - background thread support - now BacktraceClient will report exceptions/unhandled exceptions generated by any background thread. - ANR detection improvements - BacktraceClient won't report anymore ANRs detected when the application goes to the background. - `thread.main` attribute support - attribute stores an identifier of a main thread. In this situation user can use value available in this attribute to detect main thread. - Backtrace native integration will set `_mod_faulting_tid` attribute for ANR reports to set default faulting thread. +- Fixed arabic language bug, that generated an unhandled exception on new Unity message. ## Version 3.3.3 + - Fixed iOS compilation issue with Backtrace namespace. - Prevent displaying Backtrace configuration when `Application.isPlaying` is `true`. ## Version 3.3.2 + - ANR detection algorithm now uses `Time.unscaledTime` instead of `Time.time` to prevent ANR detection when game is paused. ## Version 3.3.1 + - Improved Out-of-memory detection on iOS - Backtrace will report Out-of-memory exceptions when a memory warning occured and the application unexpectly closed. The Out-of-memory watcher will analyse game version, system version, debugger information and even more to determine if application closed by Out-of-memory exception or not. - Backtrace will no longer send low memory warnings reports from Android or iOS. Instead, Backtrace will utilize iOS OOM detection and extend the embedded native report attributes on Android. - Users can now enable or disable out-of-memory detection any time via UI/Backtrace API. ## Version 3.3.0 + - `BacktraceReport` stack trace now includes the file name of the stack frame. - Performance improvements: - JSON algorithm performance improvements - avoid analyzing data types. - improved library attributes management. - improved Unity logs management. - Support for Low Memory error reports on Anrdoid and iOS (these are sometimes referred to as OOM or Out Of Memory errors). If a low memory situation is detected, backtrace-unity will attempt to generate and submit a native error report to the Backtrace instance. The report will have the `error.type` value of `Low Memory`. -- New support for hang detection on Android and iOS. If a game experiences non responsiviness after 5 seconds, backtrace-unity will generate an error report to the Backtrace instance. The report will have the `error.type` value of `Hang`. - +- New support for hang detection on Android and iOS. If a game experiences non responsiviness after 5 seconds, backtrace-unity will generate an error report to the Backtrace instance. The report will have the `error.type` value of `Hang`. ## Version 3.2.6 + - `BacktraceClient` will apply sampling only to errors lacking exception information. - Fixed annotations nullable value. - Renamed `BacktraceUnhandledException` classifier, which was generated from a Debug.LogError call, to `error`. - Fixed nullable environment annotation value. ## Version 3.2.5 + - Added `BacktraceClient` Initialization method that allows developer to intialize Backtrace integration without adding game object to game scene. - Fixed invalid `meta` file for iOS integration for Unity 2019.2.13f1. - HTTP communication messages improvements - right now Backtrace-Unity plugin will print only one error message when network failure happen. Backtrace-Unity will stop printing failures until next successfull report upload. -- Sampling skip fraction - Enables a new random sampling mechanism for BacktraceUnhandledExceptions (errors from Debug.LogError), by setting default sampling equal to 0.01 - which means only 1% of randomly sampled Debug.LogError reports will be send to Backtrace. If you would like to send all Debug.LogError to Backtrace - please replace 0.01 value with 1. +- Sampling skip fraction - Enables a new random sampling mechanism for BacktraceUnhandledExceptions (errors from Debug.LogError), by setting default sampling equal to 0.01 - which means only 1% of randomly sampled Debug.LogError reports will be send to Backtrace. If you would like to send all Debug.LogError to Backtrace - please replace 0.01 value with 1. **Be aware** By default Backtrace library will send only 1% of your Debug.LogError reports - please change this value if you would like to send more Debug.LogErrors to server. - - ## Version 3.2.4 + - Fixed Backtrace-Unity NDK integration database path. ## Version 3.2.3 -- Backtrace offline database will now store 8 reports by default. Previously this was not set by default. + +- Backtrace offline database will now store 8 reports by default. Previously this was not set by default. - HTTP client communication improvements - Improvements in UPM - Updated symbolication strategy on iOS crashes ## Version 3.2.2 + - Fixed native iOS attributes ## Version 3.2.1 + - Android stack trace parser improvements, - Fixed Android NDK initialization when database directory doesn't exist, - Added Privacy section to Readme - ## Version 3.2.0 + - This release adds the ability to capture native iOS crashes from Unity games deployed to iOS. The Backtrace Configuration now exposes a setting for games being prepared for iOS to choose `Capture native crashes`. When enabled, the backtrace-unity client will capture and submit native iOS crashes to the configured Backtrace instance. To generate human readable callstacks, game programmers will need to generate and upload appropriate debug symbols. - Added default uname.sysname attributes for some platforms. The following is the list of uname.sysname platforms that can be populated. list "Android, IOS, Linux, Mac OS, ps3, ps4, Samsung TV, tvOS, WebGL, WiiU, Switch, Xbox". Note 'Switch' had previously been reported as 'switch' - Added a new attribute 'error.type' that allows developers to quickly filter error reports based on the type of error - The list includes "Crash, Message, Hang, Unhandled Exception, Exception". - Updated Android NDK libraries used by Unity plugin. ## Version 3.1.2 + - `BacktraceData` allows to edit list of environment variables collected by `BacktraceAnnotations` - `SourceCode` object description for PII purpose - `Annotations` class exposes EnvironmentVariableCache dictionary - dictionary that stores environment variables collected by library. For example - to replace `USERNAME` environment variable collected by Backtrace library with random string you can easily edit annotations environment varaible and Backtrace-Untiy will reuse them on report creation. @@ -81,6 +91,7 @@ Annotations.EnvironmentVariablesCache["USERNAME"] = "%USERNAME%"; ``` Also you can still use BeforeSend event to edit collected diagnostic data: + ```csharp client.BeforeSend = (BacktraceData data) => { @@ -90,32 +101,39 @@ Also you can still use BeforeSend event to edit collected diagnostic data: ``` ## Version 3.1.1 + - Prevent erroneously extending backtraceClient attributes with backtraceReport attributes. - Removed randomly generated path to assembly from callstacks. - Prevent client from multi initialization. ## Version 3.1.0 + This release adds an ability to capture native NDK crashes from Unity games deployed on Android. The Backtrace Configuration now exposes a setting for games being prepared for Android OS to choose `Capture native crashes`. When enabled, Backtrace will capture and symbolicate native stack traces from crashes impacting the Unity Engine or any Unity Engine Plugin. -When develoing for Andriod, Unity users who want to debug native NDK crash report can specify a Backtrace Symbols Server Token to support the optional uploading of debug symbols from Unity Editor to Backtrace during build. Uploaded symbols are needed to generate human readable stack trace with proper function names for identifying issues. +When develoing for Andriod, Unity users who want to debug native NDK crash report can specify a Backtrace Symbols Server Token to support the optional uploading of debug symbols from Unity Editor to Backtrace during build. Uploaded symbols are needed to generate human readable stack trace with proper function names for identifying issues. Backtrace library now allows to set client attributes, that will be included in every report. In addition to that, Backtrace client attributes will be available in the native crashes generated by Android games. To setup client attributes you can simply type + ```csharp BacktraceClient["name-of-attribute"] = "value-of-attribute"; ``` -If you already have dictionary of attributes you can use `SetAttributes` method. + +If you already have dictionary of attributes you can use `SetAttributes` method. ## Version 3.0.4 + Preliminary Nintendo Switch support has been introduced. The offline database is not currently supported in this version, but will be included in an upcoming release. ## Version 3.0.3 + This release includes significant improvements to performance by way of report filtering as well as improved performance diagnostics. Learn more below. - + - `BacktraceClient` now supports report filtering. Report filtering is enabled by using the `Filter reports` option in the user interface or for more advanced use-cases, the `SkipReport` delegate available in the BacktraceClient. - -Sample code: + +Sample code: + ```csharp // Return true to ignore a report, return false to handle the report // and generate one for the error. @@ -129,19 +147,21 @@ Sample code: return type != ReportFilterType.Hang && type != ReportFilterType.UnhandledException; }; ``` - + For example, to only get error reporting for hangs or crashes then only return false for Hang or UnhandledException or set the corresponding options in the user interface as shown below. ![Sample report filter](./Documentation~/images/report-filter.PNG) -- Support for backtrace-unity timing observability. To enable sending performance information to Backtrace set the`Enable performance statistics` option in the UI. Attributes are created under the performance.* namespace, time unit is microseconds: - * Report creation time (`performance.report`), - * JSON serialization time (`performance.json`), - * Database add operation time (`performance.database`), - * Database single send method time (`performance.send`), - * Database single flush method time (`performance.flush`) + +- Support for backtrace-unity timing observability. To enable sending performance information to Backtrace set the`Enable performance statistics` option in the UI. Attributes are created under the performance.\* namespace, time unit is microseconds: + - Report creation time (`performance.report`), + - JSON serialization time (`performance.json`), + - Database add operation time (`performance.database`), + - Database single send method time (`performance.send`), + - Database single flush method time (`performance.flush`) - Improvements to JIT stack frame parsing. ## Version 3.0.2 + - `BacktraceDatabase` now provides a new `Send` method. This method will try to send all objects from the database respecting the client side deduplication and retry setting. This can be used as an alternative to the `Flush` method which will try to send all objects from the database ignoring any client side deduplication and retry settings. - `BacktraceClient` has been optimized to only serialize data as needed. - `BacktraceDatabase` `AutoSend` function has been optimized for performance improvements. @@ -149,14 +169,16 @@ For example, to only get error reporting for hangs or crashes then only return f - Fixed invalid meta file. ## Version 3.0.1 + - The `BacktraceDatabase` class will now create database directory before final database validation. Previously, when directory didn't exist, BacktraceDatabase was disabled. -- The `BacktraceDatabase` field now allows users to pass interpolated string in Database options. Developer can use `${Application.dataPath}` or `${Application.persistentDataPath}` to set path to database. -- The backtrace-unity library will generate screenshot image files in .jpg format. -- Optimizations in ANR watchdog and `BacktraceLogManager` initialization - The Backtrace client will now create a class instance of `BacktraceAnrWatchdog` class, instead of creating instance via static class method. The `BacktraceLogManager` (class responsible for storing log data) will be initialized in `CaptureUnityMessages`. +- The `BacktraceDatabase` field now allows users to pass interpolated string in Database options. Developer can use `${Application.dataPath}` or `${Application.persistentDataPath}` to set path to database. +- The backtrace-unity library will generate screenshot image files in .jpg format. +- Optimizations in ANR watchdog and `BacktraceLogManager` initialization - The Backtrace client will now create a class instance of `BacktraceAnrWatchdog` class, instead of creating instance via static class method. The `BacktraceLogManager` (class responsible for storing log data) will be initialized in `CaptureUnityMessages`. ## Version 3.0.0 -*New Features* +_New Features_ + - The backtrace-unity library (Backtrace) now allows detection of ANR (Application not responding) events on Android devices. - Unhandled exception output from the Unity runtime and executables is now prominently displayed in the Debugger. - Backtrace will try to guess unhandled exception classifier based on exception message/stack trace. @@ -164,11 +186,12 @@ For example, to only get error reporting for hangs or crashes then only return f - Backtrace now allows you to add a screenshot as an attachment when an exception occured. - Backtrace now allows you to capture last n lines of game logs. You can define how many lines of logs Backtrace should store by settings `Collect last n number of logs` property in the Unity editor. - Backtrace will capture any native Unity Engine crash dumps on Windows OS. -- Backtrace will capture and index native metadata from the Android OS as Backtrace Attribuces, including vm, system.memory, and device details. +- Backtrace will capture and index native metadata from the Android OS as Backtrace Attribuces, including vm, system.memory, and device details. - Backtrace allows you control whether or not a report should send via the BeforeSend event. If you return a null value from a BeforeSend event, Backtrace will discard the report and not send. -*General Improvements* -- `BacktraceClient`, `BacktraceReport`, `BacktraceData`, `BacktraceData` and `BacktraceDatabase` now allow users to pass attributes in dictionary form with string key and string values. Attributes must now be provided with the Dictionary data structure to allow the serializer to be as fast as possible. +_General Improvements_ + +- `BacktraceClient`, `BacktraceReport`, `BacktraceData`, `BacktraceData` and `BacktraceDatabase` now allow users to pass attributes in dictionary form with string key and string values. Attributes must now be provided with the Dictionary data structure to allow the serializer to be as fast as possible. - Removed dependancy on 3rd party JSON.NET library to reduce the size of the package. Backtrace-unity now provides it's own serializer for BacktraceReport usage. - Further reduction in size of Backtrace.Unity assembly with BacktraceJObject. - `BacktraceDatabase` won't try to deserialize `BacktraceReport` anymore - because of that, callback api won't return `BacktraceReport` object in `BacktraceResult`. @@ -176,12 +199,12 @@ For example, to only get error reporting for hangs or crashes then only return f - Support has been improved for parsing unhandled exception output from the Unity runtime and Unity executables. **NOTE:** When migrating from previous releases, there is an API change that developers will want to uptake for attribute submission. Specifically, attribute definitions previously used a signature -attributes: `new Dictionary() { { "key", "value" } }`, +attributes: `new Dictionary() { { "key", "value" } }`, In this release, we made a change to require a string for the value instead of an object for faster performance. -attributes: `new Dictionary() { { "key", "value" } }`, +attributes: `new Dictionary() { { "key", "value" } }`, +_Bug Fixes_ -*Bug Fixes* - Annotation name typo - updated `children` from `childrens` ## Version 2.1.6 diff --git a/README.md b/README.md index e34b21de..08e9b91f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,9 @@ - # Backtrace Unity support [Backtrace](http://backtrace.io/)'s integration with Unity allows developers to capture and report log errors, handled and unhandled Unity exceptions, and native crashes to their Backtrace instance, instantly offering the ability to prioritize and debug software errors. [![openupm](https://img.shields.io/npm/v/io.backtrace.unity?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/io.backtrace.unity/) - [github release]: (https://github.com/backtrace-labs/backtrace-labs/) - [Features Summary](#features-summary) @@ -20,14 +18,13 @@ - [Architecture description](#architecture-description) - [Investigating an Error in Backtrace](#investigating-an-error-in-backtrace) - ## Usage ```csharp //Read from manager BacktraceClient instance var backtraceClient = GameObject.Find("_Manager").GetComponent(); -try +try { //throw exception here } @@ -40,10 +37,10 @@ catch(Exception exception) # Feature Summary -- Lightweight library that quickly submits log errors, handled and unhandled exceptions, and native crashes to Backtrace +- Lightweight library that quickly submits log errors, handled and unhandled exceptions, and native crashes to Backtrace - Supports wide range of Unity versions (2017.4+) and deployments (iOS, Android, Windows, Mac, WebGL, PS4/5 Xbox One/S/X, Nintendo Switch, Stadia) - Install via [OpenUPM](https://openupm.com/packages/io.backtrace.unity/) and the Unity Package Manager -- Collect detailed context +- Collect detailed context - Callstacks, including function names and line numbers where possible - System metadata including device GUID, OS version, memory usage, process age - Custom metadata including app version, scene info, device drivers @@ -65,20 +62,22 @@ catch(Exception exception) - Backtrace instance - Create your own at https://backtrace.io/create-unity # Platforms Supported + Backtrace-unity has been tested and certified for games deployed on the following platforms: Mobile - Android, iOS PC - Windows, Mac Web - WebGL Game Consoles - PlayStation4, Xbox One, Nintendo Switch There are some differences in capabilities that backtrace-unity provides based on the platform. Major capabilities are summarized as follows: -* All Platforms - Errors, Unhandled Exceptions, Handled Exceptions, Custom Indexable Metadata, File Attachments*, Last N Log Lines, Automatic attachment of Screenshots, Client Side Deduplication Rules*, Client Side Submission Filtering, Client Side Submission Limits, Performance Diagnostics, Offline Database*(Except Nintendo Switch) -* Android -Identified by attribute `uname.sysname` = Android; ANRs (Hangs), Native Process and Memory Information, Java Exception Handler (Plugins, Exported Game in Android Studio), NDK crashes, low memory warnings. -* iOS - Identified by attribute `uname.sysname` = IOS; ANRs (Hangs), Native Engine, Memory and Plugin Crashes. -* WebGL - Identified by attribute `uname.sysname` = WebGL. The attribute device.model is currently used to share the browser information. Note that stacktraces for WebGL errors are only available if you choose to enable them in the Publishing Settings / Enable Exceptions drop down. More details [here](https://docs.unity3d.com/Manual/webgl-building.html) -* Switch - Identified by attribute `uname.sysname` = Switch. Note that the attribute GUID is regenerated with each Switch restart (It is not an accurate count of number of Users or Devices. It is a count of Switch Sessions). Note that the current release does no support Offline Database or related features. -* PlayStation4 - Identified by attribute `uname.sysname` = PS4 -* Windows - Identified by attribute `uname.sysname` = Windows. Provides an option to capture Minidumps for Engine Crashes. -* MacOS - Identified by attribute `uname.sysname` = MacOS. + +- All Platforms - Errors, Unhandled Exceptions, Handled Exceptions, Custom Indexable Metadata, File Attachments*, Last N Log Lines, Automatic attachment of Screenshots, Client Side Deduplication Rules*, Client Side Submission Filtering, Client Side Submission Limits, Performance Diagnostics, Offline Database\*(Except Nintendo Switch) +- Android -Identified by attribute `uname.sysname` = Android; ANRs (Hangs), Native Process and Memory Information, Java Exception Handler (Plugins, Exported Game in Android Studio), NDK crashes, low memory warnings. +- iOS - Identified by attribute `uname.sysname` = IOS; ANRs (Hangs), Native Engine, Memory and Plugin Crashes. +- WebGL - Identified by attribute `uname.sysname` = WebGL. The attribute device.model is currently used to share the browser information. Note that stacktraces for WebGL errors are only available if you choose to enable them in the Publishing Settings / Enable Exceptions drop down. More details [here](https://docs.unity3d.com/Manual/webgl-building.html) +- Switch - Identified by attribute `uname.sysname` = Switch. Note that the attribute GUID is regenerated with each Switch restart (It is not an accurate count of number of Users or Devices. It is a count of Switch Sessions). Note that the current release does no support Offline Database or related features. +- PlayStation4 - Identified by attribute `uname.sysname` = PS4 +- Windows - Identified by attribute `uname.sysname` = Windows. Provides an option to capture Minidumps for Engine Crashes. +- MacOS - Identified by attribute `uname.sysname` = MacOS. Note: Unity allows you to disable stack trace information in player properties. If this is set, the call stack and the log lines section in Backtrace will be empty. @@ -89,12 +88,15 @@ List of steps necessary to setup full Backtrace Unity integration. ## Installation guide ### OpenUPM + - See [our package](https://openupm.com/packages/io.backtrace.unity/) and installation instructions on OpenUPM. ### Git Url + Since Unity 2018.3 the Unity Package Manager allows you to install a package directly via [Git](https://docs.unity3d.com/Manual/upm-ui-giturl.html). You can use the clone URL on the main page of our repository. ### Manual download + - Download the backtrace-unity zip file. Unzip it and keep the folder in a known location. It can be downloaded [here](https://github.com/backtrace-labs/backtrace-unity/releases) - Open your Unity project - Use the Unity Package Manager to install the backtrace-unity library (Window -> Package Manager -> Add Package From Disk -> `KnownFolder/package.json`) @@ -121,7 +123,8 @@ One of the integration paths require to create game object in your game scene. I attributes: attributes); ``` -If you need to use more advanced configuration, `Initialize` method accepts a `BacktraceConfiguration` scriptable object. +If you need to use more advanced configuration, `Initialize` method accepts a `BacktraceConfiguration` scriptable object. + ```csharp var configuration = ScriptableObject.CreateInstance(); configuration.ServerUrl = serverUrl; @@ -138,18 +141,19 @@ If you need to use more advanced configuration, `Initialize` method accepts a `B # Plugin best practices The plugin will report on 6 'classes' or errors: -1) Log Errors - Programmers use [Debug.LogError](https://docs.unity3d.com/ScriptReference/Debug.LogError.html), a variant of Debug.Log, to log error messages to the console. -2) Unhandled Exceptions - Unhandled Exceptions are exceptions in a game that occur outside of an explicit try / catch statement. -3) Handled Exceptions - Exceptions that are explicitly caught and handled. -4) Crashes - An end to the game play experience. The game crashes or restarts. -5) Hangs - A game is non responsive. Some platforms will tell the user “This app has stopped responding -6) Low memory warning - A game is receiving signals from the OS that memory is under pressure or crashed under memory pressure. - -The plugin provides 3 controls for managing what the client will report. -- [SkipReports](#filtering-a-report) allows you to tell the client to only report on specific classes of these errors. -- [Log Error Sampling](#sampling-log-errors) allows you to tell the client to sample the Debug Log errors. Programmers may not be aware of the frequency that Debug Log errors are being generated when released in retail, and we recommend you are intentional about capturing these types of errors. -- [Client Side Deduplication](#client-side-deduplication) allows you to aggregate the reports based on callstack, error message, or classifier, and send only a single message to Backtrace each time the offline database is flushed. +1. Log Errors - Programmers use [Debug.LogError](https://docs.unity3d.com/ScriptReference/Debug.LogError.html), a variant of Debug.Log, to log error messages to the console. +2. Unhandled Exceptions - Unhandled Exceptions are exceptions in a game that occur outside of an explicit try / catch statement. +3. Handled Exceptions - Exceptions that are explicitly caught and handled. +4. Crashes - An end to the game play experience. The game crashes or restarts. +5. Hangs - A game is non responsive. Some platforms will tell the user “This app has stopped responding +6. Low memory warning - A game is receiving signals from the OS that memory is under pressure or crashed under memory pressure. + +The plugin provides 3 controls for managing what the client will report. + +- [SkipReports](#filtering-a-report) allows you to tell the client to only report on specific classes of these errors. +- [Log Error Sampling](#sampling-log-errors) allows you to tell the client to sample the Debug Log errors. Programmers may not be aware of the frequency that Debug Log errors are being generated when released in retail, and we recommend you are intentional about capturing these types of errors. +- [Client Side Deduplication](#client-side-deduplication) allows you to aggregate the reports based on callstack, error message, or classifier, and send only a single message to Backtrace each time the offline database is flushed. ## Backtrace Client and Offline Database Settings @@ -163,15 +167,15 @@ The following is a reference guide to the Backtrace Client fields: - Send unhandled native game crashes on startup: Try to find game native crashes and send them on Game startup. - Handle unhandled exceptions: Toggle this on or off to set the library to handle unhandled exceptions that are not captured by try-catch blocks. - Symbols upload token - If you want to upload Unity debug symbols for Android NDK Native Crash debugging, enter your Backtrace Symbol upload token here. This option is available only in Android build. -- Log random sampling rate - Enables a random sampling mechanism for DebugLog.error messages - **by default** sampling is equal to **0.01** - which means only **1%** of randomply sampling **reports will be send** to Backtrace. If you would like to send all DebugLog.error messages to Backtrace - please replace 0.01 value with 1. +- Log random sampling rate - Enables a random sampling mechanism for DebugLog.error messages - **by default** sampling is equal to **0.01** - which means only **1%** of randomply sampling **reports will be send** to Backtrace. If you would like to send all DebugLog.error messages to Backtrace - please replace 0.01 value with 1. - Game Object Depth Limit: Allows developer to filter number of game object childrens in Backtrace report. -- Collect last n game logs: Collect last n number of logs generated by game. +- Collect last n game logs: Collect last n number of logs generated by game. - Enabled performance statistics: Allows `BacktraceClient` to measure execution time and include performance information as report attributes. - Ignore SSL validation: Unity by default will validate ssl certificates. By using this option you can avoid ssl certificates validation. However, if you don't need to ignore ssl validation, please set this option to false. - Handle ANR (Application not responding) - this options is available only in Android and iOS build. It allows to catch ANR (application not responding) events happened to your game in Android/iOS devices. In this release, ANR is set to detect after 5 seconds. This will be configurable in a future release. - Enable Database: When this setting is toggled, the backtrace-unity plugin will configure an offline database that will store reports if they can't be submitted do to being offline or not finding a network. When toggled on, there are a number of Database settings to configure. -- Backtrace Database path: This is the path to directory where the Backtrace database will store reports on your game. You can use interpolated strings SUCH AS -`${Application.persistentDataPath}/backtrace/database` to dynamically look up a known directory structure to use. NOTE: Backtrace database will remove all existing files in the database directory upion first initialization. +- Backtrace Database path: This is the path to directory where the Backtrace database will store reports on your game. You can use interpolated strings SUCH AS + `${Application.persistentDataPath}/backtrace/database` to dynamically look up a known directory structure to use. NOTE: Backtrace database will remove all existing files in the database directory upion first initialization. - Create database directory toggle: If toggled, the library will create the offline database directory if the provided path doesn't exists, - Client-side deduplication: Backtrace-unity plugin allows you to combine the same reports. By using deduplication rules, you can tell backtrace-unity plugin how we should merge reports. - Capture native crashes: This option will appear for games being deployed to Android or iOS and will allow Backtrace to capture and symbolicate native stack traces from crashes impacting the Unity Engine or any Unity Plugin. @@ -184,6 +188,7 @@ The following is a reference guide to the Backtrace Client fields: - Retry interval: If the database is unable to send its record, this setting specifies how many seconds the library should wait between retries. - Maximum retries: If the database is unable to send its record, this setting specifies the maximum number of retries before the system gives up. - Retry order: This specifies in which order records are sent to the Backtrace server. + # Android Specific information The backtrace-unity library includes support for capturing Android NDK crashes and additional Android Native information, from underlying Android OS (Memory and process related), JNI, and NDK layers. @@ -202,20 +207,22 @@ Backtrace can detect low memory situations for a game running in Unity on Androi ## Symbols upload -Unity allows developer to generate symbols archive called `symbols.zip` in the il2cpp build pipeline in the root directory of your game. In this archive you can find generated symbols for your game libraries. When your game crashes due to a native exception, your stack trace will contain only memory addresses instead of function name. Symbols from `symbols.zip` archive allows Backtrace to match function address to function name in your source code. +Unity allows developer to generate symbols archive called `symbols.zip` in the il2cpp build pipeline in the root directory of your game. In this archive you can find generated symbols for your game libraries. When your game crashes due to a native exception, your stack trace will contain only memory addresses instead of function name. Symbols from `symbols.zip` archive allows Backtrace to match function address to function name in your source code. To generate `symbols.zip` archive make sure: -* you selected il2cpp build, -* you checked `Create symbols.zip` in the Build settings window -![Create symbols.zip](./Documentation~/images/symbols.png) + +- you selected il2cpp build, +- you checked `Create symbols.zip` in the Build settings window + ![Create symbols.zip](./Documentation~/images/symbols.png) Backtrace offers to upload symbols automatically from Unity Editor to your Backtrace instance. Backtrace symbols upload pipeline will be triggered after successfull build of il2cpp Android game and when Symbols upload token is available in Backtrace Client options. After successfull build, upload pipeline will confirm symbols upload. -If you build outside the Unity Editor and need to manually upload symbols to Backtrace, you must rename symbols generated by Unity end simply with a `.so` extension. By default, symbol files within the .zip will end with extension `.sym.so`. or `.dbg.so` Backtrace will only match symbols to files based on the ending with `.so` extension. Please ensure all files have a single `.so` extention before uploading the zip. +If you build outside the Unity Editor and need to manually upload symbols to Backtrace, you must rename symbols generated by Unity end simply with a `.so` extension. By default, symbol files within the .zip will end with extension `.sym.so`. or `.dbg.so` Backtrace will only match symbols to files based on the ending with `.so` extension. Please ensure all files have a single `.so` extention before uploading the zip. To learn more about how to submit those symbol files to Backtrace, please see the Project Settings / Symbols. You can manage submission tokens, upload via the UI, or configure external Symbol Servers to connect and discover required symbols. Please review additional Symbol documentaion at https://support.backtrace.io/hc/en-us/articles/360040517071-Symbolication-Overview # iOS Specific information + The backtrace-unity library includes support for capturing native iOS crashes as well as iOS native memory and process information from underlying iOS layer. ## Native process and memory related information @@ -223,16 +230,20 @@ The backtrace-unity library includes support for capturing native iOS crashes as system and vm usage related information including system.memory.free, system.memory.used, system.memory.total, system.memory.active, system.memory.inactive, system.memory.wired are avaialble. ## Hangs + When configuring the backtrace-unity client for an iOS deployment, programmers will have a toggle available in the backtrace-unity GUI in the Unity Editor to enable or disable ANR or Hang reports. This will use the default of 5 seconds. The `error.type` for these reports will be `Hang`. ## Low Memory Reports (Early access) + Backtrace can detect low memory situations for a game running in Unity on iOS devices, and attempt to generate an error report with an associated dump object for further investigation. When configuring the backtrace-unity client for an iOS deployment, programmers will have a toggle available in the backtrace-unity GUI in the Unity Editor to enable or disable sending Out of memory exceptions to Backtrace. The `error.type` for these reports wiill be `Low Memory`. ## Native Crashes + When configuring the backtrace-unity client for an iOS deployment in the Unity Editor, programmers will have a toggle to enable or disable `Capture native crashes`. If this is enabled, the backtrace-unity client will ensure the crash report is generated, stored locally, and uploaded upon next game start. Unity crash reporter might prevent Backtrace Crash reporter from sending crashes to Backtrace. To be sure Backtrace is able to collect and send data please set "Enable CrashReport API" to false. ![Enable symbols](./Documentation~/images/Disable-ios-unity-crash-reporter.png) ## Debug Symbol upload + When building your iOS game in Xcode, you must make sure you configure the build settings to generate "`DWARF with dSYM files` for any build that you want to debug with Backtrace (By default, it may only generate `DWARF`). In the example below, `DWARF with dSYM files` is enabled in the `Project Build Settings` for each `Target`. ![Enable symbols](./Documentation~/images/xCode-enable-debugging-symbols.png) @@ -246,8 +257,8 @@ To learn more about how to submit those symbol files to Backtrace, please see th Backtrace-Unity allows developers to remove and modify data that the library collects when an exception occurs using the following methods: -* BeforeSend event -The library will fire an event every time an exception in the managed environment occurs. The BeforeEvent trigger allows you to skip the report (you can do that by returning null value) or to modify data that library collected before sending the report. BeforeSend event might be useful in case if you would like to extend attributes or json object data based on data that application has at the time of exception. +- BeforeSend event + The library will fire an event every time an exception in the managed environment occurs. The BeforeEvent trigger allows you to skip the report (you can do that by returning null value) or to modify data that library collected before sending the report. BeforeSend event might be useful in case if you would like to extend attributes or json object data based on data that application has at the time of exception. Example code: @@ -262,14 +273,15 @@ _backtraceClient.BeforeSend = (BacktraceData data) => }; ``` -* Environment Variable Management -The `Annotations` class exposes the EnvironmentVariableCache dictionary - a dictionary that stores environment variables collected by the library. You can manipulate the data in this cache before the report is sent. For example - to replace the`USERNAME` environment variable collected by Backtrace library with random string you can easily edit annotations environment varaible and Backtrace-Untiy will reuse them on report creation. +- Environment Variable Management + The `Annotations` class exposes the EnvironmentVariableCache dictionary - a dictionary that stores environment variables collected by the library. You can manipulate the data in this cache before the report is sent. For example - to replace the`USERNAME` environment variable collected by Backtrace library with random string you can easily edit annotations environment varaible and Backtrace-Untiy will reuse them on report creation. ```csharp Annotations.EnvironmentVariablesCache["USERNAME"] = "%USERNAME%"; ``` Also you can still use BeforeSend event to edit collected diagnostic data: + ```csharp client.BeforeSend = (BacktraceData data) => { @@ -278,7 +290,6 @@ Also you can still use BeforeSend event to edit collected diagnostic data: } ``` - # API Overview You can further configure your game to submit crashes by making further changes in the C# code for your game. @@ -385,7 +396,7 @@ backtraceClient.BeforeSend = { var data = model; //do something with data for example: - data.Attributes.Add("eventAttribute", "EventAttributeValue"); + data.Attributes.Attributes.Add("eventAttribute", "EventAttributeValue"); if(data.Classifier == null || !data.Classifier.Any()) { data.Attachments.Add("path to attachment"); @@ -404,12 +415,14 @@ backtraceClient.BeforeSend = ## Reporting unhandled application exceptions -`BacktraceClient` supports reporting of unhandled application exceptions not captured by your try-catch blocks. To enable reporting of unhandled exceptions please use Backtrace configuration UI available in the Unity IDE. +`BacktraceClient` supports reporting of unhandled application exceptions not captured by your try-catch blocks. To enable reporting of unhandled exceptions please use Backtrace configuration UI available in the Unity IDE. + +## Filtering a report -## Filtering a report Report filtering is enabled by using the `Filter reports` option in the user interface or for more advanced use-cases, the `SkipReport` delegate available in the BacktraceClient. - -Sample code: + +Sample code: + ```csharp // Return true to ignore a report, return false to handle the report // and generate one for the error. @@ -423,12 +436,13 @@ Sample code: return type != ReportFilterType.Hang && type != ReportFilterType.UnhandledException; }; ``` - + For example, to only get error reporting for hangs or crashes then only return false for Hang or UnhandledException or set the corresponding options in the user interface as shown below. ![Sample report filter](./Documentation~/images/report-filter.PNG) ## Sampling Log Errors -`BacktraceClient` allows a configuration setting for log error sampling rate, which enables a random sampling mechanism for the errors captured via the DebugLog.error call. By default this sampling is equal to 0.01 - which means 1 of randomly sampled DebugLog Error Reports will be sent to Backtrace. This is a measure to prevent users from inadvertantly collecting hundreds of thousands of error messages from released games that they may not intend to. If you would like to send all DebugLog.error messages to Backtrace - please replace 0.01 value with 1. + +`BacktraceClient` allows a configuration setting for log error sampling rate, which enables a random sampling mechanism for the errors captured via the DebugLog.error call. By default this sampling is equal to 0.01 - which means 1 of randomly sampled DebugLog Error Reports will be sent to Backtrace. This is a measure to prevent users from inadvertantly collecting hundreds of thousands of error messages from released games that they may not intend to. If you would like to send all DebugLog.error messages to Backtrace - please replace 0.01 value with 1. ## Flush database @@ -439,6 +453,7 @@ backtraceDatabase.Flush(); ``` ## Send database + This method will try to send all objects from the database respecting the client side deduplication and retry setting. This can be used as an alternative to the `Flush` method which will try to send all objects from the database ignoring any client side deduplication and retry settings. ```csharp @@ -461,7 +476,7 @@ Backtrace unity integration allows you to aggregate the same reports and send on Deduplication strategy types: - Ignore - ignore deduplication strategy -- Default - deduplication strategy will use current strack trace to find duplicated reports +- Default - deduplication strategy will use current strack trace to find duplicated reports - Classifier - deduplication strategy will use stack trace and exception type to find duplicated reports - Message - deduplication strategy will use stack trace and exception message to find duplicated reports diff --git a/Runtime/BacktraceClient.cs b/Runtime/BacktraceClient.cs index 489e5668..56036097 100644 --- a/Runtime/BacktraceClient.cs +++ b/Runtime/BacktraceClient.cs @@ -8,6 +8,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.Threading; using UnityEngine; @@ -21,7 +22,7 @@ public class BacktraceClient : MonoBehaviour, IBacktraceClient { public BacktraceConfiguration Configuration; - public const string VERSION = "3.4.0-rc1"; + public const string VERSION = "3.4.0-rc2"; public bool Enabled { get; private set; } /// @@ -676,7 +677,7 @@ record = Database.Add(data); if (data.Deduplication != 0) { - queryAttributes["_mod_duplicate"] = data.Deduplication.ToString(); + queryAttributes["_mod_duplicate"] = data.Deduplication.ToString(CultureInfo.InvariantCulture); } StartCoroutine(BacktraceApi.Send(json, data.Attachments, queryAttributes, (BacktraceResult result) => @@ -916,7 +917,7 @@ private bool ShouldSendReport(Exception exception, List attachmentPaths, } //check rate limiting - bool shouldProcess = _reportLimitWatcher.WatchReport(new DateTime().Timestamp()); + bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp()); if (shouldProcess) { // This condition checks if we should send exception from current thread @@ -926,7 +927,7 @@ private bool ShouldSendReport(Exception exception, List attachmentPaths, if (Thread.CurrentThread.ManagedThreadId != _current.ManagedThreadId) { var report = new BacktraceReport(exception, attributes, attachmentPaths); - report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(); + report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture); BackgroundExceptions.Push(report); return false; } @@ -951,7 +952,7 @@ private bool ShouldSendReport(string message, List attachmentPaths, Dict } //check rate limiting - bool shouldProcess = _reportLimitWatcher.WatchReport(new DateTime().Timestamp()); + bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp()); if (shouldProcess) { // This condition checks if we should send exception from current thread @@ -961,7 +962,7 @@ private bool ShouldSendReport(string message, List attachmentPaths, Dict if (Thread.CurrentThread.ManagedThreadId != _current.ManagedThreadId) { var report = new BacktraceReport(message, attributes, attachmentPaths); - report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(); + report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture); BackgroundExceptions.Push(report); return false; } @@ -990,7 +991,7 @@ private bool ShouldSendReport(BacktraceReport report) return false; } //check rate limiting - bool shouldProcess = _reportLimitWatcher.WatchReport(new DateTime().Timestamp()); + bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp()); if (shouldProcess) { // This condition checks if we should send exception from current thread @@ -999,7 +1000,7 @@ private bool ShouldSendReport(BacktraceReport report) // and let update method send data to Backtrace. if (Thread.CurrentThread.ManagedThreadId != _current.ManagedThreadId) { - report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(); + report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture); BackgroundExceptions.Push(report); return false; } diff --git a/Runtime/BacktraceDatabase.cs b/Runtime/BacktraceDatabase.cs index b5a1b29b..b9a8dcd3 100644 --- a/Runtime/BacktraceDatabase.cs +++ b/Runtime/BacktraceDatabase.cs @@ -6,6 +6,7 @@ using Backtrace.Unity.Types; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using UnityEngine; @@ -372,7 +373,7 @@ private void FlushRecord(BacktraceDatabaseRecord record) return; } - queryAttributes["_mod_duplicate"] = record.Count.ToString(); + queryAttributes["_mod_duplicate"] = record.Count.ToString(CultureInfo.InvariantCulture); StartCoroutine( BacktraceApi.Send(backtraceData, record.Attachments, queryAttributes, (BacktraceResult result) => @@ -403,7 +404,7 @@ private void SendData(BacktraceDatabaseRecord record) stopWatch.Stop(); queryAttributes["performance.database.send"] = stopWatch.GetMicroseconds(); } - queryAttributes["_mod_duplicate"] = record.Count.ToString(); + queryAttributes["_mod_duplicate"] = record.Count.ToString(CultureInfo.InvariantCulture); StartCoroutine( BacktraceApi.Send(backtraceData, record.Attachments, queryAttributes, (BacktraceResult sendResult) => @@ -418,7 +419,7 @@ private void SendData(BacktraceDatabaseRecord record) BacktraceDatabaseContext.IncrementBatchRetry(); return; } - bool shouldProcess = _reportLimitWatcher.WatchReport(new DateTime().Timestamp()); + bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp()); if (!shouldProcess) { return; diff --git a/Runtime/Common/DateTimeHelper.cs b/Runtime/Common/DateTimeHelper.cs new file mode 100644 index 00000000..97684a43 --- /dev/null +++ b/Runtime/Common/DateTimeHelper.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Backtrace.Unity.Common +{ + internal static class DateTimeHelper + { + public static int Timestamp() + { + return (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; + } + } +} diff --git a/Runtime/Extensions/DateTimeExtensions.cs.meta b/Runtime/Common/DateTimeHelper.cs.meta similarity index 83% rename from Runtime/Extensions/DateTimeExtensions.cs.meta rename to Runtime/Common/DateTimeHelper.cs.meta index 0a8c805e..7822f1b5 100644 --- a/Runtime/Extensions/DateTimeExtensions.cs.meta +++ b/Runtime/Common/DateTimeHelper.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 279528ffbca9ca5439d18486d7041e53 +guid: c42c5cb61bddb6e419b9dd89f24c94b8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Runtime/Extensions/DateTimeExtensions.cs b/Runtime/Extensions/DateTimeExtensions.cs deleted file mode 100644 index 8b4466b8..00000000 --- a/Runtime/Extensions/DateTimeExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Backtrace.Unity.Common -{ - public static class DateTimeExtensions - { - - public static int Timestamp(this DateTime dateTime) - { - return (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; - } - } - -} \ No newline at end of file diff --git a/Runtime/Extensions/ThreadExtensions.cs b/Runtime/Extensions/ThreadExtensions.cs index b916bf63..6318fe4a 100644 --- a/Runtime/Extensions/ThreadExtensions.cs +++ b/Runtime/Extensions/ThreadExtensions.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.Globalization; +using System.Threading; namespace Backtrace.Unity.Extensions { @@ -18,7 +19,7 @@ public static string GenerateValidThreadName(this Thread thread) //in worst scenario thread name should be managedThreadId var threadName = thread.Name; threadName = string.IsNullOrEmpty(threadName) - ? thread.ManagedThreadId.ToString() + ? thread.ManagedThreadId.ToString(CultureInfo.InvariantCulture) : threadName; return threadName; diff --git a/Runtime/Json/BacktraceJObject.cs b/Runtime/Json/BacktraceJObject.cs index b07ed8d7..f42aaffd 100644 --- a/Runtime/Json/BacktraceJObject.cs +++ b/Runtime/Json/BacktraceJObject.cs @@ -47,7 +47,7 @@ public BacktraceJObject(Dictionary source) /// value public void Add(string key, bool value) { - PrimitiveValues.Add(key, value.ToString().ToLower()); + PrimitiveValues.Add(key, value.ToString(CultureInfo.InvariantCulture).ToLower()); } @@ -100,7 +100,7 @@ public void Add(string key, string value) /// value public void Add(string key, long value) { - PrimitiveValues.Add(key, value.ToString()); + PrimitiveValues.Add(key, value.ToString(CultureInfo.InvariantCulture)); } /// diff --git a/Runtime/Model/BacktraceReport.cs b/Runtime/Model/BacktraceReport.cs index 0b286bb6..6c368101 100644 --- a/Runtime/Model/BacktraceReport.cs +++ b/Runtime/Model/BacktraceReport.cs @@ -30,7 +30,7 @@ public class BacktraceReport /// /// UTC timestamp in seconds /// - public readonly long Timestamp = new DateTime().Timestamp(); + public readonly long Timestamp = DateTimeHelper.Timestamp(); /// /// Get information aboout report type. If value is true the BacktraceReport has an error information diff --git a/Runtime/Model/BacktraceStackFrame.cs b/Runtime/Model/BacktraceStackFrame.cs index 1d6a2afd..e0d02585 100644 --- a/Runtime/Model/BacktraceStackFrame.cs +++ b/Runtime/Model/BacktraceStackFrame.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Reflection; @@ -165,7 +166,7 @@ public BacktraceStackFrame(StackFrame frame, bool generatedByException) Column = frame.GetFileColumnNumber(); try { - MemberInfo = method.MetadataToken.ToString(); + MemberInfo = method.MetadataToken.ToString(CultureInfo.InvariantCulture); } catch (InvalidOperationException) { @@ -277,7 +278,7 @@ private string GetFileNameFromFunctionName() public override string ToString() { - return string.Format("{0} (at {1}:{2})", FunctionName, Library, Line.ToString()); + return string.Format("{0} (at {1}:{2})", FunctionName, Library, Line.ToString(CultureInfo.InvariantCulture)); } } } diff --git a/Runtime/Model/BacktraceUnityMessage.cs b/Runtime/Model/BacktraceUnityMessage.cs index f9802d3f..cd3d3102 100644 --- a/Runtime/Model/BacktraceUnityMessage.cs +++ b/Runtime/Model/BacktraceUnityMessage.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; using UnityEngine; @@ -48,7 +49,7 @@ private string GetFormattedMessage(bool backtraceFrame) var stringBuilder = new StringBuilder(); stringBuilder.AppendFormat( "[{0}] {1}<{2}>: {3}", new object[4] { - DateTime.Now.ToUniversalTime().ToString(), + DateTime.Now.ToUniversalTime().ToString(CultureInfo.InvariantCulture), backtraceFrame ? "(Backtrace)" : string.Empty, Enum.GetName(typeof(LogType), Type), Message} diff --git a/Runtime/Model/JsonData/Annotations.cs b/Runtime/Model/JsonData/Annotations.cs index 1a352805..70bc4dd4 100644 --- a/Runtime/Model/JsonData/Annotations.cs +++ b/Runtime/Model/JsonData/Annotations.cs @@ -135,13 +135,13 @@ private BacktraceJObject GetJObject(GameObject gameObject, string parentName = " return new BacktraceJObject(new Dictionary() { { "name", gameObject.name}, - {"isStatic", gameObject.isStatic.ToString().ToLower() }, + {"isStatic", gameObject.isStatic.ToString(CultureInfo.InvariantCulture).ToLower() }, {"layer", gameObject.layer.ToString(CultureInfo.InvariantCulture) }, {"transform.position", gameObject.transform.position.ToString()}, {"transform.rotation", gameObject.transform.rotation.ToString()}, {"tag",gameObject.tag}, - {"activeInHierarchy", gameObject.activeInHierarchy.ToString().ToLower()}, - {"activeSelf", gameObject.activeSelf.ToString().ToLower() }, + {"activeInHierarchy", gameObject.activeInHierarchy.ToString(CultureInfo.InvariantCulture).ToLower()}, + {"activeSelf", gameObject.activeSelf.ToString(CultureInfo.InvariantCulture).ToLower() }, {"instanceId", gameObject.GetInstanceID().ToString(CultureInfo.InvariantCulture) }, { "parnetName", string.IsNullOrEmpty(parentName) ? "root object" : parentName } }); diff --git a/Runtime/Model/JsonData/BacktraceAttributes.cs b/Runtime/Model/JsonData/BacktraceAttributes.cs index 02f77113..4fd94ef4 100644 --- a/Runtime/Model/JsonData/BacktraceAttributes.cs +++ b/Runtime/Model/JsonData/BacktraceAttributes.cs @@ -3,6 +3,7 @@ using Backtrace.Unity.Json; using System; using System.Collections.Generic; +using System.Globalization; #if !UNITY_WEBGL using System.Linq; using System.Net.NetworkInformation; @@ -121,15 +122,15 @@ private void SetLibraryAttributes(BacktraceReport report) Attributes["application.id"] = Application.identifier; Attributes["application.installer.name"] = Application.installerName; Attributes["application.internet_reachability"] = Application.internetReachability.ToString(); - Attributes["application.editor"] = Application.isEditor.ToString(); - Attributes["application.focused"] = Application.isFocused.ToString(); - Attributes["application.mobile"] = Application.isMobilePlatform.ToString(); - Attributes["application.playing"] = Application.isPlaying.ToString(); - Attributes["application.background"] = Application.runInBackground.ToString(); + Attributes["application.editor"] = Application.isEditor.ToString(CultureInfo.InvariantCulture); + Attributes["application.focused"] = Application.isFocused.ToString(CultureInfo.InvariantCulture); + Attributes["application.mobile"] = Application.isMobilePlatform.ToString(CultureInfo.InvariantCulture); + Attributes["application.playing"] = Application.isPlaying.ToString(CultureInfo.InvariantCulture); + Attributes["application.background"] = Application.runInBackground.ToString(CultureInfo.InvariantCulture); Attributes["application.sandboxType"] = Application.sandboxType.ToString(); Attributes["application.system.language"] = Application.systemLanguage.ToString(); Attributes["application.unity.version"] = Application.unityVersion; - Attributes["application.debug"] = Debug.isDebugBuild.ToString(); + Attributes["application.debug"] = Debug.isDebugBuild.ToString(CultureInfo.InvariantCulture); #if !UNITY_SWITCH Attributes["application.temporary_cache"] = Application.temporaryCachePath; #endif @@ -220,21 +221,21 @@ internal void SetSceneInformation(bool onlyBuiltInAttributes = false) //The number of Scenes which have been added to the Build Settings. The Editor will contain Scenes that were opened before entering playmode. if (SceneManager.sceneCountInBuildSettings > 0) { - Attributes["scene.count.build"] = SceneManager.sceneCountInBuildSettings.ToString(); + Attributes["scene.count.build"] = SceneManager.sceneCountInBuildSettings.ToString(CultureInfo.InvariantCulture); } - Attributes["scene.count"] = SceneManager.sceneCount.ToString(); + Attributes["scene.count"] = SceneManager.sceneCount.ToString(CultureInfo.InvariantCulture); if (onlyBuiltInAttributes) { return; } var activeScene = SceneManager.GetActiveScene(); Attributes["scene.active"] = activeScene.name; - Attributes["scene.buildIndex"] = activeScene.buildIndex.ToString(); + Attributes["scene.buildIndex"] = activeScene.buildIndex.ToString(CultureInfo.InvariantCulture); #if UNITY_2018_4_OR_NEWER - Attributes["scene.handle"] = activeScene.handle.ToString(); + Attributes["scene.handle"] = activeScene.handle.ToString(CultureInfo.InvariantCulture); #endif - Attributes["scene.isDirty"] = activeScene.isDirty.ToString(); - Attributes["scene.isLoaded"] = activeScene.isLoaded.ToString(); + Attributes["scene.isDirty"] = activeScene.isDirty.ToString(CultureInfo.InvariantCulture); + Attributes["scene.isLoaded"] = activeScene.isLoaded.ToString(CultureInfo.InvariantCulture); Attributes["scene.name"] = activeScene.name; Attributes["scene.path"] = activeScene.path; } @@ -248,8 +249,8 @@ private void SetProcessAttributes(bool onlyBuiltInAttributes = false) { return; } - Attributes["gc.heap.used"] = GC.GetTotalMemory(false).ToString(); - Attributes["process.age"] = Math.Round(Time.realtimeSinceStartup).ToString(); + Attributes["gc.heap.used"] = GC.GetTotalMemory(false).ToString(CultureInfo.InvariantCulture); + Attributes["process.age"] = Math.Round(Time.realtimeSinceStartup).ToString(CultureInfo.InvariantCulture); } private void SetGraphicCardInformation() @@ -259,19 +260,19 @@ private void SetGraphicCardInformation() //The number is the same across operating systems and driver versions. //Note that device IDs are only implemented on PC(Windows / Mac / Linux) platforms and on Android when running //Vulkan; on other platforms you'll have to do name-based detection if needed. - Attributes["graphic.id"] = SystemInfo.graphicsDeviceID.ToString(); + Attributes["graphic.id"] = SystemInfo.graphicsDeviceID.ToString(CultureInfo.InvariantCulture); Attributes["graphic.name"] = SystemInfo.graphicsDeviceName; Attributes["graphic.type"] = SystemInfo.graphicsDeviceType.ToString(); Attributes["graphic.vendor"] = SystemInfo.graphicsDeviceVendor; - Attributes["graphic.vendor.id"] = SystemInfo.graphicsDeviceVendorID.ToString(); + Attributes["graphic.vendor.id"] = SystemInfo.graphicsDeviceVendorID.ToString(CultureInfo.InvariantCulture); Attributes["graphic.driver.version"] = SystemInfo.graphicsDeviceVersion; - Attributes["graphic.memory"] = SystemInfo.graphicsMemorySize.ToString(); - Attributes["graphic.multithreaded"] = SystemInfo.graphicsMultiThreaded.ToString(); + Attributes["graphic.memory"] = SystemInfo.graphicsMemorySize.ToString(CultureInfo.InvariantCulture); + Attributes["graphic.multithreaded"] = SystemInfo.graphicsMultiThreaded.ToString(CultureInfo.InvariantCulture); - Attributes["graphic.shader"] = SystemInfo.graphicsShaderLevel.ToString(); - Attributes["graphic.topUv"] = SystemInfo.graphicsUVStartsAtTop.ToString(); + Attributes["graphic.shader"] = SystemInfo.graphicsShaderLevel.ToString(CultureInfo.InvariantCulture); + Attributes["graphic.topUv"] = SystemInfo.graphicsUVStartsAtTop.ToString(CultureInfo.InvariantCulture); } @@ -286,7 +287,7 @@ private void SetMachineAttributes(bool onlyBuiltInAttributes = false) var batteryLevel = SystemInfo.batteryLevel == -1 ? -1 : SystemInfo.batteryLevel * 100; - Attributes["battery.level"] = batteryLevel.ToString(); + Attributes["battery.level"] = batteryLevel.ToString(CultureInfo.InvariantCulture); Attributes["battery.status"] = SystemInfo.batteryStatus.ToString(); } @@ -312,11 +313,11 @@ private void SetMachineAttributes(bool onlyBuiltInAttributes = false) Attributes["uname.version"] = Environment.OSVersion.Version.ToString(); Attributes["uname.fullname"] = SystemInfo.operatingSystem; Attributes["uname.family"] = SystemInfo.operatingSystemFamily.ToString(); - Attributes["cpu.count"] = SystemInfo.processorCount.ToString(); - Attributes["cpu.frequency"] = SystemInfo.processorFrequency.ToString(); + Attributes["cpu.count"] = SystemInfo.processorCount.ToString(CultureInfo.InvariantCulture); + Attributes["cpu.frequency"] = SystemInfo.processorFrequency.ToString(CultureInfo.InvariantCulture); Attributes["cpu.brand"] = SystemInfo.processorType; - Attributes["audio.supported"] = SystemInfo.supportsAudio.ToString(); + Attributes["audio.supported"] = SystemInfo.supportsAudio.ToString(CultureInfo.InvariantCulture); //Time when system was booted int boottime = Environment.TickCount; @@ -324,7 +325,7 @@ private void SetMachineAttributes(bool onlyBuiltInAttributes = false) { boottime = int.MaxValue; } - Attributes["cpu.boottime"] = boottime.ToString(); + Attributes["cpu.boottime"] = boottime.ToString(CultureInfo.InvariantCulture); //The hostname of the crashing system. Attributes["hostname"] = Environment.MachineName; @@ -332,7 +333,7 @@ private void SetMachineAttributes(bool onlyBuiltInAttributes = false) if (SystemInfo.systemMemorySize != 0) { //number of kilobytes that application is using. - Attributes["vm.rss.size"] = (SystemInfo.systemMemorySize * 1048576L).ToString(); + Attributes["vm.rss.size"] = (SystemInfo.systemMemorySize * 1048576L).ToString(CultureInfo.InvariantCulture); } #endif } diff --git a/Runtime/Native/Android/NativeClient.cs b/Runtime/Native/Android/NativeClient.cs index e2075075..88b45d03 100644 --- a/Runtime/Native/Android/NativeClient.cs +++ b/Runtime/Native/Android/NativeClient.cs @@ -2,6 +2,7 @@ using Backtrace.Unity.Model.JsonData; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -393,7 +394,7 @@ public void SetAttribute(string key, string value) public bool OnOOM() { SetAttribute("memory.warning", "true"); - SetAttribute("memory.warning.date", DateTime.Now.ToString()); + SetAttribute("memory.warning.date", DateTime.Now.ToString(CultureInfo.InvariantCulture)); return true; } diff --git a/Runtime/Services/BacktraceApi.cs b/Runtime/Services/BacktraceApi.cs index 01bd42de..5bac1c8a 100644 --- a/Runtime/Services/BacktraceApi.cs +++ b/Runtime/Services/BacktraceApi.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -196,7 +197,7 @@ public IEnumerator Send(string json, List attachments, int deduplication var queryAttributes = new Dictionary(); if (deduplication > 0) { - queryAttributes["_mod_duplicate"] = deduplication.ToString(); + queryAttributes["_mod_duplicate"] = deduplication.ToString(CultureInfo.InvariantCulture); } yield return Send(json, attachments, queryAttributes, callback); diff --git a/Runtime/Services/ReportLimitWatcher.cs b/Runtime/Services/ReportLimitWatcher.cs index 77614a1a..d9d750e1 100644 --- a/Runtime/Services/ReportLimitWatcher.cs +++ b/Runtime/Services/ReportLimitWatcher.cs @@ -139,7 +139,7 @@ private void DisplayReportLimitHitMessage() /// private void Clear() { - long currentTime = new DateTime().Timestamp(); + long currentTime = DateTimeHelper.Timestamp(); bool clear = false; while (!clear && _reportQueue.Count != 0) { diff --git a/Tests/Runtime/RateLimit/RateLimitTests.cs b/Tests/Runtime/RateLimit/RateLimitTests.cs index 67463388..faeae7e2 100644 --- a/Tests/Runtime/RateLimit/RateLimitTests.cs +++ b/Tests/Runtime/RateLimit/RateLimitTests.cs @@ -14,7 +14,7 @@ public void TestReportLimit_ShouldDeclineLastReport_ShouldReturnFalseForLastReco { uint reportLimitWatcherSize = 5; var reportLimitWatcher = new ReportLimitWatcher(reportLimitWatcherSize); - var timestamp = new DateTime().Timestamp(); + var timestamp = DateTimeHelper.Timestamp(); for (int i = 0; i < reportLimitWatcherSize; i++) { var result = reportLimitWatcher.WatchReport(timestamp); @@ -29,7 +29,7 @@ public void TestReportLimitWarningMessage_ShouldPrintWarningMessage_ShouldDispla { uint reportLimitWatcherSize = 5; var reportLimitWatcher = new ReportLimitWatcher(reportLimitWatcherSize); - var timestamp = new DateTime().Timestamp(); + var timestamp = DateTimeHelper.Timestamp(); for (int i = 0; i < reportLimitWatcherSize; i++) { var result = reportLimitWatcher.WatchReport(timestamp); @@ -60,7 +60,7 @@ public void TestReportLimitFromMultipleThreads_ShouldDeclineReportAfterLimitHit_ { for (int i = 0; i < reportLimitWatcherSize; i++) { - var result = reportLimitWatcher.WatchReport(new DateTime().Timestamp()); + var result = reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp()); if (result) { acceptedReports++; diff --git a/Tests/Runtime/SourceCode/LogManagerTests.cs b/Tests/Runtime/SourceCode/LogManagerTests.cs index e754005e..35b38404 100644 --- a/Tests/Runtime/SourceCode/LogManagerTests.cs +++ b/Tests/Runtime/SourceCode/LogManagerTests.cs @@ -1,7 +1,9 @@ using Backtrace.Unity.Model; using NUnit.Framework; using System; +using System.Globalization; using System.Linq; +using System.Threading; using UnityEngine; namespace Backtrace.Unity.Tests.Runtime @@ -57,11 +59,15 @@ public void TestMessageQueue_AddMultipleLosgToEnabledManager_ShouldEnqueueLimitM } - [TestCase(5)] - [TestCase(10)] - [TestCase(25)] - public void TestLogManagerLimit_AddMessagesThatMatchLimitCriteria_AllMessagesShouldBeInLogManager(int numberOfLogs) + [TestCase(5, "ar-DZ")] + [TestCase(10, "ar-SA")] + [TestCase(25, "ko-KR")] + public void TestLogManagerLimit_AddMessagesThatMatchLimitCriteria_AllMessagesShouldBeInLogManager(int numberOfLogs, string cultureName) { + var culture = CultureInfo.GetCultureInfo(cultureName); + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = culture; + var message = "fake message"; var stackTrace = string.Empty; var type = LogType.Log; diff --git a/iOS/libBacktrace-Unity-Cocoa.a b/iOS/libBacktrace-Unity-Cocoa.a index 98600b92..2e7bf4af 100644 Binary files a/iOS/libBacktrace-Unity-Cocoa.a and b/iOS/libBacktrace-Unity-Cocoa.a differ diff --git a/package.json b/package.json index bba35f73..48689380 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "io.backtrace.unity", "displayName": "Backtrace", - "version": "3.4.0-rc1", + "version": "3.4.0-rc2", "unity": "2017.1", "description": "Backtrace's integration with Unity games allows customers to capture and report handled and unhandled Unity exceptions to their Backtrace instance, instantly offering the ability to prioritize and debug software errors.", "keywords": [