5 Best Practices for C# Logging for IT Pros

By dnsstuff on April 2, 2020

In modern IT environments, the importance of log management cannot be overemphasized. Organizations use a wide range of log management tools to generate, transmit, store, analyze, archive, and replace old log files with new data files in large volumes within a centralized system. Logging implementation in C# helps determine the behavior of web apps. It can help you collect, store, and index logs for quick searching and easy debugging. It also helps gather in-app user statistics such as demographics, usage trends, and interaction to further help in monitoring and analysis.

However, logs created by computing resources and applications vary in content and format they are stored. In the computing world, a log is a record, message, or an event trail with timestamps automatically produced by almost all apps and computers. Logging refers to the writing of messages and exceptions to a log file in a particular format (e.g., JSON log file). There are many logging tools, log managers, and logging-as-a-service (LaaS) platforms available in the market documenting and processing log files in machine-readable format efficiently.

This article contains a list of the five industry-standard best practices for logging data in C#:

  1. Do not invest your time in writing logging library from scratch
  2. Structured logging brings business intelligence to help your IT pros stay in shape
  3. Leverage efficient third-party logging frameworks
  4. Use log exceptions and contextual data for effective production debugging
  5. Set and segment logging levels to filter out data

Before discussing them, let’s look at the essential elements of logging first.

While writing logging code for your applications, you need to have a clear understanding of the following:

  • Logging frameworks or libraries: You can use these for creating, structuring, and managing log events. Some of the popular logging frameworks are NLog, log4net, log4j, Serilog, Error Logging Modules and Handlers (ELMAH), and Microsoft TraceSource.
  • Logging levels: Leveraging levels, you can classify data entries in the log files and filter out relevant information by urgency. Some standard levels used in application logging are: FATAL, WARN, ERROR, DEBUG, INFO, TRACE, ALL, and OFF.
  • Log targets: Log targets help in logging or capturing messages from various sources – objects, services, etc. Logging frameworks have built-in appenders to send log entries to different log target types. Common log target types are File, Cache, Database, Console, syslog, Event Tracing for Windows (ETW), and more.

Understanding C# Logging With an Example

Let’s assume a use case where there’s an application created as a ConsoleProject in Visual Studio. It displays “Welcome User” as a message and dismisses as you press “Enter.” The lines of code written to your Program class defined are as follows:

static void Main(string[] args)
{
var displayMessage = “Welcome User”;
Console.WriteLine(displayMessage);
Console.ReadLine();
}

But, if you want to log the events occurring in this app, embed the following line of code in your existing codebase. Do not forget to add the “using System.IO;” namespace at the top.
static void Main(string[] args)

{
var displayMessage = “Welcome User”;
File.WriteAllText(“log.txt,” displayMessage);
Console.WriteLine(displayMessage);
Console.ReadLine();
}

Now, when you refresh your application by pressing F5 or Ctrl-R, the same “Welcome User” message will be displayed, but with a log file will be created in the project directory. You can search and find the log file by navigating back to the Bin → Debug folder.
However, this was the most basic example of logging code in C#. For more advanced applications, you need efficient logging frameworks and package managers.
Moving on to the top five best practices for C# logging:

1) Do not invest your time in writing logging library from scratch

Writing your bespoke logging library or framework from scratch is time-consuming. With the growth of complex applications and huge volumes of data, it becomes difficult to manage, maintain, and update the in-house library. It’s a smart move to implement a native, standard logging framework having all the APIs for logging, tracing, and debugging.

2) Structured logging brings business intelligence to help your IT pros stay in shape

Structured logging, also known as semantic logging, is a useful practice for writing logs using a pre-defined, consistent message format with semantics. The log data aggregated through this technique is well-structured and enables tools you to extract valuable insights using any log analyzer or log management tool . On the other hand, the basic logging process is arbitrary, which requires custom parsing for attribute extraction.

Structured logging records and displays log events in a simple, easy-to-ready JSON encoded format. Also, you don’t need to write any custom parsing rules to make the data readable. It will help you deep dive into log entries and diagnose errors or issues in your applications using a capable log management and monitoring tool.

SolarWinds® Papertrail is one such highly recommended tool. The tool allows you to make the most of your logs with powerful search and log tail features, which help you monitor and resolve issues in real time.

Papertrail log monitoring

In addition to making search and analysis faster, Papertrail also simplifies C# log management. It supports all types of logging frameworks, whether it’s log4net, NLog, serilog, or the syslog library. A familiar command line interface with highly intuitive tagging and filtering features make Papertrail popular among developers. You can also get a lifetime free trial of Papertrail here.

3) Leverage efficient third-party logging frameworks

There are various third-party libraries that are easily configurable, flexible, and offer built-in logging APIs. For example, you can easily install and setup the log4net library in the system using Microsoft’s Visual Studio package manager – NuGet. The ready-made tested libraries do the heavy lifting, where a logger is created for writing messages to files and rolling log files at regular intervals.

4) Use log exceptions and contextual data for effective production debugging

Debugging applications in a production environment is complex. It’s essential to log exceptions and contextual data to understand application errors occurring in production. Both handled and unhandled exceptions are vital pieces of information required to fix the bug. While writing a logging code or configuring a logger, you must add a try or catch statement – log. Error() for handled exceptions and register for events catching thrown exceptions in the code.

On the other hand, contextual data is equally important for an effective debugging workflow in the production stage. Logging context such as HTTP requests, current machine in use, existing threads, state of the machine, and timestamps of transactions made by users helps in monitoring, analysis, and troubleshooting web apps.

5) Set and segment logging levels to filter out data

Most of the logging frameworks have default logging levels allowing them to filter out irrelevant log messages for a particular scenario or use case. Each logging level assigned to a logger shows only a specific set of logs or information and adds context to the scenario.

For example, in case of unexpected errors (like misconfiguration, loss of connection, etc.), your IT and developers team would want to see all the Error messages during exception catches to understand root causes. Using the ERROR level will send only the messages of ERROR priority in your config file. You surely don’t want to go through thousands of log entries while trying to diagnose a particular problem.

As a best practice, you should set up logging levels in separate configuration files located in the same folder as your app executable. This segmentation sends different types of log messages into respective files. E.g., DEBUG priority messages will go to debug.log, FATAL logs to fatal.log, and so on.

Related Posts