/// <summary> /// Initializes a new instance of the <see cref="CommunicationEventArgs"/> class. /// </summary> /// <param name="config">The configuration.</param> /// <param name="payload">The payload.</param> /// <param name="response">The response.</param> public CommunicationEventArgs(RollbarConfig config, Payload payload, RollbarResponse response) : base(config, payload) { this.Response = response; }
/// <summary> /// Processes the queues. /// </summary> /// <param name="tokenMetadata">The token metadata.</param> private void ProcessQueues(AccessTokenQueuesMetadata tokenMetadata) { // let's see if we can unregister any recently released queues: var releasedQueuesToRemove = tokenMetadata.PayloadQueues.Where(q => q.IsReleased && (q.GetPayloadCount() == 0)).ToArray(); if (releasedQueuesToRemove != null && releasedQueuesToRemove.LongLength > 0) { foreach (var queue in releasedQueuesToRemove) { this.Unregister(queue); } } // process the access token's queues: foreach (var queue in tokenMetadata.PayloadQueues) { if (DateTimeOffset.Now < queue.NextDequeueTime) { // this means the queue overrides its reporting rate limit via its configuration settings // let's observe its settings and skip processing: continue; } if (tokenMetadata.IsTransmissionSuspended && DateTimeOffset.Now < tokenMetadata.NextTimeTokenUsage) { // the token is suspended and the next usage time is not reached, // let's flush the token queues (we are not allowed to transmit anyway) // and quit processing this token's queues this time (until next processing iteration): foreach (var tokenQueue in tokenMetadata.PayloadQueues) { foreach (var flushedBundle in tokenQueue.Flush()) { this.OnRollbarEvent( new PayloadDropEventArgs( queue.Logger, flushedBundle.GetPayload(), PayloadDropEventArgs.DropReason.TokenSuspension ) ); } } return; } PayloadBundle payloadBundle = null; RollbarResponse response = null; try { payloadBundle = Process(queue, out response); } catch (AggregateException aggregateException) { if (aggregateException.InnerExceptions.Any(e => e is HttpRequestException)) { this.Persist(queue); continue; } else { var bundle = queue.Dequeue(); this.OnRollbarEvent( new PayloadDropEventArgs(queue.Logger, bundle.GetPayload(), PayloadDropEventArgs.DropReason.InvalidPayload) ); queue.Dequeue(); throw; } } catch (System.Exception ex) { Debug.WriteLine($"EXCEPTION: {ex}"); this.Persist(queue); continue; } if (payloadBundle != null && response == null) { var bundle = queue.Dequeue(); this.OnRollbarEvent( new PayloadDropEventArgs(queue.Logger, bundle.GetPayload(), PayloadDropEventArgs.DropReason.AllTransmissionRetriesFailed) ); } if (payloadBundle == null || response == null) { continue; } tokenMetadata.UpdateNextTimeTokenUsage(response.RollbarRateLimit); switch (response.Error) { case (int)RollbarApiErrorEventArgs.RollbarError.None: payloadBundle.Signal?.Release(); queue.Dequeue(); break; case (int)RollbarApiErrorEventArgs.RollbarError.TooManyRequests: ObeyPayloadTimeout(payloadBundle, queue); this.OnRollbarEvent( new RollbarApiErrorEventArgs(queue.Logger, payloadBundle.GetPayload(), response) ); return; default: ObeyPayloadTimeout(payloadBundle, queue); this.OnRollbarEvent( new RollbarApiErrorEventArgs(queue.Logger, payloadBundle.GetPayload(), response) ); break; } } }
/// <summary> /// Initializes a new instance of the <see cref="CommunicationEventArgs"/> class. /// </summary> /// <param name="logger">The logger.</param> /// <param name="payload">The payload.</param> /// <param name="response">The response.</param> internal CommunicationEventArgs(RollbarLogger logger, Payload payload, RollbarResponse response) : base(logger, payload) { this.Response = response; }
private PayloadBundle Process(PayloadQueue queue, out RollbarResponse response) { response = null; PayloadBundle payloadBundle = queue.Peek(); while (payloadBundle != null && (payloadBundle.Ignorable || payloadBundle.GetPayload() == null)) { queue.Dequeue(); //throw away the useless one... payloadBundle = queue.Peek(); //try next... } if (payloadBundle == null) { return(null); //no bundles to process... } Payload payload = payloadBundle.GetPayload(); if (payload == null) { return(null); } int retries = this._totalRetries; while (retries > 0) { try { response = queue.Client.PostAsJson(payloadBundle); } catch (WebException ex) { retries--; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); continue; } catch (ArgumentNullException ex) { retries = 0; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); continue; } catch (System.Exception ex) { retries = 0; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); continue; } retries = 0; } if (response != null) { this.OnRollbarEvent( new CommunicationEventArgs(queue.Logger, payload, response) ); } return(payloadBundle); }
/// <summary> /// Processes the specified queue. /// </summary> /// <param name="queue">The queue.</param> /// <param name="response">The response.</param> /// <returns>PayloadBundle.</returns> private PayloadBundle Process(PayloadQueue queue, out RollbarResponse response) { response = null; PayloadBundle payloadBundle; Payload payload = null; bool ignorableBundle = false; do { payloadBundle = queue.Peek(); if (payloadBundle == null) { return(null); // the queue is already empty, nothing to process... } try { ignorableBundle = (payloadBundle.Ignorable || payloadBundle.GetPayload() == null); } catch (System.Exception ex) { RollbarErrorUtility.Report( null, payloadBundle, InternalRollbarError.DequeuingError, "While attempting to dequeue a payload bundle...", ex, payloadBundle ); ignorableBundle = true; // since something is not kosher about this bundle/payload, it is wise to ignore one... } if (ignorableBundle) { queue.Dequeue(); //throw away the ignorable... this.OnRollbarEvent( new PayloadDropEventArgs(queue.Logger, null, PayloadDropEventArgs.DropReason.IgnorablePayload) ); } else { payload = payloadBundle.GetPayload(); } }while (ignorableBundle); if (payloadBundle == null || payload == null) // one more sanity check before proceeding further... { return(null); } if (queue.Logger?.Config != null && !queue.Logger.Config.Transmit) { response = new RollbarResponse(); this.OnRollbarEvent( new TransmissionOmittedEventArgs(queue.Logger, payload) ); return(payloadBundle); } int retries = this._totalRetries; while (retries > 0) { try { response = queue.Client.PostAsJson(payloadBundle); } catch (WebException ex) { retries--; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); payloadBundle.Register(ex); Thread.Sleep(this._sleepInterval); // wait a bit before we retry it... continue; } catch (ArgumentNullException ex) { retries = 0; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); payloadBundle.Register(ex); continue; } catch (System.Exception ex) { retries = 0; this.OnRollbarEvent( new CommunicationErrorEventArgs(queue.Logger, payload, ex, retries) ); payloadBundle.Register(ex); continue; } retries = 0; } if (response != null) { this.OnRollbarEvent( new CommunicationEventArgs(queue.Logger, payload, response) ); } else { queue.Dequeue(); //we tried our best... payloadBundle.Register(new RollbarException(InternalRollbarError.DequeuingError, "Payload dropped!")); } return(payloadBundle); }