Beispiel #1
0
 private async Task PersistLogAsync(Log log, State state)
 {
     try
     {
         await _storage.PutLog(Name, log).ConfigureAwait(false);
     }
     catch (StorageException e)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, "Error persisting log", e);
         return;
     }
     try
     {
         bool enabled;
         using (await _mutex.GetLockAsync(state).ConfigureAwait(false))
         {
             _pendingLogCount++;
             enabled = _enabled;
         }
         if (enabled)
         {
             CheckPendingLogs(state);
             return;
         }
         AppCenterLog.Warn(AppCenterLog.LogTag, "Channel is temporarily disabled; log was saved to disk");
     }
     catch (StatefulMutexException)
     {
         AppCenterLog.Warn(AppCenterLog.LogTag, "The PersistLog operation has been cancelled");
     }
 }
        /// <summary>
        /// Initializes the singleton application object. This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            // Init settings.
            localSettings = ApplicationData.Current.LocalSettings;
            TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs args) =>
            {
                // If you see this message while testing the app and if the stack trace is SDK related, we might have a bug in the SDK as we don't want to leak any exception from the SDK.
                AppCenterLog.Error("AppCenterPuppet", "Unobserved exception observed=" + args.Observed, args.Exception);
            };
            CoreApplication.EnablePrelaunch(true);
            InitializeComponent();
            AppCenter.LogLevel = LogLevel.Verbose;
            AppCenter.SetLogUrl("https://in-integration.dev.avalanch.es");

            // Set data from local storage.
            var countryCode = localSettings.Values[Constants.KeyCountryCode] as string;

            if (!string.IsNullOrEmpty(countryCode))
            {
                AppCenter.SetCountryCode(countryCode);
            }
            var storageSize = localSettings.Values[Constants.KeyStorageMaxSize] as long?;

            if (storageSize != null && storageSize > 0)
            {
                AppCenter.SetMaxStorageSizeAsync((long)storageSize);
            }

            // User callbacks.
            Crashes.ShouldProcessErrorReport = (report) =>
            {
                Log($"Determining whether to process error report with an ID: {report.Id}");
                return(true);
            };
            Crashes.GetErrorAttachments = GetErrorAttachmentsHandler;

            // Event handlers.
            Crashes.SendingErrorReport      += (_, args) => Log($"Sending error report for an error ID: {args.Report.Id}");
            Crashes.SentErrorReport         += (_, args) => Log($"Sent error report for an error ID: {args.Report.Id}");
            Crashes.FailedToSendErrorReport += (_, args) => Log($"Failed to send error report for an error ID: {args.Report.Id}");

            // Start App Center.
            AppCenter.Start("2daf2955-b4e4-4206-b38a-fedcdc6f4f84", typeof(Analytics), typeof(Crashes));

            // Set userId.
            var userId = localSettings.Values[Constants.KeyUserId] as string;

            if (!string.IsNullOrEmpty(userId))
            {
                AppCenter.SetUserId(userId);
            }
            Crashes.HasCrashedInLastSessionAsync().ContinueWith(hasCrashed =>
            {
                Log("Crashes.HasCrashedInLastSession=" + hasCrashed.Result);
            });
            Crashes.GetLastSessionCrashReportAsync().ContinueWith(task =>
            {
                Log("Crashes.LastSessionCrashReport.StackTrace=" + task.Result?.StackTrace);
            });
        }
        private async Task <string[]> LoadDeliveryTimeList()
        {
            try
            {
                var timeList = await restActions.GetDeliveryTime();

                string[] time = new string[timeList.Count];
                int      i    = 0;

                foreach (var deliveryTimeObj in timeList)
                {
                    time[i] = deliveryTimeObj.DELIVERY_TIME;
                    i++;
                }


                return(time);
            }
            catch (Exception e)
            {
                AppCenterLog.Error("ERROR", e.Message, e);
            }

            return(null);
        }
        private List <object[]> ExecuteSelectionSqlQuery(string query, IList <object> args = null)
        {
            var db     = _db ?? throw new StorageException("The database wasn't initialized.");
            var result = raw.sqlite3_prepare_v2(db, query, out var stmt);

            if (result != raw.SQLITE_OK)
            {
                throw ToStorageException(result, "Failed to prepare SQL query");
            }
            try
            {
                var entries = new List <object[]>();
                BindParameters(stmt, args);
                while (raw.sqlite3_step(stmt) == raw.SQLITE_ROW)
                {
                    var count = raw.sqlite3_column_count(stmt);
                    entries.Add(Enumerable.Range(0, count).Select(i => GetColumnValue(stmt, i)).ToArray());
                }
                return(entries);
            }
            finally
            {
                result = raw.sqlite3_finalize(stmt);
                if (result != raw.SQLITE_OK)
                {
                    AppCenterLog.Error(AppCenterLog.LogTag, $"Failed to finalize statement, result={result}");
                }
            }
        }
