コード例 #1
0
        /// <summary>
        /// Reload Backtrace database configuration. Reloading configuration is required, when you change
        /// BacktraceDatabase configuration options.
        /// </summary>
        public void Reload()
        {
            // validate configuration
            if (Configuration == null)
            {
                Configuration = GetComponent <BacktraceClient>().Configuration;
            }
            if (Configuration == null || !Configuration.IsValid())
            {
                Debug.LogWarning("Configuration doesn't exists or provided serverurl/token are invalid");
                Enable = false;
                return;
            }


            //setup database object
            DatabaseSettings = new BacktraceDatabaseSettings(Configuration);

            Enable = Configuration.Enabled && BacktraceConfiguration.ValidateDatabasePath(Configuration.DatabasePath);
            if (!Enable)
            {
                Debug.LogWarning("Cannot initialize database - invalid database configuration. Database is disabled");
                return;
            }
            CreateDatabaseDirectory();
            SetupMultisceneSupport();
            _lastConnection = Time.time;

            //Setup database context
            BacktraceDatabaseContext     = new BacktraceDatabaseContext(DatabasePath, DatabaseSettings.RetryLimit, DatabaseSettings.RetryOrder, DatabaseSettings.DeduplicationStrategy);
            BacktraceDatabaseFileContext = new BacktraceDatabaseFileContext(DatabasePath, DatabaseSettings.MaxDatabaseSize, DatabaseSettings.MaxRecordCount);
            BacktraceApi        = new BacktraceApi(Configuration.ToCredentials());
            _reportLimitWatcher = new ReportLimitWatcher(Convert.ToUInt32(Configuration.ReportPerMin));
        }
コード例 #2
0
        private void FlushRecord(BacktraceDatabaseRecord record)
        {
            if (record == null)
            {
                return;
            }
            var stopWatch = Configuration.PerformanceStatistics
                ? new System.Diagnostics.Stopwatch()
                : System.Diagnostics.Stopwatch.StartNew();

            var backtraceData = record.BacktraceDataJson();

            Delete(record);
            var queryAttributes = new Dictionary <string, string>();

            if (Configuration.PerformanceStatistics)
            {
                stopWatch.Stop();
                queryAttributes["performance.database.flush"] = stopWatch.GetMicroseconds();
            }

            if (backtraceData == null)
            {
                return;
            }

            queryAttributes["_mod_duplicate"] = record.Count.ToString();

            StartCoroutine(
                BacktraceApi.Send(backtraceData, record.Attachments, queryAttributes, (BacktraceResult result) =>
            {
                record = BacktraceDatabaseContext.FirstOrDefault();
                FlushRecord(record);
            }));
        }
コード例 #3
0
        private void SendData(BacktraceDatabaseRecord record)
        {
            var backtraceData = record?.BacktraceData;

            //meanwhile someone delete data from a disk
            if (backtraceData == null || backtraceData.Report == null)
            {
                Delete(record);
            }
            else
            {
                StartCoroutine(
                    BacktraceApi.Send(backtraceData, (BacktraceResult sendResult) =>
                {
                    if (sendResult.Status == BacktraceResultStatus.Ok)
                    {
                        Delete(record);
                    }
                    else
                    {
                        record.Dispose();
                        BacktraceDatabaseContext.IncrementBatchRetry();
                    }
                    record = BacktraceDatabaseContext.FirstOrDefault();
                    SendData(record);
                }));
            }
        }
