示例#1
0
        /// <summary>
        /// Truncates the payload.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool TruncatePayload(PayloadBundle payloadBundle)
        {
            if (this._payloadTruncationStrategy == null)
            {
                return(true); // as far as truncation is concerned - everything is good...
            }

            Payload payload = payloadBundle.GetPayload();

            if (this._payloadTruncationStrategy.Truncate(payload) > this._payloadTruncationStrategy.MaxPayloadSizeInBytes)
            {
                var exception = new ArgumentOutOfRangeException(
                    paramName: nameof(payload),
                    message: $"Payload size exceeds {this._payloadTruncationStrategy.MaxPayloadSizeInBytes} bytes limit!"
                    );

                RollbarErrorUtility.Report(
                    this._rollbarLogger,
                    payload,
                    InternalRollbarError.PayloadTruncationError,
                    "While truncating a payload...",
                    exception,
                    payloadBundle
                    );

                return(false);
            }

            return(true);
        }
示例#2
0
        /// <summary>
        /// Builds the payload record.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <param name="payloadQueue">The payload queue.</param>
        /// <returns>PayloadRecord.</returns>
        private PayloadRecord BuildPayloadRecord(PayloadBundle payloadBundle, PayloadQueue payloadQueue)
        {
            try
            {
                if (payloadBundle.Ignorable ||
                    payloadBundle.GetPayload() == null ||
                    !payloadQueue.Client.EnsureHttpContentToSend(payloadBundle)
                    )
                {
                    return(null);
                }

                Task <string> task = payloadBundle.AsHttpContentToSend.ReadAsStringAsync();
                task.Wait();
                return(new PayloadRecord()
                {
                    Timestamp = payloadBundle.GetPayload().TimeStamp,
                    ConfigJson = JsonUtil.SerializeAsJsonString(payloadBundle.GetPayload().Data.Notifier.Configuration),
                    PayloadJson = task.Result,
                });
            }
            catch (System.Exception ex)
            {
                RollbarErrorUtility.Report(
                    payloadQueue.Logger,
                    payloadBundle.GetPayload(),
                    InternalRollbarError.PersistentPayloadRecordError,
                    "While attempting to build persistent payload record...",
                    ex,
                    null
                    );
                return(null);
            }
        }
        /// <summary>
        /// Builds the payload record.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <param name="payloadQueue">The payload queue.</param>
        /// <returns>PayloadRecord.</returns>
        private IPayloadRecord BuildPayloadRecord(PayloadBundle payloadBundle, PayloadQueue payloadQueue)
        {
            try
            {
                if (payloadBundle.Ignorable ||
                    payloadBundle.GetPayload() == null ||
                    !payloadQueue.Client.EnsureHttpContentToSend(payloadBundle)
                    )
                {
                    return(null);
                }

                Task <string> task = payloadBundle.AsHttpContentToSend.ReadAsStringAsync();
                task.Wait();

                return(_storeRepository.CreatePayloadRecord(payloadBundle.GetPayload(), task.Result));
            }
            catch (System.Exception ex)
            {
                RollbarErrorUtility.Report(
                    payloadQueue.Logger,
                    payloadBundle.GetPayload(),
                    InternalRollbarError.PersistentPayloadRecordError,
                    "While attempting to build persistent payload record...",
                    ex,
                    null
                    );
                return(null);
            }
        }
示例#4
0
 /// <summary>
 /// Obeys the payload timeout.
 /// </summary>
 /// <param name="payloadBundle">The payload bundle.</param>
 /// <param name="queue">The queue.</param>
 private void ObeyPayloadTimeout(PayloadBundle payloadBundle, PayloadQueue queue)
 {
     if (payloadBundle.TimeoutAt.HasValue && (DateTime.Now.Add(this._sleepInterval) >= payloadBundle.TimeoutAt.Value))
     {
         queue.Dequeue();
     }
 }
示例#5
0
        /// <summary>
        /// Serializes the payload as json string.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>System.String.</returns>
        private string SerializePayloadAsJsonString(PayloadBundle payloadBundle)
        {
            Payload payload = payloadBundle.GetPayload();

            string jsonData;

            try
            {
                jsonData = JsonConvert.SerializeObject(payload);
            }
            catch (System.Exception exception)
            {
                RollbarErrorUtility.Report(
                    this._rollbarLogger,
                    payload,
                    InternalRollbarError.PayloadSerializationError,
                    "While serializing a payload...",
                    exception,
                    payloadBundle
                    );

                return(null);
            }

            return(jsonData);
        }
