Пример #1
0
        /// <summary>
        /// Collect additional report information from client and convert report to backtrace data
        /// </summary>
        /// <param name="report">Backtrace report</param>
        /// <returns>Backtrace data</returns>
        private BacktraceData SetupBacktraceData(BacktraceReport report)
        {
            // apply _mod fingerprint attribute when client should use
            // normalized exception message instead environment stack trace
            // for exceptions without stack trace.
            if (Configuration.UseNormalizedExceptionMessage)
            {
                report.SetReportFingerPrintForEmptyStackTrace();
            }

            // add environment information to backtrace report
            var sourceCode = _backtraceLogManager.Disabled
                ? new BacktraceUnityMessage(report).ToString()
                : _backtraceLogManager.ToSourceCode();

            report.AssignSourceCodeToReport(sourceCode);

            // pass copy of dictionary to prevent overriding client attributes
            var result = report.ToBacktraceData(null, GameObjectDepth);

            // add native attributes to client report
            if (_nativeClient != null)
            {
                _nativeClient.GetAttributes(result.Attributes.Attributes);
            }

            // apply client attributes
            foreach (var attribute in _clientAttributes)
            {
                result.Attributes.Attributes[attribute.Key] = attribute.Value;
            }

            return(result);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldGenerateFingerprintForExceptionReportWithoutStackTrace_ShouldIncludeFingerprintInBacktraceReport()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var exception = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var expectedNormalizedMessage = "Unhandledexception";
            var report = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                Assert.IsNotNull(data.Attributes.Attributes["_mod_fingerprint"]);
                Assert.AreEqual(expectedNormalizedMessage.GetSha(), data.Attributes.Attributes["_mod_fingerprint"]);
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));


            Assert.IsTrue(eventFired);
        }
Пример #3
0
        private async Task <BacktraceResult> HandleAggregateException(BacktraceReport report)
        {
            var             aggregateException = report.Exception as AggregateException;
            BacktraceResult result             = null;

            foreach (var ex in aggregateException.InnerExceptions)
            {
                var innerReport = new BacktraceReport(
                    exception: ex,
                    attributes: report.Attributes,
                    attachmentPaths: report.AttachmentPaths,
                    reflectionMethodName: report._reflectionMethodName)
                {
                    Factor      = report.Factor,
                    Fingerprint = report.Fingerprint
                };

                if (result == null)
                {
                    result = await SendAsync(innerReport);
                }
                else
                {
                    result.AddInnerResult(await SendAsync(innerReport));
                }
            }
            return(result ?? new BacktraceResult()
            {
                Status = BacktraceResultStatus.Empty, BacktraceReport = report
            });
        }
        private IEnumerator Send(string json, List <string> attachments, BacktraceReport report, Action <BacktraceResult> callback)
        {
            using (var request = new UnityWebRequest(_serverurl, "POST"))
            {
                AppendBodyToFile(json);
                byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
                request.uploadHandler   = (UploadHandler) new UploadHandlerRaw(bodyRaw);
                request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
                request.SetRequestHeader("Content-Type", "application/json");
                yield return(request.SendWebRequest());

                BacktraceResult result;
                if (request.responseCode == 200)
                {
                    result = new BacktraceResult();
                    OnServerResponse?.Invoke(result);
                    var response = BacktraceResult.FromJson(request.downloadHandler.text);
                    if (attachments != null && attachments.Count > 0)
                    {
                        var stack = new Stack <string>(attachments);
                        yield return(SendAttachment(response.Object, stack));
                    }
                }
                else
                {
                    PrintLog(request);
                    var exception = new Exception(request.error);
                    result = BacktraceResult.OnError(report, exception);
                    OnServerError?.Invoke(exception);
                }
                callback?.Invoke(result);
                yield return(result);
            }
        }