コード例 #4
0
        public void Refresh()
        {
            if (Configuration == null || !Configuration.IsValid())
            {
                return;
            }

            Enabled = true;
            Annotations.GameObjectDepth = Configuration.GameObjectDepth;
            HandleUnhandledExceptions();
            _reportLimitWatcher = new ReportLimitWatcher(Convert.ToUInt32(Configuration.ReportPerMin));


#if UNITY_2018_4_OR_NEWER
            BacktraceApi = new BacktraceApi(
                credentials: new BacktraceCredentials(Configuration.GetValidServerUrl()),
                ignoreSslValidation: Configuration.IgnoreSslValidation);
#else
            BacktraceApi = new BacktraceApi(new BacktraceCredentials(Configuration.GetValidServerUrl()));
#endif

            if (Configuration.DestroyOnLoad == false)
            {
                DontDestroyOnLoad(gameObject);
                _instance = this;
            }
            Database = GetComponent <BacktraceDatabase>();
            if (Database == null)
            {
                return;
            }
            Database.Reload();
            Database.SetApi(BacktraceApi);
            Database.SetReportWatcher(_reportLimitWatcher);
        }
コード例 #5
0
        private void Awake()
        {
            Configuration = GetComponent <BacktraceClient>().Configuration;
            if (Configuration == null || !Configuration.IsValid())
            {
                Debug.LogWarning("Configuration doesn't exists or provided serverurl/token are invalid");
                _enable = false;
                return;
            }

            DatabaseSettings = new BacktraceDatabaseSettings(Configuration);
            if (DatabaseSettings == null)
            {
                _enable = false;
                return;
            }
            if (Configuration.CreateDatabase)
            {
                Directory.CreateDirectory(Configuration.DatabasePath);
            }
            _enable = Configuration.Enabled && BacktraceConfiguration.ValidateDatabasePath(Configuration.DatabasePath);

            if (!_enable)
            {
                return;
            }

            _lastConnection = Time.time;

            BacktraceDatabaseContext     = new BacktraceDatabaseContext(DatabasePath, DatabaseSettings.RetryLimit, DatabaseSettings.RetryOrder);
            BacktraceDatabaseFileContext = new BacktraceDatabaseFileContext(DatabasePath, DatabaseSettings.MaxDatabaseSize, DatabaseSettings.MaxRecordCount);
            BacktraceApi = new BacktraceApi(Configuration.ToCredentials(), Convert.ToUInt32(Configuration.ReportPerMin));
        }
コード例 #6
0
        public void Setup()
        {
            //prepare mock object
            //mock database
            var database = new Mock <IBacktraceDatabase>();

            database.Setup(n =>
                           n.Add(It.IsAny <BacktraceReport>(),
                                 It.IsAny <Dictionary <string, object> >(),
                                 It.IsAny <MiniDumpType>()));

            database.Setup(n =>
                           n.Delete(It.IsAny <BacktraceDatabaseRecord>()));

            var credentials = new BacktraceCredentials("https://validurl.com/", "validToken");

            //mock api
            var serverUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
            var mockHttp  = new MockHttpMessageHandler();

            mockHttp.When(serverUrl)
            .Respond("application/json", "{'object' : 'aaa'}");
            var api = new BacktraceApi(credentials, 0)
            {
                HttpClient = mockHttp.ToHttpClient()
            };

            //setup new client
            _backtraceClient = new BacktraceClient(credentials, database: database.Object)
            {
                BacktraceApi = api
            };

            //Add new scoped attributes
            _backtraceClient.Attributes["ClientAttributeNumber"]      = 1;
            _backtraceClient.Attributes["ClientAttributeString"]      = "string attribute";
            _backtraceClient.Attributes["ClientAttributeCustomClass"] = new
            {
                Name = "BacktraceIntegrationTest",
                Type = "Library"
            };
            _backtraceClient.Attributes["ComplexObject"] = new Dictionary <string, Uri>()
            {
                { "backtrace.io", new Uri("http://backtrace.io") },
                { "Google url", new Uri("http://google.com") }
            };
            //to check if client report limit reached use OnClientReportLimitReached
            _backtraceClient.OnClientReportLimitReached = (BacktraceReport report) =>
            {
                clientReportLimitReached = true;
            };
        }
