Ive been trying to get an
ASP.NET Core site working with NLog. It works fine until I try to write to a SQL Database. I've tried local databases and Azure databases - all with the same problem. I've even added the nlog table to a known database, one the site already connects to (with EF).
Error Error when writing to database. Exception: System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections.
NLog is a logging framework for .NET. It has rich log routing and managementcapabilities and greatly helps you to produce and manage logs. NLog supportsstructured logs, multiple logging targets, and everything a modern loggingframework should support. In the long list of the NLog's features, you can find:
Before starting to work on the application, you need to install some dependencypackages. Visual Studio provides multiple ways to use the NuGet Package Manager.In the tutorial we will use the Package Manager Console.
The first thing you have to do is to open the Package Manager Console. You cando it using Tools > NuGet Package Manager > Package Manager Console.Alternatively, you can sequentially press ALT, V, E, and O.
NLog has rich configuration abilities and provides two ways to configure thelogger: programmatically or via a configuration file. You can get advancedinformation about each of themin the documentation.
Then, you have to set the file's Copy to Output Directory property to Copyalways. It can be done by right-clicking the file in the solution explorer andselecting the Properties option.
We've decided to add 3 logging targets for the application: the colorizedconsole and 2 files. In the config file, each of them will be represented by aseparate XML element. Let's write the targets in the nlog.config file.
Proper logging can greatly assist in the support and development of yourapplication. This may seem like a daunting task, but NLog is a fast andconfigurable logging framework that greatly simplifies the task.
When NLog originally came out, I was hooked. Such a step up from the world of log4net. Then Serilog came out and I lost track of the progress on NLog. For years I even considered it dead. Boy was I wrong. NLog has developed impressively over the years and offers all of the modern features available in similar logging frameworks like Serilog and Microsoft.Extensions.Logging. In this post, I'll tell you everything there is to know about NLog.
Let's start with the basics. NLog is a logging framework for .NET. Ok, you probably already knew that. Much like log4net and Serilog, NLog lets you log messages to a range of data stores (called targets). Everything from the console to SQL Server, document databases, and
elmah.io is supported and there are almost 100 of them. Also, NLog offers great flexibility when it comes to formatting messages and including additional information on each message.
NLog provides a great API for logging messages to one or more targets. If you are already familiar with similar logging frameworks, you will quickly be up and running logging with NLog. Let's dig into the details.
Understanding log levels and putting the right level on each message is very important. Log levels are used to mark the severity of each message as well as other features in NLog like log filtering. Consider the scenario where you are logging both to a local file and
elmah.io. You may want to log everything to the file but only Warn and up to
elmah.io. Putting the right log level on each message is essential for this to work properly.
Creating a new logger using the GetCurrentClassLogger method is the easiest way to obtain a logger for the current context. There are other ways to get a new logger and dependency injection is also available with NLog. I may write something about this later if you guys are interested.
As you already figured out, each log level has its own logging method. There is a range of different overloads accepting exceptions and other parameters. If you want greater control of what is getting logged, you can use a special overload accepting a LogEventInfo object:
NLog supports semantic/structured logging known from similar frameworks like Serilog and Microsoft.Extensions.Logging. With structured logging, you no longer log just simple text messages. Structured properties can be embedded directly as part of the message logged to the target (or through adding key/value pairs to Properties as shown in the previous section).
This will output the text This is a message from Mickey Donovan in the configured targets. For simple text files, this is probably just fine. But when storing errors in a database or cloud service, you may want to search for log messages containing a specific user's name. Full-text search is available in some databases and products, but it would be even easier if the target could persist both the full log message as well as the properties used to generate the message.
Notice the User property embedded in the log message? NLog will automatically format the string when generating the full log message, producing the same string as before. But by giving the property a name (`User`), we also tell NLog that this is a structured property. Depending on how the configured target is implemented, this can be used for various purposes. Like searching:
Improved searching is probably why most people use structured logging. But there is a range of new possibilities when storing log messages as structured data. Logging metrics as part of log messages can be used to produce advanced dashboards when using something like Elasticsearch/Kibana. Consider a log message produced on every HTTP request to a website:
With these data in a modern data store, you can create a dashboard showing the average response times either overall or grouped by URL. I'll show you an example of how to do this later in this article, but let's just agree on one thing so far: structured logging is pretty darn cool!
Sometimes (ok often) it makes sense to write additional properties as part of a log message, without including it in the log messages or as structured properties (also goes into the message when rendered). NLog provides a range of different context classes to do so. In this section, I'll introduce you to the various context types, how to use them, and when to use which one.
Context types available in NLog are generally dictionaries and stacks, keeping additional properties. The context can be either global for the entire application lifespan or scoped for something shorter living like a thread. Context properties can be used to include contextual information to each log message. As I will show you later in this tutorial, the context can be accessed from both NLog targets as well as log message rendering using Layouts.
This context is implemented in the GlobalDiagnosticsContext class and represents a dictionary spanning the entire lifetime of your application. This context is great for including global properties to all log messages. A global property could be the name of the application, the version number, or other common information that you want access to on all log messages.
MappedDiagnosticsLogicalContext works much like GlobalDiagnosticsContext. It's a dictionary of property keys and values. But, unlike GlobalDiagnosticsContext where properties are global, MappedDiagnosticsLogicalContext lets you add thread-local properties. This means that the added properties will be available inside the current thread only. This works great for something like including HTTP contextual properties per web request (each web request launch a new thread) or other threaded applications.
While browsing the NLog documentation or googling blog posts, you may find examples using a class named MappedDiagnosticsContext. This is the old, now obsolete, way of adding thread-local properties with NLog. New code should be based on the MappedDiagnosticsLogicalContext class. If you are using NLog 5, both MappedDiagnosticsContext and MappedDiagnosticsLogicalContext should be replaced with ScopeContext.
The NestedDiagnosticsLogicalContext class works a bit different than the context classes we have already looked at. It's a stack where you can push and pop one or more objects. This can be used for a range of different scenarios, like pushing a user's navigational journey throughout an application and logging this as part of a potential error.
In this example we push two strings on the context, run some code, pop one of the strings, run some more code, and finally pop the last string. In the Layout renderers section, I will show you how to use NestedDiagnosticsLogicalContext in your log messages and targets.
The ScopeContext was added in NLog 5 as a replacement for MappedDiagnosticsContext and MappedDiagnosticLogicalContext. All diagnostics properties should now be based on ScopeContext rather than using the old contexts:
In the Logging messages section, we saw how to log both simple and structured text messages. The rendered text message will typically be part of a larger context when written to a text file, database, remote logger, etc. Let's look at an example that most developers have seen IRL. A log statement like this:
So, why does the outputted line contain more information than the logged text message? Say hello to NLog layouts. Layouts are formatters for NLog log messages. Most targets include the following default if not overwritten in config:
As you can see a Layout consists of text and one or more macro-like strings (like $message) called layout renderers. Layout renderers aren't something that I have met a lot of people digging into and that's a bit of a shame. Layout renderers is a very strong feature of NLog and can be used for a range of possibilities.
Layout is something that can be changed on all targets. In the Configuration section, I'll show you how to update the layout. Before we start looking at the configuration, let's go through a couple of the most common layout renderers part of NLog.
3a8082e126