C#ログ出力の実装方法を徹底解説|初心者向けに標準機能・NLog・log4netの使い方まで紹介

はじめに

C#でアプリケーションを開発していると、「処理がどこまで進んだのか」「なぜエラーが発生したのか」「本番環境で何が起きているのか」を確認したい場面が必ず出てきます。そのときに重要になるのがログ出力です。

C#のログ出力は、初心者であればConsole.WriteLineから始められますが、実際の開発ではMicrosoft.Extensions.Logging、NLog、log4netなどを使って、ログレベルや出力先を管理するのが一般的です。特にWebアプリや業務システムでは、ログの残し方によって障害調査や保守のしやすさが大きく変わります。

この記事では、「C# ログ」と検索している初心者向けに、ログ出力の基本、標準機能での実装方法、ファイル出力、NLog、log4netの使い方、ライブラリの選び方、実装時のベストプラクティスまで分かりやすく解説します。

1. C#のログ出力とは?初心者がまず押さえるべき基本

1-1. ログ出力の役割と必要性

ログ出力とは、アプリケーションの実行中に発生した情報を記録する仕組みです。たとえば、処理の開始・終了、ユーザー操作、データベースアクセス、例外エラー、警告などを文字列として出力します。

C#でログを残しておくと、次のような場面で役立ちます。

・エラー発生時に原因を調査できる
・処理が正しく実行されたか確認できる
・本番環境で発生した問題を後から追跡できる
・パフォーマンスの遅い処理を見つけられる
・ユーザー操作やシステム状態を記録できる

開発中はデバッガーで処理を追えますが、本番環境ではVisual Studioで直接デバッグできないことがほとんどです。そのため、ログはアプリケーションの状態を知るための重要な手がかりになります。

1-2. ログで確認できる情報

C#のログでは、主に次のような情報を確認できます。

・ログ出力日時
・ログレベル
・実行された処理名
・メソッド名やクラス名
・入力値や処理対象のID
・エラーメッセージ
・例外のスタックトレース
・ユーザーIDやリクエストID
・処理時間

たとえば、注文処理でエラーが発生した場合、単に「エラーが発生しました」と出力するだけでは原因を特定しにくくなります。

C#
注文処理でエラーが発生しました

より実用的なログにするなら、次のように処理対象や例外情報を含めます。

C#
注文処理でエラーが発生しました。OrderId=12345, UserId=1001
System.InvalidOperationException: 在庫数が不足しています

このように、ログは「後から読んだ人が状況を再現できること」を意識して出力することが大切です。

1-3. Console.WriteLineとの違い

C#初心者が最初に使うログ出力の方法として、Console.WriteLineがあります。

C#
Console.WriteLine("処理を開始しました");

Console.WriteLineは簡単に使えるため、学習用や小さなコンソールアプリでは便利です。しかし、実務で使うログ出力としては機能が不足しやすいです。

Console.WriteLineでは、ログレベルの管理、ファイル出力、出力形式の統一、ログローテーション、環境ごとの設定変更などを自前で実装する必要があります。

一方、ILogger、NLog、log4netのようなログ機能を使うと、次のようなことが簡単にできます。

・Error以上だけをファイルに出力する
・Debugログは開発環境だけに出力する
・ログの出力形式を統一する
・日付ごとにログファイルを分ける
・古いログファイルを自動的に整理する
・コンソールとファイルの両方に出力する

つまり、Console.WriteLineは簡易確認用、ログライブラリは運用を考えた本格的なログ出力用と考えると分かりやすいです。

1-4. C#でログ出力を実装する主な方法

C#でログ出力を実装する方法には、主に次の種類があります。

方法特徴向いている用途
Console.WriteLine最も簡単学習用、簡易確認
Debug.WriteLineデバッグ時のみ使いやすい開発中の確認
Trace.WriteLineトレース情報を出力できる動作確認、診断
Microsoft.Extensions.Logging.NET標準のログ抽象化ASP.NET Core、汎用アプリ
NLog高機能で設定しやすいファイル出力、業務システム
log4net歴史が長く実績がある既存システム、レガシー環境

近年の.NETでは、ILoggerを中心としたMicrosoft.Extensions.Loggingが標準的に使われます。Microsoft公式ドキュメントでも、.NETはILogger APIを通じて構造化ログをサポートし、複数のログプロバイダーに出力できると説明されています。

2. C#ログ出力でよく使うログレベル

2-1. Trace・Debug・Information・Warning・Error・Criticalの違い

