namespace Cnh.SysConsole.AuditLogging.MessageBroker
using System.Threading.Tasks;
using MassTransit.Testing;
using Microsoft.Extensions.DependencyInjection;
using CNH.Products.Lib.Model.Contracts;
using Cnh.SysConsole.AuditLogging.MessageBroker.Consumers.ProductsDomain;
using Serilog.Formatting.Compact;
public static async Task Main()
var provider = new ServiceCollection()
.AddSerilog((services, cfg) =>
.WriteTo.Console(new RenderedCompactJsonFormatter()))
.AddMassTransitTestHarness(cfg =>
cfg.AddConsumer<ProductCreatedConsumer>();
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<ITestHarness>();
await harness.Bus.Publish<IActiveProductCreatedEvent>(new
namespace CNH.Products.Lib.Model.Contracts
using System.ComponentModel;
[Description("Active product created")]
public interface IActiveProductCreatedEvent : IProductCreated
string PartNumber { get; }
[Description("... Product created ...")]
public interface IProductCreated
namespace Cnh.SysConsole.AuditLogging.MessageBroker.Consumers.ProductsDomain
using System.Threading.Tasks;
using CNH.Products.Lib.Model.Contracts;
using Microsoft.Extensions.Logging;
using Cnh.Psca.AuditLogger.Abstractions.Logging;
public class ProductCreatedConsumer : IConsumer<IActiveProductCreatedEvent>
private readonly ILogger<ProductCreatedConsumer> _logger;
public ProductCreatedConsumer(ILogger<ProductCreatedConsumer> logger)
public async Task Consume(ConsumeContext<IActiveProductCreatedEvent> context)
var @event = context.Message;
_logger.LogInformation("Message received: {@IActiveProductCreatedEvent}", @event);
var logEvent = new AuditLogEvent<IActiveProductCreatedEvent>(_logger, @event);
_logger.LogInformation("Log event: {@LogEvent}", logEvent);
namespace Cnh.Psca.AuditLogger.Abstractions.Logging
using Cnh.Psca.AuditLogger.Abstractions.Extensions;
using Microsoft.Extensions.Logging;
public class AuditLogEvent<TEvent>
public string Name { get; }
public string DisplayName { get; }
public string Json { get; }
public AuditLogEvent(ILogger logger, TEvent @event)
ArgumentNullException.ThrowIfNull(@event);
var type = @event.GetType();
DisplayName = type.GetDescription() ?? Name;
Json = JsonSerializer.Serialize(@event);
public AuditLogEvent(ILogger logger, TEvent @event, string eventJson)
ArgumentNullException.ThrowIfNull(@event);
ArgumentNullException.ThrowIfNull(eventJson);
var type = @event.GetType();
DisplayName = type.GetDescription() ?? Name;
namespace Cnh.Psca.AuditLogger.Abstractions.Extensions
using System.ComponentModel;
public static class TypeExtensions
public static string? GetDescription(this Type sourceType)
var descriptionAttribute = sourceType
.GetCustomAttribute<DescriptionAttribute>(false);
var description = descriptionAttribute?.Description;
if (!String.IsNullOrWhiteSpace(description))
foreach (var interfaceType in sourceType.GetInterfaces())
description = interfaceType.GetDescription();
if (!String.IsNullOrWhiteSpace(description))