modules/HomeLab.Logging/Public/Write-Log.ps1
function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [AllowEmptyString()] [string]$Message, [Parameter(Mandatory = $false)] [ValidateSet('Info','Warning','Error','Success', 'Debug', 'Verbose', IgnoreCase = $true)] [string]$Level = 'Info', [Parameter(Mandatory = $false)] [string]$Color, [Parameter(Mandatory = $false)] [string]$LogFile = $script:LogFile, # Use script-level variable as fallback [Parameter(Mandatory = $false)] [switch]$NoConsole, [Parameter(Mandatory = $false)] [switch]$NoLog, [Parameter(Mandatory = $false)] [switch]$Force, [Parameter(Mandatory = $false)] [switch]$NoPrefix ) # Handle empty messages if ([string]::IsNullOrWhiteSpace($Message)) { $Message = "(Empty message)" } # Define default colors for log levels $defaultColors = @{ 'Verbose' = 'Gray' 'Debug' = 'Cyan' 'Info' = 'White' 'Success' = 'Green' 'Warning' = 'Yellow' 'Error' = 'Red' } # Define log level priorities $logLevelPriority = @{ 'Verbose' = -2 'Debug' = -1 'Info' = 0 'Success' = 1 'Warning' = 2 'Error' = 3 } # Use provided color if any; otherwise default based on log level if (-not $Color) { $Color = $defaultColors[$Level] } # Use the provided LogFile if available; otherwise use the one in global config # Add fallback to script-level variable if global config is not available if (-not $LogFile) { if ($Global:Config -and $Global:Config.LogFile) { $LogFile = $Global:Config.LogFile } elseif ($script:LogFile) { $LogFile = $script:LogFile } else { # Ultimate fallback - create a log in the current directory $LogFile = Join-Path -Path $PSScriptRoot -ChildPath "logs\homelab_$(Get-Date -Format 'yyyyMMdd').log" } } # Format the timestamp and construct the log message $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Create different messages for console and file # Console message can optionally skip the prefix $consoleMessage = if ($NoPrefix) { $Message } else { "[$timestamp] [$Level] $Message" } $fileLogMessage = "[$timestamp] [$Level] $Message" # Default log levels if config is not available $defaultLogLevel = 'Info' $consoleLogLevel = $defaultLogLevel $fileLogLevel = $defaultLogLevel # Try to get log levels from config with proper error handling if ($Global:Config -and $Global:Config.Logging) { # Get console log level from config with fallbacks if ($Global:Config.Logging.ConsoleLogLevel) { $consoleLogLevel = $Global:Config.Logging.ConsoleLogLevel } elseif ($Global:Config.Logging.DefaultLogLevel) { $consoleLogLevel = $Global:Config.Logging.DefaultLogLevel } # Get file log level from config with fallbacks if ($Global:Config.Logging.FileLogLevel) { $fileLogLevel = $Global:Config.Logging.FileLogLevel } elseif ($Global:Config.Logging.DefaultLogLevel) { $fileLogLevel = $Global:Config.Logging.DefaultLogLevel } # Check if file logging is enabled in config $fileLoggingEnabled = $Force -or ($Global:Config.Logging.EnableFileLogging -eq $true) # Check if console logging is enabled in config $consoleLoggingEnabled = $Force -or ($Global:Config.Logging.EnableConsoleLogging -eq $true) } else { # Default to enabled if config is not available $fileLoggingEnabled = $Force -or $true $consoleLoggingEnabled = $Force -or $true } # Check if we should write to console based on log level priority and settings $writeToConsole = $consoleLoggingEnabled -and (-not $NoConsole) -and ($logLevelPriority[$Level] -ge $logLevelPriority[$consoleLogLevel]) # Check if we should write to log file based on log level priority and settings $writeToFile = $fileLoggingEnabled -and (-not $NoLog) -and ($logLevelPriority[$Level] -ge $logLevelPriority[$fileLogLevel]) # Write to log file if logging is not suppressed and meets the minimum level if ($writeToFile -and $LogFile) { # Create the directory if it doesn't exist $logDir = Split-Path -Parent $LogFile if (-not (Test-Path $logDir)) { New-Item -Path $logDir -ItemType Directory -Force | Out-Null } try { $fileLogMessage | Out-File -FilePath $LogFile -Append -ErrorAction Stop } catch { # If we can't write to the log file, at least output an error to the console Write-Host "ERROR: Failed to write to log file $LogFile : $($_.Exception.Message)" -ForegroundColor Red } } # Write to console if not suppressed and meets the minimum level if ($writeToConsole) { Write-Host $consoleMessage -ForegroundColor $Color [Console]::Out.Flush() } } |