ログレベルとは、ログの重要度を表す分類です。C#のログ出力では、ログレベルを適切に使い分けることで、必要な情報だけを効率よく確認できます。

代表的なログレベルは次のとおりです。

ログレベル用途
Trace最も詳細なログ。細かい処理の流れを追跡したいとき
Debug開発中のデバッグ情報
Information通常の処理結果や状態の記録
Warningエラーではないが注意が必要な状態
Error処理に失敗したエラー
Criticalシステム停止につながる重大な障害

Microsoft.Extensions.LoggingのILoggerには、LogTraceLogDebugLogInformationLogWarningなどのメソッドが用意されています。

ログレベルは、重要度が低い順に並べると次のようになります。

Trace < Debug < Information < Warning < Error < Critical

たとえば、通常処理の開始はInformation、入力値が不正だが処理を継続できる場合はWarning、例外で処理に失敗した場合はErrorを使います。

2-2. 開発環境と本番環境で出力レベルを分ける考え方

C#ログ出力では、開発環境と本番環境で出力するログレベルを分けることが重要です。

開発環境では、原因調査や動作確認のためにDebugTraceも出力したいことがあります。一方、本番環境で詳細なログを大量に出力すると、ログファイルが肥大化したり、パフォーマンスに影響したり、機密情報が残ってしまう可能性があります。

一般的には、次のように分けると管理しやすくなります。

環境推奨されるログレベル
開発環境Trace、Debug、Information以上
検証環境Information、Warning、Error以上
本番環境InformationまたはWarning以上
障害調査時一時的にDebugを有効化

本番環境では、通常はInformation以上、ログ量を抑えたい場合はWarning以上に設定することが多いです。

2-3. ログレベルを使い分ける実装例

ILoggerを使うと、ログレベルごとにメソッドを分けてログを出力できます。

C#
using Microsoft.Extensions.Logging;

public class OrderService
{
private readonly ILogger<OrderService> _logger;

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

public void CreateOrder(int orderId)
{
_logger.LogTrace("CreateOrderメソッドを開始しました。OrderId={OrderId}", orderId);

_logger.LogDebug("注文データを検証しています。OrderId={OrderId}", orderId);

try
{
_logger.LogInformation("注文処理を開始しました。OrderId={OrderId}", orderId);

// 注文処理
if (orderId <= 0)
{
_logger.LogWarning("不正な注文IDが指定されました。OrderId={OrderId}", orderId);
return;
}

_logger.LogInformation("注文処理が完了しました。OrderId={OrderId}", orderId);
}
catch (Exception ex)
{
_logger.LogError(ex, "注文処理でエラーが発生しました。OrderId={OrderId}", orderId);
throw;
}
}
}

この例では、処理の詳細な流れはTraceDebug、通常の処理結果はInformation、注意すべき状態はWarning、例外はErrorとして出力しています。

3. C#標準機能でログ出力を実装する方法

3-1. Console.WriteLineで簡易的にログを出力する方法

最も簡単なC#ログ出力は、Console.WriteLineを使う方法です。

C#
using System;

class Program
{
static void Main()
{
Console.WriteLine("アプリケーションを開始しました");

int userId = 1001;
Console.WriteLine($"ユーザーID: {userId} の処理を開始します");

Console.WriteLine("アプリケーションを終了しました");
}
}

実行すると、コンソールに文字列が表示されます。学習中や簡単な確認には十分ですが、ログレベルや出力先を柔軟に切り替えたい場合には不向きです。

3-2. Debug.WriteLineでデバッグ用ログを出力する方法

Debug.WriteLineは、デバッグ時に情報を出力したい場合に使います。

C#
using System.Diagnostics;

class Program
{
static void Main()
{
Debug.WriteLine("デバッグログを出力しました");

int count = 10;
Debug.WriteLine($"count={count}");
}
}

Visual Studioでは、出力ウィンドウにデバッグログが表示されます。開発中の確認には便利ですが、本番環境のログとして使うものではありません。

3-3. Trace.WriteLineでトレースログを出力する方法

Trace.WriteLineは、アプリケーションの動作を追跡するためのログ出力に使えます。

C#
using System.Diagnostics;

class Program
{
static void Main()
{
Trace.WriteLine("トレースログを出力しました");

ExecuteTask();
}

static void ExecuteTask()
{
Trace.WriteLine("ExecuteTaskを開始しました");
Trace.WriteLine("ExecuteTaskを終了しました");
}
}

