If you’re writing ASP.NET apps with the latest tooling, you will inevitably encounter the Microsoft.Framework.Logging package. It’s a dependency of ASP.NET MVC, WebForms and much of the related infrastructure. “What is this thing?” you ask. Great question!
The Framework writes log events
When an MVC controller is selected, when a static file is served, when an error is caught… ASP.NET and other framework libraries helpfully log this information.
In past .NET versions, System.Diagnostics.Trace was the output of choice, but the world has moved on and the newer package is an alternative with a more modern-feeling API.
What does it look like?
Like ASP.NET 5, your applications and libraries can write events to the framework’s logging pipeline:
var logger = loggerFactory.CreateLogger(typeof(Program).FullName);
logger.LogInformation("Handled in {ExecutionTime} ms", executionTime);
An ILoggerFactory
creates ILoggers
, and these provide the typical methods you’d expect for logging errors, warnings, debug events and so-on.
You might be surprised (or, you might not!) that just like Serilog, Microsoft.Framework.Logging supports {Named}
holes in its format strings, in addition to the typical {0}
and {1}
. This technique enables structured loggers to provide first-class search operations on not just the raw text of the log message, but the individual property values as well:
The great thing is that if you’re not using a structured approach, messages will just come through the pipeline as strings – everyone’s looked after.
Microsoft.Framework.Logging vs. Serilog, NLog, SLAB, log4net…
The designers of ASP.NET faced the same dilemma as other library authors in .NET: which logging library should they use to write events? The choice of logger is typically one the application author will make, so frameworks and libraries need a way to support more than one option.
Over time we’ve had a few solutions to this – Common.Logging has been popular, and more recently LibLog does a good of providing a dependency-free API on top of several loggers.
Microsoft.Framework.Logging today is another of these, though it’s somewhat more capable (and in many ways it’s a very nice one).
Although out-of-the-box implementations are provided for basic console logging and a few other targets, you’ll need a logging back-end like Serilog or NLog to gain the kind of functionality expected by non-trivial apps.
So, how does that work?
Getting started
We’ll assume you want to use Serilog. (Instructions for NLog are pretty similar, and an example that uses it can be found here.) The ASP.NET Team wrote the original Serilog back-end for Microsoft.Framework.Logging, and transferred it to the Serilog project where it’s currently supported and maintained.
First, install the Serilog.Framework.Logging
NuGet packag into your web or console app.
Next, in your application’s Startup()
method, configure Serilog first:
public class Startup
{
public Startup(IHostingEnvironment env)
{
Log.Logger = new LoggerConfiguration()
#if DNXCORE50
.WriteTo.TextWriter(Console.Out)
#else
.WriteTo.Trace()
#endif
.CreateLogger();
// Other startup code
The conditional compilation (#if
) is necessary if you’re targeting the CoreCLR runtime, for which there are currently few Serilog sinks. If you’re targeting the full .NET framework you can just use .WriteTo.Trace()
, or any other available sink.
Finally, in your Startup
class’s Configure()
method, call AddSerilog()
on the provided loggerFactory
.
ILoggerFactory loggerfactory)
{
loggerfactory.AddSerilog();
That’s it! With the level bumped up a little you should see log output like:
Routes:
Microsoft.AspNet.Mvc.Routing.AttributeRoute
{controller=Home}/{action=Index}/{id?}
Handled? True
2015-05-15 22:14:44.647 +10:00 [Debug] RouterMiddleware.Invoke
Handled? True
2015-05-15 22:14:45.706 +10:00 [Debug] /lib/jquery/jquery.js not modified
2015-05-15 22:14:45.706 +10:00 [Debug] /css/site.css not modified
2015-05-15 22:14:45.741 +10:00 [Debug] Handled. Status code: 304 File: /css/site.css
An important note on levels
If you want to get more or less information from the log you’ll need to change the level.
- You need to set
MinimumLevel
on both the SerilogLoggerConfiguration
and theILoggerFactory
- Serilog and ASP.NET assign different priorities to the
Debug
andTrace
levels; Serilog’sDebug
is ASP.NET’sTrace
, and vice-versa
Which API should my application use?
Personally, I’m content to let ASP.NET write events with the Microsoft.Framework.Logging API, and to use Serilog’s native API in my application code. The designers of the framework API have gone out of their way to support a wide range of logging styles, so using either is reasonable. I’m obviously somewhat biased, but I prefer the more focused API of Serilog to the more general one from the framework. Your preferences might differ :-).
The important thing is – don’t miss the opportunity posed by ASP.NET 5 to take your logging to the next level and get some structured events through your logging pipeline.
Getting help
If you have questions or comments please feel free to raise an issue on the tracker. We’re also frequently in the Serilog Jabbr chat and happy to help if you get stuck!