Commit 79e08d78 authored by Savorboard's avatar Savorboard

Add support for Diganostics

parent 5e71b8cd
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
// Licensed under the MIT License. See License.txt in the project root for license information. // Licensed under the MIT License. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotNetCore.CAP.Diagnostics;
using DotNetCore.CAP.Internal; using DotNetCore.CAP.Internal;
using DotNetCore.CAP.Processor.States; using DotNetCore.CAP.Processor.States;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
...@@ -16,7 +14,6 @@ namespace DotNetCore.CAP.Kafka ...@@ -16,7 +14,6 @@ namespace DotNetCore.CAP.Kafka
{ {
private readonly IConnectionPool _connectionPool; private readonly IConnectionPool _connectionPool;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly string _serversAddress;
public KafkaPublishMessageSender( public KafkaPublishMessageSender(
CapOptions options, IStateChanger stateChanger, IStorageConnection connection, CapOptions options, IStateChanger stateChanger, IStorageConnection connection,
...@@ -25,21 +22,15 @@ namespace DotNetCore.CAP.Kafka ...@@ -25,21 +22,15 @@ namespace DotNetCore.CAP.Kafka
{ {
_logger = logger; _logger = logger;
_connectionPool = connectionPool; _connectionPool = connectionPool;
_serversAddress = _connectionPool.ServersAddress; ServersAddress = _connectionPool.ServersAddress;
} }
public override async Task<OperateResult> PublishAsync(string keyName, string content) public override async Task<OperateResult> PublishAsync(string keyName, string content)
{ {
var startTime = DateTimeOffset.UtcNow;
var stopwatch = Stopwatch.StartNew();
Guid operationId = Guid.Empty;
var producer = _connectionPool.Rent(); var producer = _connectionPool.Rent();
try try
{ {
operationId = s_diagnosticListener.WritePublishBefore(keyName, content, _serversAddress);
var contentBytes = Encoding.UTF8.GetBytes(content); var contentBytes = Encoding.UTF8.GetBytes(content);
var message = await producer.ProduceAsync(keyName, null, contentBytes); var message = await producer.ProduceAsync(keyName, null, contentBytes);
...@@ -52,16 +43,12 @@ namespace DotNetCore.CAP.Kafka ...@@ -52,16 +43,12 @@ namespace DotNetCore.CAP.Kafka
}); });
} }
s_diagnosticListener.WritePublishAfter(operationId, message.Topic, content, _serversAddress, startTime, stopwatch.Elapsed);
_logger.LogDebug($"kafka topic message [{keyName}] has been published."); _logger.LogDebug($"kafka topic message [{keyName}] has been published.");
return OperateResult.Success; return OperateResult.Success;
} }
catch (Exception ex) catch (Exception ex)
{ {
s_diagnosticListener.WritePublishError(operationId, keyName, content, _serversAddress, ex, startTime, stopwatch.Elapsed);
var wapperEx = new PublisherSentFailedException(ex.Message, ex); var wapperEx = new PublisherSentFailedException(ex.Message, ex);
return OperateResult.Failed(wapperEx); return OperateResult.Failed(wapperEx);
...@@ -74,7 +61,6 @@ namespace DotNetCore.CAP.Kafka ...@@ -74,7 +61,6 @@ namespace DotNetCore.CAP.Kafka
producer.Dispose(); producer.Dispose();
} }
} }
} }
} }
} }
\ No newline at end of file
...@@ -29,6 +29,8 @@ namespace DotNetCore.CAP.Kafka ...@@ -29,6 +29,8 @@ namespace DotNetCore.CAP.Kafka
public event EventHandler<LogMessageEventArgs> OnLog; public event EventHandler<LogMessageEventArgs> OnLog;
public string ServersAddress => _kafkaOptions.Servers;
public void Subscribe(IEnumerable<string> topics) public void Subscribe(IEnumerable<string> topics)
{ {
if (topics == null) if (topics == null)
......
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
// Licensed under the MIT License. See License.txt in the project root for license information. // Licensed under the MIT License. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotNetCore.CAP.Diagnostics;
using DotNetCore.CAP.Internal; using DotNetCore.CAP.Internal;
using DotNetCore.CAP.Processor.States; using DotNetCore.CAP.Processor.States;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
...@@ -18,7 +16,6 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -18,7 +16,6 @@ namespace DotNetCore.CAP.RabbitMQ
private readonly IConnectionChannelPool _connectionChannelPool; private readonly IConnectionChannelPool _connectionChannelPool;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly string _exchange; private readonly string _exchange;
private readonly string _hostAddress;
public RabbitMQPublishMessageSender(ILogger<RabbitMQPublishMessageSender> logger, CapOptions options, public RabbitMQPublishMessageSender(ILogger<RabbitMQPublishMessageSender> logger, CapOptions options,
IStorageConnection connection, IConnectionChannelPool connectionChannelPool, IStateChanger stateChanger) IStorageConnection connection, IConnectionChannelPool connectionChannelPool, IStateChanger stateChanger)
...@@ -27,33 +24,24 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -27,33 +24,24 @@ namespace DotNetCore.CAP.RabbitMQ
_logger = logger; _logger = logger;
_connectionChannelPool = connectionChannelPool; _connectionChannelPool = connectionChannelPool;
_exchange = _connectionChannelPool.Exchange; _exchange = _connectionChannelPool.Exchange;
_hostAddress = _connectionChannelPool.HostAddress; ServersAddress = _connectionChannelPool.HostAddress;
} }
public override Task<OperateResult> PublishAsync(string keyName, string content) public override Task<OperateResult> PublishAsync(string keyName, string content)
{ {
var startTime = DateTimeOffset.UtcNow;
var stopwatch = Stopwatch.StartNew();
Guid operationId = Guid.Empty;
var channel = _connectionChannelPool.Rent(); var channel = _connectionChannelPool.Rent();
try try
{ {
operationId = s_diagnosticListener.WritePublishBefore(keyName, content, _hostAddress);
var body = Encoding.UTF8.GetBytes(content); var body = Encoding.UTF8.GetBytes(content);
channel.ExchangeDeclare(_exchange, RabbitMQOptions.ExchangeType, true); channel.ExchangeDeclare(_exchange, RabbitMQOptions.ExchangeType, true);
channel.BasicPublish(_exchange, keyName, null, body); channel.BasicPublish(_exchange, keyName, null, body);
s_diagnosticListener.WritePublishAfter(operationId, keyName, content, _hostAddress, startTime, stopwatch.Elapsed);
_logger.LogDebug($"RabbitMQ topic message [{keyName}] has been published."); _logger.LogDebug($"RabbitMQ topic message [{keyName}] has been published.");
return Task.FromResult(OperateResult.Success); return Task.FromResult(OperateResult.Success);
} }
catch (Exception ex) catch (Exception ex)
{ {
s_diagnosticListener.WritePublishError(operationId, keyName, content, _hostAddress, ex, startTime, stopwatch.Elapsed);
var wapperEx = new PublisherSentFailedException(ex.Message, ex); var wapperEx = new PublisherSentFailedException(ex.Message, ex);
var errors = new OperateError var errors = new OperateError
{ {
......
...@@ -37,6 +37,8 @@ namespace DotNetCore.CAP.RabbitMQ ...@@ -37,6 +37,8 @@ namespace DotNetCore.CAP.RabbitMQ
public event EventHandler<LogMessageEventArgs> OnLog; public event EventHandler<LogMessageEventArgs> OnLog;
public string ServersAddress => _rabbitMQOptions.HostName;
public void Subscribe(IEnumerable<string> topics) public void Subscribe(IEnumerable<string> topics)
{ {
if (topics == null) if (topics == null)
......
...@@ -174,7 +174,7 @@ namespace DotNetCore.CAP.Diagnostics ...@@ -174,7 +174,7 @@ namespace DotNetCore.CAP.Diagnostics
var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; var subscribeGroup = context.ConsumerDescriptor.Attribute.Group;
var parameterValues = context.DeliverMessage.Content; var parameterValues = context.DeliverMessage.Content;
@this.Write(CapBeforePublish, new SubscriberInvokeEventData(operationId, operation, methodName, @this.Write(CapBeforeSubscriberInvoke, new SubscriberInvokeEventData(operationId, operation, methodName,
subscribeName, subscribeName,
subscribeGroup, parameterValues, DateTimeOffset.UtcNow)); subscribeGroup, parameterValues, DateTimeOffset.UtcNow));
...@@ -198,7 +198,7 @@ namespace DotNetCore.CAP.Diagnostics ...@@ -198,7 +198,7 @@ namespace DotNetCore.CAP.Diagnostics
var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; var subscribeGroup = context.ConsumerDescriptor.Attribute.Group;
var parameterValues = context.DeliverMessage.Content; var parameterValues = context.DeliverMessage.Content;
@this.Write(CapBeforePublish, new SubscriberInvokeEndEventData(operationId, operation, methodName, @this.Write(CapAfterSubscriberInvoke, new SubscriberInvokeEndEventData(operationId, operation, methodName,
subscribeName, subscribeName,
subscribeGroup, parameterValues, startTime, duration)); subscribeGroup, parameterValues, startTime, duration));
} }
...@@ -219,7 +219,7 @@ namespace DotNetCore.CAP.Diagnostics ...@@ -219,7 +219,7 @@ namespace DotNetCore.CAP.Diagnostics
var subscribeGroup = context.ConsumerDescriptor.Attribute.Group; var subscribeGroup = context.ConsumerDescriptor.Attribute.Group;
var parameterValues = context.DeliverMessage.Content; var parameterValues = context.DeliverMessage.Content;
@this.Write(CapBeforePublish, new SubscriberInvokeErrorEventData(operationId, operation, methodName, @this.Write(CapErrorSubscriberInvoke, new SubscriberInvokeErrorEventData(operationId, operation, methodName,
subscribeName, subscribeName,
subscribeGroup, parameterValues, ex, startTime, duration)); subscribeGroup, parameterValues, ex, startTime, duration));
} }
......
...@@ -13,6 +13,8 @@ namespace DotNetCore.CAP ...@@ -13,6 +13,8 @@ namespace DotNetCore.CAP
/// </summary> /// </summary>
public interface IConsumerClient : IDisposable public interface IConsumerClient : IDisposable
{ {
string ServersAddress { get; }
/// <summary> /// <summary>
/// Subscribe to a set of topics to the message queue /// Subscribe to a set of topics to the message queue
/// </summary> /// </summary>
......
...@@ -24,6 +24,7 @@ namespace DotNetCore.CAP ...@@ -24,6 +24,7 @@ namespace DotNetCore.CAP
private readonly TimeSpan _pollingDelay = TimeSpan.FromSeconds(1); private readonly TimeSpan _pollingDelay = TimeSpan.FromSeconds(1);
private readonly MethodMatcherCache _selector; private readonly MethodMatcherCache _selector;
private string _serverAddress;
private Task _compositeTask; private Task _compositeTask;
private bool _disposed; private bool _disposed;
...@@ -56,6 +57,8 @@ namespace DotNetCore.CAP ...@@ -56,6 +57,8 @@ namespace DotNetCore.CAP
{ {
using (var client = _consumerClientFactory.Create(matchGroup.Key)) using (var client = _consumerClientFactory.Create(matchGroup.Key))
{ {
_serverAddress = client.ServersAddress;
RegisterMessageProcessor(client); RegisterMessageProcessor(client);
client.Subscribe(matchGroup.Value.Select(x => x.Attribute.Name)); client.Subscribe(matchGroup.Value.Select(x => x.Attribute.Name));
...@@ -102,30 +105,24 @@ namespace DotNetCore.CAP ...@@ -102,30 +105,24 @@ namespace DotNetCore.CAP
{ {
var startTime = DateTimeOffset.UtcNow; var startTime = DateTimeOffset.UtcNow;
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
var operationId = Guid.Empty;
var tracingResult = TracingBefore(messageContext.Name, messageContext.Content);
var operationId = tracingResult.Item1;
var messageBody = tracingResult.Item2;
var receivedMessage = new CapReceivedMessage(messageContext) var receivedMessage = new CapReceivedMessage(messageContext)
{ {
StatusName = StatusName.Scheduled StatusName = StatusName.Scheduled,
Content = messageBody
}; };
try try
{ {
operationId = s_diagnosticListener.WriteReceiveMessageStoreBefore(
messageContext.Name,
messageContext.Content,
messageContext.Group);
StoreMessage(receivedMessage); StoreMessage(receivedMessage);
client.Commit(); client.Commit();
s_diagnosticListener.WriteReceiveMessageStoreAfter( TracingAfter(operationId, receivedMessage.Name, receivedMessage.Content, startTime,
operationId,
messageContext.Name,
messageContext.Content,
messageContext.Group,
startTime,
stopwatch.Elapsed); stopwatch.Elapsed);
_dispatcher.EnqueueToExecute(receivedMessage); _dispatcher.EnqueueToExecute(receivedMessage);
...@@ -136,12 +133,7 @@ namespace DotNetCore.CAP ...@@ -136,12 +133,7 @@ namespace DotNetCore.CAP
client.Reject(); client.Reject();
s_diagnosticListener.WriteReceiveMessageStoreError(operationId, TracingError(operationId, receivedMessage.Name, receivedMessage.Content, e, startTime,
messageContext.Name,
messageContext.Content,
messageContext.Group,
e,
startTime,
stopwatch.Elapsed); stopwatch.Elapsed);
} }
}; };
...@@ -183,5 +175,50 @@ namespace DotNetCore.CAP ...@@ -183,5 +175,50 @@ namespace DotNetCore.CAP
receivedMessage.Id = id; receivedMessage.Id = id;
} }
private (Guid, string) TracingBefore(string topic, string values)
{
Guid operationId = Guid.NewGuid();
var eventData = new BrokerConsumeEventData(
operationId, "",
_serverAddress,
topic,
values,
DateTimeOffset.UtcNow);
s_diagnosticListener.WriteConsumeBefore(eventData);
return (operationId, eventData.BrokerTopicBody);
}
private void TracingAfter(Guid operationId, string topic, string values, DateTimeOffset startTime, TimeSpan du)
{
var eventData = new BrokerConsumeEndEventData(
operationId,
"",
_serverAddress,
topic,
values,
startTime,
du);
s_diagnosticListener.WriteConsumeAfter(eventData);
}
private void TracingError(Guid operationId, string topic, string values, Exception ex, DateTimeOffset startTime, TimeSpan du)
{
var eventData = new BrokerConsumeErrorEventData(
operationId,
"",
_serverAddress,
topic,
values,
ex,
startTime,
du);
s_diagnosticListener.WriteConsumeError(eventData);
}
} }
} }
\ No newline at end of file
...@@ -21,6 +21,8 @@ namespace DotNetCore.CAP ...@@ -21,6 +21,8 @@ namespace DotNetCore.CAP
private readonly CapOptions _options; private readonly CapOptions _options;
private readonly IStateChanger _stateChanger; private readonly IStateChanger _stateChanger;
protected string ServersAddress { get; set; }
// diagnostics listener // diagnostics listener
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
protected static readonly DiagnosticListener s_diagnosticListener = protected static readonly DiagnosticListener s_diagnosticListener =
...@@ -42,25 +44,35 @@ namespace DotNetCore.CAP ...@@ -42,25 +44,35 @@ namespace DotNetCore.CAP
public async Task<OperateResult> SendAsync(CapPublishedMessage message) public async Task<OperateResult> SendAsync(CapPublishedMessage message)
{ {
var sp = Stopwatch.StartNew(); var startTime = DateTimeOffset.UtcNow;
var stopwatch = Stopwatch.StartNew();
var tracingResult = TracingBefore(message.Name, message.Content);
var operationId = tracingResult.Item1;
var result = await PublishAsync(message.Name, message.Content); var sendValues = tracingResult.Item2 != null
? Helper.AddTracingHeaderProperty(message.Content, tracingResult.Item2)
: message.Content;
sp.Stop(); var result = await PublishAsync(message.Name, sendValues);
stopwatch.Stop();
if (result.Succeeded) if (result.Succeeded)
{ {
await SetSuccessfulState(message); await SetSuccessfulState(message);
_logger.MessageHasBeenSent(sp.Elapsed.TotalSeconds); TracingAfter(operationId, message.Name, sendValues, startTime, stopwatch.Elapsed);
return OperateResult.Success; return OperateResult.Success;
} }
else else
{ {
TracingError(operationId, message.Name, sendValues, result.Exception, startTime, stopwatch.Elapsed);
_logger.MessagePublishException(message.Id, result.Exception); _logger.MessagePublishException(message.Id, result.Exception);
await SetFailedState(message, result.Exception, out bool stillRetry); await SetFailedState(message, result.Exception, out bool stillRetry);
if (stillRetry) if (stillRetry)
{ {
_logger.SenderRetrying(3); _logger.SenderRetrying(3);
...@@ -122,5 +134,51 @@ namespace DotNetCore.CAP ...@@ -122,5 +134,51 @@ namespace DotNetCore.CAP
{ {
message.Content = Helper.AddExceptionProperty(message.Content, exception); message.Content = Helper.AddExceptionProperty(message.Content, exception);
} }
private (Guid, TracingHeaders) TracingBefore(string topic, string values)
{
Guid operationId = Guid.NewGuid();
var eventData = new BrokerPublishEventData(
operationId, "",
ServersAddress, topic,
values,
DateTimeOffset.UtcNow);
s_diagnosticListener.WritePublishBefore(eventData);
return (operationId, eventData.Headers);
}
private void TracingAfter(Guid operationId, string topic, string values, DateTimeOffset startTime, TimeSpan du)
{
var eventData = new BrokerPublishEndEventData(
operationId,
"",
ServersAddress,
topic,
values,
startTime,
du);
s_diagnosticListener.WritePublishAfter(eventData);
_logger.MessageHasBeenSent(du.TotalSeconds);
}
private void TracingError(Guid operationId, string topic, string values, Exception ex, DateTimeOffset startTime, TimeSpan du)
{
var eventData = new BrokerPublishErrorEventData(
operationId,
"",
ServersAddress,
topic,
values,
ex,
startTime,
du);
s_diagnosticListener.WritePublishError(eventData);
}
} }
} }
\ No newline at end of file
...@@ -153,11 +153,11 @@ namespace DotNetCore.CAP ...@@ -153,11 +153,11 @@ namespace DotNetCore.CAP
try try
{ {
operationId = s_diagnosticListener.WriteConsumerInvokeBefore(consumerContext); operationId = s_diagnosticListener.WriteSubscriberInvokeBefore(consumerContext);
var ret = await Invoker.InvokeAsync(consumerContext); var ret = await Invoker.InvokeAsync(consumerContext);
s_diagnosticListener.WriteConsumerInvokeAfter(operationId, consumerContext, startTime, stopwatch.Elapsed); s_diagnosticListener.WriteSubscriberInvokeAfter(operationId, consumerContext, startTime, stopwatch.Elapsed);
if (!string.IsNullOrEmpty(ret.CallbackName)) if (!string.IsNullOrEmpty(ret.CallbackName))
{ {
...@@ -166,7 +166,7 @@ namespace DotNetCore.CAP ...@@ -166,7 +166,7 @@ namespace DotNetCore.CAP
} }
catch (Exception ex) catch (Exception ex)
{ {
s_diagnosticListener.WriteConsumerInvokeError(operationId, consumerContext, ex, startTime, stopwatch.Elapsed); s_diagnosticListener.WriteSubscriberInvokeError(operationId, consumerContext, ex, startTime, stopwatch.Elapsed);
throw new SubscriberExecutionFailedException(ex.Message, ex); throw new SubscriberExecutionFailedException(ex.Message, ex);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment