/// <summary> /// Initializes a new instance of the <see cref="RollbarLogger" /> class. /// </summary> /// <param name="rollbarConfig">The rollbar configuration.</param> internal RollbarLogger(IRollbarLoggerConfig?rollbarConfig) { Assumption.AssertTrue(RollbarInfrastructure.Instance.IsInitialized, nameof(RollbarInfrastructure.Instance.IsInitialized)); if (RollbarTelemetryCollector.Instance != null && !RollbarTelemetryCollector.Instance.IsAutocollecting ) { RollbarTelemetryCollector.Instance.StartAutocollection(); } if (rollbarConfig != null) { ValidateConfiguration(rollbarConfig); this._config = new RollbarLoggerConfig(this).Reconfigure(rollbarConfig); } else { this._config = new RollbarLoggerConfig(this); } // let's init proper Rollbar client: var rollbarClient = new RollbarClient(this); // let's init the corresponding queue and register it: this._payloadQueue = new PayloadQueue(this, rollbarClient); RollbarQueueController.Instance?.Register(this._payloadQueue); }
/// <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(); } }
/// <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(); } }
/// <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> /// Registers the specified queue. /// </summary> /// <param name="queue">The queue.</param> internal void Register(PayloadQueue queue) { lock (this._syncLock) { Assumption.AssertNotNull(this._config, nameof(this._config)); Assumption.AssertTrue(!this._allQueues.Contains(queue), nameof(queue)); this._allQueues.Add(queue); this.IndexByToken(queue); ((RollbarLoggerConfig)queue.Logger.Config).Reconfigured += LoggerConfig_Reconfigured; // The following debug line causes stack overflow when RollbarTraceListener is activated: Debug.WriteLineIf(RollbarTraceListener.InstanceCount == 0, this.GetType().Name + ": Registered a queue. Total queues count: " + this._allQueues.Count + "."); } }
/// <summary> /// Unregisters the specified queue. /// </summary> /// <param name="queue">The queue.</param> private void Unregister(PayloadQueue queue) { if (queue.Logger == RollbarLocator.RollbarInstance.Logger) { return; // we do not want to unregister the singleton's queue. } lock (this._syncLock) { Assumption.AssertNotNull(this._config, nameof(this._config)); Assumption.AssertTrue(this._allQueues.Contains(queue), nameof(queue)); this.DropIndexByToken(queue); this._allQueues.Remove(queue); ((RollbarLoggerConfig)queue.Logger.Config).Reconfigured -= LoggerConfig_Reconfigured; Debug.WriteLine(this.GetType().Name + ": Unregistered a queue. Total queues count: " + this._allQueues.Count + "."); } }
/// <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> /// 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); }