Reputation: 1
I make log with CorrelationId
in Serilog for email service sender and tracking pixel in asp.net core 6 web api , each message log with GUID correlationId
and when user see the message we can also log the time he opens the email message but problem is I want to make same correlationId
log for both email message and the time user see the message but each action in this app make their own correlationID.
I think the problem is in middleware correlation and program.cs
. Does anyone know how I could do that? Or is it even possible?
Thanks in advance.
The class for send email and send pixel tracking
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Options;
using MimeKit;
using MimeKit.Text;
using DAL.Model;
using ImageTracker.Service;
namespace SimpleEmailApp.Services
{
public class MailService : IMailService
{
private readonly AppSetting _mailSetting;
private readonly ILogger<MailService> _logger;
private readonly IWhichMessageIsRead _whichMessageIsRead;
// IWhichMessageIsRead whichMessageIsRead
public MailService(IOptions<AppSetting> mailSetting, ILogger<MailService> logger,
IWhichMessageIsRead whichMessageIsRead)
{
_mailSetting = mailSetting.Value;
_logger = logger;
_whichMessageIsRead = whichMessageIsRead;
}
public async Task SendEmailAsync(EmailMessage message)
{
var email = new MimeMessage();
try
{
email.Sender = MailboxAddress.Parse(_mailSetting.Mail);
email.To.Add(MailboxAddress.Parse(messsage.Reciver));
email.Subject = messsage.Subject;
// a unique-id to attach with the mail
// var messageId = Guid.NewGuid();
// bool IsRead = false;
// the server that receives the request from the image and process it
// var deliveryProcessor = "https://localhost:7156/api/Track";
// constructing the image tag with "src" pointing to the external resource
// passing the unique-id in the query-string.
var imgTag = string.Format(@"<img src=""https://localhost:7156/api/Mail"" alt ="""" width = ""1"" height = ""1""
style=""width: 0px; height: 0px; border:0px;""/>");
var builder = new BodyBuilder();
builder.HtmlBody = imgTag;
email.Body = new TextPart(TextFormat.Html)
{
Text = message.Body + " " + imgTag
};
var lg = _logger.LogInformation("");
_logger.LogInformation("Email {@mailRequest} creates for {Sender} at {now}.", message, _mailSetting.Mail, DateTime.Now);
_whichMessageIsRead. GetMessage( ,messsage);
}
catch (Exception)
{
_logger.LogError("Email is not sent.");
throw;
}
using var smtp = new SmtpClient();
try
{
smtp.Connect(_mailSetting.Host, _mailSetting.Port, SecureSocketOptions.StartTls);
smtp.Authenticate(_mailSetting.Mail, _mailSetting.Password);
await smtp.SendAsync(email);
smtp.Disconnect(true);
}
catch (Exception)
{
_logger.LogError(" SMTP Server Configuration Error occurred ");
throw;
}
}
}
}
My middleware for implementing correlationid
:
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace CorrelationProvider.Middleware
{
public class LogHeaderMiddleware
{
private readonly RequestDelegate _next;
public LogHeaderMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var header = context.Request.Headers["X-SessionId"];
if (header.Count > 0)
{
var logger = context.RequestServices.GetRequiredService<ILogger<LogHeaderMiddleware>>();
using (logger.BeginScope("{@SessionId}", header[0]))
{
await _next(context);
}
}
else
{
await _next(context);
}
}
}
}
program.cs
:
global using SimpleEmailApp.Services;
using DAL.Model;
using SimpleEmailApp.ConfgureSetting;
using Serilog;
using CorrelationProvider.Middleware;
using CorrelationProvider;
using Microsoft.AspNetCore.Mvc;
//using ImageTracker.Middleware;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddControllers();
//builder.Host.UseSerilog();
var Logger = new LoggerConfiguration()
.ReadFrom.Configuration(builder.Configuration)
.Enrich.FromLogContext()
.Enrich.WithCorrelationId()
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(Logger);
builder.Services.AddSwaggerGen();
/// <summary>
/// correlation provider
/// </summary>
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ISessionIdAccessor, SessionIdAccessor>();
/// <summary>
/// /below confiure method is add appsettings.development.json values to appsettings.json and
/// configure host(smtp server settings) for us .
/// also congigure method is made by mailsetting c# class properties and fill with mailsetting in
/// appsettings.development.json file
/// we can use appsettings.json instead appsettings.development.json .
/// </summary>
//builder.Services.Configure<AppSetting>(builder.Configuration.GetSection("MailSetting"));
builder.Services.Configure<AppSetting>(builder.Configuration.GetSection("MailSetting"));
builder.Services.ConfigureWritable<AppSetting>(builder.Configuration.GetSection("MailSetting"));
//builder.Services.AddSingleton<FileContentResult>(new FileContentResult(
// Convert.FromBase64String(builder.Configuration.GetValue<String>("Response:PixelContentBase64")),
// builder.Configuration.GetValue<String>("Response:PixelContentType")
// ));
builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("MailSetting",
optional: true,
reloadOnChange: true);
});
builder.Services.AddScoped<IMailService, MailService>();
/// <summary>
/// correlation Id
/// </summary>
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseMiddleware<LogHeaderMiddleware>();
//app.UseMiddleware<EmailTrackMiddleware>();
/// <summary>
/// static files for sending 1x1 pic
/// </summary>
//app.UseDefaultFiles();
//app.UseStaticFiles();
app.UseDeveloperExceptionPage();
app.MapControllers();
app.Run();
My appsettings.json
file:
{
"MailSetting": {
"Mail": "[email protected]",
"Password": "quafcvofqjwfvhqu",
"Host": "smtp.gmail.com",
"Port": 587
},
"Serilog": {
"Using": [
"Serilog.Sinks.File",
"Serilog.Sinks.Console"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"SimpleEmailApp.Controllers": "Information",
"Microsoft": "Information",
"Microsoft.AspNetCore": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:yyyy/MM/dd HH:mm:ss.fff zzz} {Level:u11}] {CorrelationId} {Message:lj}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact"
}
},
{
"Name": "File",
"Args": {
"path": "../logs/EmailApi-.log",
"rollingInterval": "Day",
"outputTemplate": "[{Timestamp:yyyy/MM/dd HH:mm:ss.fff zzz} {Level:u11}] {CorrelationId} {Message:lj}{NewLine}{Exception}"
}
}
]
},
"AllowedHosts": "*"
}
Any solution to solve this error?
Upvotes: 0
Views: 554
Reputation: 1
One possible I forgot to mention is in message model I can add message ID and GUID in it, with this solution we can track which message is read by client
Upvotes: 0