How to Log with ASP.NET, NLog and Amazon CloudWatch Logs
NLog is known for being a free, flexible logging solution which supports structured, as well as traditional logging within the .NET ecosystem. NLog has logging targets for the console, for files, and for databases. However, in this tutorial, we’ll use ASP.NET along with NLog to store logs in CloudWatch Logs.
Photo by Robert Larsson on Unsplash
The Solution
In this tutorial, we will build a basic ASP.NET API, with the goal of logging to Amazon CloudWatch Logs using NLog.
Remember, for any example solution from AWS with .NET, we focus on the code that exemplifies the problem we are trying to solve. We don’t include logging, input validation, exception handling, etc., and we embed the configuration data within classes instead of using environment variables, configuration files, key/value stores and the like. These items should not be skipped for proper solutions.
Prerequisites
To complete this solution, you will need the .NET CLI which is included in the .NET SDK. In addition, you will need to create an AWS IAM user with programmatic access with the appropriate permissions to interact with Amazon CloudWatch Logs. In addition, you will need to download the AWS CLI and configure your environment.
Warning: some AWS services may have fees associated with them.
Our Dev Environment
This tutorial was developed/updated using Ubuntu 24.10, .NET 8 SDK and Visual Studio Code 1.95.3. Some commands/constructs may vary across systems.
Developing the ASP.NET API
First, we’ll create the ASP.NET App using the .NET CLI.
$ dotnet new webapi -n CloudWatchNLog --use-controllers
Add App Dependencies
Let’s now add the application dependencies. We’ll add dependencies for the NLog platform, supporting ASP.NET configuration and middleware as well as using AWS CloudWatch Logs as the NLog target.
$ dotnet add package NLog
$ dotnet add package NLog.Extensions.Logging
$ dotnet add package NLog.Web.AspNetCore
$ dotnet add package AWS.Logger.NLog
Update the Application’s Program.cs File
Let’s now update the Program.cs file to pull in the NLog configuration. We’ll configure the app in a later step.
First, add the NLog related using statements.
using NLog;
using NLog.Extensions.Logging;
using NLog.Web;
Once the using statements are added, update the Program.cs file to hook up the NLog configuration right after the builder initialization.
var config = builder.Configuration;
builder.Logging.ClearProviders();
builder.Host.UseNLog();
LogManager.Setup().LoadConfigurationFromAppSettings();
When completed, the Program.cs file should look something like the following:
using NLog;
using NLog.Web;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
builder.Logging.ClearProviders();
builder.Host.UseNLog();
LogManager.Setup().LoadConfigurationFromAppSettings();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Develop an Endpoint that Logs to CloudWatch
We’ll now create a controller that will allow us to test our CloudWatch Logs integration. Let’s call this new controller, LoggingTestController. For our purposes, we’ll only need to create a controller that supports just one single GET method.
We’ll use constructor injection to get an instance of an ILogger object.
using Microsoft.AspNetCore.Mvc;
namespace CloudWatchNLog.Controllers;
[ApiController]
[Route("[controller]")]
public class LoggingTestContoller : ControllerBase
{
private readonly ILogger<LoggingTestContoller> _logger;
public LoggingTest(ILogger<LoggingTestContoller> logger)
{
_logger = logger;
}
[HttpGet]
public string Get()
{
}
}
To test NLog with Cloud Watch Logs, we’ll flesh out the Get method a bit.
We’ll first create a string variable named thatThingToLog with a simple value. We’ll then log an error using the logger that we instantiated via constructor injection, providing the variable that we just created as the data to log.
We’ll return the “thatThingToLog” variable to complete the “Get” method.
public string Get()
{
string thatThingToLog = "This is a test string to log via NLog";
_logger.LogError(thatThingToLog);
return thatThingToLog;
}
The code below is the LoggingTestController in it’s entirety.
using Microsoft.AspNetCore.Mvc;
namespace CloudWatchNLog.Controllers;
[ApiController]
[Route("[controller]")]
public class LoggingTestContoller : ControllerBase
{
private readonly ILogger<LoggingTestContoller> _logger;
public LoggingTest(ILogger<LoggingTestContoller> logger)
{
_logger = logger;
}
[HttpGet]
public string Get()
{
string thatThingToLog = "This is a test string to log via NLog";
_logger.LogError(thatThingToLog);
return thatThingToLog;
}
}
Create the CloudWatch Logs App Configuration
With the foundation of the application setup, let’s configure the application. The configuration will allow us to send our logging data to CloudWatch Logs. In this particular app, we’ll add the configuration data to the .NET appsettings.Development.json file. The configuration file should look something like the following:
{
"NLog": {
"extensions": [
{
"assembly": "NLog.Extensions.Logging"
},
{
"assembly": "NLog.Web.AspNetCore"
},
{
"assembly": "NLog.AWS.Logger"
}
],
"targets": {
"aws": {
"type": "AWSTarget",
"logGroup": "AWSwithDotnetNLog"
}
},
"rules": [
{
"logger": "\*",
"minLevel": "Info",
"writeTo": "aws"
}
]
}
}
Let’s run through the NLog portion of the appsettings.Development.json configuration file:
Extensions: This section contains a list of assemblies to load for targets and logging layouts.
Targets: This section defines a list of targets that can be used by NLog.
Target.AWS.Type: The type of logging target.
Target.AWS.LogGroup: The AWS CloudWatch log group to log to.
Rules.MinLevel: This section represents the log level threshold.
Rules.WriteTo: Configures ASP.NET/NLog to write to the log target defined above, “aws”. For this example, we are targeting CloudWatch Logs.
Test the NLog/CloudWatch .NET App
With the application developed, let’s spin up the test app.
Run the ASP.NET Web API application using the following command.
$ dotnet run
Using the host and port that is noted in the console, navigate to the URL of the LoggingTestController endpoint that we created. In our test case, it is: http://localhost:5199/loggingtest.
The console should have a message that reads like the following.
This is a test string to log via NLog
Drill into CloudWatch Logs in the AWS Console and look for your log group. Once you find it, you should see an entry like the following:
2024-07-31T2020:23.896 This is a test string to log via NLog
Summary
We have concluded this tutorial in which we have developed an application that logs ASP.NET log events to Amazon CloudWatch Logs using NLog.
Want to know more about the tech in this article? Checkout these resources:
.NET CLI, .NET SDK, AWS .NET SDK, Amazon CloudWatch Logs, NLog