Make Your Logs Work for You

The days of logging in to servers and manually viewing log files are over. SolarWinds® Papertrail™ aggregates logs from applications, devices, and platforms to a central location.

View Technology Info

FEATURED TECHNOLOGY

Troubleshoot Fast and Enjoy It

SolarWinds® Papertrail™ provides cloud-based log management that seamlessly aggregates logs from applications, servers, network devices, services, platforms, and much more.

View Capabilities Info

FEATURED CAPABILITIES

Aggregate and Search Any Log

SolarWinds® Papertrail™ provides lightning-fast search, live tail, flexible system groups, team-wide access, and integration with popular communications platforms like PagerDuty and Slack to help you quickly track down customer problems, debug app requests, or troubleshoot slow database queries.

View Languages Info

FEATURED LANGUAGES

TBD - APM Integration Title

TBD - APM Integration Description

TBD Link

APM Integration Feature List

TBD - Built for Collaboration Title

TBD - Built for Collaboration Description

TBD Link

Built for Collaboration Feature List

Tips from the Team

Centralized Logging for .NET 5 Applications

Start Free Trial

Fully Functional for 14 Days

.NET 5 is a shifting point for the .NET ecosystem, bringing Mono, Xamarin, and .NET development into a single codebase. Almost a year later, however, there’s still some confusion lingering, especially when it comes to migrating your old apps.

In this post, we’ll provide a guide to the current state of the .NET ecosystem. We’ll cover, among other things:

  • What .NET 5 is and how it relates to .NET Core
  • Why .NET 5 was created
  • Whether the “full” .NET framework is still alive

After covering those basics, we’ll move to logging: what does logging look like in .NET 5? How do you get started in practice?

What Is .NET 5?

.NET 5 is the most recent major version of .NET Core, released in November 2020. This is an open source, cross-platform, unified framework you can use to create apps and services for Windows, Linux, macOS, and mobile.

What about the choice of name and version number? Two things happened here:

  1. The “Core” was dropped to indicate there’s only one .NET going forward.
  2. The 4.0 version number was skipped since this would cause confusion with the “old” .NET framework, currently in the 4.x versions.

You might be wondering why we needed .NET 5 in the first place.

Why Does .NET 5 Exist and Why Does It Matter so Much for Cross-Platform Apps?

Why is .NET 5 a thing? After all, there were already alternatives for cross-platform development before it. The answer is: to make .NET organized and to make developers’ lives easier.

Before .NET 5, the .NET ecosystem was fragmented. As a developer writing cross-platform solutions, it was hard to know which APIs were supported by which platforms.

.NET standard—an interface or contract to express supported features—was created to solve this problem, but it adds complexities of its own. For instance, every time a new feature was added, every supported environment had to be changed.

.NET 5 solves this problem by bringing a unified codebase to support all platforms.

Is the Old .NET Framework Dead?

.NET 4.8 will be the last version of the classical .NET framework. It’s now considered legacy since it won’t receive new functionalities and APIs. But this doesn’t mean it’s dead in the sense that it’s unsafe to use. Quite the opposite: it will continue to be supported—getting security patches and critical bug fixes, for example—so you don’t necessarily have to port all your legacy code to .NET 5.

However, the sunsetting of the .NET framework means, going forward, .NET 5 and future versions should be the preferred version for all new development.

.NET 5 vs. .NET Core 3.x vs. .NET Standard: Differences and Similarities

.NET 5 was created to unify .NET going forward, but there’s still some confusion. Let’s clarify by explaining the differences and similarities between some existing nomenclature.

Let’s start with .NET standard. This isn’t a  “version” of .NET, but a target created to help developers ensure their code would run correctly on different platforms. If you configure your code to target .NET standard 2.0, for instance, you ensure it will run on all platforms that support that standard. You’ll lose access to some APIs specific to some other platforms, though.

As we’ve said, .NET 5 is the successor to .NET Core 3.x and represents the future of .NET development. It provides a unified codebase for all platforms, greatly simplifying everything. If a new API is introduced, for instance, it’s automatically available for all platforms, and all developers can start leveraging it.

Logging in .NET 5: What Does It Look Like?

For a long time, logging in the .NET framework was as fragmented as the platform itself. With .NET Core—and more recently, with .NET 5—this is no longer the case.

.NET 5 offers a dedicated API for logging, with the namespace Microsoft.Extensions.Logging. This namespace offers its own logging providers, but you can also use the logging frameworks you already know and love (NLog, Serilog, etc.) with the API.

The advantages of doing so include dependency injection—better for unit testing—easier switching to different frameworks, and better integration with .NET.

