/// <summary> /// Translates the specified plug in event data into a Rollbar.DTOs.Data instance. /// </summary> /// <param name="plugInEventData">The plug in event data.</param> /// <param name="plugInErrorLevel">The plug in error level.</param> /// <returns>Rollbar.DTOs.Data instance.</returns> protected virtual DTOs.Data Translate(TPlugInEventData plugInEventData, TPlugInErrorLevel plugInErrorLevel) { ErrorLevel errorLevel = this.Translate(plugInErrorLevel); string message = this.ExtractMessage(plugInEventData); Exception exception = this.ExtractException(plugInEventData); object pluginEventProperties = this.ExtractCustomProperties(plugInEventData); DTOs.Body rollbarBody = null; if (exception != null) { rollbarBody = new DTOs.Body(exception); } else { rollbarBody = new DTOs.Body(new DTOs.Message(message)); } IDictionary <string, object> custom = null; if (pluginEventProperties != null) { const int customCapacity = 1; custom = new Dictionary <string, object>(customCapacity); custom[this._customPrefix] = pluginEventProperties; } DTOs.Data rollbarData = new DTOs.Data(this._rollbar.Config, rollbarBody, custom) { Level = errorLevel }; return(rollbarData); }
/// <summary> /// Reports data to Rollbar. /// </summary> /// <param name="rollbarData">The Rollbar data.</param> protected void ReportToRollbar(DTOs.Data rollbarData) { if (this._rollbarLogger != null) { ReportToRollbar(this._rollbarLogger, rollbarData); } }
protected override void Write(LogEventInfo logEvent) { if (!LevelMapper.TryGetValue(logEvent.Level, out ErrorLevel rollbarLogLevel)) { rollbarLogLevel = ErrorLevel.Debug; } DTOs.Body rollbarBody = null; if (logEvent.Exception != null) { rollbarBody = new DTOs.Body(logEvent.Exception); } else { var formattedMessage = RenderLogEvent(Layout, logEvent); rollbarBody = new DTOs.Body(new DTOs.Message(formattedMessage)); } IDictionary <string, object> custom = GetAllProperties(logEvent); DTOs.Data rollbarData = new DTOs.Data(RollbarConfig, rollbarBody, custom) { Level = rollbarLogLevel }; ReportToRollbar(rollbarData); }
/// <summary> /// Reports to rollbar. /// </summary> /// <param name="plugInEventData">The plug-in event data.</param> /// <param name="plugInErrorLevel">The plug-in error level.</param> public virtual void ReportToRollbar(TPlugInEventData plugInEventData, TPlugInErrorLevel plugInErrorLevel) { if ((this._plugInEventDataType.IsClass || this._plugInEventDataType.IsInterface) && object.Equals(plugInEventData, default(TPlugInEventData))) { return; } DTOs.Data data = null; try { data = this.Translate(plugInEventData, plugInErrorLevel); } catch (Exception ex) { data = new DTOs.Data(this._rollbar.Config, new DTOs.Body(ex)); } finally { if (data != null) { this.ReportToRollbar(data); } } }
/// <summary> /// Appends the specified logging event. /// </summary> /// <param name="loggingEvent">The logging event.</param> protected override void Append(LoggingEvent loggingEvent) { if (loggingEvent == null) { return; } ErrorLevel rollbarLogLevel = Translate(loggingEvent.Level); string message = loggingEvent.RenderedMessage; DTOs.Body rollbarBody = null; if (loggingEvent.ExceptionObject != null) { rollbarBody = new DTOs.Body(loggingEvent.ExceptionObject); } else { rollbarBody = new DTOs.Body(new DTOs.Message(message)); } int customCapacity = 50; IDictionary <string, object> custom = new Dictionary <string, object>(customCapacity); custom[prefix] = loggingEvent.GetLoggingEventData(); DTOs.Data rollbarData = new DTOs.Data(this._rollbarConfig, rollbarBody, custom) { Level = rollbarLogLevel }; this.ReportToRollbar(rollbarData); }
/// <summary> /// Writes trace information, a message, and event information to the listener specific output. /// </summary> /// <param name="eventCache">A <see cref="T:System.Diagnostics.TraceEventCache"></see> object that contains the current process ID, thread ID, and stack trace information.</param> /// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param> /// <param name="eventType">One of the <see cref="T:System.Diagnostics.TraceEventType"></see> values specifying the type of event that has caused the trace.</param> /// <param name="id">A numeric identifier for the event.</param> /// <param name="message">A message to write.</param> public override void TraceEvent(TraceEventCache?eventCache, string source, TraceEventType eventType, int id, string?message) { if (this.Rollbar == null || message == null || string.IsNullOrWhiteSpace(message)) { return; } // the code below is simplified way to report events to Rollbar API, // in production code we can do better job mapping the available event data // into proper Rollbar data body: var custom = new Dictionary <string, object?>(); if (eventCache != null) { custom["callStack"] = eventCache.Callstack; custom["logicalOperationStack"] = eventCache.LogicalOperationStack; custom["processID"] = eventCache.ProcessId; custom["threadID"] = eventCache.ThreadId; custom["timestamp"] = eventCache.Timestamp; custom["dateTime"] = eventCache.DateTime; custom["eventType"] = eventType; custom["eventMessage"] = message; if (!string.IsNullOrWhiteSpace(eventCache.Callstack) #pragma warning disable CA1307 // Specify StringComparison for clarity && (message.Contains("Exception: ") || (eventType == TraceEventType.Critical) || (eventType == TraceEventType.Error))) #pragma warning restore CA1307 // Specify StringComparison for clarity { DTOs.Body body = new DTOs.Body(new DTOs.Trace(eventCache.Callstack, message)); DTOs.Data data = new DTOs.Data(this.Rollbar.Config, body, custom); data.Level = RollbarTraceListener.Translate(eventType); this.Rollbar.Log(data); return; } } switch (eventType) { case TraceEventType.Critical: this.Rollbar.Critical(message, custom); break; case TraceEventType.Error: this.Rollbar.Error(message, custom); break; case TraceEventType.Warning: this.Rollbar.Warning(message, custom); break; case TraceEventType.Information: this.Rollbar.Info(message, custom); break; default: this.Rollbar.Critical(message, custom); break; } }
/// <summary> /// Reports to Rollbar. /// </summary> /// <param name="rollbarData">The Rollbar data.</param> private void ReportToRollbar(DTOs.Data rollbarData) { if (this._rollbarAsyncLogger != null) { RollbarSink.ReportToRollbar(this._rollbarAsyncLogger, rollbarData); } else if (this._rollbarLogger != null) { RollbarSink.ReportToRollbar(this._rollbarLogger, rollbarData); } }
/// <summary> /// Reports to Rollbar. /// </summary> /// <param name="rollbarData">The Rollbar data.</param> private void ReportToRollbar(DTOs.Data rollbarData) { if (_rollbarAsyncLogger != null) { _rollbarAsyncLogger.Log(rollbarData); } else if (_rollbarLogger != null) { _rollbarLogger.Log(rollbarData); } }
/// <summary> /// Invokes this middleware instance on the specified context. /// </summary> /// <param name="context">The context.</param> /// <returns>A middleware invocation/execution task.</returns> public async Task Invoke(HttpContext context) { // as we learned from a field issue, apparently a middleware can even be invoked without a valid HttPContext: string requestId = null; requestId = context?.Features? .Get <IHttpRequestIdentifierFeature>()? .TraceIdentifier; using (_logger.BeginScope($"Request: {requestId ?? string.Empty}")) { try { RollbarScope.Current.HttpContext.HttpAttributes = new RollbarHttpAttributes(context); await this._nextRequestProcessor(context); } catch (Exception ex) { // let's custom build the Data object that includes the exception // along with the current HTTP request context: DTOs.Data data = new DTOs.Data( config: RollbarLocator.RollbarInstance.Config, body: new DTOs.Body(ex), custom: null, request: (context != null) ? new DTOs.Request(null, context.Request) : null ) { Level = ErrorLevel.Critical, }; // log the Data object (the exception + the HTTP request data): RollbarLocator.RollbarInstance.Log(data); throw new Exception("The included internal exception processed by the Rollbar middleware", ex); } finally { if (context != null && context.Response != null) { RollbarScope.Current.HttpContext.HttpAttributes.StatusCode = context.Response.StatusCode; } } } }
/// <summary> /// Logs the specified rollbar data. /// </summary> /// <param name="rollbarData">The rollbar data.</param> /// <returns>ILogger.</returns> public ILogger Log(DTOs.Data rollbarData) { return(this.Enqueue(rollbarData, rollbarData.Level ?? ErrorLevel.Debug, null)); }
/// <summary> /// Reports data to Rollbar. /// </summary> /// <param name="logger">The logger.</param> /// <param name="rollbarData">The Rollbar data.</param> private static void ReportToRollbar(ILogger logger, DTOs.Data rollbarData) { logger.Log(rollbarData); }
/// <summary> /// Emit the provided log event to the sink. /// </summary> /// <param name="logEvent">The log event to write.</param> public void Emit(LogEvent logEvent) { if (logEvent == null) { return; } ErrorLevel rollbarLogLevel; switch (logEvent.Level) { case LogEventLevel.Fatal: rollbarLogLevel = ErrorLevel.Critical; break; case LogEventLevel.Error: rollbarLogLevel = ErrorLevel.Error; break; case LogEventLevel.Warning: rollbarLogLevel = ErrorLevel.Warning; break; case LogEventLevel.Information: rollbarLogLevel = ErrorLevel.Info; break; case LogEventLevel.Verbose: case LogEventLevel.Debug: default: rollbarLogLevel = ErrorLevel.Debug; break; } string message = logEvent.RenderMessage(this._formatProvider); DTOs.Body rollbarBody = null; if (logEvent.Exception != null) { rollbarBody = new DTOs.Body(logEvent.Exception); } else { rollbarBody = new DTOs.Body(new DTOs.Message(message)); } int customCapacity = 1; if (logEvent.Properties != null) { customCapacity += logEvent.Properties.Count; } if (logEvent.Exception != null) { customCapacity++; } IDictionary <string, object> custom = new Dictionary <string, object>(customCapacity); if (logEvent.Exception != null) { custom["Serilog.LogEvent.RenderedMessage"] = message; } if (logEvent.Properties != null) { foreach (var property in logEvent.Properties) { custom[property.Key] = property.Value.ToString(); } } custom["Serilog.LogEvent.Timestamp"] = logEvent.Timestamp; DTOs.Data rollbarData = new DTOs.Data(this._rollbarConfig, rollbarBody, custom) { Level = rollbarLogLevel }; this.ReportToRollbar(rollbarData); }
/// <summary> /// Invokes this middleware instance on the specified context. /// </summary> /// <param name="context">The context.</param> /// <returns>A middleware invocation/execution task.</returns> public async Task Invoke(HttpContext context) { // as we learned from a field issue, apparently a middleware can even be invoked without a valid HttPContext: string requestId = null; requestId = context?.Features? .Get <IHttpRequestIdentifierFeature>()? .TraceIdentifier; using (_logger.BeginScope($"Request: {requestId ?? string.Empty}")) { NetworkTelemetry networkTelemetry = null; try { if (TelemetryCollector.Instance.IsAutocollecting && context != null && context.Request != null) { int?telemetryStatusCode = null; telemetryStatusCode = context?.Response?.StatusCode; networkTelemetry = new NetworkTelemetry( method: context.Request.Method, url: context.Request.Host.Value + context.Request.Path, eventStart: DateTime.UtcNow, eventEnd: null, statusCode: telemetryStatusCode ); TelemetryCollector.Instance.Capture(new Telemetry(TelemetrySource.Server, TelemetryLevel.Info, networkTelemetry)); } RollbarScope.Current.HttpContext.HttpAttributes = new RollbarHttpAttributes(context); await this._nextRequestProcessor(context); } catch (System.Exception ex) { if (networkTelemetry != null) { networkTelemetry.StatusCode = context?.Response?.StatusCode.ToString(); networkTelemetry.FinalizeEvent(); } if (!RollbarLocator.RollbarInstance.Config.CaptureUncaughtExceptions) { // just rethrow since the Rollbar SDK is configured not to auto-capture uncaught exceptions: throw ex; } if (RollbarScope.Current != null && RollbarLocator.RollbarInstance.Config.MaxItems > 0 ) { RollbarScope.Current.IncrementLogItemsCount(); if (RollbarScope.Current.LogItemsCount == RollbarLocator.RollbarInstance.Config.MaxItems) { // the Rollbar SDK just reached MaxItems limit, report this fact and pause further logging within this scope: #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed RollbarLocator.RollbarInstance.Warning(RollbarScope.MaxItemsReachedWarning); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed throw ex; } else if (RollbarScope.Current.LogItemsCount > RollbarLocator.RollbarInstance.Config.MaxItems) { // just rethrow since the Rollbar SDK already exceeded MaxItems limit: throw ex; } } else { // let's custom build the Data object that includes the exception // along with the current HTTP request context: DTOs.Data data = new DTOs.Data( config: RollbarLocator.RollbarInstance.Config, body: new DTOs.Body(ex), custom: null, request: (context != null) ? new DTOs.Request(null, context.Request) : null ) { Level = ErrorLevel.Critical, }; // log the Data object (the exception + the HTTP request data): #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed RollbarLocator.RollbarInstance.Log(data); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } throw new System.Exception("The included internal exception processed by the Rollbar middleware", ex); } finally { if (context != null && context.Response != null && RollbarScope.Current != null && RollbarScope.Current.HttpContext != null && RollbarScope.Current.HttpContext.HttpAttributes != null ) { RollbarScope.Current.HttpContext.HttpAttributes.StatusCode = context.Response.StatusCode; } if (networkTelemetry != null) { if (string.IsNullOrWhiteSpace(networkTelemetry.StatusCode)) { networkTelemetry.StatusCode = context?.Response?.StatusCode.ToString(); } networkTelemetry.FinalizeEvent(); } } } }
/// <summary> /// Writes a log entry. /// </summary> /// <typeparam name="TState"></typeparam> /// <param name="logLevel">Entry will be written on this level.</param> /// <param name="eventId">Id of the event.</param> /// <param name="state">The entry to be written. Can be also an object.</param> /// <param name="exception">The exception related to this entry.</param> /// <param name="formatter">Function to create a <c>string</c> message of the <paramref name="state" /> and <paramref name="exception" />.</param> public void Log <TState>( mslogging.LogLevel logLevel , mslogging.EventId eventId , TState state , Exception exception , Func <TState, Exception, string> formatter ) { if (!this.IsEnabled(logLevel)) { return; } if (state == null && exception == null) { return; } if (RollbarScope.Current != null && RollbarLocator.RollbarInstance.Config.MaxItems > 0 ) { RollbarScope.Current.IncrementLogItemsCount(); if (RollbarScope.Current.LogItemsCount == RollbarLocator.RollbarInstance.Config.MaxItems) { // the Rollbar SDK just reached MaxItems limit, report this fact and pause further logging within this scope: RollbarLocator.RollbarInstance.Warning(RollbarScope.MaxItemsReachedWarning); return; } else if (RollbarScope.Current.LogItemsCount > RollbarLocator.RollbarInstance.Config.MaxItems) { // the Rollbar SDK already exceeded MaxItems limit, do not log for this scope: return; } } // let's custom build the Data object that includes the exception // along with the current HTTP request context: string message = null; if (formatter != null) { message = formatter(state, exception); } Rollbar.DTOs.Body payloadBody = null; if (exception != null) { payloadBody = new DTOs.Body(exception); } else if (!string.IsNullOrWhiteSpace(message)) { payloadBody = new DTOs.Body(new DTOs.Message(message)); } else { return; //nothing to report... } Dictionary <string, object> customProperties = new Dictionary <string, object>(); customProperties.Add( "LogEventID" , $"{eventId.Id}" + (string.IsNullOrWhiteSpace(eventId.Name) ? string.Empty : $" ({eventId.Name})") ); if (exception != null && message != null) { customProperties.Add("LogMessage", message); } var currentContext = GetCurrentContext(); Dictionary <string, object> customRequestFields = null; if (currentContext != null) { customRequestFields = new Dictionary <string, object>(); customRequestFields.Add("httpRequestTimestamp", currentContext.Timestamp); if (currentContext.HttpAttributes != null) { customRequestFields.Add("httpRequestID", currentContext.HttpAttributes.RequestID); customRequestFields.Add("statusCode", currentContext.HttpAttributes.StatusCode); customRequestFields.Add("scheme", currentContext.HttpAttributes.Scheme); customRequestFields.Add("protocol", currentContext.HttpAttributes.Protocol); } } var requestDto = new DTOs.Request(customRequestFields, currentContext?.HttpAttributes); DTOs.Data dataDto = new DTOs.Data( config: RollbarLocator.RollbarInstance.Config , body: payloadBody , custom: customProperties , request: requestDto ) { Level = RollbarLogger.Convert(logLevel), }; // log the Data object (the exception + the HTTP request data): RollbarLocator.RollbarInstance.Log(dataDto); }
/// <summary> /// Writes a log entry. /// </summary> /// <typeparam name="TState"></typeparam> /// <param name="logLevel">Entry will be written on this level.</param> /// <param name="eventId">Id of the event.</param> /// <param name="state">The entry to be written. Can be also an object.</param> /// <param name="exception">The exception related to this entry.</param> /// <param name="formatter">Function to create a <c>string</c> message of the <paramref name="state" /> and <paramref name="exception" />.</param> public void Log <TState>( mslogging.LogLevel logLevel , mslogging.EventId eventId , TState state , Exception exception , Func <TState, Exception, string> formatter ) { if (!this.IsEnabled(logLevel)) { return; } if (state == null && exception == null) { return; } // let's custom build the Data object that includes the exception // along with the current HTTP request context: string message = null; if (formatter != null) { message = formatter(state, exception); } Rollbar.DTOs.Body payloadBody = null; if (!string.IsNullOrWhiteSpace(message)) { payloadBody = new DTOs.Body(new DTOs.Message(message)); } else { payloadBody = new DTOs.Body(exception); } Dictionary <string, object> customProperties = new Dictionary <string, object>(); customProperties.Add( "LogEventID" , $"{eventId.Id}" + (string.IsNullOrWhiteSpace(eventId.Name) ? string.Empty : $" ({eventId.Name})") ); if (exception != null && message != null) { customProperties.Add("LogMessage", message); } var currentContext = GetCurrentContext(); Dictionary <string, object> customRequestFields = null; if (currentContext != null) { customRequestFields = new Dictionary <string, object>(); customRequestFields.Add("httpRequestTimestamp", currentContext.Timestamp); if (currentContext.HttpAttributes != null) { customRequestFields.Add("httpRequestID", currentContext.HttpAttributes.RequestID); customRequestFields.Add("statusCode", currentContext.HttpAttributes.StatusCode); customRequestFields.Add("scheme", currentContext.HttpAttributes.Scheme); customRequestFields.Add("protocol", currentContext.HttpAttributes.Protocol); } } var requestDto = new DTOs.Request(customRequestFields, currentContext?.HttpAttributes); DTOs.Data dataDto = new DTOs.Data( config: RollbarLocator.RollbarInstance.Config , body: payloadBody , custom: customProperties , request: requestDto ) { Level = RollbarLogger.Convert(logLevel), }; // log the Data object (the exception + the HTTP request data): RollbarLocator.RollbarInstance.Log(dataDto); }
/// <summary> /// Invokes this middleware instance on the specified context. /// </summary> /// <param name="context">The context.</param> /// <returns>A middleware invocation/execution task.</returns> public async Task Invoke(HttpContext context) { // as we learned from a field issue, apparently a middleware can even be invoked without a valid HttPContext: string requestId = null; requestId = context?.Features? .Get <IHttpRequestIdentifierFeature>()? .TraceIdentifier; using (_logger.BeginScope($"Request: {requestId ?? string.Empty}")) { try { RollbarScope.Current.HttpContext.HttpAttributes = new RollbarHttpAttributes(context); await this._nextRequestProcessor(context); } catch (Exception ex) { if (!RollbarLocator.RollbarInstance.Config.CaptureUncaughtExceptions) { // just rethrow since the Rollbar SDK is configured not to auto-capture uncaught exceptions: throw ex; } if (RollbarScope.Current != null && RollbarLocator.RollbarInstance.Config.MaxItems > 0 ) { RollbarScope.Current.IncrementLogItemsCount(); if (RollbarScope.Current.LogItemsCount == RollbarLocator.RollbarInstance.Config.MaxItems) { // the Rollbar SDK just reached MaxItems limit, report this fact and pause further logging within this scope: RollbarLocator.RollbarInstance.Warning(RollbarScope.MaxItemsReachedWarning); throw ex; } else if (RollbarScope.Current.LogItemsCount > RollbarLocator.RollbarInstance.Config.MaxItems) { // just rethrow since the Rollbar SDK already exceeded MaxItems limit: throw ex; } } else { // let's custom build the Data object that includes the exception // along with the current HTTP request context: DTOs.Data data = new DTOs.Data( config: RollbarLocator.RollbarInstance.Config, body: new DTOs.Body(ex), custom: null, request: (context != null) ? new DTOs.Request(null, context.Request) : null ) { Level = ErrorLevel.Critical, }; // log the Data object (the exception + the HTTP request data): RollbarLocator.RollbarInstance.Log(data); } throw new Exception("The included internal exception processed by the Rollbar middleware", ex); } finally { if (context != null && context.Response != null) { RollbarScope.Current.HttpContext.HttpAttributes.StatusCode = context.Response.StatusCode; } } } }