示例#6
0
        private void Report(object dataObject, ErrorLevel level, IDictionary <string, object> custom = null)
        {
            using (var signal = CreateSignalObject())
            {
                PayloadBundle payloadBundle = this._asyncLogger.EnqueueData(dataObject, level, custom, this._timeout, signal);

                WaitAndCompleteReport(payloadBundle, signal);
            }
        }
示例#7
0
        public async Task <RollbarResponse> PostAsJsonAsync(PayloadBundle payloadBundle)
        {
            Assumption.AssertNotNull(payloadBundle, nameof(payloadBundle));

            Payload payload = payloadBundle.GetPayload();

            Assumption.AssertNotNull(payload, nameof(payload));

            if (payloadBundle.AsHttpContentToSend == null)
            {
                if (this._payloadTruncationStrategy.Truncate(payloadBundle.GetPayload()) > this._payloadTruncationStrategy.MaxPayloadSizeInBytes)
                {
                    throw new ArgumentOutOfRangeException(
                              paramName: nameof(payloadBundle),
                              message: $"Payload size exceeds {this._payloadTruncationStrategy.MaxPayloadSizeInBytes} bytes limit!"
                              );
                }

                var jsonData = JsonConvert.SerializeObject(payload);
                jsonData = ScrubPayload(jsonData, this._config.GetFieldsToScrub());

                payloadBundle.AsHttpContentToSend =
                    new StringContent(jsonData, Encoding.UTF8, "application/json"); //CONTENT-TYPE header
            }

            Assumption.AssertNotNull(payloadBundle.AsHttpContentToSend, nameof(payloadBundle.AsHttpContentToSend));
            Assumption.AssertTrue(string.Equals(payload.AccessToken, this._config.AccessToken), nameof(payload.AccessToken));

            HttpRequestMessage request           = new HttpRequestMessage(HttpMethod.Post, this._payloadPostUri);
            const string       accessTokenHeader = "X-Rollbar-Access-Token";

            request.Headers.Add(accessTokenHeader, this._config.AccessToken);
            request.Content = payloadBundle.AsHttpContentToSend;

            var postResponse = await this._httpClient.SendAsync(request);

            RollbarResponse response = null;

            if (postResponse.IsSuccessStatusCode)
            {
                string reply = await postResponse.Content.ReadAsStringAsync();

                response             = JsonConvert.DeserializeObject <RollbarResponse>(reply);
                response.HttpDetails =
                    $"Response: {postResponse}"
                    + Environment.NewLine
                    + $"Request: {postResponse.RequestMessage}"
                    + Environment.NewLine
                ;
            }
            else
            {
                postResponse.EnsureSuccessStatusCode();
            }

            return(response);
        }
示例#8
0
        /// <summary>
        /// Posts as json.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>RollbarResponse.</returns>
        public RollbarResponse PostAsJson(PayloadBundle payloadBundle)
        {
            Assumption.AssertNotNull(payloadBundle, nameof(payloadBundle));

            var task = this.PostAsJsonAsync(payloadBundle);

            task.Wait();

            return(task.Result);
        }
示例#9
0
        internal ILogger Enqueue(
            object dataObject,
            ErrorLevel level,
            IDictionary <string, object> custom,
            TimeSpan?timeout     = null,
            SemaphoreSlim signal = null
            )
        {
            // here is the last chance to decide if we need to actually send this payload
            // based on the current config settings:
            if (string.IsNullOrWhiteSpace(this._config.AccessToken) ||
                this._config.Enabled == false ||
                (this._config.LogLevel.HasValue && level < this._config.LogLevel.Value)
                )
            {
                // nice shortcut:
                return(this);
            }

            DateTime?timeoutAt = null;

            if (timeout.HasValue)
            {
                timeoutAt = DateTime.Now.Add(timeout.Value);
            }

            PayloadBundle payloadBundle = null;

            IRollbarPackage rollbarPackage = dataObject as IRollbarPackage;

            if (rollbarPackage != null)
            {
                if (rollbarPackage.MustApplySynchronously)
                {
                    rollbarPackage.PackageAsRollbarData();
                }
                payloadBundle =
                    new PayloadBundle(this.Config, rollbarPackage, level, custom, timeoutAt, signal);
            }
            else
            {
                payloadBundle =
                    new PayloadBundle(this.Config, dataObject, level, custom, timeoutAt, signal);
            }

            if (payloadBundle == null)
            {
                //TODO: we may want to report that there is some problem with packaging...
                return(this);
            }

            this._payloadQueue.Enqueue(payloadBundle);

            return(this);
        }