Пример #5
0
        public IEnumerator TestReportLimit_TestSendingBacktraceReport_SkippProcessingReports()
        {
            BacktraceClient.SetClientReportLimit(CLIENT_RATE_LIMIT);
            int totalNumberOfReports   = 5;
            int maximumNumberOfRetries = 0;

            BacktraceClient.RequestHandler = (string url, BacktraceData data) =>
            {
                maximumNumberOfRetries++;
                return(new BacktraceResult());
            };
            int skippedReports = 0;

            BacktraceClient.OnClientReportLimitReached = (BacktraceReport report) =>
            {
                skippedReports++;
            };

            for (int i = 0; i < totalNumberOfReports; i++)
            {
                var report = new BacktraceReport(new Exception("Exception"));
                BacktraceClient.Send(report);
            }
            Assert.AreEqual(totalNumberOfReports, maximumNumberOfRetries + skippedReports);
            Assert.AreEqual(maximumNumberOfRetries, CLIENT_RATE_LIMIT);
            Assert.AreEqual(totalNumberOfReports - CLIENT_RATE_LIMIT, skippedReports);
            yield return(null);
        }
Пример #6
0
        /// <summary>
        /// Send asynchronous report to Backtrace API
        /// </summary>
        /// <param name="report">Report to send</param>
        public virtual async Task <BacktraceResult> SendAsync(BacktraceReport report)
        {
            if (UnpackAggregateExcetpion && report.Exception is AggregateException)
            {
                return(await HandleAggregateException(report));
            }
            var record = Database.Add(report, Attributes, MiniDumpType);
            //create a JSON payload instance
            var data = record?.BacktraceData ?? report.ToBacktraceData(Attributes);

            //valid user custom events
            data = BeforeSend?.Invoke(data) ?? data;
            var result = await BacktraceApi.SendAsync(data);

            record?.Dispose();
            if (result?.Status == BacktraceResultStatus.Ok)
            {
                Database.Delete(record);
            }
            //check if there is more errors to send
            //handle inner exception
            result.InnerExceptionResult = await HandleInnerExceptionAsync(report);

            return(result);
        }
        public void TestReportStackTrace_StackTraceShouldBeTheSameLikeExceptionStackTrace_ShouldReturnCorrectStackTrace()
        {
            var exception = new Exception("exception");
            var report    = new BacktraceReport(exception);

            Assert.AreEqual(report.DiagnosticStack.Count, exception.StackTrace?.Count() ?? 0);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldGenerateFingerprintAndShouldntRemoveAnyLetter_ShouldIncludeFingerprintInBacktraceReport()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            var normalizedMessage = "Unhandledexception";
            var exception         = new BacktraceUnhandledException(normalizedMessage, string.Empty);
            var report            = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                const string modFingerprintKey = "_mod_fingerprint";
                Assert.IsTrue(data.Attributes.Attributes.ContainsKey(modFingerprintKey));
                Assert.IsNotNull(data.Attributes.Attributes[modFingerprintKey]);
                Assert.AreEqual(normalizedMessage.GetSha(), data.Attributes.Attributes[modFingerprintKey]);
                // prevent backtrace data from sending to Backtrace.
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));

            Assert.IsTrue(eventFired);
        }
Пример #9
0
        /// <summary>
        /// Create instance of Backtrace Attribute
        /// </summary>
        /// <param name="report">Received report</param>
        /// <param name="clientAttributes">Client's attributes (report and client)</param>
        public BacktraceAttributes(BacktraceReport report, Dictionary <string, string> clientAttributes, bool onlyBuiltInAttributes = false)
        {
            if (clientAttributes == null)
            {
                clientAttributes = new Dictionary <string, string>();
            }
            Attributes = clientAttributes;

            if (report != null)
            {
                // Add report attributes
                if (report.Attributes != null)
                {
                    foreach (var attribute in report.Attributes)
                    {
                        Attributes[attribute.Key] = attribute.Value;
                    }
                }
                SetExceptionAttributes(report);
            }
            //Environment attributes override user attributes
            SetLibraryAttributes(report);
            SetMachineAttributes(onlyBuiltInAttributes);
            SetProcessAttributes(onlyBuiltInAttributes);
            SetSceneInformation(onlyBuiltInAttributes);
        }