Traceは処理の流れを追いたいときに使えますが、実務ではより柔軟なILoggerやログライブラリを使うケースが多いです。

3-4. Microsoft.Extensions.Loggingを使う方法

Microsoft.Extensions.Loggingは、.NETで標準的に使われるログ出力の仕組みです。ログの出力先を「プロバイダー」として追加できるため、コンソール、デバッグ出力、EventLog、外部ログサービスなどに切り替えやすいのが特徴です。

コンソールアプリで使う場合は、NuGetで次のパッケージを追加します。

PowerShell
Install-Package Microsoft.Extensions.Logging
Install-Package Microsoft.Extensions.Logging.Console

.NET CLIを使う場合は次のように追加できます。

Bash
dotnet add package Microsoft.Extensions.Logging
dotnet add package Microsoft.Extensions.Logging.Console

3-5. ILoggerを使ったログ出力のサンプルコード

コンソールアプリでILoggerを使う基本例は次のとおりです。

C#
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

class Program
{
static void Main()
{
using var serviceProvider = new ServiceCollection()
.AddLogging(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Information);
})
.BuildServiceProvider();

var logger = serviceProvider
.GetRequiredService<ILogger<Program>>();

logger.LogInformation("アプリケーションを開始しました");

try
{
Execute();
logger.LogInformation("処理が正常に完了しました");
}
catch (Exception ex)
{
logger.LogError(ex, "処理中にエラーが発生しました");
}
}

static void Execute()
{
// 何らかの処理
}
}

ILogger<T>を使うと、ログのカテゴリ名にクラス名が使われます。これにより、どのクラスから出力されたログなのかを判別しやすくなります。

3-6. appsettings.jsonでログ設定を変更する方法

ASP.NET Coreでは、appsettings.jsonでログレベルを設定するのが一般的です。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

この設定では、アプリケーション全体の既定ログレベルをInformationにし、Microsoft.AspNetCoreカテゴリのログはWarning以上に絞っています。

開発環境だけ詳細なログを出したい場合は、appsettings.Development.jsonを使います。

JSON
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Information"
}
}
}

このように設定ファイルでログレベルを変更できるため、ソースコードを修正せずに環境ごとのログ出力を制御できます。

4. C#でファイルにログ出力する方法

4-1. StreamWriterを使ってテキストファイルに出力する方法

C#でファイルにログを出力するだけなら、StreamWriterを使って簡単に実装できます。

C#
using System;
using System.IO;

class Program
{
static void Main()
{
WriteLog("アプリケーションを開始しました");
WriteLog("処理を実行しました");
WriteLog("アプリケーションを終了しました");
}

static void WriteLog(string message)
{
string logPath = "app.log";
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {message}";

using StreamWriter writer = new StreamWriter(logPath, append: true);
writer.WriteLine(logMessage);
}
}

このコードでは、app.logというファイルにログを追記します。append: trueを指定しているため、既存のログを消さずに末尾へ追加できます。

4-2. 例外発生時のログをファイルに保存する方法

例外が発生したときは、エラーメッセージだけでなく、例外オブジェクト全体をログに残すことが大切です。

C#
using System;
using System.IO;

class Program
{
static void Main()
{
try
{
int x = 10;
int y = 0;
int result = x / y;
}
catch (Exception ex)
{
WriteLog("エラーが発生しました");
WriteLog(ex.ToString());
}
}

static void WriteLog(string message)
{
string logPath = "error.log";
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {message}";

using StreamWriter writer = new StreamWriter(logPath, append: true);
writer.WriteLine(logMessage);
}
}

ex.Messageだけを出力すると、エラー内容は分かっても、どのメソッドの何行目付近で発生したのかが分かりにくくなります。ex.ToString()を出力すると、例外の種類、メッセージ、スタックトレースをまとめて確認できます。

4-3. ログファイル名に日付を付ける方法

ログファイルが1つだけだと、長期間の運用でファイルサイズが大きくなりすぎます。簡単な対策として、ログファイル名に日付を付ける方法があります。

C#
using System;
using System.IO;

class Program
{
static void Main()
{
WriteLog("日付付きログファイルに出力しました");
}

static void WriteLog(string message)
{
string logDirectory = "logs";

if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}

string fileName = $"app_{DateTime.Now:yyyyMMdd}.log";
string logPath = Path.Combine(logDirectory, fileName);

string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {message}";

using StreamWriter writer = new StreamWriter(logPath, append: true);
writer.WriteLine(logMessage);
}
}

