/// <summary> /// Indexes the by token. /// </summary> /// <param name="queue">The queue.</param> private void IndexByToken(PayloadQueue?queue) { string?queueToken = queue?.Logger.Config.RollbarDestinationOptions.AccessToken; if (queueToken == null) { //this is a valid case for the RollbarLogger singleton instance, //when the instance is created but not configured yet... return; } if (!this._queuesByAccessToken.TryGetValue(queueToken, out AccessTokenQueuesMetadata? tokenMetadata)) { tokenMetadata = new AccessTokenQueuesMetadata(queueToken); this._queuesByAccessToken.Add(queueToken, tokenMetadata); } tokenMetadata.Register(queue); }
/// <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.GetPayloadQueues().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.GetPayloadQueues()) { 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.GetPayloadQueues()) { 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; } } }