Пример #10
0
        private bool ShouldSendReport(Exception exception, List <string> attachmentPaths, Dictionary <string, string> attributes)
        {
            // guess report type
            var filterType = ReportFilterType.Exception;

            if (exception is BacktraceUnhandledException)
            {
                filterType = (exception as BacktraceUnhandledException).Classifier == "ANRException"
                    ? ReportFilterType.Hang
                    : ReportFilterType.UnhandledException;
            }


            if (ShouldSkipReport(filterType, exception, string.Empty))
            {
                return(false);
            }
            //check rate limiting
            bool shouldProcess = _reportLimitWatcher.WatchReport(new DateTime().Timestamp());

            if (shouldProcess)
            {
                return(true);
            }
            if (OnClientReportLimitReached != null)
            {
                var report = new BacktraceReport(
                    exception: exception,
                    attachmentPaths: attachmentPaths,
                    attributes: attributes);
                _onClientReportLimitReached.Invoke(report);
            }
            return(false);
        }
        public void TestExceptionTypeAttribute_ShouldSetExceptionTypeHang_ExceptionTypeAttributeIsCorrect()
        {
            var report         = new BacktraceReport(new BacktraceUnhandledException("ANRException: Blocked thread detected", string.Empty));
            var testAttributes = new BacktraceAttributes(report, null);

            Assert.AreEqual("Hang", testAttributes.Attributes["error.type"]);
        }
        public void TestExceptionTypeAttribute_ShouldSetExceptionTypeUnhandledException_ExceptionTypeAttributeIsCorrect()
        {
            var report         = new BacktraceReport(new BacktraceUnhandledException("foo", string.Empty));
            var testAttributes = new BacktraceAttributes(report, null);

            Assert.AreEqual("Unhandled exception", testAttributes.Attributes["error.type"]);
        }
        public void TestExceptionTypeAttribute_ShouldSetExceptionTypeException_ExceptionTypeAttributeIsCorrect()
        {
            var report         = new BacktraceReport(new Exception("foo"));
            var testAttributes = new BacktraceAttributes(report, null);

            Assert.AreEqual("Exception", testAttributes.Attributes["error.type"]);
        }
Пример #14
0
        /// <summary>
        /// Set attributes from exception
        /// </summary>
        internal void SetExceptionAttributes(BacktraceReport report)
        {
            //there is no information to analyse
            if (report == null)
            {
                return;
            }
            Attributes["error.message"] = report.ExceptionTypeReport
                ? report.Exception.Message
                : report.Message;

            // detect exception type
            var errorType = "error.type";

            if (!report.ExceptionTypeReport)
            {
                Attributes[errorType] = "Message";
                return;
            }
            if (report.Exception is BacktraceUnhandledException)
            {
                if ((report.Exception as BacktraceUnhandledException).Classifier == "ANRException")
                {
                    Attributes[errorType] = "Hang";
                }
                else
                {
                    Attributes[errorType] = "Unhandled exception";
                }
            }
            else
            {
                Attributes[errorType] = "Exception";
            }
        }
        public void TestReportStackTrace_StackTraceShouldIncludeEnvironmentStackTrace_ShouldReturnCorrectStackTrace()
        {
            var environmentStackTrace = new StackTrace(true);
            var report = new BacktraceReport("msg");

            Assert.AreEqual(report.DiagnosticStack.Count, environmentStackTrace.FrameCount);
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldUseReportFingerprint_ReportFingerprintInAttributes()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = true;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var          exception           = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var          report              = new BacktraceReport(exception);
            const string expectedFingerprint = "foo-bar";

            report.Fingerprint = expectedFingerprint;

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                eventFired = true;
                Assert.IsNotNull(data.Attributes.Attributes["_mod_fingerprint"]);
                Assert.AreEqual(expectedFingerprint, data.Attributes.Attributes["_mod_fingerprint"]);
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };
            BacktraceClient.Send(report);
            yield return(new WaitForEndOfFrame());

            Assert.IsTrue(eventFired);
        }
