Skip to content

Instantly share code, notes, and snippets.

@skynyrd
Created May 9, 2017 08:08
Show Gist options
  • Save skynyrd/6d8758eb4b5d84924633b77c1b8816cc to your computer and use it in GitHub Desktop.
Save skynyrd/6d8758eb4b5d84924633b77c1b8816cc to your computer and use it in GitHub Desktop.
Add Serilog to .NET Core running in Docker Container

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"
    }
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment