internal ErrorReport(AndroidErrorReport androidReport)
        {
            Id           = androidReport.Id;
            AppStartTime = DateTimeOffset.FromUnixTimeMilliseconds(androidReport.AppStartTime.Time);
            AppErrorTime = DateTimeOffset.FromUnixTimeMilliseconds(androidReport.AppErrorTime.Time);
            Device       = androidReport.Device == null ? null : new Device(androidReport.Device);

            object androidThrowable;

            try
            {
                androidThrowable = androidReport.Throwable;
            }
            catch (Exception e)
            {
                MobileCenterLog.Debug(Crashes.LogTag, "Cannot read throwable from java point of view, probably a .NET exception", e);
                androidThrowable = null;
                byte[] exceptionBytes = AndroidExceptionDataManager.LoadWrapperExceptionData(Java.Util.UUID.FromString(Id));
                if (exceptionBytes != null)
                {
                    Exception = CrashesUtils.DeserializeException(exceptionBytes);
                }
            }

            AndroidDetails = new AndroidErrorDetails(androidThrowable, androidReport.ThreadName);
            iOSDetails     = null;
        }
Ejemplo n.º 2
0
        public static void Log(string tag, string message, Exception exception = null, MobileCenterLogType type = MobileCenterLogType.Warn)
        {
            switch (type)
            {
            case MobileCenterLogType.Info:
                MobileCenterLog.Info(tag, message, exception);
                break;

            case MobileCenterLogType.Warn:
                MobileCenterLog.Warn(tag, message, exception);
                break;

            case MobileCenterLogType.Error:
                MobileCenterLog.Error(tag, message, exception);
                break;

            case MobileCenterLogType.Assert:
                MobileCenterLog.Assert(tag, message, exception);
                break;

            case MobileCenterLogType.Verbose:
                MobileCenterLog.Verbose(tag, message, exception);
                break;

            case MobileCenterLogType.Debug:
                MobileCenterLog.Debug(tag, message, exception);
                break;

            default:
                throw new Exception("MobileCenterLogType Does Not Exist");
            }
        }
        // Determines whether the application has started already and is not suspended,
        // but ApplicationLifecycleHelper has not yet fired an initial "resume" event.
        private static async Task <bool> HasStartedAndNeedsResume()
        {
            var needsResume = false;

            try
            {
                // Don't use CurrentSynchronizationContext as that seems to cause an error in Unity applications.
                var asyncAction = CoreApplication.MainView?.CoreWindow?.Dispatcher.RunAsync(
                    CoreDispatcherPriority.Normal, () =>
                {
                    // If started already, a resume has already occurred.
                    if (_started)
                    {
                        return;
                    }
                    if (CoreApplication.Views.Any(view => view.CoreWindow != null &&
                                                  view.CoreWindow.Visible))
                    {
                        needsResume = true;
                    }
                });
                if (asyncAction != null)
                {
                    await asyncAction;
                }
            }
            catch (Exception e) when(e is COMException || e is InvalidOperationException)
            {
                // If MainView can't be accessed, a COMException or InvalidOperationException is thrown. It means that the
                // MainView hasn't been created, and thus the UI hasn't appeared yet.
                MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                      "Not invoking resume immediately because UI is not ready.");
            }
            return(needsResume);
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Asynchronously deletes all logs in a particular batch
 /// </summary>
 /// <param name="channelName">The name of the channel associated with the batch</param>
 /// <param name="batchId">The batch identifier</param>
 /// <exception cref="StorageException"/>
 public async Task DeleteLogsAsync(string channelName, string batchId)
 {
     using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false))
     {
         MobileCenterLog.Debug(MobileCenterLog.LogTag,
                               $"Deleting logs from storage for channel '{channelName}' with batch id '{batchId}'");
         try
         {
             var identifiers = _pendingDbIdentifierGroups[GetFullIdentifier(channelName, batchId)];
             _pendingDbIdentifierGroups.Remove(GetFullIdentifier(channelName, batchId));
             var deletedIdsMessage = "The IDs for deleting log(s) is/ are:";
             foreach (var id in identifiers)
             {
                 deletedIdsMessage += "\n\t" + id;
                 _pendingDbIdentifiers.Remove(id);
             }
             MobileCenterLog.Debug(MobileCenterLog.LogTag, deletedIdsMessage);
             foreach (var id in identifiers)
             {
                 await _storageAdapter.DeleteAsync <LogEntry>(entry => entry.Channel == channelName && entry.Id == id).ConfigureAwait(false);
             }
         }
         catch (KeyNotFoundException e)
         {
             throw new StorageException(e);
         }
     }
 }
        public SessionTracker(IChannelGroup channelGroup, IChannelUnit channel, IApplicationSettings applicationSettings)
        {
            // Need to lock in constructor because of the event handler being set for channelGroup.
            lock (_lockObject)
            {
                _channel                   = channel;
                _applicationSettings       = applicationSettings;
                channelGroup.EnqueuingLog += HandleEnqueuingLog;
                var sessionsString = _applicationSettings.GetValue <string>(StorageKey, null);
                if (sessionsString == null)
                {
                    return;
                }
                _sessions = SessionsFromString(sessionsString);

                // Re-write sessions in storage in case of any invalid strings
                _applicationSettings.SetValue(StorageKey, SessionsAsString());
                if (_sessions.Count == 0)
                {
                    return;
                }
                var loadedSessionsString = _sessions.Values.Aggregate("Loaded stored sessions:\n", (current, session) => current + ("\t" + session + "\n"));
                MobileCenterLog.Debug(Analytics.Instance.LogTag, loadedSessionsString);
            }
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Asynchronously deletes all logs for a particular channel
 /// </summary>
 /// <param name="channelName">Name of the channel to delete logs for</param>
 /// <exception cref="StorageException"/>
 public async Task DeleteLogsAsync(string channelName)
 {
     using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false))
     {
         MobileCenterLog.Debug(MobileCenterLog.LogTag,
                               $"Deleting all logs from storage for channel '{channelName}'");
         var fullIdentifiers = new List <string>();
         try
         {
             foreach (var fullIdentifier in _pendingDbIdentifierGroups.Keys)
             {
                 if (!ChannelMatchesIdentifier(channelName, fullIdentifier))
                 {
                     continue;
                 }
                 foreach (var id in _pendingDbIdentifierGroups[fullIdentifier])
                 {
                     _pendingDbIdentifiers.Remove(id);
                 }
                 fullIdentifiers.Add(fullIdentifier);
             }
             foreach (var fullIdentifier in fullIdentifiers)
             {
                 _pendingDbIdentifierGroups.Remove(fullIdentifier);
             }
         }
         catch (KeyNotFoundException e)
         {
             throw new StorageException(e);
         }
         await _storageAdapter.DeleteAsync <LogEntry>(entry => entry.Channel == channelName)
         .ConfigureAwait(false);
     }
 }
        /// <summary>
        /// Asynchronously deletes all logs for a particular channel
        /// </summary>
        /// <param name="channelName">Name of the channel to delete logs for</param>
        /// <exception cref="StorageException"/>
        public Task DeleteLogs(string channelName)
        {
            var task = new Task(() =>
            {
                try
                {
                    MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                          $"Deleting all logs from storage for channel '{channelName}'");
                    ClearPendingLogStateWithoutEnqueue(channelName);
                    _storageAdapter.DeleteAsync <LogEntry>(entry => entry.Channel == channelName)
                    .Wait();
                }
                catch (KeyNotFoundException e)
                {
                    throw new StorageException(e);
                }
            });

            try
            {
                _queue.Add(task);
            }
            catch (InvalidOperationException)
            {
                throw new StorageException("The operation has been cancelled");
            }
            _flushSemaphore.Release();
            return(task);
        }