Пример #17
0
        private bool ShouldSendReport(BacktraceReport report)
        {
            if (ShouldSkipReport(
                    report.ExceptionTypeReport
                        ? ReportFilterType.Exception
                        : ReportFilterType.Message,
                    report.Exception,
                    report.Message))
            {
                return(false);
            }
            //check rate limiting
            bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp());

            if (shouldProcess)
            {
                // This condition checks if we should send exception from current thread
                // if comparision result confirm that we're trying to send an exception from different
                // thread than main, we should add the exception object to the exception list
                // and let update method send data to Backtrace.
                if (Thread.CurrentThread.ManagedThreadId != _current.ManagedThreadId)
                {
                    report.Attributes["exception.thread"] = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture);
                    BackgroundExceptions.Push(report);
                    return(false);
                }
                return(true);
            }
            if (OnClientReportLimitReached != null)
            {
                _onClientReportLimitReached.Invoke(report);
            }
            return(false);
        }
        /// <summary>
        /// Set library attributes
        /// </summary>
        private void SetLibraryAttributes(BacktraceReport report)
        {
            if (!string.IsNullOrEmpty(report.Fingerprint))
            {
                Attributes["_mod_fingerprint"] = report.Fingerprint;
            }

            if (!string.IsNullOrEmpty(report.Factor))
            {
                Attributes["_mod_factor"] = report.Factor;
            }
            //A unique identifier of a machine
            Attributes["guid"] = GenerateMachineId();
            //Base name of application generating the report
            Attributes["application"]                       = Application.productName;
            Attributes["application.url"]                   = Application.absoluteURL;
            Attributes["application.company.name"]          = Application.companyName;
            Attributes["application.data_path"]             = Application.dataPath;
            Attributes["application.id"]                    = Application.identifier;
            Attributes["application.installer.name"]        = Application.installerName;
            Attributes["application.internet_reachability"] = Application.internetReachability.ToString();
            Attributes["application.editor"]                = Application.isEditor;
            Attributes["application.focused"]               = Application.isFocused;
            Attributes["application.mobile"]                = Application.isMobilePlatform;
            Attributes["application.playing"]               = Application.isPlaying;
            Attributes["application.background"]            = Application.runInBackground;
            Attributes["application.sandboxType"]           = Application.sandboxType.ToString();
            Attributes["application.system.language"]       = Application.systemLanguage.ToString();
            Attributes["application.unity.version"]         = Application.unityVersion;
            Attributes["application.temporary_cache"]       = Application.temporaryCachePath;
            Attributes["applicaiton.debug"]                 = Debug.isDebugBuild;
        }
        public IEnumerator TestFingerprintBehaviorForNormalizedExceptionMessage_ShouldntGenerateFingerprintForDisabledOption_FingerprintDoesntExist()
        {
            BacktraceClient.Configuration = GetValidClientConfiguration();
            BacktraceClient.Configuration.UseNormalizedExceptionMessage = false;
            BacktraceClient.Refresh();

            // exception without stack trace might happened when exception occured because of
            // invalid game object setting or via weird crash
            // exception below has empty exception stack trace
            var exception = new BacktraceUnhandledException("00:00:00 00/00/00 Unhandled exception", string.Empty);
            var report    = new BacktraceReport(exception);

            bool eventFired = false;

            BacktraceClient.BeforeSend = (BacktraceData data) =>
            {
                Assert.IsFalse(data.Attributes.Attributes.ContainsKey("_mod_fingerprint"));
                eventFired = true;
                // prevent backtrace data from sending to Backtrace.
                return(null);
            };

            yield return(BacktraceClient.StartCoroutine(CallBacktraceClientAndWait(report)));


            Assert.IsTrue(eventFired);
        }