この例では、logs/app_20260612.logのような形式で日付ごとにログファイルを作成します。

4-4. ファイル出力時の注意点

自前でログをファイル出力する場合は、次の点に注意が必要です。

・ログフォルダが存在しない場合は作成する
・アプリケーションに書き込み権限があるか確認する
・複数スレッドから同時に書き込む場合の競合に注意する
・ログファイルのサイズが大きくなりすぎないようにする
・例外ログ出力処理自体で例外が起きる可能性を考える
・個人情報やパスワードを出力しない

特にWebアプリやWindowsサービスでは、実行ユーザーにログフォルダへの書き込み権限がないため、ファイル出力に失敗するケースがあります。

4-5. 自前実装よりログライブラリを使うべきケース

次のような要件がある場合は、自前実装ではなくNLogやlog4netなどのログライブラリを使うのがおすすめです。

・ログレベルで出力を制御したい
・ファイルサイズや日付でログをローテーションしたい
・コンソールとファイルの両方に出力したい
・ログ形式を統一したい
・非同期でログ出力したい
・複数プロジェクトで共通のログ設定を使いたい
・本番運用を想定している

自前実装は学習には役立ちますが、実務ではログライブラリを使った方が安全で保守しやすくなります。

5. NLogを使ったC#ログ出力の実装方法

5-1. NLogとは

NLogは、.NET向けの高機能なログ出力ライブラリです。コンソール、ファイル、データベースなど複数の出力先に対応しており、設定ファイルでログの出力先や形式、ログレベルを柔軟に変更できます。NLog公式サイトでも、NLogはさまざまな.NETプラットフォーム向けの柔軟で無料のログプラットフォームであり、コンソール、ファイル、データベースなど複数のターゲットに出力できると説明されています。

NLogのメリットは次のとおりです。

・設定が分かりやすい
・ファイル出力が簡単
・ログレベルの制御がしやすい
・ログローテーションに対応しやすい
・構造化ログにも対応できる
・ASP.NET Coreでも使いやすい

C#でファイルログをしっかり残したい場合、NLogは初心者にも扱いやすい選択肢です。

5-2. NLogのインストール方法

NuGetパッケージマネージャーコンソールで、次のコマンドを実行します。

PowerShell
Install-Package NLog

.NET CLIを使う場合は次のコマンドです。

Bash
dotnet add package NLog

ASP.NET CoreでNLogを使う場合は、次のパッケージを追加することが多いです。

Bash
dotnet add package NLog.Web.AspNetCore

コンソールアプリでMicrosoft.Extensions.Loggingと連携する場合は、次のパッケージを使うケースもあります。

Bash
dotnet add package NLog.Extensions.Logging

NLogはNuGetパッケージとして提供されています。

5-3. NLog.configの基本設定

NLogでは、NLog.configにログ出力の設定を書きます。

XML
<?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">

<targets>
<target xsi:type="Console"
name="console"
layout="${longdate} ${level:uppercase=true} ${message} ${exception:format=tostring}" />

<target xsi:type="File"
name="file"
fileName="logs/app_${shortdate}.log"
layout="${longdate} ${level:uppercase=true} ${logger} ${message} ${exception:format=tostring}" />
</targets>

<rules>
<logger name="*" minlevel="Info" writeTo="console,file" />
</rules>
</nlog>

NLogでは、targetsで出力先、rulesでどのログをどの出力先に流すかを設定します。公式ドキュメントでも、NLogの設定ではTargetsがログイベントの出力先、Layoutがログ形式を表す要素として説明されています。

5-4. コンソールにログ出力する方法

NLogを使ってコンソールにログを出力する基本コードは次のとおりです。

C#
using NLog;

class Program
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

static void Main()
{
Logger.Info("アプリケーションを開始しました");
Logger.Debug("デバッグ情報です");
Logger.Warn("警告ログです");
Logger.Error("エラーログです");

LogManager.Shutdown();
}
}

NLog.configでコンソールターゲットを設定していれば、Logger.Infoなどのメソッドでログを出力できます。

5-5. ファイルにログ出力する方法

NLogでファイルにログを出力するには、NLog.configにFileターゲットを設定します。

XML
<target xsi:type="File"
name="file"
fileName="logs/app_${shortdate}.log"
layout="${longdate} ${level:uppercase=true} ${message} ${exception:format=tostring}" />

C#コード側では通常どおりログを出力します。

C#
using NLog;