示例#10
0
        /// <summary>
        /// Ensures the HTTP content to send.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns><c>true</c> if succeeds, <c>false</c> otherwise.</returns>
        public bool EnsureHttpContentToSend(PayloadBundle payloadBundle)
        {
            if (payloadBundle.AsHttpContentToSend != null)
            {
                return(true);
            }

            Payload payload = payloadBundle.GetPayload();

            Assumption.AssertNotNull(payload, nameof(payload));

            if (!TruncatePayload(payloadBundle))
            {
                return(false);
            }

            if (!ScrubHttpMessages(payloadBundle))
            {
                return(false);
            }

            string jsonData = SerializePayloadAsJsonString(payloadBundle);

            if (string.IsNullOrWhiteSpace(jsonData))
            {
                return(false);
            }

            try
            {
                jsonData = ScrubPayload(jsonData);
            }
            catch (System.Exception exception)
            {
                RollbarErrorUtility.Report(
                    this._rollbarLogger,
                    payload,
                    InternalRollbarError.PayloadScrubbingError,
                    "While scrubbing a payload...",
                    exception,
                    payloadBundle
                    );

                return(false);
            }

            payloadBundle.AsHttpContentToSend =
                new StringContent(jsonData, Encoding.UTF8, "application/json"); //CONTENT-TYPE header

            Assumption.AssertNotNull(payloadBundle.AsHttpContentToSend, nameof(payloadBundle.AsHttpContentToSend));
            Assumption.AssertTrue(string.Equals(payload.AccessToken, this._rollbarLogger.Config.AccessToken), nameof(payload.AccessToken));

            return(true);
        }
示例#11
0
        public void Enqueue(PayloadBundle payload)
        {
            Assumption.AssertNotNull(payload, nameof(payload));

            lock (this._syncLock)
            {
                if (this._logger.Config.ReportingQueueDepth == this._queue.Count)
                {
                    this._queue.Dequeue();
                }
                this._queue.Enqueue(payload);
            }
        }
示例#12
0
        public PayloadBundle Peek()
        {
            lock (this._syncLock)
            {
                PayloadBundle result = null;

                if (this._queue.Count > 0)
                {
                    result = this._queue.Peek();
                }

                return(result);
            }
        }
        /// <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);
                }
            }
        }
示例#14
0
 private void WaitAndCompleteReport(PayloadBundle payloadBundle, SemaphoreSlim signal)
 {
     if (!signal.Wait(this._timeout))
     {
         const string exceptionMessage = "Posting a payload to the Rollbar API Service timed-out";
         if (payloadBundle?.Exceptions.Count > 0)
         {
             throw new TimeoutException(exceptionMessage, new AggregateException(payloadBundle.Exceptions));
         }
         else
         {
             throw new TimeoutException(exceptionMessage);
         }
     }
 }
示例#15
0
        /// <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 = GetFirstTransmittableBundle(queue);
            Payload       payload       = payloadBundle?.GetPayload();

            if (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);
            }

            try
            {
                response = queue.Client.PostAsJson(payloadBundle);
            }
            catch (System.Exception ex)
            {
                this.OnRollbarEvent(
                    new CommunicationErrorEventArgs(queue.Logger, payload, ex, 0)
                    );
                payloadBundle.Register(ex);
                throw;
            }

            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);
        }
示例#16
0
        /// <summary>
        /// post as json as an asynchronous operation.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>Task&lt;RollbarResponse&gt;.</returns>
        public async Task <RollbarResponse> PostAsJsonAsync(PayloadBundle payloadBundle)
        {
            Assumption.AssertNotNull(payloadBundle, nameof(payloadBundle));

            // make sure there anything meaningful to send:
            if (!EnsureHttpContentToSend(payloadBundle))
            {
                return(null);
            }

            return(await PostAsJsonAsync(
                       this._payloadPostUri,
                       this._rollbarLogger.Config.AccessToken,
                       payloadBundle.AsHttpContentToSend
                       ));
        }
示例#17
0
        /// <summary>
        /// Posts as json.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>RollbarResponse.</returns>
        public RollbarResponse PostAsJson(PayloadBundle payloadBundle)
        {
            Assumption.AssertNotNull(payloadBundle, nameof(payloadBundle));

            // first, let's run quick Internet availability check
            // to minimize potential timeout of the following JSON POST call:
            if (!ConnectivityMonitor.Instance.IsConnectivityOn)
            {
                throw new HttpRequestException("Preliminary ConnectivityMonitor detected offline status!");
            }

            var task = this.PostAsJsonAsync(payloadBundle);

            //task.Wait(expectedPostToApiTimeout);
            task.Wait();

            return(task.Result);
        }