Пример #20
0
        /// <summary>
        /// Add new report to BacktraceDatabase
        /// </summary>
        public BacktraceDatabaseRecord Add(BacktraceReport backtraceReport, Dictionary <string, object> attributes, MiniDumpType miniDumpType = MiniDumpType.Normal)
        {
            if (!_enable || backtraceReport == null)
            {
                return(null);
            }
            //remove old reports (if database is full)
            //and check database health state
            var validationResult = ValidateDatabaseSize();

            if (!validationResult)
            {
                return(null);
            }
            if (miniDumpType != MiniDumpType.None)
            {
                string minidumpPath = GenerateMiniDump(backtraceReport, miniDumpType);
                if (!string.IsNullOrEmpty(minidumpPath))
                {
                    backtraceReport.SetMinidumpPath(minidumpPath);
                }
            }

            var data = backtraceReport.ToBacktraceData(attributes);

            return(BacktraceDatabaseContext.Add(data));
        }
        /// <summary>
        /// Convert custom user attributes
        /// </summary>
        /// <param name="report">Received report</param>
        /// <param name="clientAttributes">Client's attributes (report and client)</param>
        /// <returns>Dictionary of custom user attributes </returns>
        private void ConvertAttributes(BacktraceReport report, Dictionary <string, object> clientAttributes)
        {
            var attributes = BacktraceReport.ConcatAttributes(report, clientAttributes);

            foreach (var attribute in attributes)
            {
                if (attribute.Value == null)
                {
                    continue;
                }

                var type = attribute.Value.GetType();
                if (type.IsPrimitive || type == typeof(string) || type.IsEnum)
                {
                    Attributes.Add(attribute.Key, attribute.Value);
                }
                else
                {
                    ComplexAttributes.Add(attribute.Key, attribute.Value);
                }
            }
            //add exception information to Complex attributes.
            if (report.ExceptionTypeReport)
            {
                ComplexAttributes.Add("Exception Properties", report.Exception);
            }
        }
Пример #22
0
        /// <summary>
        /// Send a report to Backtrace API
        /// </summary>
        /// <param name="report">Report to send</param>
        /// <param name="sendCallback">Send report callback</param>
        public void Send(BacktraceReport report, Action <BacktraceResult> sendCallback = null)
        {
            if (Enabled == false)
            {
                Debug.LogWarning("Please enable BacktraceClient first - Please validate Backtrace client initializaiton in Unity IDE.");
                return;
            }
            //check rate limiting
            bool limitHit = _reportLimitWatcher.WatchReport(report);

            if (!limitHit)
            {
                if (_onClientReportLimitReached != null)
                {
                    _onClientReportLimitReached.Invoke(report);
                }

                if (sendCallback != null)
                {
                    sendCallback.Invoke(BacktraceResult.OnLimitReached(report));
                }

                _reportLimitWatcher.DisplayReportLimitHitMessage();
                return;
            }
            SendReport(report, sendCallback);
        }
        public IEnumerator TestCorrectDictionaryGeneration_CreateCorrectAttributesDictionary_WithDiffrentClientAttributes()
        {
            var exception            = new FileNotFoundException();
            var reportAttributeKey   = "report_attr";
            var reportAttributeValue = string.Format("{0}-value", reportAttributeKey);
            var reportAttributes     = new Dictionary <string, object>()
            {
                { reportAttributeKey, reportAttributeValue }
            };
            var exceptionReport = new BacktraceReport(exception, reportAttributes);

            string clientAttributeKey   = "client_attr";
            string clientAttributeValue = string.Format("{0}-value", clientAttributeKey);
            var    clientAttributes     = new Dictionary <string, object>()
            {
                { clientAttributeKey, clientAttributeValue }
            };

            var testObject = new BacktraceAttributes(exceptionReport, clientAttributes);

            Assert.IsTrue(testObject.Attributes.Keys.Any(n => n == clientAttributeKey));
            Assert.IsTrue(testObject.Attributes.Keys.Any(n => n == reportAttributeKey));
            Assert.IsTrue(testObject.Attributes[clientAttributeKey] as string == clientAttributeValue);
            Assert.IsTrue(testObject.Attributes[reportAttributeKey] as string == reportAttributeValue);
            yield return(null);
        }
Пример #24
0
        /// <summary>
        /// Send an exception to Backtrace API
        /// </summary>
        /// <param name="exception">Report exception</param>
        /// <param name="attachmentPaths">List of attachments</param>
        /// <param name="attributes">List of report attributes</param
        public void Send(Exception exception, List <string> attachmentPaths = null, Dictionary <string, object> attributes = null)
        {
            if (Enabled == false)
            {
                Debug.LogWarning("Please enable BacktraceClient first - Please validate Backtrace client initializaiton in Unity IDE.");
                return;
            }
            //check rate limiting
            bool limitHit = _reportLimitWatcher.WatchReport(new DateTime().Timestamp());

            if (limitHit == false && _onClientReportLimitReached == null)
            {
                _reportLimitWatcher.DisplayReportLimitHitMessage();
                return;
            }
            var report = new BacktraceReport(
                exception: exception,
                attachmentPaths: attachmentPaths,
                attributes: attributes);

            if (!limitHit)
            {
                if (_onClientReportLimitReached != null)
                {
                    _onClientReportLimitReached.Invoke(report);
                }

                _reportLimitWatcher.DisplayReportLimitHitMessage();
                return;
            }
            SendReport(report);
        }
        public void TestReportStackTrace_ShouldGenerateStackTraceForExceptionReport_ExceptionReportHasStackTrace()
        {
            //simulate real exception to generate an exception with stack trace.
            Exception exception = null;

            try
            {
                var arr = new List <int>()
                {
                    1, 2, 3, 4
                };
                arr.ElementAt(arr.Count + 1);
            }
            catch (Exception e)
            {
                exception = e;
            }


            var report = new BacktraceReport(
                exception: exception,
                attributes: reportAttributes,
                attachmentPaths: attachemnts);

            Assert.IsTrue(report.DiagnosticStack.Any());
        }
Пример #26
0
        /// <summary>
        /// Sending asynchronous Backtrace report to Backtrace API
        /// </summary>
        /// <param name="backtraceReport">Current report</param>
        /// <returns>Server response</returns>
        public override async Task <BacktraceResult> SendAsync(BacktraceReport backtraceReport)
        {
            OnReportStart?.Invoke(backtraceReport);
            var result = await base.SendAsync(backtraceReport);

            AfterSend?.Invoke(result);
            return(result);
        }
Пример #27
0
        /// <summary>
        /// Sending a backtrace report to Backtrace API
        /// </summary>
        /// <param name="backtraceReport">Current report</param>
        public override BacktraceResult Send(BacktraceReport backtraceReport)
        {
            OnReportStart?.Invoke(backtraceReport);
            var result = base.Send(backtraceReport);

            AfterSend?.Invoke(result);
            return(result);
        }
Пример #28
0
        public IEnumerator TestReportStackTrace_StackTraceShouldIncludeEnvironmentStackTrace_ShouldReturnCorrectStackTrace()
        {
            var environmentStackTrace = new StackTrace(true);
            var report = new BacktraceReport("msg");

            Assert.AreEqual(environmentStackTrace.FrameCount, report.DiagnosticStack.Count);
            yield return(null);
        }
        public IEnumerator TestReportStackTrace_StackTraceShouldBeTheSameLikeExceptionStackTrace_ShouldReturnCorrectStackTrace()
        {
            var exception = new Exception("exception");
            var report    = new BacktraceReport(exception);

            Assert.AreEqual(report.DiagnosticStack.Count, exception.StackTrace == null ? 0 : exception.StackTrace.Count());
            yield return(null);
        }
Пример #30
0
 /// <summary>
 /// Log report to Backtrace API
 /// </summary>
 /// <param name="report">Current exception or client message</param>
 public static void Log(BacktraceReport report)
 {
     if (_client == null)
     {
         return;
     }
     _client.Send(report);
 }