/// <summary> /// Serializes the payload as json string. /// </summary> /// <param name="payloadBundle">The payload bundle.</param> /// <returns>System.Nullable<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); }
/// <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); } }
/// <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); if (payloadBundle == null) { return(null); } Payload?payload = payloadBundle?.GetPayload(); if (payload == null) // one more sanity check before proceeding further... { return(null); } if (queue.Logger?.Config != null && !queue.Logger.Config.RollbarDeveloperOptions.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); }
/// <summary> /// Scrubs the HTTP messages. /// </summary> /// <param name="payloadBundle">The payload bundle.</param> /// <returns><c>true</c> if scrubbed successfully, <c>false</c> otherwise.</returns> public bool ScrubHttpMessages(PayloadBundle payloadBundle) { Payload?payload = payloadBundle.GetPayload(); if (payload == null) { return(true); } DTOs.Request?request = payload.Data.Request; if (request?.PostBody is string requestBody && request.Headers != null && request.Headers.TryGetValue("Content-Type", out string?requestContentTypeHeader) ) { request.PostBody = this.ScrubHttpMessageBodyContentString( requestBody, requestContentTypeHeader, this.ScrubMask, this.PayloadFieldNames, this.HttpRequestBodyPaths); } DTOs.Response?response = payload.Data.Response; if (response?.Body is string responseBody && response.Headers != null && response.Headers.TryGetValue("Content-Type", out string?responseContentTypeHeader) ) { response.Body = this.ScrubHttpMessageBodyContentString( responseBody, responseContentTypeHeader, this.ScrubMask, this.PayloadFieldNames, this.HttpResponseBodyPaths); } return(true); }
/// <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; } } }
/// <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); }