Ejemplo n.º 8
0
        bool ConfirmationHandler()
        {
            Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
            {
                Current.MainPage.DisplayActionSheet("Crash detected. Send anonymous crash report?", null, null, "Send", "Always Send", "Don't Send").ContinueWith((arg) =>
                {
                    var answer = arg.Result;
                    UserConfirmation userConfirmationSelection;
                    if (answer == "Send")
                    {
                        userConfirmationSelection = UserConfirmation.Send;
                    }
                    else if (answer == "Always Send")
                    {
                        userConfirmationSelection = UserConfirmation.AlwaysSend;
                    }
                    else
                    {
                        userConfirmationSelection = UserConfirmation.DontSend;
                    }
                    MobileCenterLog.Debug(LogTag, "User selected confirmation option: \"" + answer + "\"");
                    Crashes.NotifyUserConfirmation(userConfirmationSelection);
                });
            });

            return(true);
        }
        private void CheckPendingLogs(State state)
        {
            if (!_enabled)
            {
                MobileCenterLog.Info(MobileCenterLog.LogTag, "The service has been disabled. Stop processing logs.");
                return;
            }

            MobileCenterLog.Debug(MobileCenterLog.LogTag, $"CheckPendingLogs({Name}) pending log count: {_pendingLogCount}");
            using (_mutex.GetLock())
            {
                if (_pendingLogCount >= _maxLogsPerBatch)
                {
                    _batchScheduled = true;
                    Task.Run(async() =>
                    {
                        await TriggerIngestionAsync(state).ConfigureAwait(false);
                    });
                }
                else if (_pendingLogCount > 0 && !_batchScheduled)
                {
                    _batchScheduled = true;

                    // No need wait _batchTimeInterval here.
                    Task.Run(async() =>
                    {
                        await Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ConfigureAwait(false);
                        if (_batchScheduled)
                        {
                            await TriggerIngestionAsync(_mutex.State).ConfigureAwait(false);
                        }
                    });
                }
            }
        }