コード例 #7
0
        public void Setup()
        {
            _lastRecord = GetRecord();
            //get project path
            string projectPath = Path.GetTempPath();
            //setup credentials
            var credentials = new BacktraceCredentials("https://validurl.com/", "validToken");
            //mock api
            var serverUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
            var mockHttp  = new MockHttpMessageHandler();

            mockHttp.When(serverUrl)
            .Respond("application/json", "{'object' : 'aaa'}");
            var api = new BacktraceApi(credentials, 0)
            {
                HttpClient = mockHttp.ToHttpClient()
            };

            //mock file context
            var mockFileContext = new Mock <IBacktraceDatabaseFileContext>();

            mockFileContext.Setup(n => n.GetRecords())
            .Returns(new List <FileInfo>());
            mockFileContext.Setup(n => n.RemoveOrphaned(It.IsAny <IEnumerable <BacktraceDatabaseRecord> >()));

            //mock cache
            var mockCacheContext = new Mock <IBacktraceDatabaseContext>();

            mockCacheContext.Setup(n => n.Add(It.IsAny <BacktraceData>(), MiniDumpType.None))
            .Callback(() =>
            {
                mockCacheContext.Object.Add(_lastRecord);
                _lastRecord = GetRecord();
            })
            .Returns(_lastRecord);


            var database = new BacktraceDatabase(new BacktraceDatabaseSettings(projectPath)
            {
                RetryBehavior = RetryBehavior.NoRetry
            })
            {
                BacktraceDatabaseContext     = mockCacheContext.Object,
                BacktraceDatabaseFileContext = mockFileContext.Object,
            };

            //setup new client
            _backtraceClient = new BacktraceClient(backtraceCredentials: credentials, database: database, reportPerMin: 0)
            {
                BacktraceApi = api
            };
        }
コード例 #8
0
        /// <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);
                }
            }));
        }
コード例 #9
0
        private void SendData(BacktraceDatabaseRecord record)
        {
            if (record == null)
            {
                return;
            }
            var stopWatch = Configuration.PerformanceStatistics
               ? System.Diagnostics.Stopwatch.StartNew()
               : new System.Diagnostics.Stopwatch();

            var backtraceData = record != null?record.BacktraceDataJson() : null;

            //check if report exists on hard drive
            // to avoid situation when someone manually remove data
            if (string.IsNullOrEmpty(backtraceData))
            {
                Delete(record);
            }
            else
            {
                var queryAttributes = new Dictionary <string, string>();
                if (Configuration.PerformanceStatistics)
                {
                    stopWatch.Stop();
                    queryAttributes["performance.database.send"] = stopWatch.GetMicroseconds();
                }
                queryAttributes["_mod_duplicate"] = record.Count.ToString(CultureInfo.InvariantCulture);

                StartCoroutine(
                    BacktraceApi.Send(backtraceData, record.Attachments, queryAttributes, (BacktraceResult sendResult) =>
                {
                    record.Unlock();
                    if (sendResult.Status != BacktraceResultStatus.ServerError && sendResult.Status != BacktraceResultStatus.NetworkError)
                    {
                        Delete(record);
                    }
                    else
                    {
                        IncrementBatchRetry();
                        return;
                    }
                    bool shouldProcess = _reportLimitWatcher.WatchReport(DateTimeHelper.Timestamp());
                    if (!shouldProcess)
                    {
                        return;
                    }
                    record = BacktraceDatabaseContext.FirstOrDefault();
                    SendData(record);
                }));
            }
        }
コード例 #10
0
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
#if !NET35
                    BacktraceApi?.Dispose();
                    _timer?.Dispose();
#endif
                }
                _disposed = true;
            }
        }
