コード例 #1
0
 /// <summary>
 /// Delete existing record from database
 /// </summary>
 /// <param name="record">Database records to delete</param>
 public void Delete(BacktraceDatabaseRecord record)
 {
     if (record == null)
     {
         return;
     }
     for (int keyIndex = 0; keyIndex < BatchRetry.Keys.Count; keyIndex++)
     {
         var key = BatchRetry.Keys.ElementAt(keyIndex);
         for (int batchIndex = 0; batchIndex < BatchRetry[key].Count; batchIndex++)
         {
             var value = BatchRetry[key].ElementAt(batchIndex);
             if (value.Id == record.Id)
             {
                 //delete value from hard drive
                 value.Delete();
                 //delete value from current batch
                 BatchRetry[key].Remove(value);
                 //decrement all records
                 TotalRecords--;
                 //decrement total size of database
                 TotalSize -= value.Size;
                 System.Diagnostics.Debug.WriteLine($"[Delete] :: Total Size = {TotalSize}");
                 return;
             }
         }
     }
     return;
 }
コード例 #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
        /// <summary>
        /// Saves BacktraceDatabaseRecord on the hard drive
        /// </summary>
        /// <param name="record">BacktraceDatabaseRecord</param>
        /// <returns>true if file context was able to save data on the hard drive. Otherwise false</returns>
        public bool Save(BacktraceDatabaseRecord record)
        {
            try
            {
                var jsonPrefix = record.BacktraceData.UuidString;
                record.DiagnosticDataJson = record.BacktraceData.ToJson();
                record.DiagnosticDataPath = Path.Combine(_path, string.Format("{0}-attachment.json", jsonPrefix));
                record.Size += Save(record.DiagnosticDataJson, record.DiagnosticDataPath);

                // update record size based on the attachment information
                if (record.Attachments != null && record.Attachments.Count != 0)
                {
                    foreach (var attachment in record.Attachments)
                    {
                        if (IsDatabaseDependency(attachment))
                        {
                            record.Size += new FileInfo(attachment).Length;
                        }
                    }
                }
                record.RecordPath = Path.Combine(_path, string.Format("{0}-record.json", jsonPrefix));
                var recordJson = record.ToJson();
                record.Size += UTF8Encoding.Unicode.GetByteCount(recordJson);
                Save(recordJson, record.RecordPath);
                return(true);
            }
            catch (Exception e)
            {
                Debug.LogWarning(string.Format("Backtrace: Cannot save record on the hard drive. Reason: {0}", e.Message));
                Delete(record);

                return(false);
            }
        }
コード例 #4
0
 /// <summary>
 /// Delete single record from database
 /// </summary>
 /// <param name="record">Record to delete</param>
 public void Delete(BacktraceDatabaseRecord record)
 {
     if (BacktraceDatabaseContext != null)
     {
         BacktraceDatabaseContext.Delete(record);
     }
 }
コード例 #5
0
        /// <summary>
        /// Load all records stored in database path
        /// </summary>
        protected virtual void LoadReports()
        {
            if (!Enable)
            {
                return;
            }
            var files = BacktraceDatabaseFileContext.GetRecords();

            foreach (var file in files)
            {
                var record = BacktraceDatabaseRecord.ReadFromFile(file);
                if (record == null)
                {
                    continue;
                }
                record.DatabasePath(DatabaseSettings.DatabasePath);
                if (!record.Valid())
                {
                    try
                    {
                        Debug.Log("Removing record from Backtrace Database path - invalid record.");
                        record.Delete();
                    }
                    catch (Exception)
                    {
                        Debug.LogWarning(string.Format("Cannot remove file from database. File name: {0}", file.FullName));
                    }
                    continue;
                }
                BacktraceDatabaseContext.Add(record);
                ValidateDatabaseSize();
                record.Unlock();
            }
        }
コード例 #6
0
 /// <summary>
 /// Delete existing record from database
 /// </summary>
 /// <param name="record">Database records to delete</param>
 public void Delete(BacktraceDatabaseRecord record)
 {
     if (record == null)
     {
         return;
     }
     for (int keyIndex = 0; keyIndex < BatchRetry.Keys.Count; keyIndex++)
     {
         var key = BatchRetry.Keys.ElementAt(keyIndex);
         for (int batchIndex = 0; batchIndex < BatchRetry[key].Count; batchIndex++)
         {
             var value = BatchRetry[key].ElementAt(batchIndex);
             if (value.Id == record.Id)
             {
                 //delete value from hard drive
                 value.Delete();
                 //delete value from current batch
                 BatchRetry[key].Remove(value);
                 //decrement all records
                 if (value.Count > 0)
                 {
                     TotalRecords = TotalRecords - value.Count;
                 }
                 else
                 {
                     TotalRecords--;
                 }
                 //decrement total size of database
                 TotalSize -= value.Size;
                 return;
             }
         }
     }
 }
コード例 #7
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);
                }));
            }
        }