Beispiel #5
0
        private void HandleSendingFailure(State state, string batchId, IngestionException e)
        {
            var isRecoverable = e?.IsRecoverable ?? false;

            AppCenterLog.Error(AppCenterLog.LogTag, $"Sending logs for channel '{Name}', batch '{batchId}' failed: {e?.Message}");
            List <Log> removedLogs;

            using (_mutex.GetLock(state))
            {
                removedLogs = _sendingBatches[batchId];
                _sendingBatches.Remove(batchId);
                if (isRecoverable)
                {
                    _pendingLogCount += removedLogs.Count;
                }
            }
            if (!isRecoverable && FailedToSendLog != null)
            {
                foreach (var log in removedLogs)
                {
                    FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, e));
                }
            }
            Suspend(state, !isRecoverable, e);
        }
        private void ExecuteNonSelectionSqlQuery(string query, IList <object> args = null)
        {
            var db     = _db ?? throw new StorageException("The database wasn't initialized.");
            var result = raw.sqlite3_prepare_v2(db, query, out var stmt);

            if (result != raw.SQLITE_OK)
            {
                throw ToStorageException(result, "Failed to prepare SQL query");
            }
            try
            {
                BindParameters(stmt, args);
                result = raw.sqlite3_step(stmt);
                if (result != raw.SQLITE_DONE)
                {
                    throw ToStorageException(result, "Failed to run query");
                }
            }
            finally
            {
                result = raw.sqlite3_finalize(stmt);
                if (result != raw.SQLITE_OK)
                {
                    AppCenterLog.Error(AppCenterLog.LogTag, $"Failed to finalize statement, result={result}");
                }
            }
        }
        /// <summary>
        /// Saves an error log on disk.
        /// </summary>
        /// <param name="exception">The exception that caused the crash.</param>
        /// <param name="errorLog">The error log.</param>
        public virtual void InstanceSaveErrorLogFiles(System.Exception exception, ManagedErrorLog errorLog)
        {
            try
            {
                // Serialize main log file.
                var errorLogString   = LogSerializer.Serialize(errorLog);
                var errorLogFileName = errorLog.Id + ErrorLogFileExtension;
                AppCenterLog.Debug(Crashes.LogTag, "Saving uncaught exception.");
                var directory = InstanceGetErrorStorageDirectory();
                directory.CreateFile(errorLogFileName, errorLogString);
                AppCenterLog.Debug(Crashes.LogTag, $"Saved error log in directory {ErrorStorageDirectoryName} with name {errorLogFileName}.");

                try
                {
                    // Serialize exception as raw stack trace.
                    var exceptionFileName = errorLog.Id + ExceptionFileExtension;
                    directory.CreateFile(exceptionFileName, exception.ToString());
                    AppCenterLog.Debug(Crashes.LogTag, $"Saved exception in directory {ErrorStorageDirectoryName} with name {exceptionFileName}.");
                }
                catch (System.Exception ex)
                {
                    AppCenterLog.Warn(Crashes.LogTag, "Failed to serialize exception for client side inspection.", ex);
                }
            }
            catch (System.Exception ex)
            {
                AppCenterLog.Error(Crashes.LogTag, "Failed to save error log.", ex);
            }
        }
        public void OnChannelGroupReady(IChannelGroup channelGroup, string appSecret)
        {
            try
            {
#if REFERENCE
#else
                WatsonRegistrationManager.Start(appSecret);
#pragma warning disable CS0612 // Type or member is obsolete
                AppCenter.CorrelationIdChanged += (s, id) =>
                {
                    WatsonRegistrationManager.SetCorrelationId(id.ToString());
                };

                // Checking for null and setting id needs to be atomic to avoid
                // overwriting
                Guid newId = Guid.NewGuid();
                AppCenter.TestAndSetCorrelationId(Guid.Empty, ref newId);
#pragma warning restore CS0612 // Type or member is obsolete
#endif
            }
            catch (Exception e)
            {
                AppCenterLog.Error(AppCenterLog.LogTag, "Failed to register crashes with Watson", e);
            }
        }
        private async Task <Exception> HandleStorageRelatedExceptionAsync(Exception e)
        {
            // Check if database is corrupted, we have evidence (https://github.com/microsoft/appcenter-sdk-dotnet/issues/1184)
            // that it's not always originated by a proper SQLiteException (which would then be converted to StorageException in StorageAdapter).
            // If it was always the right type then the exception would not have been unobserved in that application before we changed the re-throw logic here.
            // But the message is definitely "Corrupt" and thus unfortunately that is the only check we seem to be able to do as opposed to type/property checking.
            if (e.Message == "Corrupt" || e.InnerException?.Message == "Corrupt")
            {
                AppCenterLog.Error(AppCenterLog.LogTag, "Database corruption detected, deleting the file and starting fresh...", e);
                await _storageAdapter.DeleteDatabaseFileAsync().ConfigureAwait(false);
                await InitializeDatabaseAsync().ConfigureAwait(false);
            }

            // Return exception to re-throw.
            if (e is StorageException)
            {
                // This is the expected case, storage adapter already wraps exception as StorageException, so return as is.
                return(e);
            }

            // Tasks should already be throwing only storage exceptions, but in case any are missed,
            // which has happened (the Corrupt exception mentioned previously), catch them here and wrap in a storage exception. This will prevent
            // the exception from being unobserved.
            return(new StorageException(e));
        }
