/// <summary>
        /// Serializes the payload as json string.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>System.Nullable&lt;System.String&gt;.</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);
        }
Пример #2
0
        /// <summary>
        /// Keeps the processing all queues.
        /// </summary>
        /// <param name="data">The data.</param>
        private void KeepProcessingAllQueues(object?data)
        {
            if (data == null)
            {
                RollbarErrorUtility.Report(
                    null,
                    null,
                    InternalRollbarError.QueueControllerError,
                    "While KeepProcessingAllQueues()...",
                    null,
                    null
                    );
                return;
            }

            CancellationToken cancellationToken = (CancellationToken)data;

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    lock (this._syncLock)
                    {
                        ProcessAllQueuesOnce();
                    }

                    ProcessPersistentStoreOnce();
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (System.Threading.ThreadAbortException tae)
                {
                    return;
                }
                catch (System.Exception ex)
                {
                    RollbarErrorUtility.Report(
                        null,
                        null,
                        InternalRollbarError.QueueControllerError,
                        "While KeepProcessingAllQueues()...",
                        ex,
                        null
                        );

                    //NOTE: do we want to direct the exception
                    //      to some kind of Rollbar notifier maintenance "access token"?
                }
#pragma warning restore CS0168 // Variable is declared but never used

                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                Thread.Sleep(this._sleepInterval);
            }

            CompleteProcessing();
        }
Пример #3
0
        /// <summary>
        /// Persists the specified payload queue.
        /// </summary>
        /// <param name="payloadQueue">The payload queue.</param>
        private void Persist(PayloadQueue payloadQueue)
        {
            //if (!payloadQueue.Logger.Config.EnableLocalPayloadStore)
            if (this._storeRepository == null)
            {
                return;
            }

            var items = payloadQueue.GetItemsToPersist();

            if (items == null || items.Length == 0)
            {
                return;
            }

            string?endPoint    = payloadQueue.Logger.Config.RollbarDestinationOptions.EndPoint;
            string?accessToken = payloadQueue.AccessTokenQueuesMetadata?.AccessToken;

            if (string.IsNullOrWhiteSpace(endPoint) || string.IsNullOrWhiteSpace(accessToken))
            {
                return;
            }

            var payloads = new List <IPayloadRecord>();

            foreach (var item in items)
            {
                var payloadRecord = this.BuildPayloadRecord(item, payloadQueue);
                if (payloadRecord != null)
                {
                    payloads.Add(payloadRecord);
                }
            }

            try
            {
                this._storeRepository.SavePayloads(endPoint !, accessToken !, payloads);
            }
            catch (System.Exception ex)
            {
                RollbarErrorUtility.Report(
                    payloadQueue.Logger,
                    items.Select(i => i.GetPayload()),
                    InternalRollbarError.PersistentStoreContextError,
                    "While attempting to save persistent store context...",
                    ex,
                    null
                    );
            }

            foreach (var item in items)
            {
                item.Signal?.Release();
            }
        }
Пример #4
0
        /// <summary>
        /// Posts as json.
        /// </summary>
        /// <param name="accessToken">The access token.</param>
        /// <param name="jsonContent">Content of the json.</param>
        /// <returns>System.Nullable&lt;RollbarResponse&gt;.</returns>
        /// <exception cref="System.Net.Http.HttpRequestException">
        /// Preliminary ConnectivityMonitor detected offline status!
        /// </exception>
        public RollbarResponse?PostAsJson(
            string?accessToken,
            string?jsonContent
            )
        {
            Assumption.AssertNotNullOrWhiteSpace(accessToken, nameof(accessToken));
            Assumption.AssertNotNullOrWhiteSpace(jsonContent, nameof(jsonContent));

            if (string.IsNullOrWhiteSpace(accessToken))
            {
                return(null);
            }

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

            using CancellationTokenSource cancellationTokenSource = new();
            var task = this.PostAsJsonAsync(accessToken !, jsonContent !, cancellationTokenSource.Token);

            try
            {
                if (!task.Wait(this._expectedPostToApiTimeout))
                {
                    cancellationTokenSource.Cancel(true);
                }
                return(task.Result);
            }
            catch (System.Exception ex)
            {
                RollbarErrorUtility.Report(
                    null,
                    jsonContent,
                    InternalRollbarError.PayloadPostError,
                    "While PostAsJson((string destinationUri, string accessToken, string jsonContent)...",
                    ex,
                    null
                    );
                return(null);
            }
        }