Ejemplo n.º 10
0
        private void CheckPendingLogs()
        {
            if (!_enabled)
            {
                MobileCenterLog.Info(MobileCenterLog.LogTag, "The service has been disabled. Stop processing logs.");
                return;
            }

            MobileCenterLog.Debug(MobileCenterLog.LogTag, $"CheckPendingLogs({Name}) pending log count: {_pendingLogCount}");
            if (_pendingLogCount >= _maxLogsPerBatch)
            {
                Task.Run(TriggerIngestionAsync);
            }
            else if (_pendingLogCount > 0 && !_batchScheduled)
            {
                _batchScheduled = true;
                Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ContinueWith(async completedTask =>
                {
                    if (_batchScheduled)
                    {
                        await TriggerIngestionAsync().ConfigureAwait(false);
                    }
                });
            }
        }
Ejemplo n.º 11
0
 private void OnPushNotificationReceivedHandler(PushNotificationChannel sender, WindowsPushNotificationReceivedEventArgs e)
 {
     if (e.NotificationType == PushNotificationType.Toast)
     {
         var content = e.ToastNotification.Content;
         MobileCenterLog.Debug(LogTag, $"Received push notification payload: {content.GetXml()}");
         if (ApplicationLifecycleHelper.Instance.IsSuspended)
         {
             MobileCenterLog.Debug(LogTag, "Application in background. Push callback will be called when user clicks the toast notification.");
         }
         else
         {
             var pushNotification = ParseMobileCenterPush(content);
             if (pushNotification != null)
             {
                 e.Cancel = true;
                 PushNotificationReceived?.Invoke(sender, pushNotification);
                 MobileCenterLog.Debug(LogTag, "Application in foreground. Intercept push notification and invoke push callback.");
             }
             else
             {
                 MobileCenterLog.Debug(LogTag, "Push ignored. It was not sent through Mobile Center.");
             }
         }
     }
     else
     {
         MobileCenterLog.Debug(LogTag, $"Push ignored. We only handle Toast notifications but PushNotificationType is '{e.NotificationType}'.");
     }
 }
 /// <exception cref="MobileCenterException">Attempted to add duplicate channel to group</exception>
 public IChannelUnit AddChannel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, int maxParallelBatches)
 {
     ThrowIfDisposed();
     lock (_channelGroupLock)
     {
         MobileCenterLog.Debug(MobileCenterLog.LogTag, $"AddChannel({name})");
         var newChannel = new Channel(name, maxLogsPerBatch, batchTimeInterval, maxParallelBatches, AppSecret,
                                      _ingestion, _storage);
         AddChannel(newChannel);
         return(newChannel);
     }
 }
