Exemplo n.º 1
0
        /// <summary>
        /// Gets the recommended timeout.
        /// </summary>
        /// <param name="accessToken">The Rollbar access token.</param>
        /// <returns>TimeSpan.</returns>
        public TimeSpan GetRecommendedTimeout(string accessToken)
        {
            TimeSpan payloadTimeout = TimeSpan.Zero;
            int      totalPayloads  = 0;
            AccessTokenQueuesMetadata tokenMetadata = null;

            lock (this._syncLock)
            {
                if (this._queuesByAccessToken.TryGetValue(accessToken, out tokenMetadata))
                {
                    foreach (var queue in tokenMetadata.Queues)
                    {
                        totalPayloads += queue.GetPayloadCount();
                        TimeSpan queueTimeout =
                            queue.Logger.Config.MaxReportsPerMinute.HasValue ?
                            TimeSpan.FromTicks(TimeSpan.FromMinutes(1).Ticks / queue.Logger.Config.MaxReportsPerMinute.Value)
                            : TimeSpan.Zero;
                        if (payloadTimeout < queueTimeout)
                        {
                            payloadTimeout = queueTimeout;
                        }
                    }
                }
            }
            return(TimeSpan.FromTicks((totalPayloads + 1) * payloadTimeout.Ticks));
        }
        /// <summary>
        /// Processes the persistent store once.
        /// </summary>
        /// <param name="destination">The destination.</param>
        private void ProcessPersistentStoreOnce(IDestination destination)
        {
            AccessTokenQueuesMetadata accessTokenMetadata = null;

            lock (this._syncLock)
            {
                if (!this._queuesByAccessToken.TryGetValue(destination.AccessToken, out accessTokenMetadata))
                {
                    accessTokenMetadata = new AccessTokenQueuesMetadata(destination.AccessToken);
                    this._queuesByAccessToken.Add(destination.AccessToken, accessTokenMetadata);
                }
            }

            if (accessTokenMetadata.IsTransmissionSuspended && DateTimeOffset.Now < accessTokenMetadata.NextTimeTokenUsage)
            {
                // the token is suspended and the next usage time is not reached,
                // there is no point in continuing persistent store processing for this access token:
                return;
            }

            // 1. delete all the stale records of this destination and save the store context
            //    (if any records were deleted):
            DateTime staleRecordsLimit = DateTime.UtcNow.Subtract(staleRecordAge);
            var      staleRecords      = this._storeRepository.GetStaleRecords(staleRecordsLimit);

            if (staleRecords != null && staleRecords.Length > 0)
            {
                this._storeRepository.DeleteRecords(staleRecords);
            }

            // 2. get the oldest record of this destination and try transmitting it:
            if (!ConnectivityMonitor.Instance.IsConnectivityOn)
            {
                return; // there is no point trying to transmit the oldest record (if any)...
            }
            var oldestRecord = this._storeRepository.GetOldestRecords(destination.ID);

            if (oldestRecord != null)
            {
                var rollbarResponse = TryPosting(oldestRecord);
                if (rollbarResponse == null)
                {
                    return; //could not reach Rollbar API...
                }

                this.OnRollbarEvent(
                    new CommunicationEventArgs(null, oldestRecord.PayloadJson, rollbarResponse)
                    );

                // This processor did its best communicating with Rollbar API.
                // Regardless of actual result, update next token usage and consider
                // this payload record processed so it can be deleted:
                accessTokenMetadata.UpdateNextTimeTokenUsage(rollbarResponse.RollbarRateLimit);
                this._storeRepository.DeleteRecords(oldestRecord);
            }
        }
        /// <summary>
        /// Processes the queues.
        /// </summary>
        /// <param name="tokenMetadata">The token metadata.</param>
        private void ProcessQueues(AccessTokenQueuesMetadata tokenMetadata)
        {
            foreach (var queue in tokenMetadata.Queues)
            {
                if (DateTimeOffset.Now >= queue.NextDequeueTime)
                {
                    RollbarResponse response      = null;
                    PayloadBundle   payloadBundle = Process(queue, out response);
                    if (payloadBundle == null || response == null)
                    {
                        continue;
                    }

                    switch (response.Error)
                    {
                    case (int)RollbarApiErrorEventArgs.RollbarError.None:
                        payloadBundle.Signal?.Release();
                        queue.Dequeue();
                        tokenMetadata.ResetTokenUsageDelay();
                        break;

                    case (int)RollbarApiErrorEventArgs.RollbarError.TooManyRequests:
                        ObeyPayloadTimeout(payloadBundle, queue);
                        tokenMetadata.IncrementTokenUsageDelay();
                        this.OnRollbarEvent(
                            new RollbarApiErrorEventArgs(queue.Logger, payloadBundle.GetPayload(), response)
                            );
                        return;

                    default:
                        ObeyPayloadTimeout(payloadBundle, queue);
                        this.OnRollbarEvent(
                            new RollbarApiErrorEventArgs(queue.Logger, payloadBundle.GetPayload(), response)
                            );
                        break;
                    }
                }
            }

            // let's see if we can unregister any recently released queues:
            var releasedQueuesToRemove = tokenMetadata.Queues.Where(q => q.IsReleased && (q.GetPayloadCount() == 0)).ToArray();

            if (releasedQueuesToRemove != null && releasedQueuesToRemove.LongLength > 0)
            {
                foreach (var queue in releasedQueuesToRemove)
                {
                    this.Unregister(queue);
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Gets the payload count.
        /// </summary>
        /// <param name="accessToken">Converts to ken.</param>
        /// <returns>System.Int32.</returns>
        public int GetPayloadCount(string accessToken)
        {
            int counter = 0;
            AccessTokenQueuesMetadata tokenMetadata = null;

            lock (this._syncLock)
            {
                if (this._queuesByAccessToken.TryGetValue(accessToken, out tokenMetadata))
                {
                    foreach (var queue in tokenMetadata.Queues)
                    {
                        counter += queue.GetPayloadCount();
                    }
                }
            }
            return(counter);
        }
        private void IndexByToken(PayloadQueue queue)
        {
            string queueToken = queue.Logger.Config.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.Queues.Add(queue);
        }
        private void ProcessQueues(AccessTokenQueuesMetadata tokenMetadata)
        {
            foreach (var queue in tokenMetadata.Queues)
            {
                if (DateTimeOffset.Now >= queue.NextDequeueTime)
                {
                    Payload payload = queue.Peek();
                    if (payload == null)
                    {
                        continue;
                    }

                    var response = Process(payload, queue.Logger.Config);
                    if (response == null)
                    {
                        continue;
                    }

                    switch (response.Error)
                    {
                    case (int)RollbarApiErrorEventArgs.RollbarError.None:
                        payload.Signal?.Release();
                        queue.Dequeue();
                        tokenMetadata.ResetTokenUsageDelay();
                        break;

                    case (int)RollbarApiErrorEventArgs.RollbarError.TooManyRequests:
                        ObeyPayloadTimeout(payload, queue);
                        tokenMetadata.IncrementTokenUsageDelay();
                        this.OnRollbarEvent(
                            new RollbarApiErrorEventArgs(queue.Logger.Config, payload, response)
                            );
                        return;

                    default:
                        ObeyPayloadTimeout(payload, queue);
                        this.OnRollbarEvent(
                            new RollbarApiErrorEventArgs(queue.Logger.Config, payload, response)
                            );
                        break;
                    }
                }
            }
        }
Exemplo n.º 7
0
        /// <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.Queues.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.Queues)
            {
                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.Queues)
                    {
                        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)
                {
                    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;
                }
            }
        }