私Powershellだけど日付とサイズでログを切り替えたい(log4net)

# はじめに

私が作成するpowershellスクリプトでは、log4netでログを出していたのですが、設定用にxmlを持つ動作になっているのが気になっていました。

小さいスクリプトだったら、配布するファイルが少ないほうがトラブル少なくなると思っています。

スクリプトのみで実装する方法をぐぐりましたが、FileAppenderを利用するサンプルはありましたが、より実用的なRollingFileAppenderを使うサンプルがないようだったので、まとめておきます。


# log4netの入手

まず、ログ出力用のlog4netを入手します。

[apacheの公式](https://logging.apache.org/log4net/download_log4net.cgi)からダウンロード可能ですが、[nuget](https://www.nuget.org/packages/log4net/)の方が好きなのでnugetで入手します。


## nugetの入手

nugetコマンドがインストールされていない場合は、[こちら](https://www.nuget.org/downloads)からnuget.exeを入手してください。実行ファイルだけダウンロードできるのでインストーラーとかは不要です。

任意の場所にコピーして、パスを通しておけば使えます。


## パッケージのダウンロード

以下のコマンドを実行してダウンロードしてください。

```

nuget install log4net

```

./log4net.2.0.8/lib の下に各バージョンのlog4net.dllとlog4net.xmlが保存されています。


# log4netの呼び出しサンプル

xmlは使用しないので、ps1ファイルからlog4net.dllだけをロードして使います。

以下、呼び出しサンプルです。


```powershell:sample_log4net.ps1

Add-Type -Path ".\log4net.2.0.8\lib\net45-full\log4net.dll" # パスは環境に合わせて変更

$logger = [log4net.LogManager]::GetLogger($MyInvocation.MyCommand.Path)

$Appender = new-object log4net.Appender.RollingFileAppender
$Appender.File = ([System.IO.Directory]::GetParent($MyInvocation.MyCommand.Path)).FullName + "\sample.log" # フルパス指定が重要
$Appender.Encoding= [System.Text.Encoding]::UTF8
$Appender.Threshold = [log4net.Core.Level]::Debug
$Appender.AppendToFile = $True
$Appender.StaticLogFileName = $True
$Appender.PreserveLogFileNameExtension = $True

# モードを指定 Size or Date(or Composite)
$Appender.RollingStyle = [log4net.Appender.RollingFileAppender+RollingMode]::Composite  # ここの指定方法でハマった

# RollingMode::Size (or Composite) の設定
$Appender.MaxSizeRollBackups = 5
$Appender.MaxFileSize = 1024 * 1024 * 10 # 10MB
$Appender.CountDirection = -1 # -1だと常に同じファイル名

# RollingMode::Date (or Composite)  の設定
$Appender.DatePattern = ".yyyyMMdd"

$layout = new-object log4net.Layout.PatternLayout
$layout.ConversionPattern = "%date{yyyy/MM/dd HH:mm:ss.fff},%-5p,%m%n"

$Appender.Layout = $layout
$Appender.ActivateOptions()
$logger.Logger.AddAppender($Appender)
$logger.Logger.Hierarchy.Configured = $True # 設定を有効にする

for($index = 0 ; $index -lt 100 ; $index++){

    $logger.Debug("Debug メッセージ " + $index )
    $logger.Info("Info メッセージ " + $index )
    $logger.Warn("Warn メッセージ " + $index )
    $logger.Error("Error メッセージ " + $index )
    $logger.Fatal("Fatal メッセージ " + $index )
}

[log4net.LogManager]::ResetConfiguration()  # ResetConfiguration()でファイルクローズできます


```

リファレンス通りの実装で動きましたが、RollingModeに値を設定するところで少しハマりました。

```powershell

[log4net.Appender.RollingFileAppender.RollingMode]

```

でエラーになるので、$Appender.RollingStyle.GetType().FullNameで型を調べたら

```powershell

[log4net.Appender.RollingFileAppender+RollingMode]

```

が正解とのこと。+記号ってどういう意味なの？



## 実行確認

実行すると以下のようなログファイルが出力されます

```log:sample.log

2020/04/01 10:20:30.400,DEBUG,Debug メッセージ 0
2020/04/01 10:20:30.400,INFO ,Info メッセージ 0
2020/04/01 10:20:30.400,WARN ,Warn メッセージ 0
2020/04/01 10:20:30.400,ERROR,Error メッセージ 0
2020/04/01 10:20:30.400,FATAL,Fatal メッセージ 0
2020/04/01 10:20:30.400,DEBUG,Debug メッセージ 1
2020/04/01 10:20:30.400,INFO ,Info メッセージ 1
2020/04/01 10:20:30.400,WARN ,Warn メッセージ 1
2020/04/01 10:20:30.400,ERROR,Error メッセージ 1
2020/04/01 10:20:30.400,FATAL,Fatal メッセージ 1
(略)

```


MaxFileSizeを超えるとファイルが切り替わります。

```

sample.log
sample.1.log
sample.2.log
sample.3.log
sample.4.log
sample.5.log

```


日付でのファイル切り替えを確認したい場合は、powershellからSet-ItemPropertyで過去日付に変更した後で、再度サンプルを実行してください。


```powershell

Set-ItemProperty -Path sample.log -Name LastWriteTime -Value 2020/01/01

```

日付の場合は以下のようにファイルが切り替わることを確認できます。

```

sample.log
sample.1.log
sample.2.log
sample.3.log
sample.4.log
sample.5.log
sample.20200101.log
sample.20200101.1.log
sample.20200101.2.log
sample.20200101.3.log
sample.20200101.4.log
sample.20200101.5.log

```


# おわりに

RollingFileAppenderは設定値が多く謎な動作が多いですが、上記サンプルで実運用で必要な設定は指定できると思います。

使い慣れた人はXMLのほうが良いのでしょうけど、初心者向けにはすべてスクリプト内で設定して動かすほうが理解が深まると思いました。



# 私PowerShellだけど…シリーズ

[私PowerShellだけど、君のタスクトレイで暮らしたい](https://qiita.com/magiclib/items/cc2de9169c781642e52d)
[私PowerShellだけど「送る」からファイルを受け取りたい（コンテキストメニュー登録もあるよ）](https://qiita.com/magiclib/items/7529557f756af9c8d21b)
[私powershellだけどタスクトレイの片隅でアイを叫ぶ](https://qiita.com/magiclib/items/9d0cd35814b6fcff2e44)
[私PowerShellだけど子を持つ親になるのはいろいろ大変そう](https://qiita.com/magiclib/items/ef0ab5c1fd8e0260b39d)
[私PowerShellだけどあなたにトーストを届けたい（プログレスバー付）](https://qiita.com/magiclib/items/12e2a9e1e1e823a7fa5c)


[サンプルソース置き場](https://github.com/part-time-penguin/qiita_powershell_samples)