using System; using System.Linq; using Serilog.Events; using Tapeti.Config; namespace Tapeti.Serilog.Middleware { /// /// Implements the middleware which binds any IDiagnosticContext parameter in message handlers. /// public class MessageHandlerLoggingBindingMiddleware : IControllerBindingMiddleware { private readonly IControllerMessageMiddleware controllerMessageMiddleware; /// /// Creates a new instance of the middleware which binds any IDiagnosticContext parameter in message handlers. /// /// /// public MessageHandlerLoggingBindingMiddleware(double elapsedWarningTreshold = 500, LogEventLevel defaultLevel = LogEventLevel.Debug) { controllerMessageMiddleware = new MessageHandlerLoggingMessageMiddleware(elapsedWarningTreshold, defaultLevel); } /// public void Handle(IControllerBindingContext context, Action next) { RegisterDiagnosticContextParameter(context); // All state is contained within the message context, using a single middleware instance is safe context.Use(controllerMessageMiddleware); next(); } private static void RegisterDiagnosticContextParameter(IControllerBindingContext context) { foreach (var parameter in context.Parameters.Where(p => !p.HasBinding && p.Info.ParameterType == typeof(IDiagnosticContext))) parameter.SetBinding(DiagnosticContextFactory); } private static object? DiagnosticContextFactory(IMessageContext context) { return context.TryGet(out var diagnosticContextPayload) ? diagnosticContextPayload.DiagnosticContext : null; } } }