powershell 写日志

简单日志系统

# https://github.com/EsOsO/Logging
# Install-Module Logging

Import-Module Logging

Set-LoggingDefaultLevel -Level 'WARNING'
Add-LoggingTarget -Name Console
Add-LoggingTarget -Name File -Configuration @{ Path = 'C:\Temp\example_%{+%Y%m%d}.log'; Encoding = 'UTF8'  }

$Level = 'DEBUG', 'INFO', 'WARNING', 'ERROR'
foreach ($i in 1 .. 100)
{
    Write-Log -Level ($Level | Get-Random) -Message 'Message n. {0}' -Arguments $i
    Start-Sleep -Milliseconds (Get-Random -Min 100 -Max 1000)
}

Wait-Logging # See Note

PoShLog

  • 基于 Serilog 构建, 可以指定 SinksEnrichers
  • 手册 https://github.com/PoShLog/PoShLog/wiki
  • 项目 https://github.com/PoShLog/PoShLog

基础使用

# 安装模块
Install-Module -Name PoShLog

# 导入模块 
Import-Module PoShLog

# 启动日志,想要更多设置的话,使用 New-Logger , 见下一节内容
# -MinimumLevel Verbose|Debug|Information|Warning|Error|Fatal
# -FileRollingInterval Infinite|Year|Month|Day|Hour|Minute
Start-Logger -FilePath 'C:\Data\my_awesome.log' -FileRollingInterval Day -Console

# 写入日志
Write-InfoLog 'Hurrray, my first log message'
Write-ErrorLog 'Oops, error occurred!'

# 关闭日志
Close-Logger

更多设置

https://github.com/PoShLog/PoShLog/wiki/Usage

# 创建新的记录器
New-Logger | # 创建记录器配置的新实例
    Set-MinimumLevel -Value Verbose | # 设置最小日志级别,低于该级别的事件不会产生
    Add-SinkFile -Path 'C:\Data\my_awesome-.log' -RollingInterval Day | # 添加一个将事件消息写入文件的接收器(sink)    
    Add-SinkConsole  -RestrictedToMinimumLevel Information  | # 添加一个将事件消息输出到控制台主机的接收器
    Start-Logger # 开始记录日志

# Add-Sinkxxxx # https://github.com/PoShLog/PoShLog/wiki/Sinks 中有更多接收顺
# -RestrictedToMinimumLevel 单独指定接收器的最小日志级别
# -OutputTemplate '{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}' # 指定日志输出格式, https://github.com/PoShLog/PoShLog/wiki/Enrichers 中有更多可记录属性

PWSH 包装类

# 自动判断安装与载入模块
class ModuleLoader{

    static [void] ImportModule([string]$moduleName) {
        if(-not (Get-Module -Name $moduleName -ListAvailable )){
            Write-Host "正在安装 $moduleName 模块..."
            Install-Module -Name $moduleName -Scope CurrentUser -Force -AllowClobber
        }

        if (-not (Get-Module -Name $moduleName)) {
            Import-Module $moduleName
        }
    }
}

[ModuleLoader]::ImportModule("PoShLog")

# 日志辅助
# Install-Module -Name PoShLog -Scope CurrentUser
class Logger {

    static  [Serilog.ILogger] $_logger

    static [Serilog.ILogger] getLogger() {
        return [Logger]::_logger
    }

    static [void] Initialize() {

        if (-not (Get-Module -Name PoShLog)) {
            Import-Module PoShLog
        }
    }

    static [void] start([bool]$enableFileLog = $false) {

        # 脚本目录及文件名
        $scriptPath = $PSCommandPath
        if (-not $scriptPath) {
            # 如果不是脚本中运行的,则当作是当前目录下的 psScript.ps1
            $scriptPath = Join-Path -Path (Get-Location) -ChildPath 'psScript.ps1'
        }

        $scriptDir = Split-Path -Parent $scriptPath
        $scriptName = Split-Path -Leaf $scriptPath

        $logPath = Join-Path -Path $scriptDir -ChildPath 'logs'
        if (-not (Test-Path -Path $logPath)) {
            New-Item -Path $logPath -ItemType Directory | Out-Null
        }

        $logFile = Join-Path -Path $logPath -ChildPath ($scriptName -replace '\.ps1$', '.log')

        # 创建新的记录器
        $logger = New-Logger | # 创建记录器配置的新实例
        Set-MinimumLevel  -Value Verbose | # 设置最小日志级别,低于该级别的事件不会产生        
        Add-SinkConsole  # 添加一个将事件消息输出到控制台主机的接收器

        if ($enableFileLog) {
            $logger = $logger | Add-SinkFile -Path $logFile -RollingInterval Day  # 添加一个将事件消息写入文件的接收器(sink)
        }

        [Logger]::_logger = $logger | Start-Logger -PassThru -SetAsDefault
    }

    static [void] log([string]$message, [System.Exception]$exception = $null) {

        if ($exception) {
            logError($message, $exception)
        }
        else {
            logInfo($message)
        }        
    }

    static [void] logInfo([string]$message) {
        Write-InformationLog $message
    }

    # 记录一个对象
    static [void] logInfo([System.Object]$obj) {
        Write-InformationLog -MessageTemplate "{obj}" -Property $obj
    }

    # [Logger]::logInfo("服务器获取数据:{value}",  @{word = $word; time = (Get-Date)})
    static [void] logInfo([string]$template, [System.Object]$property) {
        Write-InformationLog -MessageTemplate $template -Property $property
    }

    static [void] logError([string]$message, [System.Exception]$exception) {
        Write-ErrorLog $message -Exception $exception
    }

    static [void] logWarn([string]$message, [System.Exception]$exception = $null) {
        Write-WarningLog $message -Exception $exception
    }

    static [void] stop() {
        Close-Logger
    }
}
调用

要记得关闭,不然日志文件会被占用

[Logger]::Initialize()

[Logger]::start($true)

try {

    [Logger]::logInfo("查询单词: $word")    
    [Logger]::logInfo("服务器获取数据:{value}",  @{word = $word; time = (Get-Date)})
    [Logger]::logInfo(@{word = $word; time = (Get-Date)})

    [Logger]::logInfo("查询单词: $word")

    $logger = [Logger]::getLogger()
    Write-InformationLog  -Logger $logger  @{ word = $word }
    Write-InformationLog  -Logger $logger -MessageTemplate "日志系统初始化完成, 查询单词: {name}, {name2}, test" -Property @{ word = $word }

    # throw [System.Exception]::new("测试异常")
    throw "测试异常"

    [Logger]::logInfo("查询完成: $word")
}
catch {
    [Logger]::logError("查询单词失败: $word", $_.Exception)
}
finally {    
    [Logger]::stop()
}
上一篇
下一篇