He creado un proyecto de fregadero Serilog simple que se ve así:
namespace MyApp.Cloud.Serilog.MQSink { public class MessageQueueSink: ILogEventSink { private readonly IMQProducer _MQProducerService; public MessageQueueSink(IMQProducer mQProducerService) { _MQProducerService = mQProducerService; } public void Emit(LogEvent logEvent) { _MQProducerService.Produce<SendLog>(new SendLog() { LogEventJson = JsonConvert.SerializeObject(logEvent)}); } } }El microservicio de consumo se inicia así:
var configurationBuilder = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); var appSettings = configurationBuilder.Get<AppSettings>(); configurationBuilder = new ConfigurationBuilder().AddJsonFile("ExtendedSettings.json").Build(); Host.CreateDefaultBuilder(args) .UseMyAppCloudMQ(context => context.UseSettings(appSettings.MQSettings)) .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration)) .ConfigureServices((hostContext, services) => { services .AddHostedService<ExtendedProgService>() .Configure<MQSettings>(configurationBuilder.GetSection("MQSettings")) }) .Build().Run();La parte de serilog de appsettings.json se ve así:
"serilog": { "Using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console", "MyApp.Cloud.Serilog.MQSink" ], "MinimumLevel": { "Default": "Debug", "Override": { "Microsoft": "Warning", "System": "Warning" } }, "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId" ], "WriteTo": [ { "Name": "MessageQueueSink", "Args": {} } ] }El proyecto MQSink se agrega como referencia al proyecto de microservicio y puedo ver que el dll de MQSink termina en la carpeta bin.
El problema es que cuando se ejecuta un _logger.LogInformation (...) en el microservicio, Emit nunca se activa, pero si agrego un receptor de consola, ¿dará salida a los datos? También sospecho que el MQ inyectado no funcionará correctamente.
¿Cómo se podría solucionar esto?
EDITAR:
Encendió el registro interno de Serilog y pudo ver que no se pudo encontrar el método MessageQueueSink. No encontré ninguna forma de hacer que esto funcionara con appsetings.json, así que comencé a buscar cómo enlazar esto en el código.
Para que funcione, se tuvo que crear una extensión:
public static class MySinkExtensions { public static LoggerConfiguration MessageQueueSink( this Serilog.Configuration.LoggerSinkConfiguration loggerConfiguration, MyApp.Cloud.MQ.Interface.IMQProducer mQProducer = null) { return loggerConfiguration.Sink(new MyApp.Cloud.Serilog.MQSink.MessageQueueSink(mQProducer)); } }Esto hizo posible agregar el fregadero personalizado de esta manera:
Host.CreateDefaultBuilder(args) .UseMyAppCloudMQ(context => context.UseSettings(appSettings.MQSettings)) .ConfigureServices((hostContext, services) => { services .Configure<MQSettings>(configurationBuilder.GetSection("MQSettings")) }) .UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration).WriteTo.MessageQueueSink()) .Build().Run();El sumidero personalizado está cargado y Emit se activa, pero todavía no sé cómo inyectar el MQ en el sumidero. También sería mucho mejor si pudiera hacer toda la configuración de Serilog y hundirme en el archivo appsettings.json.
Si consulta la lista Sumideros proporcionados y examina el código fuente de algunos de ellos, notará que el patrón suele ser:
IConfiguration , en línea o una combinación de ambos)Luego, la implementación del receptor crea una instancia de los servicios necesarios para enviar los registros.
Un enfoque alternativo que podría sugerir es registrar Serilog sin ningún argumento ( UseSerilog() ) y luego configurar la clase estática Serilog.Log usando el IServiceProvider integrado:
var host = Host.CreateDefaultBuilder(args) // Register your services as usual .UseSerilog() .Build() Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(host.Services.GetRequiredService<IConfiguration>()) .WriteTo.MessageQueueSink(host.Services.GetRequiredService<IMQProducer>()) .CreateLogger(); host.Run();