Ejemplo n.º 13
0
        protected override void OnCreate()
        {
            base.OnCreate();

            AppResourcePath          = DirectoryInfo.Resource;
            DebuggingPort.MainWindow = MainWindow;
            app = new Calculator(IsLandscape());
            LoadApplication(app);

            try
            {
                MobileCenter.LogLevel = LogLevel.Verbose;
                MobileCenter.Configure("efc52dfb-3133-4f7e-b73f-b798474204b2");
                MobileCenter.Start(typeof(Analytics));
            }
            catch (System.Exception exc)
            {
                MobileCenterLog.Debug(MobileCenterLog.LogTag, $"{exc}");
            }

            // Registration for device orientation changing detection.
            MainWindow.RotationChanged += (s, e) =>
            {
                if (IsLandscape())
                {
                    try
                    {
                        Analytics.TrackEvent("Mode Changed", new Dictionary <string, string> {
                            { "mode", "Scientific" }
                        });
                    }
                    catch (System.Exception exc)
                    {
                        MobileCenterLog.Debug(MobileCenterLog.LogTag, $"{exc}");
                    }
                    app.OnOrientationChanged(AppOrientation.Landscape);
                }
                else
                {
                    try
                    {
                        Analytics.TrackEvent("Mode Changed", new Dictionary <string, string> {
                            { "mode", "Regular" }
                        });
                    }
                    catch (System.Exception exc)
                    {
                        MobileCenterLog.Debug(MobileCenterLog.LogTag, $"{exc}");
                    }
                    app.OnOrientationChanged(AppOrientation.Portrait);
                }
            };
        }
Ejemplo n.º 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
                MobileCenterLog.Debug(LogTag, "Getting push token...");
                var state = _mutex.State;
                Task.Run(async() =>
                {
                    var channel = await new WindowsPushNotificationChannelManager().CreatePushNotificationChannelForApplicationAsync()
                                  .AsTask().ConfigureAwait(false);
                    try
                    {
                        using (await _mutex.GetLockAsync(state).ConfigureAwait(false))
                        {
                            var pushToken = channel.Uri;
                            if (!string.IsNullOrEmpty(pushToken))
                            {
                                // Save channel member
                                _channel = channel;

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

                                // Send channel URI to backend
                                MobileCenterLog.Debug(LogTag, $"Push token '{pushToken}'");

                                var pushInstallationLog = new PushInstallationLog(null, null, pushToken, Guid.NewGuid());

                                // 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
                            {
                                MobileCenterLog.Error(LogTag, "Push service registering with Mobile Center backend has failed.");
                            }
                        }
                    }
                    catch (StatefulMutexException)
                    {
                        MobileCenterLog.Warn(LogTag, "Push Enabled state changed after creating channel.");
                    }
                });
            }
            else if (_channel != null)
            {
                _channel.PushNotificationReceived -= OnPushNotificationReceivedHandler;
            }
        }
Ejemplo n.º 15
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 async Task <string> GetLogsAsync(string channelName, int limit, List <Log> logs)
        {
            using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false))
            {
                logs?.Clear();
                var retrievedLogs = new List <Log>();
                MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Trying to get up to {limit} logs from storage for {channelName}");

                var idPairs = new List <Tuple <Guid?, long> >();
                var failedToDeserializeALog = false;
                var retrievedEntries        =
                    await _storageAdapter.GetAsync <LogEntry>(entry => entry.Channel == channelName, limit)
                    .ConfigureAwait(false);

                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)
                    {
                        MobileCenterLog.Error(MobileCenterLog.LogTag, "Cannot deserialize a log in storage", e);
                        failedToDeserializeALog = true;
                        await _storageAdapter.DeleteAsync <LogEntry>(row => row.Id == entry.Id).ConfigureAwait(false);
                    }
                }
                if (failedToDeserializeALog)
                {
                    MobileCenterLog.Warn(MobileCenterLog.LogTag, "Deleted logs that could not be deserialized");
                }
                if (idPairs.Count == 0)
                {
                    MobileCenterLog.Debug(MobileCenterLog.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);
            }
        }
Ejemplo n.º 16
0
 public void Pause()
 {
     lock (_lockObject)
     {
         if (_currentSessionState == SessionState.Inactive)
         {
             MobileCenterLog.Warn(Analytics.Instance.LogTag, "Trying to pause already inactive session.");
             return;
         }
         MobileCenterLog.Debug(Analytics.Instance.LogTag, "SessionTracker.Pause");
         _lastPausedTime      = TimeHelper.CurrentTimeInMilliseconds();
         _currentSessionState = SessionState.Inactive;
     }
 }
        private void ProcessLogIds(string channelName, string batchId, IEnumerable <Tuple <Guid?, long> > idPairs)
        {
            var ids     = new List <long>();
            var message = "The SID/ID pairs for returning logs are:";

            foreach (var idPair in idPairs)
            {
                var sidString = idPair.Item1?.ToString() ?? "(null)";
                message += "\n\t" + sidString + " / " + idPair.Item2;
                _pendingDbIdentifiers.Add(idPair.Item2);
                ids.Add(idPair.Item2);
            }
            _pendingDbIdentifierGroups.Add(GetFullIdentifier(channelName, batchId), ids);
            MobileCenterLog.Debug(MobileCenterLog.LogTag, message);
        }