コード例 #11
0
        public void Setup()
        {
            var credentials        = new BacktraceCredentials("https://validurl.com/", "validToken");
            var invalidCredentials = new BacktraceCredentials("https://validurl.com/", "invalidToken");
            //mock API
            var serverUrl  = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
            var invalidUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";

            var mockHttp = new MockHttpMessageHandler();

            mockHttp.When(serverUrl)
            .Respond("application/json", "{'object' : 'aaa'}");

            mockHttp.When(invalidUrl)
            .Respond("application/json", "{'message': 'invalid data'}");
            var api = new BacktraceApi(credentials, 0)
            {
                HttpClient = mockHttp.ToHttpClient()
            };

            var apiWithInvalidUrl = new BacktraceApi(invalidCredentials, 100)
            {
                HttpClient = mockHttp.ToHttpClient()
            };


            //mock database
            var database = new Mock <IBacktraceDatabase>();

            database.Setup(n =>
                           n.Add(It.IsAny <BacktraceReport>(),
                                 It.IsAny <Dictionary <string, object> >(),
                                 It.IsAny <MiniDumpType>()));

            database.Setup(n =>
                           n.Delete(It.IsAny <BacktraceDatabaseRecord>()));

            //setup new client
            _backtraceClient = new BacktraceClient(credentials, database: database.Object, reportPerMin: 0)
            {
                BacktraceApi = api,
                Database     = database.Object
            };
            _clientWithInvalidParameters = new BacktraceClient(invalidCredentials, database: database.Object, reportPerMin: 0)
            {
                BacktraceApi = apiWithInvalidUrl,
                Database     = database.Object
            };
        }
