Powershell

PowershellでLogを出力するロガーClassを自作【便利】

Powershell

PowerShellでスクリプトを作成している時に「ログ」をどうやって効率的に吐き出すことができるか悩んだことはありませんか?

ログ出力はスクリプトのデバック時にももちろん必要ですが、タスクスケジューラーなどでスクリプトをバッチ処理する際にはあとで実行結果を確認するために必須となる機能です。

私は昔にPerlを利用していた時に「log4perl」という非常に便利なログ出力モジュールを使っていたのですが、これと同じようなロガーの機能がPowerShellにはなかったのでクラスを使って自作してみました。

今回はみなさんにも利用してもらえるように使い方などを説明したいと思います。

Loggerスクリプト概要

まずは使い方ですが、以下のような感じで使います。以下を実行するとコンソールへ表示されると共にログファイルへも記録されます。

$logger.info("Logger Info")
$logger.warn("Logger Warn")
$logger.error("Logger Error")

出力されるログの形式はlog4perl風に以下の順番でログが記録されます。まずはコンソールの出力です。以下のような感じでレベルに応じてコンソールに表示される文字に色がつきます。

ログファイルは以下のように記録されます。

2020/04/12 10:34:22 INFO User01 LoggerTest.ps1 Logger Info
2020/04/12 10:34:22 WARN User01 LoggerTest.ps1 Logger Warn
2020/04/12 10:34:22 ERROR User01 LoggerTest.ps1 Logger Error

Loggerスクリプト詳細

内容デフォルト値備考
ログファイルの場所./logs/事前にフォルダを作成しておく必要があります
ログファイル名称Script名_yyyyMM.log(例)LoggerTest.ps1_202004.log
※月ごとにファイルは分割されます
※ファイルが存在しない場合には自動的に作成されます
※ログは追記されていきます
区切り文字列半角空白1つあとで自由に変更可能
(:とか-とかに変更できます)

ファイル構成

例としてこんな感じのディレクトリとファイルの構造にしています。適宜変更することができます。

Logger.ps1

以下の内容でファイルをコピペして下さい。

class Logger {
    [string] $scriptName
    [string] $scriptPath
    [string] $level
    [string] $logFolder = '\logs\'
    [string] $logFile
    [string] $execUser = (Get-Content env:username)
    [string] $encoding = "Default"
    [string] $delimiter = " "
    [string] $color = "White"
    [string] $yyyyMM

    Logger ($MyInvocation) {
        $this.scriptName = $MyInvocation.MyCommand.Name
        $this.scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
        $this.yyyyMM = Get-Date -Format yyyyMM
        $this.logFolder = $this.scriptPath + '\logs\'
        $this.logFile = $this.logFolder + $this.scriptName + "_" + $this.yyyyMM + ".log"
    }
    #*******************************************
    # Log Level Config
    #*******************************************
    [string] info($msg) {
        $this.level = "INFO"
        $this.setColor("White")
        $this.setlog($msg)
        return $null
    }

    [string] warn($msg) {
        $this.level = "WARN"
        $this.setColor("Yellow")
        $this.setlog($msg)
        return $null
    }

    [string] error($msg) {
        $this.level = "ERROR"
        $this.setColor("Red")
        $this.setlog($msg)
        return $null
    }

    # コンソールに表示する色を設定する
    [string] setColor($color) {
        $this.color = $color
        return $null
    }

    # ログの区切り文字を変更する
    [string] changeDelimiter($delimiter) {
        $this.delimiter = $delimiter
        return $null
    }

    #*******************************************
    # ログ出力
    #*******************************************
    [string] setlog($msg) {
        $txt = (Get-date -Format "yyyy/MM/dd HH:mm:ss") + `
            $this.delimiter + $this.level + `
            $this.delimiter + $this.execUser + `
            $this.delimiter + $this.scriptName + `
            $this.delimiter + $msg

        Write-Host $txt -ForegroundColor $this.color -NoNewline

        if (Test-Path $this.logFolder) {
            Write-Output $txt | Out-File -FilePath $this.logfile -Append -Encoding $this.encoding
            return $null
        }else{
            Write-host ("***** ログ保管フォルダがありません。作成してください。Folder=["+$this.logFolder + "] *****")
        }
        return $null
    }
}
# End Script...

TestLogger.ps1(スクリプトファイル)

ロガーを使うテストのためのスクリプトになります。

# Loggerクラスの呼び込み
. "./class/Logger.ps1"

# Logger Object作成
$logger = New-Object Logger($MyInvocation)

# Logを表示する
$logger.info("Logger Info")
$logger.warn("Logger Warn")
$logger.error("Logger Error")

# 区切り文字を変更する
$logger.changeDelimiter(" : ")
$logger.info("あああああ")

# End Script...

実行

コンソールに表示されると共にLoggerTest.ps1_202004.logファイルに以下のような内容が保存されているかと思います。

途中で区切り文字が「 : 」に正しく変更されていることも確認できます。

2020/04/12 11:10:25 INFO User01 LoggerTest.ps1 Logger Info
2020/04/12 11:10:25 WARN User01 LoggerTest.ps1 Logger Warn
2020/04/12 11:10:25 ERROR User01 LoggerTest.ps1 Logger Error

2020/04/12 11:10:25 : INFO : User01 : LoggerTest.ps1 : あああああ

まとめ

今回のロガーを作成することでPowerShellで「log4perl」風に簡単にログを取得することができるようになりました。今後のスクリプトでも使っていきたいと思います。

今回は以上となります。

コメント