Ejemplo n.º 18
0
 public void Resume()
 {
     lock (_lockObject)
     {
         if (_currentSessionState == SessionState.Active)
         {
             MobileCenterLog.Warn(Analytics.Instance.LogTag, "Trying to resume already active session.");
             return;
         }
         MobileCenterLog.Debug(Analytics.Instance.LogTag, "SessionTracker.Resume");
         _lastResumedTime     = TimeHelper.CurrentTimeInMilliseconds();
         _currentSessionState = SessionState.Active;
         SendStartSessionIfNeeded();
     }
 }
Ejemplo n.º 19
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
                var stateSnapshot = _stateKeeper.GetStateSnapshot();
                Task.Run(async() =>
                {
                    var channel = await new WindowsPushNotificationChannelManager().CreatePushNotificationChannelForApplicationAsync()
                                  .AsTask().ConfigureAwait(false);
                    try
                    {
                        _mutex.Lock(stateSnapshot);
                        var pushToken = channel.Uri;
                        if (!string.IsNullOrEmpty(pushToken))
                        {
                            // Save channel member
                            _channel = channel;

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

                            // Send channel URI to backend
                            MobileCenterLog.Debug(LogTag, $"Push token '{pushToken}'");
                            var pushInstallationLog = new PushInstallationLog(0, null, pushToken, Guid.NewGuid());
                            await Channel.Enqueue(pushInstallationLog).ConfigureAwait(false);
                        }
                        else
                        {
                            MobileCenterLog.Error(LogTag, "Push service registering with Mobile Center backend has failed.");
                        }
                    }
                    catch (StatefulMutexException)
                    {
                        MobileCenterLog.Warn(LogTag, "Push Enabled state changed after creating channel.");
                    }
                    finally
                    {
                        _mutex.Unlock();
                    }
                });
            }
            else if (_channel != null)
            {
                _channel.PushNotificationReceived -= OnPushNotificationReceivedHandler;
            }
        }
Ejemplo n.º 20
0
        private async Task TriggerIngestionAsync()
        {
            await _mutex.LockAsync().ConfigureAwait(false);

            var stateSnapshot = _stateKeeper.GetStateSnapshot();

            try
            {
                if (!_enabled)
                {
                    return;
                }
                MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                      $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}");
                _batchScheduled = false;
                if (_sendingBatches.Count >= _maxParallelBatches)
                {
                    MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                          "Already sending " + _maxParallelBatches + " batches of analytics data to the server");
                    return;
                }

                // Get a batch from storage
                var logs = new List <Log>();
                _mutex.Unlock();
                var batchId = await _storage.GetLogsAsync(Name, _maxLogsPerBatch, logs).ConfigureAwait(false);

                await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false);

                if (batchId != null)
                {
                    _sendingBatches.Add(batchId, logs);
                    _pendingLogCount -= logs.Count;
                    TriggerIngestion(logs, stateSnapshot, batchId);
                }
            }
            catch (StatefulMutexException e)
            {
                MobileCenterLog.Warn(MobileCenterLog.LogTag, "The TriggerIngestion operation has been cancelled", e);
            }
            finally
            {
                _mutex.Unlock();
            }
        }
        public Task Shutdown()
        {
            ThrowIfDisposed();
            var tasks = new List <Task>();

            lock (_channelGroupLock)
            {
                foreach (var channel in _channels)
                {
                    tasks.Add(channel.Shutdown());
                }
                MobileCenterLog.Debug(MobileCenterLog.LogTag, "Waiting for storage to finish operations");
                if (!_storage.Shutdown(_shutdownTimeout))
                {
                    MobileCenterLog.Warn(MobileCenterLog.LogTag, "Storage taking too long to finish operations; shutting down channel without waiting any longer.");
                }
            }
            return(Task.WhenAll(tasks));
        }
        /// <summary>
        /// Asynchronously clears the stored state of logs that have been retrieved
        /// </summary>
        /// <param name="channelName"></param>
        public Task ClearPendingLogState(string channelName)
        {
            var task = new Task(() =>
            {
                ClearPendingLogStateWithoutEnqueue(channelName);
                MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Clear pending log states for channel {channelName}");
            });

            try
            {
                _queue.Add(task);
            }
            catch (InvalidOperationException)
            {
                throw new StorageException("The operation has been cancelled");
            }
            _flushSemaphore.Release();
            return(task);
        }