Пример #5
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 IPayloadRecord?BuildPayloadRecord(PayloadBundle payloadBundle, PayloadQueue payloadQueue)
        {
            try
            {
                if (payloadBundle.Ignorable ||
                    payloadBundle.GetPayload() == null ||
                    !payloadQueue.Client.EnsureHttpContentToSend(payloadBundle)
                    )
                {
                    return(null);
                }

                if (payloadBundle.AsHttpContentToSend == null)
                {
                    return(null);
                }

                Task <string> task = payloadBundle.AsHttpContentToSend.ReadAsStringAsync();
                task.Wait();
                string  payloadContent = task.Result;
                Payload?payload        = payloadBundle.GetPayload();

                if (payload != null && !string.IsNullOrWhiteSpace(payloadContent))
                {
                    return(_storeRepository?.CreatePayloadRecord(payload, payloadContent));
                }
                else
                {
                    return(null);
                }
            }
            catch (System.Exception ex)
            {
                RollbarErrorUtility.Report(
                    payloadQueue.Logger,
                    payloadBundle.GetPayload(),
                    InternalRollbarError.PersistentPayloadRecordError,
                    "While attempting to build persistent payload record...",
                    ex,
                    null
                    );
                return(null);
            }
        }
Пример #6
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);
        }
Пример #7
0
        /// <summary>
        /// Posts as json.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns>System.Nullable&lt;RollbarResponse&gt;.</returns>
        /// <exception cref="System.Net.Http.HttpRequestException">Preliminary ConnectivityMonitor detected offline status!</exception>
        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 (RollbarConnectivityMonitor.Instance != null &&
                !RollbarConnectivityMonitor.Instance.IsConnectivityOn
                )
            {
                throw new HttpRequestException("Preliminary ConnectivityMonitor detected offline status!");
            }

            using CancellationTokenSource cancellationTokenSource = new();
            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);
            }
        }
Пример #8
0
        /// <summary>
        /// Tries the posting.
        /// </summary>
        /// <param name="payloadRecord">The payload record.</param>
        /// <returns>RollbarResponse.</returns>
        private RollbarResponse?TryPosting(IPayloadRecord payloadRecord)
        {
            if (payloadRecord.ConfigJson == null)
            {
                return(null);
            }
            IRollbarLoggerConfig?config = JsonConvert.DeserializeObject <RollbarLoggerConfig>(payloadRecord.ConfigJson);

            if (config == null)
            {
                return(null);
            }
            RollbarClient rollbarClient = new RollbarClient(config);

            try
            {
                RollbarResponse?response =
                    rollbarClient.PostAsJson(config.RollbarDestinationOptions.AccessToken, payloadRecord.PayloadJson);
                return(response);
            }
            catch (System.Exception ex)
            {
                this.OnRollbarEvent(
                    new CommunicationErrorEventArgs(null, payloadRecord.PayloadJson, ex, 0)
                    );

                RollbarErrorUtility.Report(
                    null,
                    payloadRecord,
                    InternalRollbarError.PersistentPayloadRecordRepostError,
                    "While trying to report a stored payload...",
                    ex,
                    null
                    );

                return(null);
            }
        }
