/// <summary> /// Populates fields on the GELF message that correspond to the properties of the /// <see cref="DiagnosticEvent.Message"/> /// </summary> /// <param name="gelfMessage">The GELF message to populate</param> /// <param name="event">The diagnostic event</param> protected virtual void PopulateMessageFields(GelfMessage gelfMessage, DiagnosticEvent @event) { if (@event.Message == null) { return; } var headers = @event.Message.Headers; gelfMessage.MessageId = headers.MessageId; gelfMessage.MessageName = headers.MessageName; gelfMessage.RelatedTo = headers.RelatedTo == default(MessageId) ? null : headers.MessageId.ToString(); if (headers.Origination != null) { gelfMessage.Origination = headers.Origination.ToString(); } if (headers.Destination != null) { gelfMessage.Destination = headers.Destination.ToString(); } if (headers.ReplyTo != null) { gelfMessage.Destination = headers.ReplyTo.ToString(); } }
/// <inheritdoc /> public void Consume(DiagnosticEvent @event) { if (_specification.IsSatisfiedBy(@event)) { Inner.Consume(@event); } }
/// <inheritdoc /> public Task ConsumeAsync(DiagnosticEvent @event, CancellationToken cancellationToken = default(CancellationToken)) { _consume(@event); #if NETSTANDARD2_0 || NET461 return(Task.CompletedTask); #endif #if NET452 return(Task.FromResult(false)); #endif }
/// <inheritdoc /> public void Consume(DiagnosticEvent @event) { var gelfMessage = new GelfMessage(); PopulateGelfMessage(gelfMessage, @event); var json = JsonConvert.SerializeObject(gelfMessage, _jsonSerializerSettings); Process(json); // Allow exceptions to propagate to the IDiagnosticService where they will be caught // and handled by registered DiagnosticSinkExceptionHandlers }
/// <inheritdoc /> public async Task ConsumeAsync(DiagnosticEvent @event, CancellationToken cancellationToken = new CancellationToken()) { var gelfMessage = new GelfMessage(); PopulateGelfMessage(gelfMessage, @event); var json = JsonConvert.SerializeObject(gelfMessage, _jsonSerializerSettings); await ProcessAsync(json, cancellationToken); // Allow exceptions to propagate to the IDiagnosticService where they will be caught // and handled by registered DiagnosticSinkExceptionHandlers }
/// <inheritdoc /> public void Emit(DiagnosticEvent @event) { var myConsumers = _consumers; foreach (var sink in myConsumers) { try { sink.Consume(@event); } catch (Exception ex) { RaiseExceptionEvent(@event, sink, ex); } } }
/// <summary> /// Safely raises the <see cref="Exception"/> event to invoke registered /// <see cref="DiagnosticSinkExceptionHandler"/> delegates /// </summary> /// <remarks> /// Exceptions thrown from <see cref="DiagnosticSinkExceptionHandler"/> delegates are /// swallowed and ignored. /// </remarks> /// <param name="event">The diagnostic event that was being consumed at the time the /// exception occurred</param> /// <param name="sink">The sink from which the unhandled exception was caught</param> /// <param name="ex">The unhandled exception</param> protected void RaiseExceptionEvent(DiagnosticEvent @event, IDiagnosticEventSink sink, Exception ex) { try { var handlers = Exception; if (handlers == null) { return; } var args = new DiagnosticSinkExceptionEventArgs(@event, sink, ex); handlers(this, args); } catch (Exception) { // Ignored } }
/// <inheritdoc /> public Task EmitAsync(DiagnosticEvent @event, CancellationToken cancellationToken = new CancellationToken()) { try { var receiveTasks = _consumers.Select(async sink => { try { await sink.ConsumeAsync(@event, cancellationToken); } catch (Exception ex) { RaiseExceptionEvent(@event, sink, ex); } }); return(Task.WhenAll(receiveTasks)); } catch (Exception) { // Ignored } return(Task.FromResult(0)); }
/// <summary> /// Sets the standard and common additional GELF fields with values from the specified /// diagnostic <paramref name="event"/>. /// </summary> /// <param name="gelfMessage">The GELF message to populate</param> /// <param name="event">The diagnostic event</param> /// <returns>The GELF formatted string</returns> protected virtual void PopulateGelfMessage(GelfMessage gelfMessage, DiagnosticEvent @event) { var source = @event.Source; gelfMessage.Facility = source == null ? "Platibus" : source.GetType().FullName; gelfMessage.Level = GetSyslogLevel(@event.Type.Level); gelfMessage.Timestamp = @event.Timestamp; gelfMessage.EventType = @event.Type; gelfMessage.Queue = @event.Queue; gelfMessage.Topic = @event.Topic; if (MessageTooLong(@event.Detail, out string shortMessage)) { gelfMessage.ShortMessage = shortMessage; gelfMessage.FullMessage = @event.Detail; } else { gelfMessage.ShortMessage = @event.Detail; } if (string.IsNullOrWhiteSpace(gelfMessage.ShortMessage)) { // Short message is required. Default to the event type. gelfMessage.ShortMessage = @event.Type; } if (@event.Exception != null) { gelfMessage.Exception = @event.Exception.ToString(); } PopulateMessageFields(gelfMessage, @event); PopulateHttpFields(gelfMessage, @event as HttpEvent); PopulateFilesystemFields(gelfMessage, @event as FilesystemEvent); }
/// <summary> /// Formats the log message /// </summary> /// <param name="event">The diagnostic event</param> /// <returns>Returns a formatted log message</returns> protected virtual string FormatLogMessage(DiagnosticEvent @event) { var source = @event.Source; var timestamp = @event.Timestamp.ToString("s"); var level = @event.Type.Level.ToString("G"); var category = source == null ? "Platibus" : source.GetType().FullName; var message = timestamp + " " + level + " " + category + " " + @event.Type.Name; if (@event.Detail != null) { message += ": " + @event.Detail; } var fields = new OrderedDictionary(); if (@event.Message != null) { var headers = @event.Message.Headers; fields["MessageId"] = headers.MessageId; fields["Origination"] = headers.Origination; fields["Destination"] = headers.Destination; } fields["Queue"] = @event.Queue; fields["Topic"] = @event.Topic; var fieldsStr = string.Join("; ", fields .OfType <DictionaryEntry>() .Where(f => f.Value != null) .Select(f => f.Key + "=" + f.Value)); if (!string.IsNullOrWhiteSpace(fieldsStr)) { message += " (" + fieldsStr + ")"; } return(message); }
/// <inheritdoc /> public Task ConsumeAsync(DiagnosticEvent @event, CancellationToken cancellationToken = new CancellationToken()) { return(_specification.IsSatisfiedBy(@event) ? Inner.ConsumeAsync(@event, cancellationToken) : Task.FromResult(0)); }
/// <inheritdoc /> public Task ConsumeAsync(DiagnosticEvent @event, CancellationToken cancellationToken = new CancellationToken()) { return(_writer.WriteLineAsync(FormatLogMessage(@event))); // Allow exceptions to propagate to the IDiagnosticService where they will be caught // and handled by registered DiagnosticSinkExceptionHandlers }
private void IncrementCounters(DiagnosticEvent @event) { switch (@event.Type.Level) { case DiagnosticEventLevel.Error: Interlocked.Increment(ref _fields.Errors); break; case DiagnosticEventLevel.Warn: Interlocked.Increment(ref _fields.Warnings); break; } if (@event.Type == HttpEventType.HttpRequestReceived) { Interlocked.Increment(ref _fields.Requests); } else if (@event.Type == DiagnosticEventType.MessageReceived) { Interlocked.Increment(ref _fields.Received); } else if (@event.Type == DiagnosticEventType.MessageAcknowledged) { Interlocked.Increment(ref _fields.Acknowledgements); } else if (@event.Type == DiagnosticEventType.MessageNotAcknowledged) { Interlocked.Increment(ref _fields.AcknowledgementFailures); } else if (@event.Type == DiagnosticEventType.MessageSent) { Interlocked.Increment(ref _fields.Sent); } else if (@event.Type == DiagnosticEventType.MessagePublished) { Interlocked.Increment(ref _fields.Published); } else if (@event.Type == DiagnosticEventType.MessageDelivered) { Interlocked.Increment(ref _fields.Delivered); } else if (@event.Type == DiagnosticEventType.MessageDeliveryFailed) { Interlocked.Increment(ref _fields.DeliveryFailures); } else if (@event.Type == DiagnosticEventType.MessageExpired) { Interlocked.Increment(ref _fields.Expired); } else if (@event.Type == DiagnosticEventType.DeadLetter) { Interlocked.Increment(ref _fields.Dead); } bool takeMeasurement; lock (_syncRoot) { takeMeasurement = DateTime.UtcNow >= _nextMeasurement; if (takeMeasurement) { _nextMeasurement += _sampleRate; } } if (takeMeasurement) { RecordMeasurements(); } }
/// <inheritdoc /> public Task ConsumeAsync(DiagnosticEvent @event, CancellationToken cancellationToken = new CancellationToken()) { IncrementCounters(@event); return(Task.FromResult(0)); }
/// <inheritdoc /> public void Consume(DiagnosticEvent @event) { IncrementCounters(@event); }
/// <summary> /// Initializes a new <see cref="DiagnosticSinkExceptionEventArgs"/> /// </summary> /// <param name="diagnosticEvent">The event being handled</param> /// <param name="diagnosticEventSink">The data sink from which the exception was thrown</param> /// <param name="exception">The unhandled exception</param> public DiagnosticSinkExceptionEventArgs(DiagnosticEvent diagnosticEvent, IDiagnosticEventSink diagnosticEventSink, Exception exception) { DiagnosticEvent = diagnosticEvent; DiagnosticEventSink = diagnosticEventSink; Exception = exception; }
/// <inheritdoc /> public void Consume(DiagnosticEvent @event) { _writer.WriteLine(FormatLogMessage(@event)); // Allow exceptions to propagate to the IDiagnosticService where they will be caught // and handled by registered DiagnosticSinkExceptionHandlers }
/// <inheritdoc /> public void Consume(DiagnosticEvent @event) { _consume(@event); }