Beispiel #10
0
        async void RunMBaaSAsync(object sender, EventArgs e)
        {
            try
            {
                userInfo = await Auth.SignInAsync();

                if (userInfo.AccountId != null)
                {
                    Application.Current.Properties[AccountId] = userInfo.AccountId;
                    SignInInformationButton.Text = "User authenticated";
                }
                AppCenterLog.Info(App.LogTag, "Auth.SignInAsync succeeded accountId=" + userInfo.AccountId);
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Auth scenario failed", ex);
                Crashes.TrackError(ex);
            }
            try
            {
                var list = await Data.ListAsync <CustomDocument>(DefaultPartitions.UserDocuments);

                foreach (var doc in list)
                {
                    AppCenterLog.Info(App.LogTag, "List result=" + doc.DeserializedValue.id);
                }
                var document = list.CurrentPage.Items.First();
                AppCenterLog.Info(App.LogTag, "List first result=" + document.DeserializedValue.id);
                document = await Data.DeleteAsync <CustomDocument>(document.Id, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Delete result=" + document.DeserializedValue);
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Data list/delete first scenario failed", ex);
                Crashes.TrackError(ex);
            }
            try
            {
                var customDoc = new CustomDocument
                {
                    id        = Guid.NewGuid(),
                    timestamp = DateTime.UtcNow
                };
                var id       = customDoc.id.ToString();
                var document = await Data.ReplaceAsync(id, customDoc, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Replace result=" + document.DeserializedValue.id);
                document = await Data.ReadAsync <CustomDocument>(id, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Read result=" + document.DeserializedValue.id);
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Data person scenario failed", ex);
                Crashes.TrackError(ex);
            }
        }
 /// <summary>
 /// Check if userId is valid for App Center.
 /// </summary>
 /// <param name="userId"></param>
 /// <returns>true if valid, false otherwise.</returns>
 public static bool CheckUserIdValidForAppCenter(String userId)
 {
     if (userId != null && userId.Length > UserIdMaxLength)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, "userId is limited to " + UserIdMaxLength + " characters.");
         return(false);
     }
     return(true);
 }
        private void CreatePushNotificationChannel(Action <PushNotificationChannel> created)
        {
            Task <PushNotificationChannel> CreatePushNotificationChannelForApplicationAsync()
            {
                try
                {
                    return(new WindowsPushNotificationChannelManager()
                           .CreatePushNotificationChannelForApplicationAsync()
                           .AsTask());
                }
                catch (Exception e)
                {
                    return(Task.FromException <PushNotificationChannel>(e));
                }
            }

            void OnNetworkStateChange(object sender, EventArgs e)
            {
                if (NetworkStateAdapter.IsConnected)
                {
                    NetworkStateAdapter.NetworkStatusChanged -= OnNetworkStateChange;
                    AppCenterLog.Debug(LogTag, "Second attempt to create notification channel...");

                    // Second attempt is the last one anyway.
                    CreatePushNotificationChannelForApplicationAsync().ContinueWith(task =>
                    {
                        if (task.IsFaulted)
                        {
                            AppCenterLog.Error(LogTag, "Unable to create notification channel.", task.Exception);
                            return;
                        }
                        created?.Invoke(task.Result);
                    });
                }
            }

            // If this isn't the first time after installation, the notification channel is created successfully even without network.
            CreatePushNotificationChannelForApplicationAsync().ContinueWith(task =>
            {
                if (task.IsFaulted && NetworkStateAdapter.IsConnected)
                {
                    AppCenterLog.Error(LogTag, "Unable to create notification channel.", task.Exception);
                    return;
                }
                if (!task.IsFaulted && task.Result != null)
                {
                    created?.Invoke(task.Result);
                    return;
                }
                AppCenterLog.Debug(LogTag, "The network isn't connected, another attempt to crate push notification channel " +
                                   "will be made after the network is available.");
                NetworkStateAdapter.NetworkStatusChanged += OnNetworkStateChange;
            });
        }
 static StorageAdapter()
 {
     try
     {
         Batteries_V2.Init();
     }
     catch (Exception e)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, "Failed to initialize sqlite3 provider.", e);
     }
 }