Ejemplo n.º 23
0
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
            global::Xamarin.Forms.Forms.Init();

            // Code for starting up the Xamarin Test Cloud Agent
#if ENABLE_TEST_CLOUD
            Xamarin.Calabash.Start();
#endif


            Appearance.Configure();

            MobileCenter.Start("b7cd7b07-85af-45eb-87e0-74f05d88acd4");
            LoadApplication(new App());
            MobileCenterLog.Debug("AppDelegate", "DidFinishLaunchingWithOptions");

            return(base.FinishedLaunching(app, options));
        }
Ejemplo n.º 24
0
        // Internal and static so that it can be tested more easily
        internal static bool HasSessionTimedOut(long now, long lastQueuedLogTime, long lastResumedTime, long lastPausedTime)
        {
            var noLogSentForLong = lastQueuedLogTime == 0 || (now - lastQueuedLogTime) >= SessionTimeout;

            if (lastPausedTime == 0)
            {
                return(lastResumedTime == 0 && noLogSentForLong);
            }
            if (lastResumedTime == 0)
            {
                return(noLogSentForLong);
            }
            var isBackgroundForLong  = (lastPausedTime >= lastResumedTime) && ((now - lastPausedTime) >= SessionTimeout);
            var wasBackgroundForLong = (lastResumedTime - Math.Max(lastPausedTime, lastQueuedLogTime)) >= SessionTimeout;

            MobileCenterLog.Debug(Analytics.Instance.LogTag, $"noLogSentForLong={noLogSentForLong} " +
                                  $"isBackgroundForLong={isBackgroundForLong} " +
                                  $"wasBackgroundForLong={wasBackgroundForLong}");
            return(noLogSentForLong && (isBackgroundForLong || wasBackgroundForLong));
        }
        private async Task TriggerIngestionAsync(State state)
        {
            using (await _mutex.GetLockAsync(state).ConfigureAwait(false))
            {
                if (!_enabled || !_batchScheduled)
                {
                    return;
                }
                MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                      $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}");
                _batchScheduled = false;
                if (_sendingBatches.Count >= _maxParallelBatches)
                {
                    MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                          "Already sending " + _maxParallelBatches + " batches of analytics data to the server");
                    return;
                }
            }

            // Get a batch from storage
            var logs    = new List <Log>();
            var batchId = await _storage.GetLogsAsync(Name, _maxLogsPerBatch, logs).ConfigureAwait(false);

            if (batchId != null)
            {
                using (await _mutex.GetLockAsync(state).ConfigureAwait(false))
                {
                    _sendingBatches.Add(batchId, logs);
                    _pendingLogCount -= logs.Count;
                }
                try
                {
                    TriggerIngestion(state, logs, batchId);
                    CheckPendingLogs(state);
                }
                catch (StorageException)
                {
                    MobileCenterLog.Warn(MobileCenterLog.LogTag, "Something went wrong sending logs to ingestion");
                }
            }
        }
        /// <summary>
        /// Asynchronously deletes all logs in a particular batch
        /// </summary>
        /// <param name="channelName">The name of the channel associated with the batch</param>
        /// <param name="batchId">The batch identifier</param>
        /// <exception cref="StorageException"/>
        public Task DeleteLogs(string channelName, string batchId)
        {
            var task = new Task(() =>
            {
                try
                {
                    MobileCenterLog.Debug(MobileCenterLog.LogTag,
                                          $"Deleting logs from storage for channel '{channelName}' with batch id '{batchId}'");
                    var identifiers = _pendingDbIdentifierGroups[GetFullIdentifier(channelName, batchId)];
                    _pendingDbIdentifierGroups.Remove(GetFullIdentifier(channelName, batchId));
                    var deletedIdsMessage = "The IDs for deleting log(s) is/ are:";
                    foreach (var id in identifiers)
                    {
                        deletedIdsMessage += "\n\t" + id;
                        _pendingDbIdentifiers.Remove(id);
                    }
                    MobileCenterLog.Debug(MobileCenterLog.LogTag, deletedIdsMessage);
                    foreach (var id in identifiers)
                    {
                        _storageAdapter
                        .DeleteAsync <LogEntry>(entry => entry.Channel == channelName && entry.Id == id)
                        .Wait();
                    }
                }
                catch (KeyNotFoundException e)
                {
                    throw new StorageException(e);
                }
            });

            try
            {
                _queue.Add(task);
            }
            catch (InvalidOperationException)
            {
                throw new StorageException("The operation has been cancelled");
            }
            _flushSemaphore.Release();
            return(task);
        }
