Serilogを使ってUWPアプリでログを出力できるようにする

# 背景

UWPアプリでログを出力できるようにしようとNLogを使おうとしたのですが、出力できませんでした。
いろいろ調べてみたところ、以下が候補として上がりました。

- [MetroLog](https://github.com/novotnyllc/MetroLog)
- [Serilog](https://serilog.net/)

MetroLogは更新履歴が数年前で止まっていて、使えなさそうだと判断し、Serilogを使うことにしました。
また、日本語での情報がほとんどなかったので、記事として残そうと思います。
（UWPアプリ開発されている人が少ないんですね。。）

# Serilogとは

公式サイトによると、
>.NET用の他の多くのライブラリと同様に、Serilogはファイル、コンソール、その他の場所への診断ロギングを提供します。セットアップが簡単で、APIがクリーンで、最近の.NETプラットフォーム間での移植性があります。

>他のロギングライブラリとは異なり、Serilogは強力な構造化イベントデータを念頭に置いて構築されています。

とのことです。
プラットフォームとしては、NET 4.5+, Windows (8/WinRT/Universal+) and Windows Phone 8+をサポートしています。

# インストール方法

必要なのは、

- Serilog
- Serilog.Sinks.File

になります。

[ツール] > [NuGet パッケージ マネージャー] > [パッケージ マネージャー コンソール]で下記のコマンドを実行するか、

```
PM> Install-Package Serilog
PM> Install-Package Serilog.Sinks.File
```

ソリューション エクスプローラーで [参照] を右クリックし、 [NuGet パッケージの管理] を選択し、「Serilog」で検索して最新版をインストールしてください。

# 設定方法

以下のようにLoggerConfigurationクラスを使って設定を行います。

```cs
string logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "logs/log.txt");
Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.File(logFilePath, rollingInterval: RollingInterval.Day)
    .CreateLogger();
```

`MinimumLevel`はログ出力の最小レベル、`WriteTo.File`は出力先ファイルを示しています。
`ApplicationData.Current.LocalFolder.Path`はローカルストアを示していて、その中にlogsフォルダを作成して、さらにその下にlogが保存される仕組みです。
また、`rollingInterval`はファイルの分割単位を示していて、`RollingInterval.Day`は日毎にログファイルを分割する設定です。
ちなみに、ファイル容量はデフォルトで1GB、ファイル数は直近の３１ファイルまで（1ヶ月分）保存されます。
（ファイル容量とファイル数の設定を変更することも可能ですが、今回は割愛します）

上記のように設定すると、`c:\users\<user name>\AppData\Local\Packages\<app package identifier>\LocalState\logs`に、以下のようにログファイルが保存されていきます。

```
log20180631.txt
log20180701.txt
log20180702.txt
```

他にも様々な設定ができるようなので、必要あればまた調べてみたいと思います。

# 使用方法

ログレベルごとに関数が用意されており、単純に出力したいログレベルの関数に文字列を渡すだけです。
ここは他のロガーライブラリと同様かと思います。

```
Log.Information("Informationレベルで出力されます");
Log.Debug("Debugレベルで出力されます");
Log.Warning("Warningレベルで出力されます");
Log.Error("Errorレベルで出力されます");
```

# 便利な使い方

一例として、以下のようなLogUtilクラス（ラッパークラス）を作っておくとかなり楽になります。
参考にしてみてください。

```cs:LogUtil.cs
public static class LogUtil
{
    private static bool isInitialized = false;
    public static void Information(string message)
    {
        if (!isInitialized)
        {
            Initialize();
        }
        Log.Information(message);
    }
    public static void Debug(string message)
    {
        if (!isInitialized)
        {
            Initialize();
        }
        Log.Debug(message);
    }
    public static void Warning(string message)
    {
        if (!isInitialized)
        {
            Initialize();
        }
        Log.Warning(message);
    }
    public static void Error(string message)
    {
        if (!isInitialized)
        {
            Initialize();
        }
        Log.Error(message);
    }
    private static void Initialize()
    {
        string logFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "logs/log.txt");
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .WriteTo.File(logFilePath, rollingInterval: RollingInterval.Day)
            .CreateLogger();
        isInitialized = true;
        Log.Debug("Initialized Serilog");
    }
}
```

# 参考URL

- [logging - Logger for Windows 10 UWP app - Stack Overflow](https://stackoverflow.com/questions/32886613/logger-for-windows-10-uwp-app)
- [Question: How to use this in UWP? · Issue #985 · serilog/serilog · GitHub](https://github.com/serilog/serilog/issues/985)
- [GitHub - serilog/serilog-sinks-file: Write Serilog events to files in text and JSON formats, optionally rolling on time or size](https://github.com/serilog/serilog-sinks-file)
https://github.com/serilog/serilog-sinks-file
- [ファイルの操作 - UWP applications | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/uwp/get-started/fileio-learning-track)