はじめに
powershellを触っていてロガーがほしくなったので作ってみました。
ネットを探すとロガーはいくつか出てくる([これ1][]・[これ2][])し、基本的にそれを使えばいいんだけど自分好みに作りたい&勉強もかねて作成してみることに。
[これ1]:https://qiita.com/miyamiya/items/f36ce9c4b0ffea26afe0
[これ2]:https://qiita.com/asterisk9101/items/d13bf7bdd87a14ccbcaf
やりたいこと
- コンソールとファイルへの同時出力
- コンソールへの出力は指定した文字のみを出力
- ファイルへの出力には特定の書式(年月日をつけるとか)+指定した文字で出力
- ログレベルを指定してDebugログは開発時以外では出ないようにとかしたい
- 変数の出力とかも簡単にできたら嬉しい
こんな感じで使いたい
# ログレベルをInfoで設定したとして
$logger.Info("ほげほげ")
# =>consol:ほげほげ file:yyyy/mm/dd hh:mm:ss [Info] ほげほげ
$logger.Debug("ふがふが")
# =>consol:出力なし file:出力なし
# こんなのもできたら嬉しい
# ログレベルがDebugとして
$a = Get-ChildItem
$logger.Debug($a)
# =>consol:Get-ChildItemの結果 file:yyyy/mm/dd hh:mm:ss [Debug]Get-ChildItemの結果
実装結果・使い方
やりたいことはほぼほぼできた感じ。
ログレベルはError,Warn,Info,Debugの4段階で作成。
使い方1
# ロガーの取得
$logger = Get-Logger -logLevel Info -logFilePath hoge.log
#ログ出力
$logger.Error("エラー!")
# =>consol:エラー!
# =>hoge.log:2019/04/03 00:29:01.450 [Error] エラー!
$logger.Warn("警告!")
# =>consol:警告!
# =>hoge.log:2019/04/03 00:29:01.465 [Warn] 警告!
$logger.Info("インフォメーション")
# =>consol:インフォメーション
# =>hoge.log:00:29:01.465 [Info] インフォメーション
$logger.Debug("出ない・・・")
# =>consol:(出力なし)
# =>hoge.log:(出力なし)
変数の出力も一応できる
Get-ChildItem
# Mode LastWriteTime Length Name
# ---- ------------- ------ ----
# -a---- 2019/04/03 0:29 132 hoge.log
$logger2 = Get-Logger -logLevel Debug -logFilePath huga.log
$a = Get-ChiledItem
$logger2.Debug($a)
# =>consol:hoge.log
# =>huga.log:2019/04/03 00:29:01.490 [Debug] hoge.log
コンソールには出さないスイッチも付けてみた。
使い方2
$logger3 = Get-Logger -logLevel Info -logFilePath hunga.txt -NoDisplay
$logger3.Info("コンソールには出力しない")
# =>consol:(出力なし)
# =>hunga.log:2019/04/03 00:29:01.503 [Info] コンソールには出力しない
実装
logger.ps1
$source = "public enum LogLevel{Error=0, Warn=1, Info=2, Debug=3}"
Add-Type -Language CSharp -TypeDefinition $source
function Get-Logger
{
Param(
[Parameter(Mandatory)]
[String] $logFilePath,
[Parameter(Mandatory)]
[LogLevel] $logLevel,
[Switch] $NoDisplay
)
$loggerObj = New-Object psobject
#メンバ変数の追加
$loggerObj | Add-Member -MemberType NoteProperty -Name logFilePath -Value $logFilePath
$loggerObj | Add-Member -MemberType NoteProperty -Name logLevel -Value $logLevel
#メソッドの追加
#画面表示用スクリプト
$outHostScript = {
Param(
[Parameter(Mandatory)] [string] $logStr
)
Write-Host $logStr
}
$loggerObj | Add-Member -MemberType ScriptMethod -Name OutHost -Value $outHostScript
#ファイル出力用スクリプト
$outFileScript ={
Param(
[Parameter(Mandatory)] [string] $logStr,
[Parameter(Mandatory)] [LogLevel] $level
)
$logStr = (Get-Date).ToString("yyyy/MM/dd HH:mm:ss.fff") + " [$($level)] $logStr"
$logStr | Out-File -FilePath $this.logFilePath -Append -Encoding default
}
$loggerObj | Add-Member -MemberType ScriptMethod -Name OutFile -Value $outFileScript
#ログ出力用スクリプト
$script = {
Param(
[Parameter(Mandatory)] [System.Object[]] $logStrArray
)
if($this.logLevel -ge $Script:level)
{
foreach($log in $logStrArray ){
if( -Not($NoDisplay)){
$this.OutHost($log)
}
$this.OutFile($log, $Script:level)
}
}
}
#logLevel分メソッド作成
foreach($level_tmep in ([System.Enum]::GetNames([LogLevel])))
{
[LogLevel] $level = $level_tmep
$loggerObj | Add-Member -MemberType ScriptMethod -Name $level.toString() -Value $script.GetNewClosure()
}
return $loggerObj
}
#解説
気が向いたら書きます。