class Program
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

static void Main()
{
try
{
Logger.Info("ファイルログの出力を開始しました");

Execute();

Logger.Info("ファイルログの出力が完了しました");
}
catch (Exception ex)
{
Logger.Error(ex, "処理中に例外が発生しました");
}
finally
{
LogManager.Shutdown();
}
}

static void Execute()
{
// 何らかの処理
}
}

NLogを使うと、日付付きファイル名や例外の詳細出力を設定ファイル側で管理できるため、自前でStreamWriterを実装するより保守しやすくなります。

5-6. ログレベルや出力形式を変更する方法

NLogでは、rulesminlevelを変更することで出力するログレベルを制御できます。

XML
<rules>
<logger name="*" minlevel="Warn" writeTo="file" />
</rules>

この設定では、Warning以上のログだけがファイルに出力されます。

出力形式を変更したい場合は、layoutを編集します。

XML
layout="${longdate} [${level:uppercase=true}] ${logger} - ${message} ${exception:format=tostring}"

出力例は次のようになります。

2026-06-12 10:15:30.1234 [ERROR] MyApp.Program - 処理中に例外が発生しました System.Exception: ...

クラス名、スレッドID、リクエストIDなどを追加すれば、より調査しやすいログになります。

5-7. NLogでよくあるエラーと対処法

NLogでログが出力されない場合は、次の点を確認してください。

原因対処法
NLog.configが読み込まれていない出力ディレクトリにコピーされているか確認する
minlevelが高すぎるDebugInfoが出る設定か確認する
ファイルパスに書き込み権限がないlogsフォルダの権限を確認する
ターゲット名とwriteToが一致していないnamewriteToを確認する
アプリ終了時にログが書き切れていないLogManager.Shutdown()を呼ぶ

特に初心者がつまずきやすいのは、NLog.configが実行時の出力フォルダにコピーされていないケースです。Visual Studioでファイルのプロパティを開き、「出力ディレクトリにコピー」を「新しい場合はコピーする」に設定すると解決することがあります。

6. log4netを使ったC#ログ出力の実装方法

6-1. log4netとは

log4netは、Apache Logging Servicesが提供する.NET向けのログ出力ライブラリです。歴史が長く、既存の業務システムやレガシー環境で使われていることも多いです。

log4netでは、ログの出力先をAppender、ログの出力形式をLayoutとして設定します。設定ファイルを使って、コンソール出力、ファイル出力、ローリングファイル出力などを管理できます。

Apache log4netの公式ドキュメントでは、設定ファイルを使ってlog4netを構成する方法が推奨されています。

6-2. log4netのインストール方法

NuGetパッケージマネージャーコンソールで、次のコマンドを実行します。

PowerShell
Install-Package log4net

.NET CLIを使う場合は次のコマンドです。

Bash
dotnet add package log4net

インストール後、log4net.configを作成してログ出力設定を書きます。

6-3. log4net.configの基本設定

基本的なlog4net.configの例は次のとおりです。

XML
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline%exception" />
</layout>
</appender>

<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline%exception" />
</layout>
</appender>

<root>
<level value="INFO" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="FileAppender" />
</root>
</log4net>

ConsoleAppenderはコンソール出力、FileAppenderはファイル出力を行います。rootlevelで出力するログレベルを指定します。

6-4. コンソールにログ出力する方法

log4netを使ってログを出力するコード例は次のとおりです。

C#
using log4net;
using log4net.Config;
using System.Reflection;

class Program
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(Program));

static void Main()
{
var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));

Logger.Info("アプリケーションを開始しました");
Logger.Debug("デバッグログです");
Logger.Warn("警告ログです");
Logger.Error("エラーログです");
}
}

XmlConfigurator.Configurelog4net.configを読み込むことで、設定に従ってログが出力されます。

6-5. ファイルにログ出力する方法

ファイルにログを出力するには、FileAppenderを設定します。

XML
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline%exception" />
</layout>
</appender>

例外をログに残す場合は、次のようにLogger.Errorの第2引数に例外を渡します。

C#
try
{
throw new InvalidOperationException("サンプル例外です");
}
catch (Exception ex)
{
Logger.Error("処理中に例外が発生しました", ex);
}

これにより、例外メッセージだけでなくスタックトレースもログに出力できます。

6-6. RollingFileAppenderでログファイルをローテーションする方法

