NLogを.Net Standard/Coreで使用する
はじめに
.Net Core等は下記バージョンでお送りします。
- netstandard: 2.0
- netcoreapp: 2.2
- AspNetCore: 2.2.0
- NLog: 4.6.3
あらまし
NLogを使うとかは今更ではあるのですが
.Net CoreのExeアプリケーションからASP.net WebAPIアプリケーションで
NLogを使用する機会があったので、学習ついでの備忘録な感じのトピックです。
NLog.configの設定を外に出す
基本的な使い方は本家のGitHubやググったら山程でてくるので割愛…
NLogのログ出力の設定は、nlog.config
のXML形式ファイルに記述していく感じです。
が、これはいまいち好きじゃない。
と、いうのもASPにしてもCoreの普通のアプリにしてもjsonファイルにアプリケーション設定を記述していますし
あちこちのファイルに設定内容が散らばっているのも少し邪魔くさい。
ASP.netに関してはWebAppsがもっているアプリケーション設定で出力先をいろいろ設定できるようにすれば
CI/CD側の負担も軽くなるんでは?と思ったわけです。
(nlog.configのようなXMLファイルの設定もWebAppsの設定上でできるのであればいいのですが…ない?ですよね?)
NLog.configの構成
まずはXMLで設定されるNLogの構成を見てみます。
<?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 name="console" xsi:type="Console" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="console" /> </rules> </nlog>
これはLogの内容をConsoleに吐き出す設定ですが、target
で「何に対して」ログ出力するか指定し
rule
で 'target' に対して出力するログの内容を指定しています。
この場合、「Info
レベルからのログを Console
に出力する」という設定になっているわけですね。
NLogのTarget/Ruleの関係は、下記サイトが参考になりました。
NLogの設定を動的に指定する
こちらのサイトを参考にしました。
NLogをプログラマブルに初期化し動的に構成変更する - M12i.
NLog.Target
名前空間に ConsoleTarget
というClassが存在します。
NLog/ConsoleTarget.cs at dev · NLog/NLog · GitHub
他にも FileTarget
や DatabaseTarget
が存在します。
Classにあるプロパティを見てみると、Layout
やConnectionString
などXMLで設定するプロパティが存在するのが確認できます。
XMLの設定を確認しながら、TargetClassの同名プロパティに値を設定していく…という方法でNLogの設定ができそうです。
で、出来上がったのが下記です。
public static void ConsoleLogInit() { var conf = LogManager.Configuration; var console = new ConsoleTarget("console"); // consoleターゲットを生成 console.Layout = LogLayout; // アウトプットフォーマットレイアウトを設定 conf.AddTarget(console); // NLogの設定に生成したターゲット情報を追加 conf.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, console)); // consoleターゲットを使用するルールを追加 LogManager.Configuration = conf; // NLogの設定に反映 }
あとは同じように設定するだけ
TargetのClassにたいしてどのようなAPIが存在してどのような引数が求められているのかは
上記のGitHubのソースコードやドキュメントから抑えることができるので
ファイルに出力する場合やDBに出力する場合も同じように設定していくだけです。
ファイルに出力する場合はファイル名称やエンコードを指定するAPIが追加されていたりします。
public static void WriteLogToFileInit(string filePath, LogLevel targetLogLevel) { var conf = LogManager.Configuration; var file = new FileTarget("file"); file.Encoding = Encoding.UTF8; file.FileName = filePath; file.Layout = LogLayout; conf.AddTarget(file); conf.LoggingRules.Add(new LoggingRule("*", targetLogLevel, file)); LogManager.Configuration = conf; }
Databaseはちょっと変わり種でDatabaseParameterInfoのインスタンスにLayoutを設定しないといけません。
public static void WriteLogToSqlDatabaseInit(string connectionString, LogLevel targetLogLevel) { var conf = LogManager.Configuration; var dbtarget = new DatabaseTarget(); dbtarget.ConnectionString = connectionString; dbtarget.Name = "dbtarget"; dbtarget.DBProvider = "System.Data.SqlClient"; dbtarget.CommandText = "Insert Into LoggingTable(" + "Logged," + ") values (" + "@logged," + ")"; var loggedParam = new DatabaseParameterInfo(); loggedParam.Name = "@logged"; loggedParam.Layout = "${date}"; dbtarget.Parameters.Add(loggedParam); conf.AddTarget(dbtarget); conf.LoggingRules.Add(new LoggingRule("*", targetLogLevel, dbtarget)); LogManager.Configuration = conf; }
外部からNLogの設定を行う!
と、いうわけでソースコード上でNLogの設定が十二分に行えることがわかりました。
あとは、ASP.net WebAPIなどのappsettings.jsonなどに適当な設定を作ってあげればいいだけです。
適当に↓な感じでaapsettings.jsonを作って
{ "Logging": { "LogLevel": { "Default": "Warning" }, "OutputToLogFile": { "FilePath": "logfile.txt", "LogLevel": "Error" }, "OutputToDatabase": { "ConnectionString": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=Logging;Integrated Security=True;", "LogLevel": "Info" } }, "AllowedHosts": "*" }
Startup.cs
あたりで設定ファイルを読み込んでNlogを設定すればいい感じかなと思います。
private void NLogSettings() { Logging.LoggingSettings.ConsoleLogInit(); var fileName = this.Configuration["Logging:OutputToLogFile:FilePath"]; var logLevel = this.Configuration["Logging:OutputToLogFile:LogLevel"]; // NLogの設定を行う~~ }
これでWebAppsのアプリケーション設定への設定のみでログ出力先の挿げ替えなどが簡単に行えるようになりました。
終わりに
今回作成したモロモロのデモは下記リポジトリになります。
ASP.net WebAPIの ActionFilterAttribute
や ExceptionFilterAttribute
使ったり
EntityFrameworkの実行SQLをログ出力したりする実験コードも含んでたりします。