Beispiel #14
0
        /// <summary>
        /// If enabled, register push channel and send URI to backend.
        /// Also start intercepting pushes.
        /// If disabled and previously enabled, stop listening for pushes (they will still be received though).
        /// </summary>
        private void ApplyEnabledState(bool enabled)
        {
            if (enabled)
            {
                // We expect caller of this method to lock on _mutex, we can't do it here as that lock is not recursive
                AppCenterLog.Debug(LogTag, "Getting push token...");
                var state = _mutex.State;
                CreatePushNotificationChannel(channel =>
                {
                    try
                    {
                        using (_mutex.GetLock(state))
                        {
                            LatestPushToken = channel?.Uri;
                            if (!string.IsNullOrEmpty(LatestPushToken))
                            {
                                // Save channel member
                                _channel = channel;

                                // Subscribe to UserId Change.
                                UserIdContext.UserIdUpdated -= OnUserIdUpdated;
                                UserIdContext.UserIdUpdated += OnUserIdUpdated;

                                // Subscribe to push.
                                channel.PushNotificationReceived += OnPushNotificationReceivedHandler;

                                // Send channel URI to backend
                                AppCenterLog.Debug(LogTag, $"Push token '{LatestPushToken}'");
                                var pushInstallationLog = new PushInstallationLog(null, LatestPushToken, null, Guid.NewGuid(), UserIdContext.Instance.UserId);

                                // Do not await the call to EnqueueAsync or the UI thread can be blocked!
#pragma warning disable CS4014
                                Channel.EnqueueAsync(pushInstallationLog);
#pragma warning restore
                            }
                            else
                            {
                                AppCenterLog.Error(LogTag, "Push service registering with App Center backend has failed.");
                            }
                        }
                    }
                    catch (StatefulMutexException)
                    {
                        AppCenterLog.Warn(LogTag, "Push Enabled state changed after creating channel.");
                    }
                });
            }
            else if (_channel != null)
            {
                LatestPushToken                    = null;
                UserIdContext.UserIdUpdated       -= OnUserIdUpdated;
                _channel.PushNotificationReceived -= OnPushNotificationReceivedHandler;
            }
        }
