If you are getting started with ASP.NET Core, you are probably wondering what has changed with logging. In short, the answer is both nothing and everything. The common logging libraries you have always used with .NET still work. Microsoft does provide its own interface for logging with .NET Core and it uses it for .NET internals.
In this article, we will discuss using traditional .NET logging frameworks and some new changes in ASP.NET Core and .NET Core.
The three most popular libraries for logging support .NET Core. If you are converting your application from ASP.NET to Core, you won’t have to make any code changes. Just upgrade to the latest NuGet packages. Although you may want to move your logging config to its own file since your web.config will now be gone in favor of the new appsetting.json.
When .NET Core 1.0 launched, log4net had not been ported to support .NET Core (it has since). Their long delay in support for .NET Core is just one example of where log4net has been slow to keep up with new trends and features in logging frameworks. It may be the most popular framework, but NLog and Serilog are on the leading edge.
NLog has quickly become the second most popular framework for .NET logging. They had support for .NET Core when v1.0 came out and continue to rapidly add new features. NLog even works across Xamarin, Mono, and other runtimes. NLog is a safe bet if you are thinking about selecting a new logging framework for ASP.NET Core.
Be sure to check out our tips and best practices guide on NLog.
Serilog was created to bring more structure to logging variables and objects. It has become very popular and continues to grow. It supports all the common logging features you would support, like configurable output targets and is much more modern than log4net.
ASP.NET Core now has a built-in logging framework that you can use. It is not as feature-rich as third party libraries. Let me give you a quick and dirty tour of the new ILoggerFactory that is built into .NET Core.
Also, check out our in-depth article about How to Use LoggerFactory and Microsoft.Extensions.Logging.
If you have created a brand new ASP.NET Core web application, you have likely seen these loggerFactory lines of code in your Startup class.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); //removed the rest of the lines }
You will also find some logging settings in the default appsettings.json.
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } }
If you run the default app, you can see it write out some details in the debug window in Visual Studio that shows when MVC actions happen and how long they take.
Microsoft.AspNetCore.Hosting.Internal.WebHost: Information: Request starting HTTP/1.1 GET http://localhost:29564/ Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Information: Executing action method ASPNetCore.Controllers.HomeController.Index (CoreSharedLib) with arguments () - ModelState is Valid Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor: Information: Executing ViewResult, running view at path /Views/Home/Index.cshtml. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Information: Executed action ASPNetCore.Controllers.HomeController.Index (CoreSharedLib) in 26.8787ms Microsoft.AspNetCore.Hosting.Internal.WebHost: Information: Request finished in 60.9946ms 200 text/html; charset=utf-8
If you want to disable these built-in messages all together, you can simply remove the AddConsole() and AddDebug() methods. If you want to reduce how much they log then you can adjust their log levels.
For AddConsole() you will notice that you can pass into it Configuration.GetSection(“Logging”) which pulls the log levels from your appsettings.json configuration, or other custom providers you may be using. By setting a log level to “None” it will disable it. Just above is an example of an appsettings.json that I am referring to here.
AddDebug(), for some reason, does not support the same configuration-based initialization. You can instead specify a log level in your code directly, which I guess is fine since debug is really just meant for use in development and wouldn’t need to be configured differently in QA or production.
These log levels are all supported: None, Trace, Debug, Information, Warning, Error, Critical.
You don’t have to use the built-in logging. You can – and I would probably recommend this – use NLog, Serilog, or log4net. If you want to capture the internal logging coming from .NET Core and send it to your separate logging framework, you can. You just have to configure it!
For NLog/Serilog, all you have to do is add one line of code in your Startup Configure() method. This adds a special logging provider for NLog/Serilog that redirects the messages.
loggerFactory.AddNLog(); or loggerFactory.AddSerilog();
Being able to see all of the .NET Core internal logging is cool, but what about my own logging?
One of the big additions to .NET Core is built-in dependency injection. You can use the ILoggerFactory via dependency injection in your own code as shown below.
public class HomeController : Controller { ILoggerFactory _loggerFactory; public HomeController(ILoggerFactory loggerFactory) { _loggerFactory = loggerFactory; } public string Ping() { var logger = _loggerFactory.CreateLogger("LoggerCategory"); logger.LogInformation("Calling the ping action"); return "pong"; } }
Now, when I execute this code I see similar logging as I showed before, but I also see my extra logging line.
LoggerCategory: Information: Calling the ping action
So, you can see how easy it is to use the new built-in ASP.NET Core logging via ILoggerFactory and dependency injection.
The new logging API currently supports the following built-in providers:
So if you have followed along this far, I’m sure you are wondering about how to make the built-in logging write to a file on disk. You have to use a 3rd party extension to do it.
Since .NET Core does not support logging to file directly, you will want to use an extension from NLog or Serilog that can route .NET Core logging to those libraries. Then you can take full advantage of their features. I am going to assume that they left a File writer option out because of the complexity it creates. It opens up a huge set of requirements around max file sizes, rolling files, deleting files, file writing performance, etc.
Read more: NLog Extensions
Read more: Serilog.Extensions.Logging.File
Using Serilog as an example, all you have to do is install their Extensions NuGet package and, with one line of code, do an AddFile in your Startup class. Now you have a log file on disk!
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddFile("Logs/mylog-{Date}.txt"); //other code removed for example }
The built-in logging doesn’t provide much for configuration. All you can do is configure the logging level (Debug, Warning, Error, etc) by logging category name.
You can use Prefix, Stackify’s free ASP.NET Profiler, to view all of your logging statements during development. Prefix can show you all of your logs, errors, SQL queries, HTTP calls, and much more.
If you only send your logging to a file on disk, it can be pretty hard to get a lot of use out of them once you deploy your app to a server somewhere. You really need to centralize your logs with a log management system. This gives you the ability to do full-text searching across all of your logs for all applications and servers from one place.
Stackify Retrace starts at just $10 a month per server for non-production servers. Give it a try!
Have any other tips about logging in ASP.NET Core? Let us know in the comments!
If you would like to be a guest contributor to the Stackify blog please reach out to stackify@stackify.com