GinShell.Logging/Public/Write-GsLokiLog.ps1
|
function Write-GsLokiLog { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Message, [Parameter()] [ValidateSet('verbose', 'debug', 'action', 'success', 'info', 'warning', 'error', 'critical')] [string]$Type = 'info', [Parameter()] [hashtable]$Labels, [Parameter()] [string]$LokiUri ) $resolvedUri = $LokiUri if ([string]::IsNullOrWhiteSpace($resolvedUri)) { $resolvedUri = $global:GsLokiUri } if ([string]::IsNullOrWhiteSpace($resolvedUri)) { $resolvedUri = $env:GS_LOKI_URI } if ([string]::IsNullOrWhiteSpace($resolvedUri)) { Write-Error "The loki endpoint is not set yet, hence unable to send log to loki endpoint"; return } $finalLabels = @{} if ($global:GsLokiLabels -is [hashtable]) { $global:GsLokiLabels.GetEnumerator() | ForEach-Object { $finalLabels[$_.Key] = $_.Value } } if (-not [string]::IsNullOrWhiteSpace($env:GS_LOKI_LABELS)) { try { $envLabels = $env:GS_LOKI_LABELS | ConvertFrom-Json -AsHashtable $envLabels.GetEnumerator() | ForEach-Object { $finalLabels[$_.Key] = $_.Value } } catch { Write-Warning "Invalid JSON in GS_LOKI_LABELS environment variable: $($env:GS_LOKI_LABELS)" } } if ($Labels -is [hashtable]) { $Labels.GetEnumerator() | ForEach-Object { $finalLabels[$_.Key] = $_.Value } } if (-not $finalLabels.ContainsKey('type')) { $finalLabels['type'] = $Type } if (-not $finalLabels.ContainsKey('hostname')) { $finalLabels['hostname'] = $env:COMPUTERNAME } if (-not $finalLabels.ContainsKey('script_path')) { $finalLabels['script'] = if ($MyInvocation.ScriptName) { $MyInvocation.ScriptName } else { 'Interactive_powershell' } } if (-not $finalLabels.ContainsKey('run_as')) { $finalLabels['run_as'] = $env:USERNAME } if (-not $finalLabels.ContainsKey('powershell_version')) { $finalLabels['powershell_version'] = $PSVersionTable.PSVersion.ToString() } if (-not $finalLabels.ContainsKey('app')) { if ($MyInvocation.ScriptName) { $finalLabels['app'] = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName) } else { $finalLabels['app'] = 'Interactive_PowerShell' } } # Getting Time Stamp in Nanoseconds $timestampNs = if ($PSVersionTable.PSVersion.Major -ge 6) { [bigint](([datetimeoffset]::UtcNow) - ([datetimeoffset]::UnixEpoch)).Ticks * 100 } else { $unixEpoch = New-Object DateTime(1970, 1, 1, 0, 0, 0, [System.DateTimeKind]::Utc) $timeSpan = (Get-Date).ToUniversalTime() - $unixEpoch ($timeSpan.Ticks * 100).ToString('F0') } $payload = @{ streams = @( @{ stream = $finalLabels values = @( , @([string]$timestampNs, $Message) ) } ) } $jsonPayload = $payload | ConvertTo-Json -Depth 5 -Compress $pushUrl = "$($resolvedUri.TrimEnd('/'))/loki/api/v1/push" try { $output = Invoke-RestMethod -Uri $pushUrl -Method Post -Body $jsonPayload -ContentType 'application/json' -ErrorAction Stop Write-Verbose "Loki log sent to $pushUrl and received response: $($output | ConvertTo-Json -Depth 5)" } catch { Write-Error "Loki log failed: $($_.Exception.Message)" Write-Debug "Payload: $jsonPayload" } } |