Beispiel #15
0
 private async Task InitializeDatabaseAsync()
 {
     try
     {
         await _storageAdapter.CreateTableAsync <LogEntry>().ConfigureAwait(false);
     }
     catch (Exception e)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, "An error occurred while initializing storage", e);
     }
 }
Beispiel #16
0
        /// <summary>
        /// Track a handled error.
        /// </summary>
        /// <param name="exception">The .NET exception describing the handled error.</param>
        /// <param name="properties">Optional properties.</param>
#endif
        public static void TrackError(Exception exception, IDictionary <string, string> properties = null)
        {
            if (exception == null)
            {
                AppCenterLog.Error(LogTag, "TrackError exception parameter cannot be null.");
            }
            else
            {
                PlatformTrackError(exception, properties);
            }
        }
 public long GetMaxStorageSize()
 {
     try
     {
         return(GetMaxPageCount() * GetPageSize());
     }
     catch (StorageException)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, $"Could not get max storage size.");
         return(-1);
     }
 }
 /// <summary>
 /// Reads an exception file from the given file.
 /// </summary>
 /// <param name="file">The file that contains exception.</param>
 /// <returns>An exception stack trace or null if the file cannot be read.</returns>
 public virtual string InstanceReadExceptionFile(File file)
 {
     try
     {
         return(file.ReadAllText());
     }
     catch (System.Exception e)
     {
         AppCenterLog.Error(Crashes.LogTag, $"Encountered an unexpected error while reading stack trace file: {file.Name}", e);
     }
     return(null);
 }