log4netでログファイルの肥大化を防ぐには、RollingFileAppenderを使います。RollingFileAppenderは、日付やファイルサイズに応じてログファイルを切り替えるAppenderです。Apache log4netの公式ドキュメントでも、日付単位でログファイルをロールする設定例が紹介されています。

日付ごとにログファイルを分ける設定例は次のとおりです。

XML
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="'.'yyyyMMdd'.log'" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline%exception" />
</layout>
</appender>

サイズでローテーションする場合は、次のように設定します。

XML
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logs/app.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maximumFileSize value="10MB" />
<maxSizeRollBackups value="5" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%level] %logger - %message%newline%exception" />
</layout>
</appender>

この設定では、ログファイルが10MBを超えるとローテーションされ、バックアップファイルを最大5個まで保持します。

6-7. log4netでよくあるエラーと対処法

log4netでログが出力されない場合は、次の原因が考えられます。

原因対処法
log4net.configを読み込んでいないXmlConfigurator.Configureを呼ぶ
configファイルが出力フォルダにないコピー設定を確認する
appender-refの名前が間違っているAppender名と参照名を一致させる
rootのlevelが高すぎるDEBUGINFOに変更して確認する
ログフォルダに書き込み権限がないフォルダ権限を確認する
conversionPatternが不正設定をシンプルにして確認する

log4netは設定ファイルの読み込みが重要です。特に.NET Coreや.NET 5以降のプロジェクトでは、log4net.configが実行フォルダにコピーされているか必ず確認しましょう。

7. C#のログ出力ライブラリを比較

7-1. 標準機能・NLog・log4netの違い

C#ログ出力でよく使われる標準機能、NLog、log4netを比較すると次のようになります。

項目Microsoft.Extensions.LoggingNLoglog4net
位置づけ.NET標準のログ抽象化高機能ログライブラリ歴史あるログライブラリ
初心者向け比較的分かりやすい分かりやすい設定に慣れが必要
ファイル出力追加プロバイダーが必要得意得意
ASP.NET Core非常に相性が良い対応しやすい利用可能
設定の柔軟性高い非常に高い高い
既存システムでの採用多い多い多い
新規開発でのおすすめ度高い高い既存環境次第

Microsoft.Extensions.Loggingはログの共通インターフェースとして優れており、ASP.NET Coreでは標準的に使いやすいです。NLogはファイル出力や細かな設定に強く、log4netは既存システムでの利用実績が豊富です。

7-2. 初心者におすすめのログ出力方法

C#初心者には、目的に応じて次の順番で学ぶのがおすすめです。

まずはConsole.WriteLineでログ出力の考え方を理解します。次にILoggerでログレベルや設定ファイルによる制御を学びます。その後、ファイル出力やログローテーションが必要になったらNLogを使うとスムーズです。

学習順としては、次の流れが分かりやすいです。

Console.WriteLine

Debug.WriteLine / Trace.WriteLine

Microsoft.Extensions.Logging

NLog

log4net

新規開発で特別な理由がなければ、まずはMicrosoft.Extensions.Loggingを使い、ファイル出力を本格的に行いたい場合はNLogを組み合わせる方法が扱いやすいです。

7-3. 小規模開発に向いている方法

小規模なコンソールアプリや学習用プログラムであれば、Console.WriteLineや簡単なStreamWriterでも十分な場合があります。

ただし、次のような場合は小規模でもILoggerやNLogを使った方がよいです。

・エラー調査を後から行いたい
・ログファイルを日付ごとに分けたい
・ログレベルを切り替えたい
・将来的に機能拡張する予定がある
・複数人で開発する

小さなアプリでも、最初からログ出力の形を整えておくと、後から保守しやすくなります。

7-4. Webアプリや業務システムに向いている方法

ASP.NET CoreのWebアプリや業務システムでは、Microsoft.Extensions.Loggingを基本にするのがおすすめです。ASP.NET CoreではDIとILogger<T>の相性が良く、コントローラーやサービスクラスに簡単にロガーを注入できます。

例は次のとおりです。

C#
using Microsoft.AspNetCore.Mvc;

public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

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

public IActionResult Index()
{
_logger.LogInformation("Indexアクションが呼び出されました");
return View();
}
}

ファイル出力、ログローテーション、詳細な出力形式が必要な場合は、NLogやSerilogなどの外部プロバイダーと組み合わせることもあります。この記事の範囲では、初心者にも設定しやすいNLogが有力な選択肢です。

7-5. 選び方の判断基準

C#ログ出力の方法を選ぶときは、次の基準で判断すると分かりやすいです。