Ejemplo n.º 27
0
        public SessionTracker(IChannelGroup channelGroup, IChannelUnit channel)
        {
            _channel = channel;
            channelGroup.EnqueuingLog += HandleEnqueuingLog;
            var sessionsString = _applicationSettings.GetValue <string>(StorageKey, null);

            if (sessionsString == null)
            {
                return;
            }
            _sessions = SessionsFromString(sessionsString);
            // Re-write sessions in storage in case of any invalid strings
            _applicationSettings[StorageKey] = SessionsAsString();
            if (_sessions.Count == 0)
            {
                return;
            }
            var loadedSessionsString = _sessions.Values.Aggregate("Loaded stored sessions:\n", (current, session) => current + ("\t" + session + "\n"));

            MobileCenterLog.Debug(Analytics.Instance.LogTag, loadedSessionsString);
        }
Ejemplo n.º 28
0
        private void PushNotificationReceivedHandler(object sender, PushNotificationReceivedEventArgs args)
        {
            string title      = args.Title;
            string message    = args.Message;
            var    customData = args.CustomData;

            string customDataString = string.Empty;

            foreach (var pair in customData)
            {
                customDataString += $"key='{pair.Key}', value='{pair.Value}'";
            }

            if (!string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(message))
            {
                MobileCenterLog.Debug(MobileCenterLog.LogTag, $"PushNotificationReceivedHandler received title:'{title}', message:'{message}', customData:{customDataString}");
            }
            else
            {
                MobileCenterLog.Debug(MobileCenterLog.LogTag, $"PushNotificationReceivedHandler received customData:{customDataString}");
            }
        }
Ejemplo n.º 29
0
        public static void Log(Exception exception, MobileCenterLogType type = MobileCenterLogType.Warn)
        {
            var exceptionType = exception.GetType().ToString();
            var message       = exception.Message;

            System.Diagnostics.Debug.WriteLine(exceptionType);
            System.Diagnostics.Debug.WriteLine($"Error: {message}");

            switch (type)
            {
            case MobileCenterLogType.Info:
                MobileCenterLog.Info(exceptionType, message, exception);
                break;

            case MobileCenterLogType.Warn:
                MobileCenterLog.Warn(exceptionType, message, exception);
                break;

            case MobileCenterLogType.Error:
                MobileCenterLog.Error(exceptionType, message, exception);
                break;

            case MobileCenterLogType.Assert:
                MobileCenterLog.Assert(exceptionType, message, exception);
                break;

            case MobileCenterLogType.Verbose:
                MobileCenterLog.Verbose(exceptionType, message, exception);
                break;

            case MobileCenterLogType.Debug:
                MobileCenterLog.Debug(exceptionType, message, exception);
                break;

            default:
                throw new Exception("MobileCenterLogType Does Not Exist");
            }
        }
 //NOTE: This method MUST be called from the UI thread
 public static void RefreshDisplayCache()
 {
     lock (LockObject)
     {
         DisplayInformation displayInfo = null;
         try
         {
             // This can throw exceptions that aren't well documented, so catch-all and ignore
             displayInfo = DisplayInformation.GetForCurrentView();
         }
         catch (Exception e)
         {
             MobileCenterLog.Warn(MobileCenterLog.LogTag, "Could not get display information.", e);
             return;
         }
         if (_cachedScreenSize == ScreenSizeFromDisplayInfo(displayInfo))
         {
             return;
         }
         _cachedScreenSize = ScreenSizeFromDisplayInfo(displayInfo);
         MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Cached screen size updated to {_cachedScreenSize}");
         InformationInvalidated?.Invoke(null, EventArgs.Empty);
     }
 }