示例#18
0
        /// <summary>
        /// Enqueues the specified payload.
        /// </summary>
        /// <param name="payload">The payload.</param>
        public void Enqueue(PayloadBundle payload)
        {
            Assumption.AssertNotNull(payload, nameof(payload));

            if (payload == null)
            {
                return; // no one needs to enqueue "nothing"...
            }

            lock (this._syncLock)
            {
                if (this._logger.Config.ReportingQueueDepth == this._queue.Count)
                {
                    this._queue.Dequeue();
                }
                this._queue.Enqueue(payload);
            }
        }
示例#19
0
        public PayloadBundle Dequeue()
        {
            lock (this._syncLock)
            {
                PayloadBundle result = null;

                if (this._queue.Count > 0)
                {
                    result = this._queue.Dequeue();

                    TimeSpan delta = TimeSpan.FromTicks(
                        TimeSpan.FromMinutes(1).Ticks / this.Logger.Config.MaxReportsPerMinute
                        );
                    this.NextDequeueTime = DateTimeOffset.Now.Add(delta);
                }

                return(result);
            }
        }
示例#20
0
        /// <summary>
        /// Gets the first transmittabl bundle.
        /// </summary>
        /// <param name="queue">The queue.</param>
        /// <returns>PayloadBundle.</returns>
        private PayloadBundle GetFirstTransmittableBundle(PayloadQueue queue)
        {
            PayloadBundle payloadBundle = 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)
                        );
                }
            }while (ignorableBundle);

            return(payloadBundle);
        }
示例#21
0
        /// <summary>
        /// Posts as json.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>RollbarResponse.</returns>
        public RollbarResponse PostAsJson(PayloadBundle payloadBundle)
        {
            Assumption.AssertNotNull(payloadBundle, nameof(payloadBundle));

            // first, let's run quick Internet availability check
            // to minimize potential timeout of the following JSON POST call:
            if (!ConnectivityMonitor.Instance.IsConnectivityOn)
            {
                throw new HttpRequestException("Preliminary ConnectivityMonitor detected offline status!");
            }

            using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource())
            {
                var task = this.PostAsJsonAsync(payloadBundle, cancellationTokenSource.Token);

                try
                {
                    if (!task.Wait(this._expectedPostToApiTimeout))
                    {
                        cancellationTokenSource.Cancel(true);
                    }
                    return(task.Result);
                }
                catch (System.Exception ex)
                {
                    RollbarErrorUtility.Report(
                        null,
                        payloadBundle.AsHttpContentToSend,
                        InternalRollbarError.PayloadPostError,
                        "While PostAsJson(PayloadBundle payloadBundle)...",
                        ex,
                        payloadBundle
                        );
                    return(null);
                }
            }
        }
示例#22
0
        /// <summary>
        /// Creates the payload bundle.
        /// </summary>
        /// <param name="dataObject">The data object.</param>
        /// <param name="level">The level.</param>
        /// <param name="custom">The custom.</param>
        /// <param name="timeout">The timeout.</param>
        /// <param name="signal">The signal.</param>
        /// <returns>PayloadBundle.</returns>
        private PayloadBundle CreatePayloadBundle(
            object dataObject,
            ErrorLevel level,
            IDictionary <string, object> custom,
            TimeSpan?timeout     = null,
            SemaphoreSlim signal = null
            )
        {
            DateTime?timeoutAt = null;

            if (timeout.HasValue)
            {
                timeoutAt = DateTime.Now.Add(timeout.Value);
            }

            PayloadBundle payloadBundle = null;

            IRollbarPackage rollbarPackage = dataObject as IRollbarPackage;

            if (rollbarPackage != null)
            {
                if (rollbarPackage.MustApplySynchronously)
                {
                    rollbarPackage.PackageAsRollbarData();
                }

                payloadBundle =
                    new PayloadBundle(this, rollbarPackage, level, custom, timeoutAt, signal);
            }
            else
            {
                payloadBundle =
                    new PayloadBundle(this, dataObject, level, custom, timeoutAt, signal);
            }

            return(payloadBundle);
        }