コード例 #8
0
        /// <summary>
        /// Load all records stored in database path
        /// </summary>
        protected virtual void LoadReports()
        {
            if (!Enable)
            {
                return;
            }
            var files = BacktraceDatabaseFileContext.GetRecords();

            foreach (var file in files)
            {
                var record = BacktraceDatabaseRecord.ReadFromFile(file);
                if (record == null)
                {
                    continue;
                }
                if (!BacktraceDatabaseFileContext.IsValidRecord(record))
                {
                    BacktraceDatabaseFileContext.Delete(record);
                    continue;
                }
                BacktraceDatabaseContext.Add(record);
                ValidateDatabaseSize();
                record.Unlock();
            }
        }
 public void Delete(BacktraceDatabaseRecord record)
 {
     if (OnDelete != null)
     {
         OnDelete.Invoke(record);
     }
     return;
 }
 public bool IsValidRecord(BacktraceDatabaseRecord record)
 {
     if (OnValidRecord != null)
     {
         return(OnValidRecord.Invoke(record));
     }
     return(false);
 }
コード例 #11
0
 /// <summary>
 /// Determine if BacktraceDatabaseRecord is valid.
 /// </summary>
 /// <param name="record">Database record</param>
 /// <returns>True, if the record exists. Otherwise false.</returns>
 public bool IsValidRecord(BacktraceDatabaseRecord record)
 {
     if (record == null)
     {
         return(false);
     }
     return(File.Exists(record.DiagnosticDataPath));
 }
 public bool Save(BacktraceDatabaseRecord record)
 {
     if (OnSave != null)
     {
         return(OnSave.Invoke(record));
     }
     return(true);
 }
コード例 #13
0
        /// <summary>
        /// Convert Backtrace data to Backtrace record and save it.
        /// </summary>
        /// <param name="backtraceData">Backtrace data</param>
        /// <param name="hash">deduplicaiton hash</param>
        /// <returns></returns>
        protected virtual BacktraceDatabaseRecord ConvertToRecord(BacktraceData backtraceData, string hash)
        {
            //create new record and save it on hard drive
            var record = new BacktraceDatabaseRecord(backtraceData, _path)
            {
                Hash = hash
            };

            record.Save();
            return(record);
        }
コード例 #14
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
            };
        }
コード例 #15
0
        /// <summary>
        /// Add new record to database
        /// </summary>
        /// <param name="backtraceData">Diagnostic data that should be stored in database</param>
        /// <returns>New instance of DatabaseRecordy</returns>
        public BacktraceDatabaseRecord Add(BacktraceData backtraceData)
        {
            if (backtraceData == null)
            {
                throw new NullReferenceException(nameof(backtraceData));
            }
            //create new record and save it on hard drive
            var record = new BacktraceDatabaseRecord(backtraceData, _path);

            record.Save();
            //add record to database context
            return(Add(record));
        }
コード例 #16
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);
                }));
            }
        }
コード例 #17
0
 /// <summary>
 /// Deletes backtrace database record from persistent data storage
 /// </summary>
 /// <param name="record">Database record</param>
 public void Delete(BacktraceDatabaseRecord record)
 {
     // remove json objects
     Delete(record.DiagnosticDataPath);
     Delete(record.RecordPath);
     //remove database attachments
     if (record.Attachments == null || record.Attachments.Count == 0)
     {
         return;
     }
     // remove associated attachments
     foreach (var attachment in record.Attachments)
     {
         Delete(attachment);
     }
 }
コード例 #18
0
 /// <summary>
 /// Add existing record to database
 /// </summary>
 /// <param name="backtraceRecord">Database record</param>
 public BacktraceDatabaseRecord Add(BacktraceDatabaseRecord backtraceRecord)
 {
     if (backtraceRecord == null)
     {
         throw new NullReferenceException(nameof(BacktraceDatabaseRecord));
     }
     //lock record, because Add method returns record
     backtraceRecord.Locked = true;
     //increment total size of database
     TotalSize += backtraceRecord.Size;
     //add record to first batch
     BatchRetry[0].Add(backtraceRecord);
     //increment total records
     TotalRecords++;
     return(backtraceRecord);
 }
コード例 #19
0
        /// <summary>
        /// Load all records stored in database path
        /// </summary>
        private void LoadReports()
        {
            var files = BacktraceDatabaseFileContext.GetRecords();

            foreach (var file in files)
            {
                var record = BacktraceDatabaseRecord.ReadFromFile(file);
                if (!record.Valid())
                {
                    record.Delete();
                    continue;
                }
                BacktraceDatabaseContext.Add(record);
                ValidateDatabaseSize();
                record.Dispose();
            }
        }
コード例 #20
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);
            }));
        }