Beispiel #19
0
        async void RunMBaaSAsync(object sender, EventArgs e)
        {
            try
            {
                var userInfo = await Auth.SignInAsync();

                AppCenterLog.Info(App.LogTag, "Auth.SignInAsync succeeded accountId=" + userInfo.AccountId);
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Auth scenario failed", ex);
                Crashes.TrackError(ex);
            }
            try
            {
                var list = await Data.ListAsync <CustomDocument>(DefaultPartitions.UserDocuments);

                foreach (var doc in list)
                {
                    AppCenterLog.Info(App.LogTag, "List result=" + JsonConvert.SerializeObject(doc));
                }
                var document = list.CurrentPage.Items.First();
                AppCenterLog.Info(App.LogTag, "List first result=" + JsonConvert.SerializeObject(document));
                document = await Data.DeleteAsync <CustomDocument>(document.Id, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Delete result=" + JsonConvert.SerializeObject(document));
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Data list/delete first scenario failed", ex);
                Crashes.TrackError(ex);
            }
            try
            {
                var customDoc = new CustomDocument
                {
                    Id        = Guid.NewGuid(),
                    TimeStamp = DateTime.UtcNow
                };
                var id       = customDoc.Id.ToString();
                var document = await Data.ReplaceAsync(id, customDoc, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Replace result=" + JsonConvert.SerializeObject(document));
                document = await Data.ReadAsync <CustomDocument>(id, DefaultPartitions.UserDocuments);

                AppCenterLog.Info(App.LogTag, "Read result=" + JsonConvert.SerializeObject(document));
            }
            catch (Exception ex)
            {
                AppCenterLog.Error(App.LogTag, "Data person scenario failed", ex);
                Crashes.TrackError(ex);
            }
        }
Beispiel #20
0
        static void OnUnhandledException(object sender, RaiseThrowableEventArgs e)
        {
            var exception = e.Exception;

            AppCenterLog.Error(LogTag, "Unhandled Exception:", exception);
            var javaThrowable  = exception as Throwable;
            var modelException = GenerateModelException(exception, true);

            byte[] rawException = javaThrowable == null?CrashesUtils.SerializeException(exception) : null;

            WrapperSdkExceptionManager.SaveWrapperException(Thread.CurrentThread(), javaThrowable, modelException, rawException);
        }
Beispiel #21
0
        /// <summary>
        /// Asynchronously retrieves logs from storage and flags them to avoid duplicate retrievals on subsequent calls
        /// </summary>
        /// <param name="channelName">Name of the channel to retrieve logs from</param>
        /// <param name="limit">The maximum number of logs to retrieve</param>
        /// <param name="logs">A list to which the retrieved logs will be added</param>
        /// <returns>A batch ID for the set of returned logs; null if no logs are found</returns>
        /// <exception cref="StorageException"/>
        public Task <string> GetLogsAsync(string channelName, int limit, List <Log> logs)
        {
            return(AddTaskToQueue(() =>
            {
                logs?.Clear();
                var retrievedLogs = new List <Log>();
                AppCenterLog.Debug(AppCenterLog.LogTag,
                                   $"Trying to get up to {limit} logs from storage for {channelName}");
                var idPairs = new List <Tuple <Guid?, long> >();
                var failedToDeserializeALog = false;
                var objectEntries = _storageAdapter.Select(TableName, ColumnChannelName, channelName, ColumnIdName, _pendingDbIdentifiers.Cast <object>().ToArray(), limit);
                var retrievedEntries = objectEntries.Select(entries =>
                                                            new LogEntry()
                {
                    Id = (long)entries[0],
                    Channel = (string)entries[1],
                    Log = (string)entries[2]
                }
                                                            ).ToList();
                foreach (var entry in retrievedEntries)
                {
                    try
                    {
                        var log = LogSerializer.DeserializeLog(entry.Log);
                        retrievedLogs.Add(log);
                        idPairs.Add(Tuple.Create(log.Sid, Convert.ToInt64(entry.Id)));
                    }
                    catch (JsonException e)
                    {
                        AppCenterLog.Error(AppCenterLog.LogTag, "Cannot deserialize a log in storage", e);
                        failedToDeserializeALog = true;
                        _storageAdapter.Delete(TableName, ColumnIdName, entry.Id);
                    }
                }
                if (failedToDeserializeALog)
                {
                    AppCenterLog.Warn(AppCenterLog.LogTag, "Deleted logs that could not be deserialized");
                }
                if (idPairs.Count == 0)
                {
                    AppCenterLog.Debug(AppCenterLog.LogTag,
                                       $"No available logs in storage for channel '{channelName}'");
                    return null;
                }

                // Process the results
                var batchId = Guid.NewGuid().ToString();
                ProcessLogIds(channelName, batchId, idPairs);
                logs?.AddRange(retrievedLogs);
                return batchId;
            }));
        }
Beispiel #22
0
 /// <summary>
 /// Initializes the singleton application object.  This is the first line of authored code
 /// executed, and as such is the logical equivalent of main() or WinMain().
 /// </summary>
 public App()
 {
     TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs args) =>
     {
         // If you see this message while testing the app and if the stack trace is SDK related, we might have a bug in the SDK as we don't want to leak any exception from the SDK.
         AppCenterLog.Error("AppCenterDemo", "Unobserved exception observed=" + args.Observed, args.Exception);
     };
     CoreApplication.EnablePrelaunch(true);
     InitializeComponent();
     Suspending        += OnSuspending;
     AppCenter.LogLevel = LogLevel.Verbose;
     AppCenter.Start("e8354a9a-001a-4728-be65-a6477e57f2e7", typeof(Analytics), typeof(Crashes));
 }
 /// <summary>
 /// Reads an error log file from the given file.
 /// </summary>
 /// <param name="file">The file that contains error log.</param>
 /// <returns>An error log instance or null if the file doesn't contain an error log.</returns>
 public virtual ManagedErrorLog InstanceReadErrorLogFile(File file)
 {
     try
     {
         var errorLogString = file.ReadAllText();
         return((ManagedErrorLog)LogSerializer.DeserializeLog(errorLogString));
     }
     catch (System.Exception e)
     {
         AppCenterLog.Error(Crashes.LogTag, $"Encountered an unexpected error while reading an error log file: {file.Name}", e);
     }
     return(null);
 }
Beispiel #24
0
        static void OnUnhandledException(Exception exception, string source)
        {
            if (_exception == null)
            {
                AppCenterLog.Error(LogTag, $"Unhandled Exception from source={source}", exception);
                var    javaThrowable  = exception as Throwable;
                var    modelException = GenerateModelException(exception, true);
                byte[] rawException   = javaThrowable == null?CrashesUtils.SerializeException(exception) : null;

                WrapperSdkExceptionManager.SaveWrapperException(Thread.CurrentThread(), javaThrowable, modelException, rawException);
                _exception = exception;
            }
        }
Beispiel #25
0
        /// <summary>
        /// Asynchronously retrieves logs from storage and flags them to avoid duplicate retrievals on subsequent calls
        /// </summary>
        /// <param name="channelName">Name of the channel to retrieve logs from</param>
        /// <param name="limit">The maximum number of logs to retrieve</param>
        /// <param name="logs">A list to which the retrieved logs will be added</param>
        /// <returns>A batch ID for the set of returned logs; null if no logs are found</returns>
        /// <exception cref="StorageException"/>
        public Task <string> GetLogsAsync(string channelName, int limit, List <Log> logs)
        {
            return(AddTaskToQueue(() =>
            {
                logs?.Clear();
                var retrievedLogs = new List <Log>();
                AppCenterLog.Debug(AppCenterLog.LogTag,
                                   $"Trying to get up to {limit} logs from storage for {channelName}");
                var idPairs = new List <Tuple <Guid?, long> >();
                var failedToDeserializeALog = false;
                var retrievedEntries =
                    _storageAdapter.GetAsync <LogEntry>(entry => entry.Channel == channelName, limit)
                    .GetAwaiter().GetResult();
                foreach (var entry in retrievedEntries)
                {
                    if (_pendingDbIdentifiers.Contains(entry.Id))
                    {
                        continue;
                    }
                    try
                    {
                        var log = LogSerializer.DeserializeLog(entry.Log);
                        retrievedLogs.Add(log);
                        idPairs.Add(Tuple.Create(log.Sid, Convert.ToInt64(entry.Id)));
                    }
                    catch (JsonException e)
                    {
                        AppCenterLog.Error(AppCenterLog.LogTag, "Cannot deserialize a log in storage", e);
                        failedToDeserializeALog = true;
                        _storageAdapter.DeleteAsync <LogEntry>(row => row.Id == entry.Id)
                        .GetAwaiter().GetResult();
                    }
                }
                if (failedToDeserializeALog)
                {
                    AppCenterLog.Warn(AppCenterLog.LogTag, "Deleted logs that could not be deserialized");
                }
                if (idPairs.Count == 0)
                {
                    AppCenterLog.Debug(AppCenterLog.LogTag,
                                       $"No available logs in storage for channel '{channelName}'");
                    return null;
                }

                // Process the results
                var batchId = Guid.NewGuid().ToString();
                ProcessLogIds(channelName, batchId, idPairs);
                logs?.AddRange(retrievedLogs);
                return batchId;
            }));
        }
        public bool SetMaxStorageSize(long sizeInBytes)
        {
            var db = _db ?? throw new StorageException("The database wasn't initialized.");

            // Check the current number of pages in the database to determine whether the requested size will shrink the database.
            var currentPageCount = GetPageCount();
            var pageSize         = GetPageSize();

            AppCenterLog.Info(AppCenterLog.LogTag, $"Found {currentPageCount} pages in the database.");
            var requestedMaxPageCount = Convert.ToBoolean(sizeInBytes % pageSize) ? sizeInBytes / pageSize + 1 : sizeInBytes / pageSize;

            if (currentPageCount > requestedMaxPageCount)
            {
                AppCenterLog.Warn(AppCenterLog.LogTag, $"Cannot change database size to {sizeInBytes} bytes as it would cause a loss of data. " +
                                  "Maximum database size will not be changed.");
                return(false);
            }
            else
            {
                // Attempt to set the limit and check the page count to make sure the given limit works.
                var result = raw.sqlite3_exec(db, $"PRAGMA max_page_count = {requestedMaxPageCount};");
                if (result != raw.SQLITE_OK)
                {
                    AppCenterLog.Error(AppCenterLog.LogTag, $"Could not change maximum database size to {sizeInBytes} bytes. SQLite error code: {result}.");
                    return(false);
                }
                else
                {
                    var currentMaxPageCount = GetMaxPageCount();
                    var actualMaxSize       = currentMaxPageCount * pageSize;
                    if (requestedMaxPageCount != currentMaxPageCount)
                    {
                        AppCenterLog.Error(AppCenterLog.LogTag, $"Could not change maximum database size to {sizeInBytes} bytes, current maximum size is {actualMaxSize} bytes.");
                        return(false);
                    }
                    else
                    {
                        if (sizeInBytes == actualMaxSize)
                        {
                            AppCenterLog.Info(AppCenterLog.LogTag, $"Changed maximum database size to {actualMaxSize} bytes.");
                        }
                        else
                        {
                            AppCenterLog.Info(AppCenterLog.LogTag, $"Changed maximum database size to {actualMaxSize} bytes (next multiple of 4KiB).");
                        }
                        return(true);
                    }
                }
            }
        }
        private async Task <PushNotificationChannel> CreatePushNotificationChannelAsync()
        {
            PushNotificationChannel channel = null;

            try
            {
                // If this isn't the first time after installation, the notification channel is created successfully even without network.
                channel = await new WindowsPushNotificationChannelManager().CreatePushNotificationChannelForApplicationAsync()
                          .AsTask().ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                if (NetworkStateAdapter.IsConnected)
                {
                    AppCenterLog.Error(LogTag, "Unable to create notification channel.", exception);
                    return(null);
                }
            }
            if (channel != null)
            {
                return(channel);
            }
            AppCenterLog.Debug(LogTag, "The network isn't connected, another attempt will be made after the network is available.");
            var networkSemaphore = new SemaphoreSlim(0);

            void NetworkStateChangeHandler(object sender, EventArgs e)
            {
                if (NetworkStateAdapter.IsConnected)
                {
                    networkSemaphore.Release();
                }
            }

            NetworkStateAdapter.NetworkStatusChanged += NetworkStateChangeHandler;
            await networkSemaphore.WaitAsync().ConfigureAwait(false);

            NetworkStateAdapter.NetworkStatusChanged -= NetworkStateChangeHandler;
            AppCenterLog.Debug(LogTag, "Second attempt to create notification channel...");
            try
            {
                // Second attempt is the last one anyway.
                return(await new WindowsPushNotificationChannelManager().CreatePushNotificationChannelForApplicationAsync()
                       .AsTask().ConfigureAwait(false));
            }
            catch (Exception exception)
            {
                AppCenterLog.Error(LogTag, "Unable to create notification channel.", exception);
                return(null);
            }
        }
Beispiel #28
0
 private static void DeleteAndroid()
 {
     try
     {
         var dbFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "../databases");
         Directory.Delete(dbFolder, true);
     } catch (DirectoryNotFoundException e)
     {
         AppCenterLog.Error(LogTag, $"Android DB not found {e.ToString()}.");
     }
     catch (IOException e)
     {
         AppCenterLog.Error(LogTag, $"Encountered IOException when tried to delete Android DB: {e.ToString()}.");
     }
 }
        partial void SaveStorageSize(NSObject sender)
        {
            var inputText = StorageSizeText.Text;

            if (int.TryParse(inputText, out var size))
            {
                AppCenter.SetMaxStorageSizeAsync(size);
                var plist = NSUserDefaults.StandardUserDefaults;
                plist.SetInt(size, Constants.StorageSizeKey);
            }
            else
            {
                AppCenterLog.Error(LogTag, "Wrong number value for the max storage size.");
            }
        }
Beispiel #30
0
 private void InitializeDatabase()
 {
     EnsureDatabaseDirectoryExists();
     try
     {
         _storageAdapter.Initialize(_databasePath);
         _storageAdapter.CreateTable(TableName,
                                     new[] { ColumnIdName, ColumnChannelName, ColumnLogName },
                                     new[] { "INTEGER PRIMARY KEY AUTOINCREMENT", "TEXT NOT NULL", "TEXT NOT NULL" });
     }
     catch (Exception e)
     {
         AppCenterLog.Error(AppCenterLog.LogTag, "An error occurred while initializing storage", e);
     }
 }