はじめに
技術調査の段階では軽視されがちなログ出力ですが、実運用となるとログがなければ問題解決の話にならないこの現実は厳しいなと思う今日この頃、みなさまにおかれましてはログをどのように扱っているでしょうか?
さて、ちょっと変わった出だしですが大事ですよね。ログ。
では、.NET Core でログ出力をどのようにすればよいのかですが、いくつか候補はあるものの最近は NLog が人気があるようです。ですので、この記事では NLog でどのようにログ出力すればよいのかをご紹介します。
なお、環境は、Mac (macOS High Sierra 10.13.3) で .NET Core SDK 2.1.4、Visual Studio Code になります。
とは言っても、Windowsでもパスを読み替えれば使えると思います。もともと Windows のツールですので。
コンソールアプリケーションの作成
まずは、コンソールアプリケーションを以下のコマンドで作成しましょう。
$ dotnet new console -o ConsoleLog
パッケージのインストール
NLog 関連のパッケージを NuGet でインストールします。.NET Core 2.0 では NLog 4.5.x 以上が必要とのことなので、正式版ではありませんが最新版をインストールします。対象は、NLog.Extensions.Logging と NLog になります。
なお、ASP.NET Core では NLog.Extensions.Logging ではなく NLog.Web.AspNetCore をインストールする必要があります。間違えないようにしましょう。
DI (Dependency Injection) を使用してログを出力するのが .NET Core 時代の普通らしいので、DI のパッケージもインストールします。対象は、Microsoft.Extensions.DependencyInjection になります。
$ dotnet add package Microsoft.Extensions.DependencyInjection --version 2.0.0 $ dotnet add package NLog.Extensions.Logging --version 1.0.0-rtm-rc7 $ dotnet add package NLog --version 4.5.0-rc07
NLog の設定ファイル作成
NLog の設定ファイルを nlog.config という名称で作成します。ファイル名は全て小文字になります。
<?xml version="1.0" encoding="utf-8" ?> <!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema--> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogFile="/tmp/log/console-internal.log" internalLogLevel="Info" > <targets> <!-- Eventlog --> <target xsi:type="File" name="event" fileName="/tmp/log/event-${shortdate}.log" layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" /> <!-- Errorlog --> <target xsi:type="File" name="error" fileName="/tmp/log/error.log" layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" /> </targets> <rules> <logger name="*" maxlevel="Warn" writeTo="event" /> <logger name="*" minlevel="Error" writeTo="error" /> </rules> </nlog>
ログレベルが Trace, Debug, Warn の場合は event-日付.log ファイルに、Error, Fatal の場合は error.log ファイルにログを出力するようになってます。なお、${shortdate} とすることでファイル名に日付を入れることができます。
ソースコードの修正
今回は、Program.cs を以下のように修正します。
using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; namespace ConsoleLog { class Program { static void Main(string[] args) { //Set log provider var servicesProvider = BuildDi(); var runner = servicesProvider.GetRequiredService(); //Write log runner.DoAction("LogAction"); // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) NLog.LogManager.Shutdown(); } private static IServiceProvider BuildDi() { var services = new ServiceCollection(); //Runner is the custom class services.AddTransient<Runner>(); services.AddSingleton<ILoggerFactory, LoggerFactory>(); services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); services.AddLogging((builder) => builder.SetMinimumLevel(LogLevel.Trace)); var serviceProvider = services.BuildServiceProvider(); var loggerFactory = serviceProvider.GetRequiredService<ILoggerFactory>(); //configure NLog loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties =true }); loggerFactory.ConfigureNLog("nlog.config"); return serviceProvider; } } public class Runner { private readonly ILogger<Runner> _logger; public Runner(ILogger<Runner> logger) { _logger = logger; } public void DoAction(string name) { //ログの出力 _logger.LogTrace("trace message {Action}", name); _logger.LogDebug("debug message {Action}", name); _logger.LogWarning("warning message {Action}", name); _logger.LogError("error message {Action}", name); _logger.LogCritical("critical message {Action}", name); } } }
まあ、ほぼ見たままなのですが、Runner クラスの DoAction メソッドでログを出力しています。実際に使う場合は、DoXxxx という感じでメソッドを増やしていって各メソッドで1つのログを出力することになると思います。
ログを出力したい場合は、その場所で Main メソッドに書かれている手順でログ出力の記述をするのでしょう。
DI を使っているためちょっと直感的ではないのですが、.NET Core ではこのようにログ出力を行うようです。
ビルドと実行
ここまでできたら、ビルドと実行ですね。
Visual Studio Code のいつものように、下記コマンドを実行します。
すると、なんということでしょう。例外が発生してしまいました。
Unhandled Exception: System.IO.FileNotFoundException: Could not find file '/Users/xxx/Projects/ConsoleLog/bin/Debug/netcoreapp2.0/nlog.config'.
nlog.config が見つからないというエラーですね。
このエラーですが、ネットで調べてもなかなか情報がなかったのですが、なんのことはないビルド「先」に nlog.config が存在していないだけなんですよね。なので、ビルド先に nlog.config をコピーすれば問題解消です。
最初と nlog.config を変更した場合は以下のようにコマンドを実行します。
$ dotnet build $ cp nlog.config bin/Debug/netcoreapp2.0 $ dotnet run
ちなみに、Visual Studio では nlog.config ファイルのプロパティで「常にコピー」を設定しておけばよいようです。
では、実行結果を確認します。
$ cat event-2018-03-20.log 2018/03/20 14:43:02.707|TRACE|trace message LogAction |ConsoleLog.Runner|Action=LogAction 2018/03/20 14:43:02.797|DEBUG|debug message LogAction |ConsoleLog.Runner|Action=LogAction 2018/03/20 14:43:02.800|WARN|warning message LogAction |ConsoleLog.Runner|Action=LogAction $ cat error.log 2018/03/20 14:43:02.800|ERROR|error message LogAction |ConsoleLog.Runner|Action=LogAction 2018/03/20 14:43:02.801|FATAL|critical message LogAction |ConsoleLog.Runner|Action=LogAction
おわりに
.NET Core で人気があるらしい NLog を使ってログを出力する方法をご紹介してみました。
ちょっとクセはありますが、 ログの出力先をファイルだけではなくデータベースやメールなども選択できるようですし、ログのローテートもできるみたいなので、なかなか良い感じではないでしょうか。