Dependencies:
"Serilog.Settings.Configuration": "2.3.1",
"Serilog.Sinks.Literate": "2.1.0",
"Serilog.Extensions.Logging": "1.4.0"
Your Startup constructor:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile($"AppSettings/appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.CreateLogger();
}
Your Configure Method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
...
loggerfactory.AddSerilog();
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMiddleware(typeof(RequestIdLoggingMiddleware));
...
}
Add ErrorHandlingMiddleware
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
private readonly ILogger logger = Log.ForContext<ErrorHandlingMiddleware>();
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception exception)
{
logger.Error(exception.ToString());
await HandleExceptionAsync(context, exception);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
if (exception == null) return;
var code = ExceptionStatusCodeMapper.MapExceptions(exception);
await WriteExceptionAsync(context, exception, code).ConfigureAwait(false);
}
private static async Task WriteExceptionAsync(HttpContext context, Exception exception, HttpStatusCode code)
{
var response = context.Response;
response.ContentType = "application/json";
response.StatusCode = (int)code;
var bodyText = JsonConvert.SerializeObject(new
{
error = new
{
message = exception.Message,
exception = exception.GetType().Name
}
});
await response.WriteAsync(bodyText).ConfigureAwait(false);
}
Add RequestIdLoggingMiddleware:
public class RequestIdLoggingMiddleware
{
private readonly RequestDelegate next;
public RequestIdLoggingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
using (LogContext.PushProperty("RId", Guid.NewGuid()))
{
await next.Invoke(context);
}
}
}
Add to appsettings.json:
"Serilog": {
"Using": [ "Serilog.Sinks.Literate" ],
"MinimumLevel": "Warning",
"WriteTo": [
{
"Name": "LiterateConsole",
"Args": {
"outputTemplate": "{Timestamp:o} [{Level}] [{RId}] ({SourceContext}) {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "Sample"
}
}