[C#] Outputting Logs to Files with NLog (.NET Generic Host)

The standard Microsoft.Extensions.Logging in .NET is excellent, but its default capabilities for “outputting logs to text files” and “log rotation” (switching files by date) are limited. By introducing NLog, a high-performance third-party library, you can achieve flexible file output and advanced formatting.

目次

Table of Contents

  • Implementation Steps
    1. Installing Packages
    2. Creating and Configuring nlog.config
    3. Program.cs (Enabling NLog)
    4. MyWorker.cs (Implementing Log Output)
  • Explanation
    • Benefits of NLog
    • The Role of UseNLog()

Implementation Steps

1. Installing Packages

Install the necessary package to use NLog with a .NET console application (Generic Host).

Bash

dotnet add package NLog.Extensions.Logging

Note: For web applications (ASP.NET Core), NLog.Web.AspNetCore is used, but for batch or console apps, the package above is the standard choice.

2. Creating and Configuring nlog.config

Create an XML file named nlog.config at the root of your project. Important: After creating the file, set its properties to “Copy to Output Directory: Copy always.”

The following configuration separates logs into two files: “Debug” (detailed) and “Error” (important), depending on the log level.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogLevel="Info"
      internalLogFile="internal-nlog.txt">

  <targets>
    <target xsi:type="File" name="debugLog" fileName="logs/debug-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />

    <target xsi:type="File" name="errorLog" fileName="logs/error-${shortdate}.log"
            layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />

    <target xsi:type="Console" name="console" 
            layout="${date:format=HH\:mm\:ss} [${uppercase:${level}}] ${message}" />
  </targets>

  <rules>
    <logger name="*" minlevel="Trace" writeTo="console" />

    <logger name="*" minlevel="Trace" maxlevel="Warn" writeTo="debugLog" />

    <logger name="*" minlevel="Error" writeTo="errorLog" />
  </rules>
</nlog>

3. Program.cs (Enabling NLog)

By calling .UseNLog() when building the Generic Host, NLog will run behind the standard ILogger.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using NLog.Extensions.Logging; // Required for UseNLog

namespace TaskApp
{
    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                await CreateHostBuilder(args).Build().RunAsync();
            }
            catch (Exception ex)
            {
                // Backup logging in case the program stops due to setup errors
                var logger = NLog.LogManager.GetCurrentClassLogger();
                logger.Error(ex, "Stopped program because of exception");
                throw;
            }
            finally
            {
                // Ensure to flush and stop internal timers/threads before application-exit
                NLog.LogManager.Shutdown();
            }
        }

        private static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging((context, logging) =>
                {
                    // Clear default providers and let NLog handle logging
                    logging.ClearProviders();
                    logging.SetMinimumLevel(LogLevel.Trace);
                })
                .UseNLog() // Enable NLog
                .ConfigureServices((context, services) =>
                {
                    services.AddHostedService<MyWorker>();
                });
    }
}

4. MyWorker.cs (Implementing Log Output)

The code here is exactly the same as when using the standard Microsoft.Extensions.Logging.ILogger. You do not need to be specifically aware that you are using NLog.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace TaskApp
{
    public class MyWorker : BackgroundService
    {
        private readonly ILogger<MyWorker> _logger;

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

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // Output logs at various levels
            // These are routed to files or the console based on nlog.config
            _logger.LogTrace("Trace: Tracing variable values...");
            _logger.LogDebug("Debug: Checking process branches");
            _logger.LogInformation("Information: Application has started");
            _logger.LogWarning("Warning: The process is taking a long time");
            
            // Logs at Error level or higher will be output to the errorLog file
            _logger.LogError("Error: Unexpected data received");
            _logger.LogCritical("Critical: Cannot connect to the database");

            return Task.CompletedTask;
        }
    }
}

Explanation

Benefits of NLog

Features that are difficult to implement with standard tools can be achieved through simple XML configuration:

  • Log Rotation: By writing fileName="logs/debug-${shortdate}.log", a new log file (e.g., debug-2026-01-09.log) is automatically created every day.
  • Target Routing: It provides powerful filtering, such as sending only errors to a specific file or ignoring logs from certain classes.
  • Flexible Formatting: You can freely customize the output format (CSV, JSON, tab-separated, etc.).

The Role of UseNLog()

Calling .UseNLog() in Program.cs registers NLog into the .NET Dependency Injection (DI) container. When you use ILogger<T> in classes like MyWorker, NLog is called as the actual implementation, and it performs output according to the settings in nlog.config.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次