public void Register(IHub hub, SentryOptions options) { try { if (!Runtime.Current.IsMono()) { options.AddEventProcessor(new NetFxInstallationsEventProcessor(options)); } } catch (Exception ex) { options.LogError("Failed to register NetFxInstallations.", ex); } }
private async Task WorkerAsync() { var cancellation = _shutdownSource.Token; using var shutdownTimeout = new CancellationTokenSource(); var shutdownRequested = false; try { while (!shutdownTimeout.IsCancellationRequested) { // If the cancellation was signaled, // set the latest we can keep reading off of the queue (while there's still stuff to read) // No longer synchronized with queuedEnvelopeSemaphore (Enqueue will throw object disposed), // run until the end of the queue or shutdownTimeout if (!shutdownRequested) { try { await _queuedEnvelopeSemaphore.WaitAsync(cancellation).ConfigureAwait(false); } // Cancellation requested, scheduled shutdown but continue in case there are more items catch (OperationCanceledException) { if (_options.ShutdownTimeout == TimeSpan.Zero) { _options.LogDebug( "Exiting immediately due to 0 shutdown timeout. #{0} in queue.", _queue.Count); return; } else { _options.LogDebug( "Shutdown scheduled. Stopping by: {0}. #{1} in queue.", _options.ShutdownTimeout, _queue.Count); shutdownTimeout.CancelAfter(_options.ShutdownTimeout); } shutdownRequested = true; } } if (_queue.TryPeek(out var envelope)) // Work with the envelope while it's in the queue { try { // Dispose inside try/catch using var _ = envelope; var task = _transport.SendEnvelopeAsync(envelope, shutdownTimeout.Token); _options.LogDebug( "Envelope {0} handed off to transport. #{1} in queue.", envelope.TryGetEventId(), _queue.Count); await task.ConfigureAwait(false); } catch (OperationCanceledException) { _options.LogInfo( "Shutdown token triggered. Time to exit. #{0} in queue.", _queue.Count); return; } catch (Exception exception) { _options.LogError( "Error while processing envelope (event ID: '{0}'). #{1} in queue.", exception, envelope.TryGetEventId(), _queue.Count); } finally { _ = _queue.TryDequeue(out _); _ = Interlocked.Decrement(ref _currentItems); OnFlushObjectReceived?.Invoke(envelope, EventArgs.Empty); } } else { Debug.Assert(shutdownRequested); _options.LogInfo("Exiting the worker with an empty queue."); // Empty queue. Exit. return; } } } catch (Exception e) { _options.LogFatal("Exception in the background worker.", e); throw; } finally { _queuedEnvelopeSemaphore.Dispose(); } }