Пример #9
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.RollbarDestinationOptions.AccessToken) ||
                !this._config.RollbarDeveloperOptions.Enabled ||
                (level < this._config.RollbarDeveloperOptions.LogLevel) ||
                ((this._payloadQueue.AccessTokenQueuesMetadata != null) && this._payloadQueue.AccessTokenQueuesMetadata.IsTransmissionSuspended)
                )
            {
                // nice shortcut:
                return(null);
            }

            if (this._config.RollbarDeveloperOptions.RethrowExceptionsAfterReporting)
            {
                System.Exception?exception = dataObject as System.Exception;
                if (exception == null &&
                    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 RollbarLoggerConfig();
                        config.Reconfigure(this._config);
                        config.RollbarDeveloperOptions.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).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);
        }
        /// <summary>
        /// Ensures the HTTP content to send.
        /// </summary>
        /// <param name="payloadBundle">The payload bundle.</param>
        /// <returns><c>true</c> if XXXX, <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 (this._payloadTruncator == null ||
                !this._payloadTruncator.TruncatePayload(payloadBundle)
                )
            {
                return(false);
            }

            if (this._payloadScrubber == null ||
                !this._payloadScrubber.ScrubHttpMessages(payloadBundle)
                )
            {
                return(false);
            }

            string?jsonData = SerializePayloadAsJsonString(payloadBundle);

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

            try
            {
                jsonData = this._payloadScrubber.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)
                );
#pragma warning disable CA1307 // Specify StringComparison for clarity
            _ = Assumption.AssertTrue(
                string.Equals(payload !.AccessToken, this._rollbarLoggerConfig.RollbarDestinationOptions.AccessToken),
                nameof(payload.AccessToken)
                );
#pragma warning restore CA1307 // Specify StringComparison for clarity

            return(true);
        }
        /// <summary>
        /// Gets the payload.
        /// </summary>
        /// <returns>Payload.</returns>
        public Payload?GetPayload()
        {
            if (this._payload == null)
            {
                Data?data = this.GetPayloadData();
                if (data != null)
                {
                    data.Level = this._level;
                    //update the data timestamp from the data creation timestamp to the passed
                    //object-to-log capture timestamp:
                    data.Timestamp = DateTimeUtil.ConvertToUnixTimestampInSeconds(this._timeStamp);

                    this._payload = new Payload(this._rollbarLogger?.Config.RollbarDestinationOptions.AccessToken, data);
                    this._payload.PayloadBundle = this;

                    try // payload check-ignore:
                    {
                        if (this._rollbarLogger?.Config.RollbarPayloadManipulationOptions.CheckIgnore != null &&
                            this._rollbarLogger.Config.RollbarPayloadManipulationOptions.CheckIgnore.Invoke(this._payload)
                            )
                        {
                            this._ignorable = true;
                            return(this._payload);     //shortcut...
                        }
                    }
                    catch (System.Exception exception)
                    {
                        RollbarErrorUtility.Report(
                            this._rollbarLogger,
                            this._payload,
                            InternalRollbarError.PayloadCheckIgnoreError,
                            "While check-ignoring a payload...",
                            exception,
                            GetPrimaryErrorCollector()
                            );
                    }
                    this._ignorable = false;

                    try // payload transformation:
                    {
                        this._rollbarLogger?.Config.RollbarPayloadManipulationOptions.Transform?.Invoke(this._payload);
                    }
                    catch (System.Exception exception)
                    {
                        RollbarErrorUtility.Report(
                            this._rollbarLogger,
                            this._payload,
                            InternalRollbarError.PayloadTransformError,
                            "While transforming a payload...",
                            exception,
                            GetPrimaryErrorCollector()
                            );
                    }

                    try // payload truncation:
                    {
                        this._rollbarLogger?.Config.RollbarPayloadManipulationOptions.Truncate?.Invoke(this._payload);
                    }
                    catch (System.Exception exception)
                    {
                        RollbarErrorUtility.Report(
                            this._rollbarLogger,
                            this._payload,
                            InternalRollbarError.PayloadTruncationError,
                            "While truncating a payload...",
                            exception,
                            GetPrimaryErrorCollector()
                            );
                    }

                    try
                    {
                        this._payload.Validate();
                    }
                    catch (System.Exception exception)
                    {
                        RollbarErrorUtility.Report(
                            this._rollbarLogger,
                            this._payload,
                            InternalRollbarError.PayloadValidationError,
                            "While validating a payload...",
                            exception,
                            GetPrimaryErrorCollector()
                            );
                    }
                }
            }
            return(this._payload);
        }