条件おすすめ
とにかく簡単に確認したいConsole.WriteLine
開発中だけ確認したいDebug.WriteLine
.NET標準の仕組みを使いたいMicrosoft.Extensions.Logging
ASP.NET Coreでログを出したいILogger
ファイル出力をしっかり行いたいNLog
既存システムがlog4netを使っているlog4net
ログローテーションが必要NLogまたはlog4net

新規開発では、まずILoggerを使い、必要に応じてNLogなどのプロバイダーを追加する構成が扱いやすいです。

8. C#ログ出力の実装で押さえるべきベストプラクティス

8-1. ログに出力すべき情報

良いログには、後から原因調査しやすい情報が含まれています。C#ログ出力では、次のような情報を意識して残しましょう。

・処理の開始と終了
・処理対象のID
・ユーザーID
・リクエストID
・外部APIの呼び出し結果
・データベース更新結果
・例外情報
・処理時間
・重要な分岐条件

たとえば、次のようなログは調査しやすいです。

C#
_logger.LogInformation(
"注文登録を開始しました。OrderId={OrderId}, UserId={UserId}",
orderId,
userId);

ログメッセージには、単なる文章だけでなく、検索や集計に使える値を含めると便利です。

8-2. ログに出力してはいけない情報

ログは障害調査に役立つ一方で、機密情報を出力するとセキュリティリスクになります。

次の情報はログに出力しないようにしましょう。

・パスワード
・クレジットカード番号
・認証トークン
・APIキー
・秘密鍵
・個人番号
・不要な個人情報
・Cookieやセッション情報の全文

たとえば、ログイン失敗時にパスワードを出力するのは危険です。

C#
// 悪い例
_logger.LogWarning("ログイン失敗。UserId={UserId}, Password={Password}", userId, password);

次のように、必要最小限の情報にします。

C#
// 良い例
_logger.LogWarning("ログイン失敗。UserId={UserId}", userId);

ログは開発者だけでなく、運用担当者や外部システムが参照することもあります。出力内容は慎重に設計しましょう。

8-3. 例外ログの正しい残し方

例外ログを残すときは、例外オブジェクトをそのままログメソッドに渡すことが重要です。

C#
try
{
Execute();
}
catch (Exception ex)
{
_logger.LogError(ex, "処理中にエラーが発生しました。UserId={UserId}", userId);
throw;
}

悪い例は、例外メッセージだけを文字列として出力する方法です。

C#
// 悪い例
_logger.LogError("エラー: " + ex.Message);

この方法では、スタックトレースが失われる場合があります。スタックトレースがないと、どこでエラーが起きたのか分かりにくくなります。

また、例外を握りつぶすのも避けましょう。

C#
// 悪い例
try
{
Execute();
}
catch (Exception ex)
{
_logger.LogError(ex, "エラーが発生しました");
}

必要に応じてthrow;で再スローし、呼び出し元にエラーを伝えることが大切です。

8-4. ログメッセージを分かりやすく書くコツ

ログメッセージは、後から読む人にとって分かりやすい内容にしましょう。

良いログメッセージのポイントは次のとおりです。

・何の処理か分かる
・成功、失敗、開始、終了が分かる
・対象データが分かる
・原因調査に必要な値が含まれている
・表記が統一されている

悪い例は次のようなログです。

C#
_logger.LogInformation("開始");
_logger.LogError("エラー");

これでは、何の処理が開始したのか、どのようなエラーなのか分かりません。

良い例は次のようなログです。

C#
_logger.LogInformation("請求書作成処理を開始しました。InvoiceId={InvoiceId}", invoiceId);
_logger.LogError(ex, "請求書作成処理でエラーが発生しました。InvoiceId={InvoiceId}", invoiceId);

ログは「未来の自分や他の開発者へのメッセージ」と考えて書くと、自然と分かりやすくなります。

8-5. ログファイル肥大化を防ぐ方法

ログをファイルに出力する場合、何も対策しないとログファイルが大きくなり続けます。ログファイルが肥大化すると、ディスク容量を圧迫したり、ログ検索に時間がかかったりします。

対策としては、次の方法があります。

・日付ごとにログファイルを分ける
・一定サイズでローテーションする
・古いログを自動削除する
・本番環境ではDebugログを出さない
・大量ループ内で不要なログを出さない
・必要に応じてログを圧縮する

NLogやlog4netを使えば、ログローテーションを設定で実現できます。自前で実装するよりも、ログライブラリの機能を使う方が安全です。