In this scenario, log aggregation is very important. When you have a large organization containing many different apps generating logs, you run the risk of having siloed logs. As a result, it becomes hard to make use of the knowledge contained inside all those log files.

Log aggregation allows you to collect log entries from many disparate sources, bring them together in a centralized place, and parse and analyze them, so you can use the knowledge inside them.

.NET 5 Logging: How to Get Started

For this tutorial, we assume you have .NET 5 installed and are comfortable working with the command line. While optional, we also recommend you use Visual Studio Code to follow along.

Run the following commands:

mkdir net5log
cd net5log
dotnet new webapi
code . # replace this line if you don’t use VS Code

After opening the project, you should see something like the following image.

If you go back to your terminal—or, better yet, use the one integrated within Visual Studio Code—and execute dotnet run, you’ll be able to then open your browser at https://localhost:5001/WeatherForecast and see the API working.

In my case, I get this nice formatting for the JSON response with the help of a browser extension. Let’s get started with logging to this API.

First, go to the WeatherForecastController class, inside the Controllers folder. Notice its list of usings include this line.

using Microsoft.Extensions.Logging;

Also, look at how the class constructor takes an instance of the  ILogger<WeatherForecastController> class as a parameter.

public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

As it turns out, all the pieces are in place for us to start logging. Go to the public IEnumerable<WeatherForecast> Get() method inside WeatherForecastController and add the following three lines to it.

_logger.LogInformation("This is an INFORMATION message.");
_logger.LogWarning("This is a WARNING message.");
_logger.LogError("This is an ERROR message.");

Now, simply run the API with dotnet run and use your browser to access https://localhost:5001/WeatherForecast. On your terminal, you’ll see something like this.

Success! You’ve just written your first log messages in .NET 5.

.NET 5 Logging, A Step Further: Logging Using a Third-Party Framework

Let’s continue our tutorial, going one step further. We’ll show you how to log using the log framework log4net.

Start by installing the log4net NuGet package.

dotnet add package log4net --version 2.0.12

Then install a different NuGet package, the log4net provider for the Microsoft.Extensions.Logging interface.

dotnet add package Microsoft.Extensions.Logging.Log4Net.AspNetCore --version 5.0.4

The next step is to configure log4net. Create a file called log4net.config at the root of your project and paste the following content on it.

<log4net>
    <root>
      <level value="ALL" />
      <appender-ref ref="file" />
    </root>
    <appender name="file" type="log4net.Appender.RollingFileAppender">
      <file value="net5demo.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
      </layout>
    </appender>
  </log4net>

I won’t go into much detail about the file above. You can research later to learn more about the log4net config format. Suffice it to say that we’re defining a file appender—a target destination—configured to create new files each 10 MB.

Now we can change the code. As you’ll see, the changes will be minimal.

Start by going to the Startup.cs file. Change the Configure method, including a third parameter of type ILoggerFactory.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)

Then, inside the method, just add this line.

loggerFactory.AddLog4Net();

That’s it. Now, .NET will make sure to instantiate the correct instance of ILogger and pass it to the controller. Since the interface is the same, the controller code won’t even notice something has changed!

Now run the project again (dotnet run), and use the browser (or CURL, or Postman) to access the https://localhost:5001/WeatherForecast endpoint.

Then, afterward, go to the projects folder. Inside the bin folder you’ll find the log file.

Conclusion

Logging is essential for virtually all applications. It’s what prevents you from going blind when trying to debug or postmortem an app that’s misbehaving in production. That’s true for all tech stacks and environments; .NET is no exception.

In this post, we’ve seen how .NET used to be a fragmented ecosystem. This changed with the arrival of .NET 5, which represents the ideal of a unified .NET going forward. For logging, .NET 5 brings a new namespace with a universal abstraction to facilitate dependency injection and testing, and to allow developers to freely choose between competing logging providers. If you also want an easier way to manage your logs, check out SolarWinds® Papertrail.

Thanks for reading, and until next time.

This post was written by Carlos Schults. Carlos is a consultant and software engineer with experience in desktop, web, and mobile development. Though his primary language is C#, he has experience with a number of languages and platforms. His main interests include automated testing, version control, and code quality.

Aggregate, organize, and manage your logs

  • Collect real-time log data from your applications, servers, cloud services, and more
  • Search log messages to analyze and troubleshoot incidents, identify trends, and set alerts
  • Create comprehensive per-user access control policies, automated backups, and archives of up to a year of historical data
START FREE TRIAL

Fully Functional for 30 Days

Let's talk it over

Contact our team, anytime.