【.NET Core 3.1】Prism Template で NLog を使う

# はじめに

Prism Template Pack を使って生成した WPF アプリで`NLog`を使いたい

## 結論

以下の記事通りに進めれば、難なく`NLog`を使うことができる

https://qiita.com/sampo-cure/items/7a41fc43a7942893d3a3

### この記事の存在意義

- 実際に自分で手を動かしてみて**ハマったポイントを書き残す**
- 随時更新する**`NLog.config`ファイルを置いておくための場所**とする
    - 最新の NLog.config ファイルは[付録](#設定ファイル)に記載する

#### 環境

- Windows 10 Home
- Visual Studio 2019 Community
- **.NET Core 3.1**
    - **NLog 4.7.11**
    - NLog.Extensions.Logging 1.7.4
    - Prism.Unity 8.0.0.1909
    - Microsoft.Extensions.Logging 5.0.0

# 実装

[先述の記事](https://qiita.com/sampo-cure/items/7a41fc43a7942893d3a3)から少し変更しているところもある

## DI登録`App.xaml.cs`

- `CreateLogger("")`は`CreateLogger<T>`とした
    - 理由：ロガーの名前はどうでもいいが、`""`とするのが個人的に落ち着かなかった
        - 余談：ロガーの名前は`NLog.config`のレイアウトに`${logger}`を入れるとログに仕込める
    - `T`に`App`クラスを入れておくと落ち着く

```cs:App.xaml.cs
using TestProject.Views;
using Prism.Ioc;
using System.Windows;
using Microsoft.Extensions.Logging;

namespace TestProject
{
    public partial class App
    {
        protected override Window CreateShell() => Container.Resolve<MainWindow>();

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            var factory = new NLog.Extensions.Logging.NLogLoggerFactory();
            Microsoft.Extensions.Logging.ILogger logger = factory.CreateLogger<App>();

            containerRegistry.RegisterInstance(logger);
        }
    }
}
```

## ロガーを使う側

`ViewModel`のコンストラクターに`ILogger`インターフェイスを引数として設定し
DI注入してもらった`logger`を使う

```cs:MainWindowViewModel.cs
using Microsoft.Extensions.Logging;
using Prism.Mvvm;

namespace TestProject.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        public MainWindowViewModel(ILogger logger)
        {
            logger.LogDebug("LogDebug");
            logger.LogInformation("LogInformation");
        }
    }
}
```

# ハマりポイント（この記事のメイン）

実現するまでにハマったポイントを書き残す

## NLog.configを編集することができない

Visual Studio の NuGetパッケージマネージャーから`NLog.Config`をインストールする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/c73a4c32-d30f-d43d-3b4c-b64d45b82340.png)

新たに`NLog.config`ファイルがプロジェクトに追加されるが
**ファイルに鍵マークが付いていて編集できない**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/ef30ebda-99af-ddcd-2b4d-79b6c8102717.png)

### なぜ？

昔と今ではパッケージマネージャーのやり方が違う
そして`PackageReference`を使う新しいやり方に`NLog.Config`パッケージが順応していない様子

https://docs.microsoft.com/ja-jp/nuget/consume-packages/migrate-packages-config-to-package-reference

>Note: Unfortunately this package won't work well when using PackageReference

>Advised to:

>- download manually: https://raw.githubusercontent.com/NLog/NLog/v4.4/src/NuGet/NLog.Config/content/NLog.config
- set "Copy To Output Directory" to "Copy if newer"

https://www.nuget.org/packages/NLog.config

### NLog.configを編集するためには？

前節で引用した`NLog.config`ファイルへのリンクをつかって、ファイルを保存する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/b0d59edb-cf3a-f15f-e9b5-26e8c15adc15.png)

保存した`NLog.config`をプロジェクトに追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/c8fe65ec-3315-72da-b2c9-6f64edc93258.png)

または新しい項目の追加してもよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/c69b2e3f-42ec-55f0-43f0-00e89c31c60f.png)

Visual Studio に追加されたファイルを右クリックして「新しい場合はコピーする」を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/0a64af45-25c6-f2b8-df18-bc298fb67c36.png)

## Visual Studio のデバッグ出力にログが表示されない

以下の記事で言及されているとおり、**`xsi:type="Debugger"`とすることで表示される**

https://blog.goo.ne.jp/pianyi/e/63d643b66739ea286e74bac9b39b5c2a



```diff_xml:NLog.config
- <target xsi:type="Console"  name="logconsole" />
+ <target xsi:type="Debugger" name="logconsole" />
```

Visual Studio のオプションによっては、イミディエイトウィンドウに出力される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/db1acdae-83e3-6eba-e94f-f8c6f033ee12.png)

# 付録

実際に使っている`NLog.config`を貼り付ける
随時更新する予定

## 設定ファイル

- `.log`ファイルには`Information`以上のログを出力する
    - レイアウトは[こちらの記事](https://qiita.com/shusakuorz/items/47be13a66a7c93cef460
)を参考にした
- Visual Studio のデバッグ出力にはすべてのログを表示する
    - レイアウトはデフォルトのまま

### 注意点
> **NLogのアーカイブ機能と、ファイル名の`{shotdate}`は併用できない**
（[参考記事はこちら](https://qiita.com/mak_in/items/b64899b27b5fcf472daa)）

### NLog.config

```xml:NLog.config
<?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"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

  <!-- optional, add some variables
  https://github.com/nlog/NLog/wiki/Configuration-file#variables
  -->
  <variable name="myvar" value="myvalue"/>

  <!--
  See https://github.com/nlog/nlog/wiki/Configuration-file
  for information on customizing logging rules and outputs.
   -->
  <targets>
    <!--
    add your targets here
    See https://github.com/nlog/NLog/wiki/Targets for possible targets.
    See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
    -->
    
    <!--layout="${longdate} ${logger} [${threadid:padding=8}] [${uppercase:${level:padding=-5}}] ${callsite:methodName=false} ${message} ${exception:format=tostring}"-->
    
    <target xsi:type="File" name="f"
            fileName="${basedir}/logs/trace.log"
            layout="${longdate} [${threadid:padding=8}] [${uppercase:${level:padding=-5}}] ${callsite} ${message} ${exception:format=tostring}"
            encoding="UTF-8"
            archiveFileName="${basedir}/logs/trace_{#}.log.zip"
            archiveEvery="Day"
            archiveNumbering="Date"
            enableArchiveFileCompression="true"
            />
    
    <target xsi:type="Debugger" name="d" />
  </targets>

  <rules>
    <logger name="*" minlevel="Info" writeTo="f" />
    <logger name="*" minlevel="Debug" writeTo="d" />
  </rules>

</nlog>
```