GinShell.Logging/Public/Write-GsLog.ps1

function Write-GsLog {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter()]
        [ValidateSet('verbose', 'debug', 'action', 'success', 'info', 'warning', 'error', 'critical')]
        [string]$Type = 'Info',

        [Parameter()]
        [ValidateSet('verbose', 'debug', 'action', 'success', 'info', 'warning', 'error', 'critical')]
        [string]$LogLevel = $global:GsDefaultLogLevel,

        [Parameter()]
        [bool]$EnableFileLogging = $global:GsEnableFileLogging,

        [Parameter()]
        [string]$LogFileName = $global:GsLogFileName,

        [Parameter()]
        [string]$LogDirectory = $global:GsLogDirectory,

        [Parameter()]
        [bool]$EnableLokiLogging = $global:GsEnableLokiLogging
    )

    $threshold = Get-LogLevelValue -Level $LogLevel
    $current = Get-LogLevelValue -Level $Type
    if ($current -lt $threshold) { return }

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $scriptName = $MyInvocation.PSCommandPath
    if (-not $scriptName) { $scriptName = "<interactive>" }

    $logMessage = "$timestamp [$Type] - $Message"
    $color = Get-LogColor -Type $Type

    Write-Host $logMessage -ForegroundColor $color

    # --- File Logging ---
    if ($EnableFileLogging) {
        if (-not $LogFileName) {
            $baseName = if ($MyInvocation.PSCommandPath) {
                [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.PSCommandPath)
            }
            else {
                "interactive"
            }
            $LogFilePath = Join-Path -Path $LogDirectory -ChildPath "$(Get-Date -Format 'yyyy_MM_dd')__$baseName.log"
        }
        else {
            $LogFilePath = Join-Path -Path $LogDirectory -ChildPath $LogFileName
        }

        $logDir = Split-Path -Path $LogFilePath -Parent
        if (-not (Test-Path -Path $logDir)) {
            New-Item -Path $logDir -ItemType Directory -Force | Out-Null
        }
        Add-Content -Path $LogFilePath -Value $logMessage -Encoding UTF8
    }

    # --- Loki Logging ---
    if ($EnableLokiLogging) {
        if ($global:GsLokiLabels -is [hashtable]) {
            Write-GsLokiLog -Message $Message -Type $Type -Labels $global:GsLokiLabels
        }
        else {
            Write-GsLokiLog -Message $Message -Type $Type -Labels @{
                app                = if ($MyInvocation.ScriptName) {
                    [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)
                }
                else {
                    'Interactive_PowerShell'
                }
                hostname           = $env:COMPUTERNAME
                script_path        = if ($MyInvocation.ScriptName) { $MyInvocation.ScriptName } else { 'Interactive_PowerShell' }
                run_as             = $env:USERNAME
                powershell_version = $PSVersionTable.PSVersion.ToString()
            }
        }
    }
}