Today I’ll discuss two topics. The primary topic is implementing logging by leveraging Serilog with F#. The secondary topic is F# and .NET Core version 2.0. Due to the recent release of .NET Core 2.0 (now with better F# support), I thought this would be a good time to show how to implement an F# .NET Core project.
Going forward I’ll assume you have .NET Core 2.0 installed. If you don’t, head out to the .NET Core Downloads page. Select SDK for your platform. Tangential, but you can also get here by going to dot.net, then navigating to
Getting started, create the project. For this post, the example will be a console app. I also have a preference for the Paket package manager. This isn’t strictly necessary, but the benefits are worth the adjustment. To do this I need to convert the project to use Paket. If you want to stick with the default nuget, that’s fine, you’ll just need to do ignore a couple commands and mentally map
paket add to
dotnet new console --language F# --name SerilogExample
Next, add the required packages for configuration and logging. Since I will use config file based configuration, I use the
ConfigurationBuilder that .NET Core apps commonly use. At this point I should note that Serilog has additional Sinks as logging targets. Check them out if you want more than plain logfiles.
paket add Microsoft.Extensions.ConfigurationBuilder --project SerilogExample.fsproj
Time to open up
Program.fs and get to work. First, add the necessary namespaces.
The logger object can be created in a couple different ways. The first way I’ll examine is being entirely configuration file driven. To do this I need a Configuration object loaded from a json formatted file.
Before going any further, the configuration file needs created. Add a
config.json file to the root of the project and populate as below. Other application-specific configuration can be in here as well, but the Serilog settings need to be under the
Serilog section. This example will only log messages with a log level of
Information and higher. The Serilog
LiterateConsole is used for outputting to STDOUT.
RollingFile is used for the logfile creation (including a templated name, max file size, and max file count).
Now that a configuration file is created, there is an additional need to address. By default the config file does not get copied to the bin directory on compilation. To ensure the config file ends up where desired (and needed), the
.fsproj file needs modified. Adding
config.json as a content file, copies it to the output directory when building the project.
By this point, most of the work has been done. All that is left to do is feed the configuration object to the Serilog constructor. Logger created.
use logger =
Using the logger is straight forward. If you haven’t used Serilog before, it also supports string interpolation.
let foo = "bar"
Note, the logging level is set to
Information in the config file, so the debug message doesn’t display. Here is how it looks in the console and logfile.
Done, right? Not so fast. Serilog does not need to be entirely config file driven. I’m going to replace the previous logger creation with the below code. There are a couple difference. First, I make the log level
Debug. More interestly I leverage Serilog’s ability for structured logging.
use logger =
Now I run the same logger calls, and here is how it looks in the console and logfile. You can see the debug messages, but more importantly, the log file now has structured events.
Hopefully you have found these Serilog examples useful when integrating logging into your new .NET Core F# applications. Until next time.