Private/Common/Write-PukLog.ps1

function Write-PukLog {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateSet('Debug', 'Info', 'Warning', 'Error')]
        [string]$Level,

        [Parameter(Mandatory)]
        [string]$Message,

        [psobject]$Config
    )

    if (-not $Config) {
        $Config = Get-PukModuleConfig
    }

    $severityRank = @{ Debug = 0; Info = 1; Warning = 2; Error = 3 }
    if ($severityRank[$Level] -lt $severityRank[$Config.logging.level]) {
        return
    }

    $line = "$((Get-Date).ToString('o')) [$Level] $Message"

    if ($Config.logging.target -in @('File', 'Both')) {
        try {
            $logPath = $Config.logging.file.path
            $directory = Split-Path -Path $logPath -Parent
            if ($directory -and -not (Test-Path -LiteralPath $directory)) {
                New-Item -ItemType Directory -Path $directory -Force | Out-Null
            }
            Add-Content -LiteralPath $logPath -Value $line -Encoding utf8 -ErrorAction Stop
        }
        catch {
            Write-Warning "PWSHPUKMGT: failed to write to log file '$($Config.logging.file.path)': $($_.Exception.Message)"
        }
    }

    if ($Config.logging.target -in @('EventLog', 'Both')) {
        try {
            $logName = $Config.logging.eventLog.logName
            $source = $Config.logging.eventLog.source
            $eventId = $Config.logging.eventLog.eventId

            # SourceExists() enumerates every local event log (including admin-only logs like
            # Security) to check for the source, and throws in a non-elevated session rather
            # than just returning false. Treat that as "unknown" and still attempt creation.
            $sourceExists = $false
            try {
                $sourceExists = [System.Diagnostics.EventLog]::SourceExists($source)
            }
            catch {
                $sourceExists = $false
            }

            if (-not $sourceExists) {
                New-EventLog -LogName $logName -Source $source -ErrorAction Stop
            }

            $entryType = switch ($Level) {
                'Error' { [System.Diagnostics.EventLogEntryType]::Error }
                'Warning' { [System.Diagnostics.EventLogEntryType]::Warning }
                default { [System.Diagnostics.EventLogEntryType]::Information }
            }

            Write-EventLog -LogName $logName -Source $source -EventId $eventId -EntryType $entryType -Message $Message -ErrorAction Stop
        }
        catch {
            Write-Warning "PWSHPUKMGT: failed to write to the Windows Event Log (source '$($Config.logging.eventLog.source)'): $($_.Exception.Message)"
        }
    }
}