2018-08-30 13:53:16 +00:00
using System ;
2021-09-02 11:58:01 +00:00
using System.Collections.Generic ;
2021-09-02 14:16:11 +00:00
using System.Text ;
2019-08-14 10:20:53 +00:00
using Tapeti.Config ;
2022-11-22 12:20:47 +00:00
using Tapeti.Connection ;
2019-08-14 10:20:53 +00:00
using ISerilogLogger = Serilog . ILogger ;
2018-08-30 13:53:16 +00:00
2019-01-24 21:52:21 +00:00
// ReSharper disable UnusedMember.Global
2018-08-30 13:53:16 +00:00
namespace Tapeti.Serilog
{
2019-08-14 10:20:53 +00:00
/// <summary>
/// Implements the Tapeti ILogger interface for Serilog output.
/// </summary>
2020-03-05 09:27:46 +00:00
public class TapetiSeriLogger : IBindingLogger
2018-08-30 13:53:16 +00:00
{
2021-09-02 14:16:11 +00:00
/// <summary>
/// Implements the Tapeti ILogger interface for Serilog output. This version
/// includes the message body and information if available when an error occurs.
/// </summary>
public class WithMessageLogging : TapetiSeriLogger
{
/// <inheritdoc />
public WithMessageLogging ( ISerilogLogger seriLogger ) : base ( seriLogger ) { }
internal override bool IncludeMessageInfo ( ) = > true ;
}
2019-08-14 10:20:53 +00:00
private readonly ISerilogLogger seriLogger ;
2018-08-30 13:53:16 +00:00
2019-08-14 10:20:53 +00:00
2020-03-05 09:27:46 +00:00
/// <summary>
/// Create a Tapeti ILogger implementation to output to the specified Serilog.ILogger interface
/// </summary>
/// <param name="seriLogger">The Serilog.ILogger implementation to output Tapeti log message to</param>
2019-08-14 10:20:53 +00:00
public TapetiSeriLogger ( ISerilogLogger seriLogger )
2018-08-30 13:53:16 +00:00
{
this . seriLogger = seriLogger ;
}
2019-08-14 10:20:53 +00:00
/// <inheritdoc />
2019-10-10 14:03:12 +00:00
public void Connect ( IConnectContext connectContext )
2018-08-30 13:53:16 +00:00
{
2019-08-14 10:20:53 +00:00
seriLogger
2019-10-10 14:03:12 +00:00
. ForContext ( "isReconnect" , connectContext . IsReconnect )
2019-08-14 10:20:53 +00:00
. Information ( "Tapeti: trying to connect to {host}:{port}/{virtualHost}" ,
2019-10-10 14:03:12 +00:00
connectContext . ConnectionParams . HostName ,
connectContext . ConnectionParams . Port ,
connectContext . ConnectionParams . VirtualHost ) ;
2018-08-30 13:53:16 +00:00
}
2019-08-14 10:20:53 +00:00
/// <inheritdoc />
2019-10-10 14:03:12 +00:00
public void ConnectFailed ( IConnectFailedContext connectContext )
2018-08-30 13:53:16 +00:00
{
2019-10-10 14:03:12 +00:00
seriLogger . Error ( connectContext . Exception , "Tapeti: could not connect to {host}:{port}/{virtualHost}" ,
connectContext . ConnectionParams . HostName ,
connectContext . ConnectionParams . Port ,
connectContext . ConnectionParams . VirtualHost ) ;
2018-08-30 13:53:16 +00:00
}
2019-08-14 10:20:53 +00:00
/// <inheritdoc />
2019-10-10 14:03:12 +00:00
public void ConnectSuccess ( IConnectSuccessContext connectContext )
2018-08-30 13:53:16 +00:00
{
2019-08-14 10:20:53 +00:00
seriLogger
2019-10-10 14:03:12 +00:00
. ForContext ( "isReconnect" , connectContext . IsReconnect )
. Information ( "Tapeti: successfully connected to {host}:{port}/{virtualHost} on local port {localPort}" ,
connectContext . ConnectionParams . HostName ,
connectContext . ConnectionParams . Port ,
connectContext . ConnectionParams . VirtualHost ,
connectContext . LocalPort ) ;
}
/// <inheritdoc />
public void Disconnect ( IDisconnectContext disconnectContext )
{
seriLogger
. Information ( "Tapeti: connection closed, reply text = {replyText}, reply code = {replyCode}" ,
disconnectContext . ReplyText ,
disconnectContext . ReplyCode ) ;
2018-08-30 13:53:16 +00:00
}
2019-08-14 10:20:53 +00:00
/// <inheritdoc />
public void ConsumeException ( Exception exception , IMessageContext messageContext , ConsumeResult consumeResult )
2018-08-30 13:53:16 +00:00
{
2021-09-02 14:16:11 +00:00
var message = new StringBuilder ( "Tapeti: exception in message handler" ) ;
2022-11-23 08:13:38 +00:00
var messageParams = new List < object? > ( ) ;
2021-09-02 14:16:11 +00:00
2019-08-14 10:20:53 +00:00
var contextLogger = seriLogger
. ForContext ( "consumeResult" , consumeResult )
. ForContext ( "exchange" , messageContext . Exchange )
. ForContext ( "queue" , messageContext . Queue )
. ForContext ( "routingKey" , messageContext . RoutingKey ) ;
2021-09-02 14:16:11 +00:00
if ( messageContext . TryGet < ControllerMessageContextPayload > ( out var controllerPayload ) )
2019-08-14 10:20:53 +00:00
{
contextLogger = contextLogger
2021-09-02 14:16:11 +00:00
. ForContext ( "controller" , controllerPayload . Binding . Controller . FullName )
. ForContext ( "method" , controllerPayload . Binding . Method . Name ) ;
message . Append ( " {controller}.{method}" ) ;
messageParams . Add ( controllerPayload . Binding . Controller . FullName ) ;
messageParams . Add ( controllerPayload . Binding . Method . Name ) ;
}
if ( IncludeMessageInfo ( ) )
{
message . Append ( " on exchange {exchange}, queue {queue}, routingKey {routingKey}, replyTo {replyTo}, correlationId {correlationId} with body {body}" ) ;
messageParams . Add ( messageContext . Exchange ) ;
messageParams . Add ( messageContext . Queue ) ;
messageParams . Add ( messageContext . RoutingKey ) ;
messageParams . Add ( messageContext . Properties . ReplyTo ) ;
messageParams . Add ( messageContext . Properties . CorrelationId ) ;
messageParams . Add ( messageContext . RawBody ! = null ? Encoding . UTF8 . GetString ( messageContext . RawBody ) : null ) ;
2019-08-14 10:20:53 +00:00
}
2021-09-02 14:16:11 +00:00
contextLogger . Error ( exception , message . ToString ( ) , messageParams . ToArray ( ) ) ;
2018-08-30 13:53:16 +00:00
}
2019-08-20 09:47:53 +00:00
2020-03-05 09:27:46 +00:00
/// <inheritdoc />
public void QueueDeclare ( string queueName , bool durable , bool passive )
{
if ( passive )
seriLogger . Information ( "Tapeti: verifying durable queue {queueName}" , queueName ) ;
else
seriLogger . Information ( "Tapeti: declaring {queueType} queue {queueName}" , durable ? "durable" : "dynamic" , queueName ) ;
}
2021-09-02 11:58:01 +00:00
/// <inheritdoc />
2022-11-23 08:13:38 +00:00
public void QueueExistsWarning ( string queueName , IRabbitMQArguments ? existingArguments , IRabbitMQArguments ? arguments )
2021-09-02 11:58:01 +00:00
{
2022-11-17 15:47:07 +00:00
seriLogger . Warning ( "Tapeti: durable queue {queueName} exists with incompatible x-arguments ({existingArguments} vs. {arguments}) and will not be redeclared, queue will be consumed as-is" ,
2021-09-02 11:58:01 +00:00
queueName ,
2022-11-17 15:47:07 +00:00
existingArguments ,
2021-09-02 11:58:01 +00:00
arguments ) ;
}
2020-03-05 09:27:46 +00:00
/// <inheritdoc />
public void QueueBind ( string queueName , bool durable , string exchange , string routingKey )
{
seriLogger . Information ( "Tapeti: binding {queueName} to exchange {exchange} with routing key {routingKey}" ,
queueName ,
exchange ,
routingKey ) ;
}
/// <inheritdoc />
public void QueueUnbind ( string queueName , string exchange , string routingKey )
{
seriLogger . Information ( "Tapeti: removing binding for {queueName} to exchange {exchange} with routing key {routingKey}" ,
queueName ,
exchange ,
routingKey ) ;
}
/// <inheritdoc />
public void ExchangeDeclare ( string exchange )
{
seriLogger . Information ( "Tapeti: declaring exchange {exchange}" , exchange ) ;
}
2019-08-20 09:47:53 +00:00
/// <inheritdoc />
public void QueueObsolete ( string queueName , bool deleted , uint messageCount )
{
if ( deleted )
seriLogger . Information ( "Tapeti: obsolete queue {queue} has been deleted" , queueName ) ;
else
seriLogger . Information ( "Tapeti: obsolete queue {queue} has been unbound but not yet deleted, {messageCount} messages remaining" , queueName , messageCount ) ;
}
2021-09-02 14:16:11 +00:00
internal virtual bool IncludeMessageInfo ( ) = > false ;
2018-08-30 13:53:16 +00:00
}
}