How to log different levels of information in your ASP.NET Core app

September 21, 2016 · 5 minute read

You’ve got your basic ASP.NET Core app running and configured logging so you can see what’s going on “under the hood”.

Now you want to take it a step further and log your own messages to see what’s going on when your app is running and when something goes wrong.

Log all the things

To do this you’ll need to bring an instance of ILogger into your controller.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

public class ContactUsController : Controller
{
    ILogger<ContactUsController> _logger;

    public ContactUsController (ILogger<ContactUsController> logger)
    {
        _logger = logger;      
    }
}

Now you’re probably wondering where that ILogger instance has come from.

.NET Core comes with dependency injection out of the box. It doesn’t take any extra configuration to set up the ILogger dependency, it’s automatically registered and available to be injected into your controllers/classes.

By specifying this as an instance of ILogger you indicate that the controller’s name should be used as the description when the logger logs any messages.

With that in place you can log messages whenever you see fit.

public IActionResult Index()
{
    _logger.LogInformation("The Index Action was invoked");
    return View();
}

If you’ve set up logging to the console you’ll see this message when you run your app and try to access this controller action.

logging-your-own-information

Level up

2443635669_93eafe69ef_m

It’s time to think about levels.

If you log too much at the wrong level you run the risk of important messages getting lost in the noise. It’s not just your logs you need to consider, third party libraries and .NET Core will log messages at different levels too.

The documentation in the source code for Microsoft.Extensions.Logging offers some advice on which level to use when.

You can control what gets logged by changing Startup.cs.

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(LogLevel.Warning);
    
    // ---
}

Now your app will log anything at Warning level or above to the console.

You can test this by hitting your controller action again with the above change to Startup.cs. note how no information messages get logged.

nologs

But fixing the log level in code isn’t much use. What if you want to vary the log level depending on other factors?

Struggling to wrap your head round all the moving parts of ASP.NET Core MVC?

You're not alone, pop your email in the box below and I'll ping you a link to the subscribers only vault where you'll find tutorials, videos and my quickstart tutorial for getting up and running with Practical ASP.NET Core MVC quickly.

I respect your email privacy. Unsubscribe with one click.

    It’s all about configuration

    This is where IConfiguration comes in. Instead of fixing the log level, you can provide a mechanism to read settings which control how your application logs.

    Let’s try reading the settings from a JSON File.

    Create an appsettings.json file with the following contents in your root directory for your web app.

    {
        "Logging": {
            "LogLevel": {
                "Default": "Debug"           
            }
        }
    }
    

    With that in place you’ll need to update Startup.cs to read this file and pass the relevant configuration section on to the Console logger.

    using System.IO;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    
    namespace ConsoleApplication
    {
        public class Startup
        {
            IConfiguration Configuration;
    
            public Startup()
            {
                var configBuilder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
    
                Configuration = configBuilder.Build();
            }
    
            public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
            {
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    
                // ....
            }
        }
    }
    

    First up you’ve added a Configuration builder, pointed it to your base directory and added your appsettings.json file to it’s list of configuration sources.

    Then you’ve told the AddConsole method to take it’s configuration from this appsettings.json file, specifically from the “Logging” configuration section.

    The Microsoft.Extensions.Logging framework will do the rest and automatically look for a property called “LogLevel” in these settings.

    For this to work you’ll also need to bring in the Microsoft.Extensions.Configuration.Json dependency to your project.json file.

    "frameworks": {
      "netcoreapp1.0": {
        "dependencies": {
          "Microsoft.NETCore.App": {
            "type": "platform",
            "version": "1.0.0"
          },
          "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
          "Microsoft.AspNetCore.Mvc": "1.0.1",
          "Microsoft.AspNetCore.Mvc.Core": "1.0.1",
          "Microsoft.AspNetCore.StaticFiles": "1.0.0",
          "Microsoft.Extensions.Logging": "1.0.0",
          "Microsoft.Extensions.Logging.Console": "1.0.0",
          "Microsoft.Extensions.Configuration.Json": "1.0.0"
        },
    

    Now if you run your app at this point you’re going to find that the logging is a bit “chatty”.

    chatty-logs

    What if you want to see your own debug logs but not Microsoft’s?

    Easy, just change your appsettings.json.

    {
        "Logging": {
            "LogLevel": {
                "Default": "Debug",
                "Microsoft": "Information"        
            }
        }
    }
    

    The logging framework will look for a specific setting for the prefix of whatever is being logged and use that, else fall back to the default.

    So for example, if I add a setting called ContactUsController and set it to Warning then nothing below a warning will be shown for logs from the ContactUsController, but anything else logged in my application will stick to the default level of Debug.

    {
        "Logging": {
            "LogLevel": {
                "ContactUsController": "Warning",
                "Default": "Debug",
                "Microsoft": "Warning"        
            }
        }
    }
    

    In this case, I’ve gone a step further and set the Microsoft logs to “Warning” which means I won’t see Microsoft’s debug or information logs.

    photo credit: Tetris via photopin (license)

    Join the Practical ASP.NET Newsletter

    Ship better Blazor apps, faster. One practical tip every Tuesday.

    I respect your email privacy. Unsubscribe with one click.