/// <summary> /// In most situation when application crash, main process wont wait till we prepare report and send it to API. /// Method allows you to get all necessary data required by BacktraceClient and wait till report will be send on server /// This method is invoked when application crash, so BacktraceClient override all existing events to make sure /// we can handle request end /// </summary> private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = e.ExceptionObject as Exception; Database?.Add(new BacktraceReport(exception), Attributes, MiniDumpType); OnUnhandledApplicationException?.Invoke(exception); }
/// <summary> /// Send a report to Backtrace API after first type of report validation rules /// </summary> /// <param name="report">Backtrace report</param> /// <param name="sendCallback">send callback</param> private void SendReport(BacktraceReport report, Action <BacktraceResult> sendCallback = null) { var record = Database != null?Database.Add(report, Attributes, MiniDumpType) : null; //create a JSON payload instance BacktraceData data = null; data = (record != null ? record.BacktraceData : null) ?? report.ToBacktraceData(Attributes); //valid user custom events data = (BeforeSend != null ? BeforeSend.Invoke(data) : null) ?? data; if (BacktraceApi == null) { if (record != null) { record.Dispose(); } Debug.LogWarning("Backtrace API doesn't exist. Please validate client token or server url!"); return; } StartCoroutine(BacktraceApi.Send(data, (BacktraceResult result) => { if (record != null) { record.Dispose(); //Database?.IncrementRecordRetryLimit(record); } if (result != null) { if (result.Status == BacktraceResultStatus.Ok) { if (Database != null) { Database.Delete(record); } } } //check if there is more errors to send //handle inner exception HandleInnerException(report, (BacktraceResult innerResult) => { result.InnerExceptionResult = innerResult; }); if (sendCallback != null) { sendCallback.Invoke(result); } })); }
/// <summary> /// Send a report to Backtrace API /// </summary> /// <param name="report">Report to send</param> public virtual BacktraceResult Send(BacktraceReport report) { #if !NET35 if (UnpackAggregateExcetpion && report.Exception is AggregateException) { return(HandleAggregateException(report).Result); } #endif 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 = BacktraceApi.Send(data); record?.Dispose(); if (result?.Status == BacktraceResultStatus.Ok) { Database.Delete(record); } //check if there is more errors to send //handle inner exception result.InnerExceptionResult = HandleInnerException(report); return(result); }
/// <summary> /// Send a report to Backtrace API /// </summary> /// <param name="report">Report to send</param> public void Send(BacktraceReport report, Action <BacktraceResult> sendCallback = null) { var record = Database?.Add(report, Attributes, MiniDumpType); //create a JSON payload instance BacktraceData data = null; try { data = record?.BacktraceData ?? report.ToBacktraceData(Attributes); } catch (Exception e) { Debug.Log(e); } //valid user custom events data = BeforeSend?.Invoke(data) ?? data; if (BacktraceApi == null) { record?.Dispose(); Debug.LogWarning("Backtrace API not exisits. Please validate client token or server url!"); return; } StartCoroutine(BacktraceApi.Send(data, (BacktraceResult result) => { record?.Dispose(); if (result?.Status == BacktraceResultStatus.Ok) { Database?.Delete(record); } //check if there is more errors to send //handle inner exception HandleInnerException(report, (BacktraceResult innerResult) => { result.InnerExceptionResult = innerResult; }); sendCallback?.Invoke(result); })); }
/// <summary> /// Collect diagnostic data and send to API /// </summary> /// <param name="report">Backtrace Report</param> /// <param name="sendCallback">Coroutine callback</param> /// <returns>IEnumerator</returns> private IEnumerator CollectDataAndSend(BacktraceReport report, Action <BacktraceResult> sendCallback) { var queryAttributes = new Dictionary <string, string>(); var stopWatch = EnablePerformanceStatistics ? System.Diagnostics.Stopwatch.StartNew() : new System.Diagnostics.Stopwatch(); BacktraceData data = SetupBacktraceData(report); if (EnablePerformanceStatistics) { stopWatch.Stop(); queryAttributes["performance.report"] = stopWatch.GetMicroseconds(); } if (BeforeSend != null) { data = BeforeSend.Invoke(data); if (data == null) { yield break; } } BacktraceDatabaseRecord record = null; if (Database != null && Database.Enabled()) { yield return(new WaitForEndOfFrame()); if (EnablePerformanceStatistics) { stopWatch.Restart(); } record = Database.Add(data); // handle situation when database refuse to store report. if (record != null) { //Extend backtrace data with additional attachments from backtrace database data = record.BacktraceData; if (EnablePerformanceStatistics) { stopWatch.Stop(); queryAttributes["performance.database"] = stopWatch.GetMicroseconds(); } if (record.Duplicated) { record.Unlock(); yield break; } } else { yield break; } } if (EnablePerformanceStatistics) { stopWatch.Restart(); } // avoid serializing data twice // if record is here we should try to send json data that are available in record // otherwise we can still use BacktraceData.ToJson(). string json = record != null ? record.BacktraceDataJson() : data.ToJson(); if (EnablePerformanceStatistics) { stopWatch.Stop(); queryAttributes["performance.json"] = stopWatch.GetMicroseconds(); } yield return(new WaitForEndOfFrame()); if (string.IsNullOrEmpty(json)) { yield break; } //backward compatibility if (RequestHandler != null) { yield return(RequestHandler.Invoke(BacktraceApi.ServerUrl, data)); yield break; } if (data.Deduplication != 0) { queryAttributes["_mod_duplicate"] = data.Deduplication.ToString(); } StartCoroutine(BacktraceApi.Send(json, data.Attachments, queryAttributes, (BacktraceResult result) => { if (record != null) { record.Unlock(); if (Database != null && result.Status != BacktraceResultStatus.ServerError && result.Status != BacktraceResultStatus.NetworkError) { Database.Delete(record); } } //check if there is more errors to send //handle inner exception HandleInnerException(report); if (sendCallback != null) { sendCallback.Invoke(result); } })); }