8-6. 本番運用を意識したログ設計

本番運用を意識するなら、C#ログ出力は「とりあえず出す」のではなく、設計として考えることが重要です。

本番運用で意識したいポイントは次のとおりです。

・障害調査に必要なログが残ること
・ログ量が多すぎないこと
・機密情報が含まれないこと
・ログレベルが適切であること
・ログファイルがローテーションされること
・複数サーバーでも追跡できること
・リクエストIDや相関IDで処理を追えること

Webアプリでは、1つのリクエストが複数のサービスやデータベース処理を呼び出すことがあります。そのため、リクエストIDやユーザーIDをログに含めると、処理全体を追いやすくなります。

9. C#ログ出力でよくある質問

9-1. C#で一番簡単にログ出力する方法は?

一番簡単な方法はConsole.WriteLineです。

C#
Console.WriteLine("ログを出力しました");

ただし、これは学習用や簡易確認向けです。実務では、ログレベルや出力先を管理できるILogger、NLog、log4netを使うのがおすすめです。

9-2. Console.WriteLineはログ出力として使ってもよい?

小規模なコンソールアプリや学習用であれば、Console.WriteLineをログ出力として使っても問題ありません。

ただし、本番運用するアプリケーションでは注意が必要です。Console.WriteLineだけでは、ログレベルの制御、ファイル出力、ローテーション、環境ごとの設定変更が難しいためです。

本格的なC#ログ出力を行うなら、Microsoft.Extensions.LoggingやNLogを使いましょう。

9-3. NLogとlog4netはどちらを使うべき?

新規開発で初心者が使うなら、NLogの方が始めやすいことが多いです。設定が分かりやすく、ファイル出力やログローテーションも扱いやすいためです。

一方、既存システムですでにlog4netが使われている場合は、無理にNLogへ移行せず、log4netを継続利用する方が安全なケースもあります。

判断基準は次のとおりです。

状況おすすめ
新規開発NLogまたはILogger
ASP.NET CoreILogger、必要に応じてNLog
既存システムがlog4netlog4net
初心者がファイルログを学ぶNLog

9-4. ログをファイルに出力できないときの原因は?

C#でログをファイルに出力できない場合、よくある原因は次のとおりです。

・ログフォルダが存在しない
・書き込み権限がない
・設定ファイルが読み込まれていない
・ログレベル設定により出力対象外になっている
・ファイルパスが想定と違う
・アプリケーションの実行ディレクトリを誤解している
・ログライブラリの初期化ができていない

まずは、ログ出力先を絶対パスにして確認すると原因を切り分けやすくなります。また、NLogやlog4netの設定ファイルが出力ディレクトリにコピーされているかも確認しましょう。

9-5. ASP.NET Coreではどのログ出力方法がおすすめ?

ASP.NET Coreでは、まずILogger<T>を使うのがおすすめです。標準でDIに統合されており、コントローラーやサービスクラスに簡単に注入できます。

C#
public class ProductService
{
private readonly ILogger<ProductService> _logger;

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

public void UpdateProduct(int productId)
{
_logger.LogInformation("商品更新を開始しました。ProductId={ProductId}", productId);
}
}

ファイル出力や詳細なログ設定が必要な場合は、NLogなどのログプロバイダーを追加するとよいでしょう。

まとめ

C#のログ出力は、アプリケーションの状態を把握し、エラー原因を調査し、安定した運用を行うために欠かせない仕組みです。

初心者はまずConsole.WriteLineでログ出力の基本を理解し、その後Debug.WriteLineTrace.WriteLineMicrosoft.Extensions.Loggingへ進むと分かりやすいです。実務では、ILoggerを使ってログレベルを管理し、必要に応じてNLogやlog4netでファイル出力やログローテーションを実装します。

C#ログ出力で特に重要なのは、次のポイントです。

・ログレベルを適切に使い分ける
・開発環境と本番環境で出力内容を変える
・例外ログには例外オブジェクトを渡す
・ログに機密情報を出力しない
・ログファイルの肥大化を防ぐ
・後から調査しやすいメッセージを書く

小規模な開発ではConsole.WriteLineStreamWriterでも始められますが、本番運用を考えるならMicrosoft.Extensions.Logging、NLog、log4netのようなログ機能を使うのがおすすめです。

C#でログ出力を正しく実装できるようになると、開発中のデバッグだけでなく、本番環境での障害対応や保守作業も大きく効率化できます。