コード例 #21
0
        /// <summary>
        /// Add new record to database
        /// </summary>
        /// <param name="backtraceData">Diagnostic data that should be stored in database</param>
        /// <returns>New instance of DatabaseRecordy</returns>
        public virtual BacktraceDatabaseRecord Add(BacktraceData backtraceData, MiniDumpType miniDumpType = MiniDumpType.None)
        {
            if (backtraceData == null)
            {
                throw new NullReferenceException(nameof(backtraceData));
            }
            string hash = GetHash(backtraceData);

            if (!string.IsNullOrEmpty(hash))
            {
                var existRecord = BatchRetry.SelectMany(n => n.Value)
                                  .FirstOrDefault(n => n.Hash == hash);

                if (existRecord != null)
                {
                    existRecord.Locked = true;
                    existRecord.Increment();
                    TotalRecords++;
                    return(existRecord);
                }
            }

            string minidumpPath = GenerateMiniDump(backtraceData.Report, miniDumpType);

            backtraceData.Report.SetMinidumpPath(minidumpPath);
            backtraceData.Attachments.Add(minidumpPath);

            //create new record and save it on hard drive
            var record = new BacktraceDatabaseRecord(backtraceData, _path)
            {
                Hash = hash
            };

            record.Save();
            //add record to database context
            return(Add(record));
        }
コード例 #22
0
        /// <summary>
        /// Load all records stored in database path
        /// </summary>
        private void LoadReports()
        {
            var files = BacktraceDatabaseFileContext.GetRecords();

            foreach (var file in files)
            {
                var record = BacktraceDatabaseRecord.ReadFromFile(file);
                if (!record.Valid())
                {
                    try
                    {
                        record.Delete();
                    }
                    catch (Exception)
                    {
                        Debug.LogWarning($"Cannot remove file from database. File name: {file.FullName}");
                    }
                    continue;
                }
                BacktraceDatabaseContext.Add(record);
                ValidateDatabaseSize();
                record.Dispose();
            }
        }
コード例 #23
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);
                }));
            }
        }
コード例 #24
0
 /// <summary>
 /// Delete single record from database
 /// </summary>
 /// <param name="record">Record to delete</param>
 public void Delete(BacktraceDatabaseRecord record)
 {
     BacktraceDatabaseContext?.Delete(record);
 }
コード例 #25
0
        /// <summary>
        /// Add new report to BacktraceDatabase
        /// </summary>
        public BacktraceDatabaseRecord Add(BacktraceData data, bool @lock = true)
        {
            if (data == null || !Enable)
            {
                return(null);
            }
            //remove old reports (if database is full)
            //and check database health state
            var validationResult = ValidateDatabaseSize();

            if (!validationResult)
            {
                return(null);
            }

            // validate if record already exists in the database object
            var hash = BacktraceDatabaseContext.GetHash(data);

            if (!string.IsNullOrEmpty(hash))
            {
                var existingRecord = BacktraceDatabaseContext.GetRecordByHash(hash);
                if (existingRecord != null)
                {
                    BacktraceDatabaseContext.AddDuplicate(existingRecord);
                    return(existingRecord);
                }
            }

            //add built-in attachments
            var attachments = BacktraceDatabaseFileContext.GenerateRecordAttachments(data);

            for (int attachmentIndex = 0; attachmentIndex < attachments.Count(); attachmentIndex++)
            {
                if (!string.IsNullOrEmpty(attachments.ElementAt(attachmentIndex)))
                {
                    data.Attachments.Add(attachments.ElementAt(attachmentIndex));
                }
            }
            // add to fresh new record breadcrumb attachment
            if (Breadcrumbs != null)
            {
                data.Attachments.Add(Breadcrumbs.GetBreadcrumbLogPath());
                data.Attributes.Attributes["breadcrumbs.lastId"] = Breadcrumbs.BreadcrumbId().ToString("F0", CultureInfo.InvariantCulture);
            }

            // now we now we're adding new unique report to database
            var record = new BacktraceDatabaseRecord(data)
            {
                Hash = hash
            };

            // save record on the hard drive and add it to database context
            var saveResult = BacktraceDatabaseFileContext.Save(record);

            if (!saveResult)
            {
                // file context won't remove json object that wasn't stored in the previous method
                // but will clean up attachments associated with this record.
                BacktraceDatabaseFileContext.Delete(record);
                return(null);
            }

            BacktraceDatabaseContext.Add(record);
            if (!@lock)
            {
                record.Unlock();
            }

            return(record);
        }
コード例 #26
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);
                }
            }));
        }
コード例 #27
0
 /// <summary>
 /// Check if any record exists
 /// </summary>
 /// <param name="record"></param>
 /// <returns></returns>
 public bool Any(BacktraceDatabaseRecord record)
 {
     return(BatchRetry.SelectMany(n => n.Value).Any(n => n.Id == record.Id));
 }
コード例 #28
0
 public void Delete(BacktraceDatabaseRecord record)
 {
     OnDelete?.Invoke(record);
     return;
 }
コード例 #29
0
 public bool IsValidRecord(BacktraceDatabaseRecord record)
 {
     return(OnValidRecord?.Invoke(record) ?? true);
 }
コード例 #30
0
 public bool Save(BacktraceDatabaseRecord record)
 {
     return(OnSave?.Invoke(record) ?? true);
 }