diff --git a/src/DotNetCore.CAP/Diagnostics/DiagnosticListenerExtensions.cs b/src/DotNetCore.CAP/Diagnostics/DiagnosticListenerExtensions.cs new file mode 100644 index 0000000..b9b5ba4 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/DiagnosticListenerExtensions.cs @@ -0,0 +1,250 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using DotNetCore.CAP.Internal; +using DotNetCore.CAP.Models; + +namespace DotNetCore.CAP.Diagnostics +{ + /// + /// Extension methods on the DiagnosticListener class to log CAP data + /// + public static class CapDiagnosticListenerExtensions + { + public const string DiagnosticListenerName = "CapDiagnosticListener"; + + private const string CapPrefix = "DotNetCore.CAP."; + + public const string CapBeforePublishMessageStore = CapPrefix + nameof(WritePublishMessageStoreBefore); + public const string CapAfterPublishMessageStore = CapPrefix + nameof(WritePublishMessageStoreAfter); + public const string CapErrorPublishMessageStore = CapPrefix + nameof(WritePublishMessageStoreError); + + public const string CapBeforePublish = CapPrefix + nameof(WritePublishBefore); + public const string CapAfterPublish = CapPrefix + nameof(WritePublishAfter); + public const string CapErrorPublish = CapPrefix + nameof(WritePublishError); + + public const string CapBeforeReceiveMessageStore = CapPrefix + nameof(WriteReceiveMessageStoreBefore); + public const string CapAfterReceiveMessageStore = CapPrefix + nameof(WriteReceiveMessageStoreAfter); + public const string CapErrorReceiveMessageStore = CapPrefix + nameof(WriteReceiveMessageStoreError); + + public const string CapBeforeConsumerInvoke = CapPrefix + nameof(WriteConsumerInvokeBefore); + public const string CapAfterConsumerInvoke = CapPrefix + nameof(WriteConsumerInvokeAfter); + public const string CapErrorConsumerInvoke = CapPrefix + nameof(WriteConsumerInvokeError); + + public static Guid WritePublishMessageStoreBefore(this DiagnosticListener @this, + CapPublishedMessage message, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapBeforePublishMessageStore)) + { + Guid operationId = Guid.NewGuid(); + + @this.Write(CapBeforePublishMessageStore, new + { + OperationId = operationId, + Operation = operation, + MessageName = message.Name, + MessageContent = message.Content + }); + + return operationId; + } + return Guid.Empty; + } + + public static void WritePublishMessageStoreAfter(this DiagnosticListener @this, + Guid operationId, + CapPublishedMessage message, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapAfterPublishMessageStore)) + { + @this.Write(CapAfterPublishMessageStore, new + { + OperationId = operationId, + Operation = operation, + MessageId = message.Id, + MessageName = message.Name, + MessageContent = message.Content, + Timestamp = Stopwatch.GetTimestamp() + }); + } + } + + public static void WritePublishMessageStoreError(this DiagnosticListener @this, + Guid operationId, + CapPublishedMessage message, + Exception ex, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapErrorPublishMessageStore)) + { + @this.Write(CapErrorPublishMessageStore, new + { + OperationId = operationId, + Operation = operation, + MessageName = message.Name, + MessageContent = message.Content, + Exception = ex, + Timestamp = Stopwatch.GetTimestamp() + }); + } + } + + public static Guid WritePublishBefore(this DiagnosticListener @this, + string topic, + string body, + string brokerAddress, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapBeforePublish)) + { + Guid operationId = Guid.NewGuid(); + + @this.Write(CapBeforePublish, new BrokerPublishEventData(operationId, operation, brokerAddress, topic, body, DateTimeOffset.UtcNow)); + + return operationId; + } + return Guid.Empty; + } + + public static void WritePublishAfter(this DiagnosticListener @this, + Guid operationId, + string topic, + string body, + string brokerAddress, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapAfterPublish)) + { + @this.Write(CapAfterPublish, new BrokerPublishEndEventData(operationId, operation, brokerAddress, topic, body, startTime, duration)); + } + } + + public static void WritePublishError(this DiagnosticListener @this, + Guid operationId, + string topic, + string body, + string brokerAddress, + Exception ex, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapErrorPublish)) + { + @this.Write(CapErrorPublish, new BrokerPublishErrorEventData(operationId, operation, brokerAddress, topic, body, ex, startTime, duration)); + } + } + + public static Guid WriteReceiveMessageStoreBefore(this DiagnosticListener @this, + string topic, + string body, + string groupName, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapBeforeReceiveMessageStore)) + { + Guid operationId = Guid.NewGuid(); + + @this.Write(CapBeforePublish, new BrokerConsumeEventData(operationId, operation, groupName, topic, body, DateTimeOffset.UtcNow)); + + return operationId; + } + return Guid.Empty; + } + + public static void WriteReceiveMessageStoreAfter(this DiagnosticListener @this, + Guid operationId, + string topic, + string body, + string groupName, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapAfterReceiveMessageStore)) + { + @this.Write(CapAfterPublish, new BrokerConsumeEndEventData(operationId, operation, groupName, topic, body, startTime, duration)); + } + } + + public static void WriteReceiveMessageStoreError(this DiagnosticListener @this, + Guid operationId, + string topic, + string body, + string groupName, + Exception ex, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapErrorReceiveMessageStore)) + { + @this.Write(CapErrorPublish, new BrokerConsumeErrorEventData(operationId, operation, groupName, topic, body, ex, startTime, duration)); + } + } + + public static Guid WriteConsumerInvokeBefore(this DiagnosticListener @this, + ConsumerContext context, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapBeforeConsumerInvoke)) + { + Guid operationId = Guid.NewGuid(); + + var methodName = context.ConsumerDescriptor.MethodInfo.Name; + var subscribeName = context.ConsumerDescriptor.Attribute.Name; + var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; + var parameterValues = context.DeliverMessage.Content; + + @this.Write(CapBeforePublish, new SubscriberInvokeEventData(operationId, operation, methodName, subscribeName, + subscribeGroup, parameterValues, DateTimeOffset.UtcNow)); + + return operationId; + } + return Guid.Empty; + } + + public static void WriteConsumerInvokeAfter(this DiagnosticListener @this, + Guid operationId, + ConsumerContext context, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapAfterConsumerInvoke)) + { + var methodName = context.ConsumerDescriptor.MethodInfo.Name; + var subscribeName = context.ConsumerDescriptor.Attribute.Name; + var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; + var parameterValues = context.DeliverMessage.Content; + + @this.Write(CapBeforePublish, new SubscriberInvokeEndEventData(operationId, operation, methodName, subscribeName, + subscribeGroup, parameterValues, startTime, duration)); + } + } + + public static void WriteConsumerInvokeError(this DiagnosticListener @this, + Guid operationId, + ConsumerContext context, + Exception ex, + DateTimeOffset startTime, + TimeSpan duration, + [CallerMemberName] string operation = "") + { + if (@this.IsEnabled(CapErrorConsumerInvoke)) + { + var methodName = context.ConsumerDescriptor.MethodInfo.Name; + var subscribeName = context.ConsumerDescriptor.Attribute.Name; + var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; + var parameterValues = context.DeliverMessage.Content; + + @this.Write(CapBeforePublish, new SubscriberInvokeErrorEventData(operationId, operation, methodName, subscribeName, + subscribeGroup, parameterValues, ex, startTime, duration)); + } + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Consume.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Consume.cs new file mode 100644 index 0000000..c6e7454 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Consume.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerConsumeEventData : BrokerEventData + { + public DateTimeOffset StartTime { get; } + + public BrokerConsumeEventData(Guid operationId, string operation, string groupName, + string brokerTopicName, string brokerTopicBody, DateTimeOffset startTime) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody) + { + StartTime = startTime; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeEnd.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeEnd.cs new file mode 100644 index 0000000..e6bbba9 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeEnd.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerConsumeEndEventData : BrokerConsumeEventData + { + public TimeSpan Duration { get; } + + public BrokerConsumeEndEventData(Guid operationId, string operation, string groupName, string brokerTopicName, + string brokerTopicBody, DateTimeOffset startTime, TimeSpan duration) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody, startTime) + { + Duration = duration; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeError.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeError.cs new file mode 100644 index 0000000..36c1300 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.ConsumeError.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerConsumeErrorEventData : BrokerConsumeEndEventData, IErrorEventData + { + public Exception Exception { get; } + + public BrokerConsumeErrorEventData(Guid operationId, string operation, string groupName, + string brokerTopicName, string brokerTopicBody, Exception exception, DateTimeOffset startTime, TimeSpan duration) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody, startTime, duration) + { + Exception = exception; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Publish.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Publish.cs new file mode 100644 index 0000000..b7f904b --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.Publish.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerPublishEventData : BrokerEventData + { + public DateTimeOffset StartTime { get; } + + public BrokerPublishEventData(Guid operationId, string operation, string groupName, + string brokerTopicName, string brokerTopicBody, DateTimeOffset startTime) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody) + { + StartTime = startTime; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishEnd.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishEnd.cs new file mode 100644 index 0000000..e415647 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishEnd.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerPublishEndEventData : BrokerPublishEventData + { + public TimeSpan Duration { get; } + + public BrokerPublishEndEventData(Guid operationId, string operation, string groupName, string brokerTopicName, + string brokerTopicBody, DateTimeOffset startTime, TimeSpan duration) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody, startTime) + { + Duration = duration; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishError.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishError.cs new file mode 100644 index 0000000..fa4f8cb --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.PublishError.cs @@ -0,0 +1,16 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerPublishErrorEventData : BrokerPublishEndEventData, IErrorEventData + { + public Exception Exception { get; } + + public BrokerPublishErrorEventData(Guid operationId, string operation, string groupName, + string brokerTopicName, string brokerTopicBody, Exception exception, DateTimeOffset startTime, TimeSpan duration) + : base(operationId, operation, groupName, brokerTopicName, brokerTopicBody, startTime, duration) + { + Exception = exception; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Broker.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.cs new file mode 100644 index 0000000..eef7ac1 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.Broker.cs @@ -0,0 +1,22 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class BrokerEventData : EventData + { + public string GroupName { get; set; } + + public string BrokerTopicBody { get; set; } + + public string BrokerTopicName { get; set; } + + public BrokerEventData(Guid operationId, string operation, string groupName, + string brokerTopicName, string brokerTopicBody) + : base(operationId, operation) + { + GroupName = groupName; + BrokerTopicName = brokerTopicName; + BrokerTopicBody = brokerTopicBody; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvoke.cs b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvoke.cs new file mode 100644 index 0000000..021fff9 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvoke.cs @@ -0,0 +1,33 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class SubscriberInvokeEventData : EventData + { + public DateTimeOffset StartTime { get; } + + public string MethodName { get; set; } + + public string SubscribeName { get; set; } + + public string SubscribeGroup { get; set; } + + public string ParameterValues { get; set; } + + public SubscriberInvokeEventData(Guid operationId, + string operation, + string methodName, + string subscribeName, + string subscribeGroup, + string parameterValues, + DateTimeOffset startTime) + : base(operationId, operation) + { + MethodName = methodName; + SubscribeName = subscribeName; + SubscribeGroup = subscribeGroup; + ParameterValues = parameterValues; + StartTime = startTime; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeEnd.cs b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeEnd.cs new file mode 100644 index 0000000..38358a7 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeEnd.cs @@ -0,0 +1,17 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class SubscriberInvokeEndEventData : SubscriberInvokeEventData + { + public TimeSpan Duration { get; } + + public SubscriberInvokeEndEventData(Guid operationId, string operation, + string methodName, string subscribeName, string subscribeGroup, + string parameterValues, DateTimeOffset startTime, TimeSpan duration) + : base(operationId, operation, methodName, subscribeName, subscribeGroup, parameterValues, startTime) + { + Duration = duration; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeError.cs b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeError.cs new file mode 100644 index 0000000..be7a361 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.SubscriberInvokeError.cs @@ -0,0 +1,17 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class SubscriberInvokeErrorEventData : SubscriberInvokeEndEventData, IErrorEventData + { + public Exception Exception { get; } + + public SubscriberInvokeErrorEventData(Guid operationId, string operation, string methodName, + string subscribeName, string subscribeGroup, string parameterValues, Exception exception, + DateTimeOffset startTime, TimeSpan duration) : base(operationId, operation, methodName, subscribeName, + subscribeGroup, parameterValues, startTime, duration) + { + Exception = exception; + } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.cs b/src/DotNetCore.CAP/Diagnostics/EventData.cs new file mode 100644 index 0000000..94c01b8 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/EventData.cs @@ -0,0 +1,17 @@ +using System; + +namespace DotNetCore.CAP.Diagnostics +{ + public class EventData + { + public EventData(Guid operationId, string operation) + { + OperationId = operationId; + Operation = operation; + } + + public Guid OperationId { get; set; } + + public string Operation { get; set; } + } +} diff --git a/src/DotNetCore.CAP/Diagnostics/IErrorEventData.cs b/src/DotNetCore.CAP/Diagnostics/IErrorEventData.cs new file mode 100644 index 0000000..56c2278 --- /dev/null +++ b/src/DotNetCore.CAP/Diagnostics/IErrorEventData.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DotNetCore.CAP.Diagnostics +{ + public interface IErrorEventData + { + Exception Exception { get; } + } +}