You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have a architectural question about distributed logging, and I can't see any issue or discussion around this topic, so I created this discussion.
If you have n services that implement microservice architecture and communicates with other services from HTTP calls and event queues such as RabbitMQ (with masstransit), how can you log CorrelationId in this communicational flow between services? Is there a solution for that or we should implement our custom code?
I think something like that as a solution but this is open to any kind of question. Enricher part won't work right now, I will implement ILogEventEnricher in the right way if this approach works.
In summary, when the service receives a request from HTTP, CorrelationMiddleware will set the correlationId to the Correlation class. When the service receives a request from RabbitMQ via MassTransit, CorrelationConsumeFilter will set the correlationId to the Correlation class. When you publish or send an event to the queue, CorrelationPublishFilter or CorrelationSendFilter will handle the task and set the CorrelationId field in PublishContext or SendContext for the event's consumer to retrieve the correlation id. If you make an HTTP call to any service, you have to manually set the CorrelationId to be received by the receiving application.
namespaceNotification.Api.Domain.ServiceModels{publicclassCorrelation{publicGuid?CorrelationId{get;set;}}}namespaceNotification.Api.Middlewares{publicclassCorrelationEnricher:ILogEventEnricher{privatereadonlyCorrelation_correlation;publicCorrelationEnricher(Correlationcorrelation){_correlation=correlation;}publicvoidEnrich(LogEventlogEvent,ILogEventPropertyFactorypf){if(_correlation.CorrelationIdis not null){stringcorrelationId=_correlation.CorrelationId.Value.ToString();LogEventPropertyproperty=newLogEventProperty("CorrelationId",newScalarValue(correlationId));logEvent.AddOrUpdateProperty(property);}}}publicclassCorrelationMiddleware{privatereadonlyRequestDelegate_next;publicCorrelationMiddleware(RequestDelegatenext){_next=next;}publicasyncTaskInvokeAsync(HttpContextcontext,Correlationcorrelation){varcorrelationId=context.Request.Headers["CorrelationId"];if(!string.IsNullOrWhiteSpace(correlationId)){correlation.CorrelationId=Guid.Parse(correlationId.ToString());}await_next(context);}}publicclassCorrelationConsumeFilter<T>:IFilter<ConsumeContext<T>>whereT:class{privatereadonlyCorrelation_correlation;privatereadonlyIHttpContextAccessor_httpContextAccessor;publicCorrelationConsumeFilter(Correlationcorrelation,IHttpContextAccessorhttpContextAccessor){_correlation=correlation;_httpContextAccessor=httpContextAccessor;}publicTaskSend(ConsumeContext<T>context,IPipe<ConsumeContext<T>>next){varcorrelationId=context.CorrelationId;if(correlationId.HasValue){_correlation.CorrelationId=correlationId.Value;varhttpContext=_httpContextAccessor.HttpContext;if(httpContextis not null){httpContext.Request.Headers["CorrelationId"]=correlationId.Value.ToString();}}returnnext.Send(context);}publicvoidProbe(ProbeContextcontext){}}publicclassCorrelationPublishFilter<T>:IFilter<PublishContext<T>>whereT:class{readonlyCorrelation_correlation;publicCorrelationPublishFilter(Correlationcorrelation){_correlation=correlation;}publicTaskSend(PublishContext<T>context,IPipe<PublishContext<T>>next){if(_correlation.CorrelationIdis not null){context.CorrelationId=_correlation.CorrelationId;}returnnext.Send(context);}publicvoidProbe(ProbeContextcontext){}}publicclassCorrelationSendFilter<T>:IFilter<SendContext<T>>whereT:class{readonlyCorrelation_correlation;publicCorrelationSendFilter(Correlationcorrelation){_correlation=correlation;}publicTaskSend(SendContext<T>context,IPipe<SendContext<T>>next){if(_correlation.CorrelationIdis not null){context.CorrelationId=_correlation.CorrelationId;}returnnext.Send(context);}publicvoidProbe(ProbeContextcontext){}}}
Program.cs
varbuilder=WebApplication.CreateBuilder(args);// ...builder.Services.AddHttpContextAccessor();builder.Services.AddScoped<Correlation>();varmessageBroker=builder.Configuration.GetSection("MessageBroker");builder.Services.AddMassTransit(cfg =>{cfg.SetKebabCaseEndpointNameFormatter();cfg.AddConsumer<SendSmsConsumer>();cfg.AddConsumer<SendMailConsumer>();cfg.UsingRabbitMq((context,config)=>{config.UseSendFilter(typeof(CorrelationSendFilter<>),context);config.UsePublishFilter(typeof(CorrelationPublishFilter<>),context);config.UseConsumeFilter(typeof(CorrelationConsumeFilter<>),context);config.UseMessageRetry(r =>r.Immediate(5));config.Host(messageBroker["Host"],messageBroker["VirtualHost"], h =>{h.Username(messageBroker["Username"]!);h.Password(messageBroker["Password"]!);});config.ConfigureEndpoints(context);});});varindex=$"{builder.Configuration.GetValue<string>("ProjectName")}-{DateTime.Today:yyyyMMdd}";Log.Logger=newLoggerConfiguration().Enrich.With<CorrelationEnricher>().ReadFrom.Configuration(builder.Configuration).CreateLogger();builder.Host.UseSerilog();varapp=builder.Build();// ...app.UseMiddleware<CorrelationMiddleware>();// ...app.Run();
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I have a architectural question about distributed logging, and I can't see any issue or discussion around this topic, so I created this discussion.
If you have n services that implement microservice architecture and communicates with other services from HTTP calls and event queues such as RabbitMQ (with masstransit), how can you log CorrelationId in this communicational flow between services? Is there a solution for that or we should implement our custom code?
I think something like that as a solution but this is open to any kind of question. Enricher part won't work right now, I will implement ILogEventEnricher in the right way if this approach works.
In summary, when the service receives a request from HTTP, CorrelationMiddleware will set the correlationId to the Correlation class. When the service receives a request from RabbitMQ via MassTransit, CorrelationConsumeFilter will set the correlationId to the Correlation class. When you publish or send an event to the queue, CorrelationPublishFilter or CorrelationSendFilter will handle the task and set the CorrelationId field in PublishContext or SendContext for the event's consumer to retrieve the correlation id. If you make an HTTP call to any service, you have to manually set the CorrelationId to be received by the receiving application.
Program.cs
Beta Was this translation helpful? Give feedback.
All reactions