C#でNLogを使う方法|ログ出力の設定・ファイル保存・エラー対策まで初心者向けに解説
はじめに
C#でアプリケーションを作るとき、エラーの原因調査や処理の流れの確認に欠かせないのがログ出力です。開発中はConsole.WriteLineで十分に見えることもありますが、実際の運用では「いつ」「どの処理で」「どのレベルの問題が」「どんな例外とともに発生したか」を後から確認できる仕組みが必要になります。
そこでよく使われるのが、C#向けのログライブラリであるNLogです。NLogを使うと、ログをコンソールやファイルに出力したり、ログレベルごとに出力内容を分けたり、例外情報やスタックトレースをきれいに保存したりできます。NLog公式サイトでも、NLogは.NET向けの柔軟な無料オープンソースログ基盤で、コンソール・ファイル・データベースなど複数の出力先に対応すると説明されています。
この記事では、C#でNLogを使う方法を初心者向けに解説します。導入手順、nlog.configの書き方、ファイル保存、ログレベル、例外ログ、ASP.NET Coreでの利用、ログが出力されないときの対策まで、実務で使いやすい形でまとめます。
1. C#でNLogを使う前に知っておきたい基礎知識
1-1. NLogとは?C#アプリでログ出力を行うためのライブラリ
NLogは、C#やVB.NETなどの.NETアプリケーションでログ出力を行うためのライブラリです。単に文字列を画面に表示するだけではなく、ログの重要度、出力先、出力形式、ファイル保存、ローテーション、例外情報の記録などを細かく設定できます。
たとえば、次のような用途で使われます。
コンソールアプリの処理結果をログに残す
Windows FormsやWPFアプリのエラーをファイルに保存する
ASP.NET Coreアプリのリクエスト処理や例外を記録する
本番環境で発生した障害の原因を後から調査する
日付ごとにログファイルを分けて管理する
NLogは、従来のテキストログだけでなく、構造化ログにも対応しています。公式情報でも、NLogはtraditional loggingとstructured loggingの両方をサポートするとされています。
1-2. Console.WriteLineやDebug.WriteLineとの違い
C#で簡単にログのような出力を行う方法として、Console.WriteLineやDebug.WriteLineがあります。しかし、これらは本格的なログ管理には向いていません。
Console.WriteLineはコンソールに文字を表示するだけなので、ファイル保存、ログレベル管理、出力形式の変更、古いログの削除などは自分で実装する必要があります。Debug.WriteLineはデバッグ時の確認には便利ですが、本番環境で安定してログを管理する目的には不十分です。
一方、NLogでは次のようなことを設定だけで実現できます。
XML<logger name="*" minlevel="Info" writeTo="logfile" />
このように書けば、Info以上のログだけを指定した出力先へ送ることができます。アプリのコード側ではlogger.Info()やlogger.Error()のように呼び出すだけで済むため、ログ管理の処理をアプリ本体のロジックから分離できます。
1-3. log4net・Serilogとの違いとNLogを選ぶメリット
C#で使われる代表的なログライブラリには、NLogのほかにlog4netやSerilogがあります。
log4netは歴史が長く、Javaのlog4jに近い考え方で使えるログライブラリです。既存システムで採用されていることも多いですが、設定や拡張の書き方にやや古さを感じる場面があります。
Serilogは構造化ログに強いライブラリです。ログを単なる文字列ではなく、プロパティ付きのデータとして扱いやすいため、ログ分析基盤と組み合わせる場合に便利です。
NLogは、設定ファイルで柔軟に制御しやすく、ファイル出力やコンソール出力をすぐに使いやすい点が特徴です。公式サイトでも、NLogは高性能で、使いやすく、拡張しやすく、柔軟に設定できることを重視していると説明されています。
初心者が「まずC#でファイルログを出したい」「例外ログをきちんと残したい」「設定ファイルで出力先を変えたい」という場合、NLogは扱いやすい選択肢です。
1-4. NLogでできること|ファイル保存・レベル別出力・例外ログ管理
NLogでは、主に次のようなログ管理ができます。
C#logger.Trace("詳細なトレースログ");
logger.Debug("デバッグ用ログ");
logger.Info("通常の処理ログ");
logger.Warn("警告ログ");
logger.Error("エラーログ");
logger.Fatal("致命的なエラーログ");
また、設定ファイルを使うことで、次のような制御が可能です。
Info以上だけをファイルに保存するError以上だけを別ファイルに保存する日付ごとにログファイルを分ける
古いログファイルを自動で整理する
コンソールとファイルに同時出力する
例外のメッセージとスタックトレースを出力する
JSON形式でログを保存する
ASP.NET Coreの
ILoggerと連携する
NLogは、ファイル、コンソール、データベース、メール、デバッガー出力など複数のターゲットを備え、同じログイベントを複数の出力先へ送ることもできます。
2. C#でNLogを導入する準備
2-1. 対象環境|.NET Framework/.NET/ASP.NET Coreで使える?
NLogは、.NET Framework、.NET、ASP.NET Coreなど幅広い環境で利用できます。NuGet上のNLogパッケージでは、.NET 6、7、8、9、10、.NET Standard 2.0/2.1、.NET Framework 3.5〜4.8などがサポート対象として示されています。
一般的には、次のように使い分けます。
| 種類 | 主に使うパッケージ |
|---|---|
| コンソールアプリ | NLog |
| Windows Forms / WPF | NLog |
| .NET Generic Host | NLog.Extensions.Logging |
| ASP.NET Core | NLog.Web.AspNetCore |
単純なC#アプリでファイルログを出すだけなら、まずはNLogをインストールすれば十分です。ASP.NET CoreでMicrosoftのILoggerと連携したい場合は、NLog.Web.AspNetCoreを使うのが一般的です。NLog.Web.AspNetCoreは、ASP.NET Core向けのNLog連携パッケージとして提供されています。
2-2. NuGetでNLogをインストールする方法
Visual StudioでNLogを導入する場合は、NuGetパッケージマネージャーを使います。
コンソールアプリやWindows Forms、WPFの場合は、次のパッケージをインストールします。
PowerShellInstall-Package NLog
.NET CLIを使う場合は、次のコマンドです。
Bashdotnet add package NLog
ASP.NET Coreで使う場合は、次のパッケージを追加します。
Bashdotnet add package NLog.Web.AspNetCore
Microsoft.Extensions.Loggingと連携するアプリでは、NLog.Extensions.Loggingも利用できます。このパッケージはAddNLog()によってNLogをMicrosoft.Extensions.Loggingのログプロバイダーとして登録できます。
2-3. NLog.Configを追加する方法
NLogの設定は、XML形式のnlog.configまたはNLog.configに書くのが一般的です。プロジェクトにXMLファイルを追加し、次のような最小構成を記述します。
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"
autoReload="true"
throwConfigExceptions="true">
<targets>
<target xsi:type="Console"
name="console"
layout="${longdate} [${level:uppercase=true}] ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="console" />
</rules>
</nlog>
targetsにはログの出力先を書き、rulesには「どのログをどの出力先へ流すか」を書きます。
autoReload="true"を指定すると、設定ファイルの変更を再読み込みしやすくなります。throwConfigExceptions="true"は、設定ミスを早めに検知したい開発時に便利です。
2-4. Visual Studioで確認しておきたいプロジェクト設定
NLogで初心者がよくつまずくのが、nlog.configが実行フォルダにコピーされていないケースです。Visual Studioでnlog.configを選択し、プロパティを確認します。
設定例は次のとおりです。
| 項目 | 設定例 |
|---|---|
| ビルドアクション | Content |
| 出力ディレクトリにコピー | 新しい場合はコピーする / 常にコピーする |
SDK形式の.csprojで明示的に設定する場合は、次のように書けます。
XML<ItemGroup>
<None Update="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Linux環境やコンテナ環境ではファイル名の大文字小文字が区別されるため、コードや配置ファイル名が一致しているかも確認しましょう。
3. C#でNLogを使ってログを出力する基本手順
3-1. Loggerインスタンスを作成する
C#コード側では、まずLoggerインスタンスを作成します。
C#using NLog;
class Program
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
static void Main()
{
logger.Info("アプリケーションを開始しました。");
}
}
LogManager.GetCurrentClassLogger()を使うと、現在のクラス名に対応したロガーを取得できます。ログに${logger}を含めると、どのクラスから出力されたログかを確認しやすくなります。
3-2. Trace・Debug・Info・Warn・Error・Fatalの使い分け
NLogのログレベルは、重要度の低い順に次のように使い分けます。
| レベル | 用途 |
|---|---|
| Trace | 非常に詳細な処理追跡 |
| Debug | 開発中のデバッグ情報 |
| Info | 通常の処理開始・終了・成功など |
| Warn | 処理は継続できるが注意が必要な状態 |
| Error | 例外や処理失敗などのエラー |
| Fatal | アプリ継続が難しい致命的なエラー |
たとえば、本番環境ではInfo以上、開発環境ではDebug以上を出力する、といった使い分けがよく行われます。
C#logger.Trace("SQLパラメータを作成しました。");
logger.Debug("ユーザーID: 1001");
logger.Info("ログイン処理を開始しました。");
logger.Warn("外部APIの応答が遅延しています。");
logger.Error("ファイルの読み込みに失敗しました。");
logger.Fatal("アプリケーションを終了する重大エラーが発生しました。");
3-3. コンソールにログを出力するサンプルコード
まずはコンソールにログを出す最小サンプルを確認しましょう。
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"
throwConfigExceptions="true">
<targets>
<target xsi:type="Console"
name="console"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console" />
</rules>
</nlog>
C#コードは次のとおりです。
C#using NLog;
class Program
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
static void Main()
{
logger.Trace("Traceログです。");
logger.Debug("Debugログです。");
logger.Info("Infoログです。");
logger.Warn("Warnログです。");
logger.Error("Errorログです。");
logger.Fatal("Fatalログです。");
LogManager.Shutdown();
}
}
LogManager.Shutdown()は、アプリ終了時にログを確実にフラッシュするために呼び出しておくと安心です。
3-4. 初心者がまず動作確認すべき最小構成
初心者が最初に確認するなら、次の3点だけに絞ると分かりやすいです。
1つ目は、NuGetでNLogがインストールされていることです。
2つ目は、nlog.configが出力ディレクトリにコピーされていることです。
3つ目は、rulesのminlevelとコード側のログレベルが一致していることです。
たとえば、設定が次のようになっている場合、
XML<logger name="*" minlevel="Info" writeTo="console" />
コードでlogger.Debug("test")と書いても出力されません。Info以上だけが出力対象だからです。最初の確認ではminlevel="Trace"にして、すべてのログレベルが出る状態で試すと原因を切り分けやすくなります。
4. NLogでログをファイルに保存する設定方法
4-1. nlog.configの基本構成を理解する
NLogの設定ファイルは、大きく分けてtargetsとrulesで構成されます。
XML<targets>
<!-- どこに出力するか -->
</targets>
<rules>
<!-- どのログをどの出力先に流すか -->
</rules>
targetsには、コンソール、ファイル、データベースなどの出力先を定義します。公式サイトでも、NLogのTargetはログイベントを目的地へ書き込む役割を持つと説明されています。
rulesには、ロガー名、ログレベル、出力先を指定します。
XML<logger name="*" minlevel="Info" writeTo="logfile" />
この例では、すべてのロガー名に対して、Info以上のログをlogfileという出力先へ送ります。
4-2. Fileターゲットを使ってログファイルを作成する
ファイルにログを保存するには、Fileターゲットを使います。
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"
throwConfigExceptions="true">
<targets>
<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
</nlog>
${basedir}はアプリケーションの実行フォルダを表すレイアウトレンダラーです。この設定では、実行フォルダ配下のlogs/app.logにログが出力されます。
4-3. ログの出力先フォルダとファイル名を指定する
ログファイルの保存場所はfileNameで指定します。
XML<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/application.log"
layout="${longdate} [${level}] ${message}" />
Windows環境では絶対パスも指定できます。
XMLfileName="C:/Logs/MyApp/application.log"
ただし、本番環境では権限の問題が起きやすいため、アプリが確実に書き込めるフォルダを指定することが大切です。WindowsサービスやIIS上のアプリでは、実行ユーザーに書き込み権限があるかを確認してください。
4-4. 日付ごとにログファイルを分ける設定
日付ごとにログファイルを分けたい場合は、fileNameに${shortdate}を含めます。
XML<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app-${shortdate}.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message}" />
この設定では、次のようなファイル名でログが作成されます。
app-2026-06-07.log
app-2026-06-08.log
app-2026-06-09.log
日付別に分けておくと、障害発生日のログを探しやすくなります。
4-5. 古いログを自動削除・ローテーションする設定
ログファイルを出力し続けると、ディスク容量を圧迫する可能性があります。そのため、古いログの削除やローテーション設定が重要です。NLogのファイル出力は、自動ファイル名やアーカイブにも対応しています。
サイズでローテーションする例は次のとおりです。
XML<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app.log"
archiveFileName="${basedir}/logs/archive/app.{#}.log"
archiveAboveSize="10485760"
archiveNumbering="Rolling"
maxArchiveFiles="10"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message}" />
この例では、app.logが約10MBを超えるとアーカイブされ、最大10ファイルまで保持します。
日付ごとのファイル名にして、一定数だけ保持したい場合は次のようにします。
XML<target xsi:type="File"
name="dailyLog"
fileName="${basedir}/logs/app-${shortdate}.log"
maxArchiveFiles="30"
layout="${longdate} [${level:uppercase=true}] ${message}" />
実務では、ログの保持期間、ディスク容量、監査要件に合わせて保存日数を決めましょう。
5. NLogのログ出力内容をカスタマイズする
5-1. Layoutで日時・ログレベル・メッセージを整形する
NLogでは、layoutを使ってログの出力形式を指定します。公式の設定オプションでも、LayoutはJSON、CSV、プレーンテキストなどの出力形式を定義し、${message}、${exception}、${date}のようなレイアウトレンダラーを使えると説明されています。
基本的なレイアウト例は次のとおりです。
XMLlayout="${longdate} [${level:uppercase=true}] ${logger} - ${message}"
出力例は次のようになります。
2026-06-07 10:15:30.1234 [INFO] MyApp.Program - アプリケーションを開始しました。
よく使うレイアウトレンダラーは次のとおりです。
| レイアウト | 内容 |
|---|---|
${longdate} | 詳細な日時 |
${shortdate} | 日付 |
${level} | ログレベル |
${logger} | ロガー名 |
${message} | ログメッセージ |
${exception} | 例外情報 |
${callsite} | 呼び出し元情報 |
${threadid} | スレッドID |
5-2. 例外情報とスタックトレースを出力する
例外ログを出すときは、例外オブジェクトをlogger.Error()に渡します。
C#try
{
int value = int.Parse("abc");
}
catch (Exception ex)
{
logger.Error(ex, "数値変換に失敗しました。");
}
設定ファイルでは、例外情報を含めるために${exception}を使います。
XML<target xsi:type="File"
name="errorfile"
fileName="${basedir}/logs/error.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message} ${exception:format=ToString}" />
${exception:format=ToString}を使うと、例外メッセージだけでなくスタックトレースも含めて出力しやすくなります。
出力例は次のようになります。
2026-06-07 10:20:00.1234 [ERROR] MyApp.Program 数値変換に失敗しました。 System.FormatException: The input string 'abc' was not in a correct format.
at ...
5-3. クラス名・メソッド名・行番号をログに含める
どのクラスから出力されたログかを知りたい場合は、${logger}を使うのが基本です。
XMLlayout="${longdate} [${level}] ${logger} ${message}"
さらに呼び出し元のメソッドや行番号を出したい場合は、${callsite}や${callsite-linenumber}を使えます。
XML<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app.log"
layout="${longdate} [${level:uppercase=true}] ${callsite}:${callsite-linenumber} ${message}" />
ただし、呼び出し元情報の取得は通常のログ出力より負荷が高くなる場合があります。本番環境ですべてのログに行番号を含めるのではなく、エラー調査が必要なログだけに使うなど、用途を絞るとよいでしょう。
5-4. 複数の出力先に同時にログを出す方法
NLogでは、同じログを複数の出力先へ同時に出せます。公式サイトでも、NLogは同じLogEventを複数のターゲットへ送ることができると説明されています。
たとえば、コンソールとファイルに同時出力する設定は次のとおりです。
XML<targets>
<target xsi:type="Console"
name="console"
layout="${longdate} [${level}] ${message}" />
<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app.log"
layout="${longdate} [${level}] ${logger} ${message} ${exception:format=ToString}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="console,logfile" />
</rules>
また、通常ログとエラーログを別ファイルに分けることもできます。
XML<targets>
<target xsi:type="File"
name="allfile"
fileName="${basedir}/logs/all.log"
layout="${longdate} [${level}] ${message}" />
<target xsi:type="File"
name="errorfile"
fileName="${basedir}/logs/error.log"
layout="${longdate} [${level}] ${message} ${exception:format=ToString}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="allfile" />
<logger name="*" minlevel="Error" writeTo="errorfile" />
</rules>
5-5. 環境ごとにログ設定を切り替える方法
開発環境では詳細なDebugログを出し、本番環境ではInfo以上だけを出す、という運用はよくあります。
シンプルな方法は、環境ごとに設定ファイルを分けることです。
nlog.Development.config
nlog.Production.config
ASP.NET Coreでは、appsettings.jsonやappsettings.Development.jsonと組み合わせて管理する方法もあります。NLogはXMLのNLog.configだけでなく、appsettings.jsonから設定を読み込むこともできます。公式サイトでも、NLog設定はappsettings.jsonから読み込めると説明されています。
ただし、初心者のうちはまずnlog.configで基本を理解し、その後で環境別設定に進むと混乱しにくいです。
6. C#アプリでよく使うNLogの実装例
6-1. コンソールアプリでNLogを使う例
コンソールアプリの基本例です。
C#using NLog;
class Program
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
static void Main(string[] args)
{
try
{
logger.Info("処理を開始します。");
Run();
logger.Info("処理が正常に終了しました。");
}
catch (Exception ex)
{
logger.Error(ex, "処理中にエラーが発生しました。");
}
finally
{
LogManager.Shutdown();
}
}
static void Run()
{
logger.Debug("Runメソッドを実行します。");
Console.WriteLine("Hello 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"
throwConfigExceptions="true">
<targets>
<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/console-${shortdate}.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message} ${exception:format=ToString}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
6-2. Windows Forms/WPFでNLogを使う例
Windows FormsやWPFでも、基本的な使い方は同じです。画面操作中のエラーや、ボタンクリック時の処理をログに残せます。
Windows Formsの例です。
C#using NLog;
public partial class MainForm : Form
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public MainForm()
{
InitializeComponent();
logger.Info("MainFormを初期化しました。");
}
private void buttonSave_Click(object sender, EventArgs e)
{
try
{
logger.Info("保存処理を開始します。");
// 保存処理
SaveData();
logger.Info("保存処理が完了しました。");
}
catch (Exception ex)
{
logger.Error(ex, "保存処理でエラーが発生しました。");
MessageBox.Show("保存に失敗しました。ログを確認してください。");
}
}
private void SaveData()
{
// 実際の保存処理
}
}
WPFでも、WindowやViewModelにロガーを用意して同じように使えます。
C#private static readonly Logger logger = LogManager.GetCurrentClassLogger();
private void ExecuteSearch()
{
try
{
logger.Info("検索処理を開始しました。");
// 検索処理
}
catch (Exception ex)
{
logger.Error(ex, "検索処理に失敗しました。");
}
}
画面アプリでは、ユーザーには簡潔なエラーメッセージを表示し、詳細な原因はNLogのログファイルに残す設計にすると運用しやすくなります。
6-3. ASP.NET CoreでNLogを使う例
ASP.NET Coreでは、NLog.Web.AspNetCoreを使ってMicrosoftのログ機構と連携するのが一般的です。NLog.Web.AspNetCoreは、ASP.NET Core向けにNLogを統合し、HttpContextの情報をログに付与するためのレイアウトレンダラーも提供します。
まずパッケージを追加します。
Bashdotnet add package NLog.Web.AspNetCore
Program.csの例です。
C#using NLog.Web;
var logger = NLog.LogManager.Setup()
.LoadConfigurationFromFile("nlog.config")
.GetCurrentClassLogger();
try
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Host.UseNLog();
var app = builder.Build();
app.MapGet("/", () => "Hello NLog");
app.Run();
}
catch (Exception ex)
{
logger.Error(ex, "ASP.NET Coreアプリケーションの起動中にエラーが発生しました。");
throw;
}
finally
{
NLog.LogManager.Shutdown();
}
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"
autoReload="true"
throwConfigExceptions="true">
<extensions>
<add assembly="NLog.Web.AspNetCore" />
</extensions>
<targets>
<target xsi:type="File"
name="webfile"
fileName="${basedir}/logs/web-${shortdate}.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message} ${exception:format=ToString}" />
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" />
<logger name="*" minlevel="Info" writeTo="webfile" />
</rules>
</nlog>
Microsoft.*のログが多すぎる場合は、上記のように抑制するとアプリ独自のログを見やすくできます。
6-4. try-catchで例外ログを出力する例
業務アプリでは、例外が発生したときに必ずログへ残すことが重要です。
C#public void ImportCsv(string filePath)
{
try
{
logger.Info("CSV取込を開始します。FilePath={0}", filePath);
// CSV取込処理
var lines = File.ReadAllLines(filePath);
logger.Info("CSV取込が完了しました。件数={0}", lines.Length);
}
catch (FileNotFoundException ex)
{
logger.Warn(ex, "CSVファイルが見つかりません。FilePath={0}", filePath);
throw;
}
catch (Exception ex)
{
logger.Error(ex, "CSV取込中に予期しないエラーが発生しました。FilePath={0}", filePath);
throw;
}
}
ポイントは、例外オブジェクトexを必ず渡すことです。
C#logger.Error(ex, "エラーが発生しました。");
次のようにメッセージだけ出すと、スタックトレースが残らず、原因調査が難しくなります。
C#logger.Error("エラーが発生しました。");
例外ログでは、処理名、対象データ、ファイル名、ユーザー操作など、原因調査に必要な情報も一緒に残しましょう。
6-5. 共通ロガークラスを作成して使い回す例
小規模なアプリでは、各クラスでLogManager.GetCurrentClassLogger()を呼ぶだけで十分です。ただし、ログ出力の書き方を統一したい場合は、共通ロガークラスを用意することもあります。
C#using NLog;
public static class AppLogger
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public static void Info(string message)
{
logger.Info(message);
}
public static void Warn(string message)
{
logger.Warn(message);
}
public static void Error(Exception ex, string message)
{
logger.Error(ex, message);
}
}
利用例です。
C#try
{
AppLogger.Info("処理を開始しました。");
// 処理
AppLogger.Info("処理が完了しました。");
}
catch (Exception ex)
{
AppLogger.Error(ex, "処理に失敗しました。");
}
ただし、この方法ではすべて同じロガー名になりやすく、どのクラスから出たログか分かりにくくなる場合があります。クラス単位でログを追跡したい場合は、各クラスでGetCurrentClassLogger()を使う方法がおすすめです。
7. NLogでログが出力されないときの原因と対策
7-1. nlog.configが読み込まれていない
ログが出力されないときに最初に確認すべきなのは、nlog.configが読み込まれているかです。
よくある原因は次のとおりです。
nlog.configがプロジェクトに存在しない実行フォルダにコピーされていない
ファイル名の大文字小文字が環境と一致していない
XMLの構文エラーがある
targetsやrulesの名前が一致していない
設定ファイルの問題を早めに検知するには、次のようにthrowConfigExceptions="true"を付けます。
XML<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
throwConfigExceptions="true">
開発時はこの設定を有効にしておくと、NLog設定の誤りに気づきやすくなります。
7-2. ファイルの出力先パスや権限に問題がある
ファイルログが出ない場合は、保存先のパスと権限を確認します。
たとえば、次のようなパスを指定しているとします。
XMLfileName="C:/Logs/MyApp/app.log"
この場合、C:/Logs/MyAppフォルダが存在しない、またはアプリの実行ユーザーに書き込み権限がないと、ログが作成されません。
まずは、アプリケーション配下に出す設定で確認すると切り分けしやすいです。
XMLfileName="${basedir}/logs/app.log"
IIS、Windowsサービス、タスクスケジューラ、Dockerコンテナなどで動かす場合は、実行ユーザーやマウント先の権限にも注意してください。
7-3. ログレベルの設定が一致していない
rulesのminlevelより低いログは出力されません。
たとえば、設定が次の場合、
XML<logger name="*" minlevel="Info" writeTo="logfile" />
次のログは出力されません。
C#logger.Debug("このログは出ません。");
Debugログも見たい場合は、minlevelをDebugに変更します。
XML<logger name="*" minlevel="Debug" writeTo="logfile" />
最初の動作確認では、minlevel="Trace"にしておくと、ログレベルが原因かどうかを確認しやすくなります。
7-4. Copy to Output Directoryの設定漏れ
Visual Studioでnlog.configを作成しただけでは、実行フォルダにコピーされない場合があります。プロパティで次の設定を確認します。
ビルドアクション: Content
出力ディレクトリにコピー: 新しい場合はコピーする
.csprojでは次のように設定できます。
XML<ItemGroup>
<None Update="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
ビルド後に、bin/Debug/net8.0/などの実行フォルダへnlog.configがコピーされているか確認しましょう。
7-5. InternalLogを使ってNLog自体のエラーを確認する
NLog自体が設定ファイルの読み込みやファイル出力でエラーになっている場合、InternalLogを有効にすると原因を確認できます。
XML<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
internalLogLevel="Info"
internalLogFile="${basedir}/logs/internal-nlog.log"
throwConfigExceptions="true">
internal-nlog.logには、NLog内部のエラーや警告が出力されます。たとえば、ファイル出力先にアクセスできない、設定ファイルの内容が不正、ターゲット名が間違っている、といった原因を調べるのに役立ちます。
ただし、InternalLogは常時詳細に出し続けるものではありません。問題調査時だけ有効にし、解決後はinternalLogLevelを下げるか無効にするのが一般的です。
8. NLogを安全に運用するための注意点
8-1. 個人情報やパスワードをログに出さない
ログは障害調査に便利ですが、個人情報や機密情報を出力するとセキュリティリスクになります。
ログに出してはいけない情報の例です。
パスワード
APIキー
アクセストークン
クレジットカード番号
マイナンバーなどの個人識別情報
セッションID
認証Cookie
秘密鍵
個人を特定できる詳細な情報
たとえば、次のようなログは避けるべきです。
C#logger.Info("ログイン情報: user={0}, password={1}", userName, password);
代わりに、必要最小限の情報だけを残します。
C#logger.Info("ログイン試行: user={0}", userName);
ユーザーIDを残す場合も、システムの規約やセキュリティ要件に従ってマスクや匿名化を検討しましょう。
8-2. ログファイルの肥大化を防ぐ
ログを大量に出力すると、ディスク容量を圧迫します。特にDebugやTraceを本番環境で出し続けると、短期間でログファイルが巨大になることがあります。
対策として、次の設定を行います。
XML<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app.log"
archiveFileName="${basedir}/logs/archive/app.{#}.log"
archiveAboveSize="10485760"
archiveNumbering="Rolling"
maxArchiveFiles="20"
layout="${longdate} [${level}] ${message}" />
また、ログ出力の粒度も見直しましょう。ループ内で大量にログを出す場合は、件数や条件を絞ることが重要です。
C#// 大量データ処理では注意
foreach (var item in items)
{
logger.Debug("処理中: {0}", item.Id);
}
必要に応じて、100件ごとに進捗ログを出すなどの工夫をします。
C#for (int i = 0; i < items.Count; i++)
{
if (i % 100 == 0)
{
logger.Info("処理進捗: {0}/{1}", i, items.Count);
}
}
8-3. 本番環境と開発環境でログレベルを分ける
開発環境では詳細なログが役立ちますが、本番環境ではログ量とパフォーマンスのバランスが重要です。
開発環境の例です。
XML<logger name="*" minlevel="Debug" writeTo="logfile" />
本番環境の例です。
XML<logger name="*" minlevel="Info" writeTo="logfile" />
障害調査中だけ一時的にDebugを有効にし、調査が終わったらInfoに戻す運用もよく行われます。
NLogは設定ファイルで出力レベルを変えられるため、コードを変更せずにログの詳細度を調整しやすい点がメリットです。
8-4. 例外ログだけでなく処理の流れも残す
エラーが発生した瞬間の例外ログだけでは、原因が分からないことがあります。重要な処理では、開始、終了、主要な分岐、外部連携の結果なども残すと調査しやすくなります。
C#logger.Info("注文登録を開始します。OrderId={0}", orderId);
try
{
ValidateOrder(order);
logger.Debug("注文バリデーションが完了しました。OrderId={0}", orderId);
SaveOrder(order);
logger.Info("注文登録が完了しました。OrderId={0}", orderId);
}
catch (Exception ex)
{
logger.Error(ex, "注文登録に失敗しました。OrderId={0}", orderId);
throw;
}
このように処理の流れが残っていると、「どこまで成功して、どこで失敗したか」を把握しやすくなります。
8-5. パフォーマンスに配慮したログ出力の考え方
ログ出力は便利ですが、出しすぎるとパフォーマンスに影響します。特に大量ループ、頻繁に呼ばれるAPI、ファイルI/Oが多い処理では注意が必要です。
文字列連結で重いメッセージを作るより、テンプレート形式で渡す方が扱いやすいです。
C#logger.Debug("ユーザー情報: UserId={0}, Name={1}", user.Id, user.Name);
また、重い計算をログ出力のためだけに行う場合は、ログレベルを確認してから実行します。
C#if (logger.IsDebugEnabled)
{
logger.Debug("詳細情報: {0}", CreateHeavyDebugMessage());
}
本番環境では、TraceやDebugを常時大量に出すのではなく、必要な場面だけ有効にする設計が大切です。
9. C#でNLogを使うときによくある質問
9-1. NLogは無料で使える?
NLogは無料で使えるオープンソースのログライブラリです。公式サイトでも、NLogは.NET向けのflexible & free open-source loggingと説明されています。
商用アプリで利用する場合は、プロジェクトのライセンス確認ルールに従って、利用しているNLogパッケージのライセンスを確認しておくと安心です。
9-2. app.configとnlog.configはどちらを使うべき?
初心者には、まずnlog.configを使う方法がおすすめです。ログ設定をアプリ本体の設定から分離でき、NLogの設定だけを見直しやすいからです。
.NET Frameworkアプリではapp.configにNLog設定を含めることもできますが、設定が大きくなると管理しづらくなります。
ASP.NET Coreや.NETの新しい構成では、appsettings.jsonにNLog設定を書く方法もあります。NLog.Extensions.Loggingは、appsettings.jsonからのNLog設定読み込みにも対応しています。
ただし、学習段階ではnlog.configでtargetsとrulesの考え方を理解してから、appsettings.json構成に進むとよいでしょう。
9-3. ログファイルが作成されないときは何を確認すべき?
ログファイルが作成されない場合は、次の順番で確認します。
NuGetで
NLogがインストールされているかnlog.configが実行フォルダにコピーされているかXMLの構文エラーがないか
targetのnameとrulesのwriteToが一致しているかminlevelより低いログを出していないか出力先フォルダに書き込み権限があるか
InternalLogにNLog内部エラーが出ていないか
特に多いのは、Copy to Output Directoryの設定漏れと、ログレベルの不一致です。
9-4. JSON形式でログを出力できる?
NLogはJSON形式のログ出力にも対応しています。公式サイトでも、NLog LayoutsはSimple Text、JSON、XML、CSVなど複数の出力形式に対応すると説明されています。
JSON形式の設定例です。
XML<target xsi:type="File"
name="jsonfile"
fileName="${basedir}/logs/app-${shortdate}.jsonl">
<layout xsi:type="JsonLayout">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:uppercase=true}" />
<attribute name="logger" layout="${logger}" />
<attribute name="message" layout="${message}" />
<attribute name="exception" layout="${exception:format=ToString}" />
</layout>
</target>
JSON形式にしておくと、ログ収集基盤や分析ツールに取り込みやすくなります。1行1JSONのJSON Lines形式で保存すると、後から処理しやすいです。
9-5. NLogはASP.NET Coreでも使える?
NLogはASP.NET Coreでも使えます。ASP.NET Coreでは、NLog.Web.AspNetCoreを使うことで、Microsoft.Extensions.Loggingと連携できます。NLog.Web.AspNetCoreは、.NET 6、7、8、9、10のASP.NET Coreプラットフォーム向けに使えるパッケージとして案内されています。
基本的な導入手順は次のとおりです。
Bashdotnet add package NLog.Web.AspNetCore
Program.csでNLogを有効にします。
C#builder.Logging.ClearProviders();
builder.Host.UseNLog();
コントローラーやサービスでは、通常のILogger<T>を使えます。
C#public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("Indexページにアクセスしました。");
return View();
}
}
ASP.NET Coreでは、アプリ独自のログだけでなく、リクエスト、例外、外部連携、データベース処理などを適切に記録すると、運用時の調査がしやすくなります。
まとめ
C#でNLogを使うと、アプリケーションのログ出力を簡単かつ柔軟に管理できます。Console.WriteLineだけでは難しいファイル保存、ログレベル制御、例外ログ、スタックトレース、日付別ファイル、ローテーション、複数出力先への同時出力などを、設定ファイル中心で実現できるのが大きなメリットです。
基本の流れは次のとおりです。
Bashdotnet add package NLog
nlog.configを作成します。
XML<targets>
<target xsi:type="File"
name="logfile"
fileName="${basedir}/logs/app-${shortdate}.log"
layout="${longdate} [${level:uppercase=true}] ${logger} ${message} ${exception:format=ToString}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logfile" />
</rules>
C#コードからログを出します。
C#private static readonly Logger logger = LogManager.GetCurrentClassLogger();
logger.Info("処理を開始しました。");
try
{
// 処理
}
catch (Exception ex)
{
logger.Error(ex, "エラーが発生しました。");
}
finally
{
LogManager.Shutdown();
}
初心者は、まずコンソール出力で動作確認し、次にファイル出力、例外ログ、日付別ログ、ローテーションの順に試すと理解しやすいです。
ログは、障害が起きたときに原因を追跡するための重要な手がかりです。C#アプリでNLogを導入しておけば、開発中のデバッグだけでなく、本番運用でのトラブル対応にも強いアプリケーションを作れます。