コード例 #12
0
        /// <summary>
        /// Send and asynchronous delete all records from database
        /// </summary>
        public async Task FlushAsync()
        {
            if (BacktraceApi == null)
            {
                throw new ArgumentException("BacktraceApi is required if you want to use Flush method");
            }
            var record = BacktraceDatabaseContext?.FirstOrDefault();

            while (record != null)
            {
                var backtraceData = record.BacktraceData;
                Delete(record);
                record = BacktraceDatabaseContext.FirstOrDefault();
                if (backtraceData != null)
                {
                    await BacktraceApi.SendAsync(backtraceData);
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Reload Backtrace database configuration. Reloading configuration is required, when you change
        /// BacktraceDatabase configuration options.
        /// </summary>
        public void Reload()
        {
            // validate configuration
            if (Configuration == null)
            {
                Configuration = GetComponent <BacktraceClient>().Configuration;
            }
            if (Instance != null)
            {
                return;
            }
            if (Configuration == null || !Configuration.IsValid())
            {
                Enable = false;
                return;
            }

#if UNITY_SWITCH
            Enable = false;
#else
            Enable = Configuration.Enabled && InitializeDatabasePaths();
#endif
            if (!Enable)
            {
                if (Configuration.Enabled)
                {
                    Debug.LogWarning("Cannot initialize database - invalid path to database. Database is disabled");
                }
                return;
            }


            //setup database object
            DatabaseSettings = new BacktraceDatabaseSettings(DatabasePath, Configuration);
            SetupMultisceneSupport();
            _lastConnection = Time.time;
            LastFrameTime   = Time.time;
            //Setup database context
            BacktraceDatabaseContext     = new BacktraceDatabaseContext(DatabaseSettings);
            BacktraceDatabaseFileContext = new BacktraceDatabaseFileContext(DatabaseSettings.DatabasePath, DatabaseSettings.MaxDatabaseSize, DatabaseSettings.MaxRecordCount);
            BacktraceApi        = new BacktraceApi(Configuration.ToCredentials());
            _reportLimitWatcher = new ReportLimitWatcher(Convert.ToUInt32(Configuration.ReportPerMin));
        }
コード例 #14
0
        private async void OnTimedEventAsync(object source, ElapsedEventArgs e)
        {
            if (!BacktraceDatabaseContext.Any() || _timerBackgroundWork)
            {
                return;
            }

            _timerBackgroundWork = true;
            _timer.Stop();
            //read first record (keep in mind LIFO and FIFO settings) from memory database
            var record = BacktraceDatabaseContext.FirstOrDefault();

            while (record != null)
            {
                var backtraceData = record.BacktraceData;

                //meanwhile someone delete data from a disk
                if (backtraceData == null || backtraceData.Report == null)
                {
                    Delete(record);
                }
                else
                {
                    //send record from database to API
                    var result = await BacktraceApi.SendAsync(backtraceData);

                    if (result.Status == BacktraceResultStatus.Ok)
                    {
                        Delete(record);
                    }
                    else
                    {
                        record.Dispose();
                        BacktraceDatabaseContext.IncrementBatchRetry();
                        break;
                    }
                }
                record = BacktraceDatabaseContext.FirstOrDefault();
            }
            _timer.Start();
            _timerBackgroundWork = false;
        }
コード例 #15
0
        private void FlushRecord(BacktraceDatabaseRecord record)
        {
            if (record == null)
            {
                return;
            }
            var backtraceData = record.BacktraceData;

            Delete(record);
            if (backtraceData == null)
            {
                return;
            }
            StartCoroutine(
                BacktraceApi.Send(backtraceData, (BacktraceResult result) =>
            {
                record = BacktraceDatabaseContext.FirstOrDefault();
                FlushRecord(record);
            }));
        }
コード例 #16
0
        public void Setup()
        {
            var credentials = new BacktraceCredentials("https://validurl.com/", "validToken");

            //mock api
            var serverUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
            var mockHttp  = new MockHttpMessageHandler();

            mockHttp.When(serverUrl)
            .Respond("application/json", "{'object' : 'aaa'}");
            var api = new BacktraceApi(credentials, 0)
            {
                HttpClient = mockHttp.ToHttpClient()
            };

            //setup new client
            _backtraceClient = new BacktraceClient(credentials)
            {
                BacktraceApi = api
            };
        }
コード例 #17
0
        public void Setup()
        {
            //prepare mock object
            var credentials = new BacktraceCredentials("https://validurl.com/", "validToken");
            //mock api
            var serverUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";

            var mockHttp = new MockHttpMessageHandler();

            mockHttp.When(serverUrl)
            .Respond("application/json", "{'object' : 'aaa'}");

            var api = new BacktraceApi(credentials, 0)
            {
                HttpClient = mockHttp.ToHttpClient(),
                //avoid real submission
                RequestHandler = (string host, string boundaryId, BacktraceData data) =>
                {
                    return(new BacktraceResult());
                }
            };

            //mock database
            var database = new Mock <IBacktraceDatabase>();

            database.Setup(n =>
                           n.Add(It.IsAny <BacktraceReport>(),
                                 It.IsAny <Dictionary <string, object> >(),
                                 It.IsAny <MiniDumpType>()));

            database.Setup(n =>
                           n.Delete(It.IsAny <BacktraceDatabaseRecord>()));


            //setup new client
            _backtraceClient = new BacktraceClient(credentials, database: database.Object, reportPerMin: 0)
            {
                BacktraceApi = api
            };
        }
コード例 #18
0
        private void SendData(BacktraceDatabaseRecord record)
        {
            var backtraceData = record != null ? record.BacktraceData : null;

            //check if report exists on hard drive
            // to avoid situation when someone manually remove data
            if (backtraceData == null || backtraceData.Report == null)
            {
                Delete(record);
            }
            else
            {
                StartCoroutine(
                    BacktraceApi.Send(backtraceData, (BacktraceResult sendResult) =>
                {
                    if (sendResult.Status == BacktraceResultStatus.Ok)
                    {
                        Delete(record);
                    }
                    else
                    {
                        record.Dispose();
                        BacktraceDatabaseContext.IncrementBatchRetry();
                        return;
                    }
                    bool limitHit = _reportLimitWatcher.WatchReport(new DateTime().Timestamp());
                    if (!limitHit)
                    {
                        _reportLimitWatcher.DisplayReportLimitHitMessage();
                        return;
                    }
                    record = BacktraceDatabaseContext.FirstOrDefault();
                    SendData(record);
                }));
            }
        }
コード例 #19
0
        /// <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);
                }
            }));
        }