/// <summary> /// Enqueue a log asynchronously. /// </summary> /// <param name="log">log to enqueue.</param> /// <returns>The async Task for this operation.</returns> public async Task EnqueueAsync(Log log) { try { State state; bool discardLogs; using (await _mutex.GetLockAsync().ConfigureAwait(false)) { state = _mutex.State; discardLogs = _discardLogs; } if (discardLogs) { AppCenterLog.Warn(AppCenterLog.LogTag, "Channel is disabled; logs are discarded"); AppCenterLog.Debug(AppCenterLog.LogTag, $"Invoke SendingLog event for channel '{Name}'"); SendingLog?.Invoke(this, new SendingLogEventArgs(log)); AppCenterLog.Debug(AppCenterLog.LogTag, $"Invoke FailedToSendLog event for channel '{Name}'"); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); return; } AppCenterLog.Debug(AppCenterLog.LogTag, $"Invoke EnqueuingLog event for channel '{Name}'"); EnqueuingLog?.Invoke(this, new EnqueuingLogEventArgs(log)); await PrepareLogAsync(log, state).ConfigureAwait(false); AppCenterLog.Debug(AppCenterLog.LogTag, $"Invoke FilteringLog event for channel '{Name}'"); var filteringLogEventArgs = new FilteringLogEventArgs(log); FilteringLog?.Invoke(this, filteringLogEventArgs); if (filteringLogEventArgs.FilterRequested) { AppCenterLog.Warn(AppCenterLog.LogTag, $"Filtering out a log of type '{log.GetType()}' at the request of an event handler."); } else { await PersistLogAsync(log, state).ConfigureAwait(false); } } catch (StatefulMutexException) { AppCenterLog.Warn(AppCenterLog.LogTag, "The Enqueue operation has been canceled"); } }
private async Task SignalDeletingLogs(State stateSnapshot) { var logs = new List <Log>(); _mutex.Unlock(); await _storage.GetLogsAsync(Name, ClearBatchSize, logs).ConfigureAwait(false); await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); foreach (var log in logs) { _mutex.Unlock(); SendingLog?.Invoke(this, new SendingLogEventArgs(log)); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); } if (logs.Count >= ClearBatchSize) { await SignalDeletingLogs(stateSnapshot).ConfigureAwait(false); } }
private Task SignalDeletingLogs() { var logs = new List <Log>(); return(_storage.GetLogsAsync(Name, ClearBatchSize, logs) .ContinueWith(completedTask => { if (completedTask.IsFaulted) { AppCenterLog.Warn(AppCenterLog.LogTag, "Failed to invoke events for logs being deleted."); return; } foreach (var log in logs) { SendingLog?.Invoke(this, new SendingLogEventArgs(log)); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); } if (logs.Count >= ClearBatchSize) { SignalDeletingLogs(); } })); }
private void AnyChannelSendingLog(object sender, SendingLogEventArgs e) { SendingLog?.Invoke(sender, e); }
private void TriggerIngestion(IList <Log> logs, State stateSnapshot, string batchId) { // Before sending logs, trigger the sending event for this channel if (SendingLog != null) { foreach (var eventArgs in logs.Select(log => new SendingLogEventArgs(log))) { _mutex.Unlock(); SendingLog?.Invoke(this, eventArgs); _mutex.Lock(stateSnapshot); } } // If the optional Install ID has no value, default to using empty GUID var installId = MobileCenter.InstallId.HasValue ? MobileCenter.InstallId.Value : Guid.Empty; var serviceCall = _ingestion.PrepareServiceCall(_appSecret, installId, logs); serviceCall.ServiceCallFailedCallback = exception => { serviceCall.Dispose(); HandleSendingFailure(batchId, exception); }; serviceCall.ServiceCallSucceededCallback = async() => { serviceCall.Dispose(); if (!_stateKeeper.IsCurrent(stateSnapshot)) { return; } try { await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); } catch (StorageException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); } try { await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); var removedLogs = _sendingBatches[batchId]; _sendingBatches.Remove(batchId); if (SentLog != null) { foreach (var log in removedLogs) { _mutex.Unlock(); SentLog?.Invoke(this, new SentLogEventArgs(log)); _mutex.Lock(stateSnapshot); } } CheckPendingLogs(); } catch (StatefulMutexException) { } finally { _mutex.Unlock(); } }; serviceCall.Execute(); }