示例#23
0
        /// <summary>
        /// Scrubs the HTTP messages.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private bool ScrubHttpMessages(PayloadBundle payloadBundle)
        {
            Payload payload = payloadBundle.GetPayload();

            DTOs.Request request = payload.Data.Request;
            if (request?.PostBody is string requestBody)
            {
                if (request.Headers.TryGetValue("Content-Type", out string contentTypeHeader))
                {
                    request.PostBody =
                        this.ScrubHttpMessageBodyContentString(
                            requestBody,
                            contentTypeHeader,
                            this._payloadScrubber.ScrubMask,
                            this._payloadScrubber.PayloadFieldNames,
                            this._payloadScrubber.HttpRequestBodyPaths);
                }
            }

            DTOs.Response response = payload.Data.Response;
            if (response?.Body is string responseBody)
            {
                if (response.Headers.TryGetValue("Content-Type", out string contentTypeHeader))
                {
                    response.Body =
                        this.ScrubHttpMessageBodyContentString(
                            responseBody,
                            contentTypeHeader,
                            this._payloadScrubber.ScrubMask,
                            this._payloadScrubber.PayloadFieldNames,
                            this._payloadScrubber.HttpResponseBodyPaths);
                }
            }

            return(true);
        }
示例#24
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;
                }
            }
        }
示例#25
0
        /// <summary>
        /// Enqueues the data.
        /// </summary>
        /// <param name="dataObject">The data object.</param>
        /// <param name="level">The level.</param>
        /// <param name="custom">The custom.</param>
        /// <param name="timeout">The timeout.</param>
        /// <param name="signal">The signal.</param>
        /// <returns>PayloadBundle.</returns>
        internal PayloadBundle EnqueueData(
            object dataObject,
            ErrorLevel level,
            IDictionary <string, object> custom,
            TimeSpan?timeout     = null,
            SemaphoreSlim signal = null
            )
        {
            // here is the last chance to decide if we need to actually send this payload
            // based on the current config settings and rate-limit conditions:
            if (string.IsNullOrWhiteSpace(this._config.AccessToken) ||
                this._config.Enabled == false ||
                (this._config.LogLevel.HasValue && level < this._config.LogLevel.Value) ||
                ((this._payloadQueue.AccessTokenQueuesMetadata != null) && this._payloadQueue.AccessTokenQueuesMetadata.IsTransmissionSuspended)
                )
            {
                // nice shortcut:
                return(null);
            }

            if (this._config.RethrowExceptionsAfterReporting)
            {
                System.Exception exception = dataObject as System.Exception;
                if (exception == null)
                {
                    if (dataObject is Data data && data.Body != null)
                    {
                        exception = data.Body.OriginalException;
                    }
                }

                if (exception != null)
                {
                    try
                    {
                        // Here we need to create another logger instance with similar config but configured not to re-throw.
                        // This would prevent infinite recursive calls (in case if we used this instance or any re-throwing instance).
                        // Because we will be re-throwing the exception after reporting, let's report it fully-synchronously.
                        // This logic is on a heavy side. But, fortunately, RethrowExceptionsAfterReporting is intended to be
                        // a development time option:
                        var config = new RollbarConfig();
                        config.Reconfigure(this._config);
                        config.RethrowExceptionsAfterReporting = false;
                        using (var rollbar = RollbarFactory.CreateNew(config))
                        {
                            rollbar.AsBlockingLogger(TimeSpan.FromSeconds(1)).Log(level, dataObject, custom);
                        }
                    }
                    catch
                    {
                        // In case there was a TimeoutException (or any un-expected exception),
                        // there is nothing we can do here.
                        // We tried our best...
                    }
                    finally
                    {
                        if (exception is AggregateException aggregateException)
                        {
                            exception = aggregateException.Flatten();
                            ExceptionDispatchInfo.Capture(
                                exception.InnerException).Throw();
                        }
                        else
                        {
                            ExceptionDispatchInfo.Capture(exception).Throw();
                        }
                    }

                    return(null);
                }
            }


            PayloadBundle payloadBundle = null;

            try
            {
                payloadBundle = CreatePayloadBundle(dataObject, level, custom, timeout, signal);
            }
            catch (System.Exception exception)
            {
                RollbarErrorUtility.Report(
                    this,
                    dataObject,
                    InternalRollbarError.BundlingError,
                    null,
                    exception,
                    payloadBundle
                    );
                return(null);
            }

            try
            {
                this._payloadQueue.Enqueue(payloadBundle);
            }
            catch (System.Exception exception)
            {
                RollbarErrorUtility.Report(
                    this,
                    dataObject,
                    InternalRollbarError.EnqueuingError,
                    null,
                    exception,
                    payloadBundle
                    );
            }

            return(payloadBundle);
        }
        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);
        }