fix: SAC POST body null prefix from Write-Log pipeline (1.2.12-SAC)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
PTah
2026-05-28 10:44:22 +10:00
parent 5284734092
commit 74d1e4db75
3 changed files with 48 additions and 10 deletions
+1 -1
View File
@@ -80,7 +80,7 @@ $script:MonitorLoopInitialized = $false
# строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах). # строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах).
# Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только # Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только
# исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1). # исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1).
$ScriptVersion = "1.2.11-SAC" $ScriptVersion = "1.2.12-SAC"
# Логи (все под InstallRoot) # Логи (все под InstallRoot)
$LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log" $LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log"
+46 -8
View File
@@ -4,7 +4,7 @@
.DESCRIPTION .DESCRIPTION
Dot-source после login_monitor.settings.ps1 и функции Write-Log. Dot-source после login_monitor.settings.ps1 и функции Write-Log.
Ожидает: $UseSAC, $SacUrl, $SacApiKey, $ScriptVersion, $script:InstallRoot. Ожидает: $UseSAC, $SacUrl, $SacApiKey, $ScriptVersion, $script:InstallRoot.
Release: 1.2.11-SAC (JSON via JavaScriptSerializer for Cyrillic; better 422 logging). Release: 1.2.12-SAC (fix null+JSON body from pipeline; no ConvertFrom-Json on ingest).
#> #>
function Test-SacIngestAcceptedStatus { function Test-SacIngestAcceptedStatus {
@@ -29,18 +29,41 @@ function Complete-SacIngestSuccess {
function Get-SacUtf8Bytes { function Get-SacUtf8Bytes {
param([Parameter(Mandatory = $true)][string]$Text) param([Parameter(Mandatory = $true)][string]$Text)
return (New-Object System.Text.UTF8Encoding $false).GetBytes($Text) $t = Get-SacSingleString -Value $Text -Label 'request body'
if ($t.StartsWith([char]0xFEFF)) { $t = $t.Substring(1) }
# PowerShell иногда склеивает $null и JSON в "null{...}" — ломает FastAPI json parser
if ($t.Length -gt 5 -and $t.StartsWith('null', [System.StringComparison]::Ordinal) -and $t[4] -eq '{') {
Write-SacLog 'WARN: SAC stripped accidental null prefix before JSON body'
$t = $t.Substring(4)
}
return (New-Object System.Text.UTF8Encoding $false).GetBytes($t)
} }
function Write-SacLog { function Write-SacLog {
param([string]$Message) param([string]$Message)
if (Get-Command Write-Log -ErrorAction SilentlyContinue) { if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
Write-Log $Message [void](Write-Log $Message)
} else { } else {
Write-Host $Message Write-Host $Message
} }
} }
function Get-SacSingleString {
param($Value, [string]$Label)
if ($null -eq $Value) { return '' }
if ($Value -is [string]) { return $Value }
if ($Value -is [System.Array]) {
$parts = @($Value | Where-Object { $null -ne $_ -and $_ -is [string] -and $_.Length -gt 0 })
if ($parts.Count -gt 0) {
if ($parts.Count -gt 1) {
Write-SacLog "WARN: SAC $Label had $($parts.Count) string parts; using last"
}
return [string]$parts[-1]
}
}
return [string]$Value
}
function Get-SacNormalizedMode { function Get-SacNormalizedMode {
$m = if ($null -ne $UseSAC) { [string]$UseSAC } else { 'off' } $m = if ($null -ne $UseSAC) { [string]$UseSAC } else { 'off' }
return $m.Trim().ToLowerInvariant() return $m.Trim().ToLowerInvariant()
@@ -328,9 +351,16 @@ function Invoke-SacPostPayload {
$ingest = Get-SacIngestUrl $ingest = Get-SacIngestUrl
if ([string]::IsNullOrWhiteSpace($ingest)) { return $false } if ([string]::IsNullOrWhiteSpace($ingest)) { return $false }
$obj = $JsonBody | ConvertFrom-Json $jsonText = Get-SacSingleString -Value $JsonBody -Label 'spool payload'
$eventId = [string]$obj.event_id if ($jsonText -notmatch '"event_id"\s*:\s*"([0-9a-fA-F-]{36})"') {
$eventType = [string]$obj.type Write-SacLog 'WARN: SAC JSON has no event_id (uuid); skip POST'
return $false
}
$eventId = $Matches[1]
$eventType = 'unknown'
if ($jsonText -match '"type"\s*:\s*"([^"]+)"') {
$eventType = $Matches[1]
}
$timeout = if ($SacTimeoutSec) { [int]$SacTimeoutSec } else { 12 } $timeout = if ($SacTimeoutSec) { [int]$SacTimeoutSec } else { 12 }
$spoolOnFailure = $true $spoolOnFailure = $true
@@ -341,7 +371,7 @@ function Invoke-SacPostPayload {
'Content-Type' = 'application/json; charset=utf-8' 'Content-Type' = 'application/json; charset=utf-8'
'Idempotency-Key' = $eventId 'Idempotency-Key' = $eventId
} }
$bodyBytes = Get-SacUtf8Bytes -Text $JsonBody $bodyBytes = Get-SacUtf8Bytes -Text $jsonText
$resp = Invoke-WebRequest -Uri $ingest -Method Post -Headers $headers -Body $bodyBytes -UseBasicParsing -TimeoutSec $timeout $resp = Invoke-WebRequest -Uri $ingest -Method Post -Headers $headers -Body $bodyBytes -UseBasicParsing -TimeoutSec $timeout
if (Test-SacIngestAcceptedStatus -StatusCode $resp.StatusCode) { if (Test-SacIngestAcceptedStatus -StatusCode $resp.StatusCode) {
Complete-SacIngestSuccess -EventId $eventId -EventType $eventType -StatusCode $resp.StatusCode Complete-SacIngestSuccess -EventId $eventId -EventType $eventType -StatusCode $resp.StatusCode
@@ -386,7 +416,7 @@ function Invoke-SacPostPayload {
return $false return $false
} }
Write-SacSpoolFile -EventId $eventId -JsonBody $JsonBody Write-SacSpoolFile -EventId $eventId -JsonBody $jsonText
$max = if ($SacFallbackFailures) { [int]$SacFallbackFailures } else { 5 } $max = if ($SacFallbackFailures) { [int]$SacFallbackFailures } else { 5 }
$n = Get-SacFailCount + 1 $n = Get-SacFailCount + 1
Set-SacFailCount -Count $n Set-SacFailCount -Count $n
@@ -411,7 +441,15 @@ function Send-SacEvent {
} }
$payload = New-SacEventPayload -EventType $EventType -Severity $Severity -Title $Title -Summary $Summary -Details $Details $payload = New-SacEventPayload -EventType $EventType -Severity $Severity -Title $Title -Summary $Summary -Details $Details
if ($payload -is [System.Array]) {
$payload = $payload[-1]
}
$json = ConvertTo-SacJsonText -Payload $payload $json = ConvertTo-SacJsonText -Payload $payload
$json = Get-SacSingleString -Value $json -Label 'event json'
if ([string]::IsNullOrWhiteSpace($json) -or $json[0] -ne '{') {
Write-SacLog "WARN: SAC invalid JSON for type=$EventType (empty or does not start with {{)"
return $false
}
return (Invoke-SacPostPayload -JsonBody $json) return (Invoke-SacPostPayload -JsonBody $json)
} }
+1 -1
View File
@@ -1 +1 @@
1.2.11-SAC 1.2.12-SAC