owpengram-server/scripts/analyze-media-download-log.ps1

146 lines
4.6 KiB
PowerShell

<#
.SYNOPSIS
Summarizes upload.getFile requests in telesrv logs.
.DESCRIPTION
Use this after opening media history in TDesktop or Android. It groups
upload.getFile RPCs by client_type/app_version and reports request count and
duration percentiles. Pass -SinceLine from a previous baseline if desired.
#>
[CmdletBinding()]
param(
[string]$ServerLogPath,
[int]$SinceLine = 0,
[int]$Tail = 0,
[switch]$ShowSamples
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot ".."))
if (-not $ServerLogPath) {
$latestLog = Get-ChildItem (Join-Path $RepoRoot "logs") -Filter "telesrv-*.err.log" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if ($latestLog) {
$ServerLogPath = $latestLog.FullName
} else {
$ServerLogPath = Join-Path $RepoRoot "logs\telesrv.err.log"
}
}
function Read-SharedLogLines {
if (-not (Test-Path -LiteralPath $ServerLogPath)) {
return @()
}
$stream = [System.IO.File]::Open($ServerLogPath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
try {
$reader = New-Object System.IO.StreamReader($stream)
try {
$lines = New-Object System.Collections.Generic.List[string]
while (-not $reader.EndOfStream) {
$lines.Add($reader.ReadLine()) | Out-Null
}
return $lines
} finally {
$reader.Dispose()
}
} finally {
$stream.Dispose()
}
}
function Get-Field {
param([string]$Line, [string]$Name, [string]$Default = "")
if ($Line -match ('"' + [regex]::Escape($Name) + '"\s*:\s*"([^"]*)"')) {
return $Matches[1]
}
if ($Line -match ('"' + [regex]::Escape($Name) + '"\s*:\s*([^,}]+)')) {
return $Matches[1]
}
return $Default
}
function Convert-DurationMs([string]$Text) {
if (-not $Text) { return 0.0 }
if ($Text -match '^([0-9.]+)ms$') { return [double]$Matches[1] }
if ($Text -match '^([0-9.]+)s$') { return [double]$Matches[1] * 1000.0 }
if ($Text -match '^([0-9.]+)µs$') { return [double]$Matches[1] / 1000.0 }
if ($Text -match '^([0-9.]+)us$') { return [double]$Matches[1] / 1000.0 }
if ($Text -match '^([0-9.]+)ns$') { return [double]$Matches[1] / 1000000.0 }
return 0.0
}
function Percentile {
param([double[]]$Values, [double]$P)
if ($Values.Count -eq 0) { return 0.0 }
$sorted = @($Values | Sort-Object)
$idx = [int][Math]::Ceiling($P * $sorted.Count) - 1
if ($idx -lt 0) { $idx = 0 }
if ($idx -ge $sorted.Count) { $idx = $sorted.Count - 1 }
return [double]$sorted[$idx]
}
$allLines = @(Read-SharedLogLines)
$lineCount = $allLines.Count
$lines = $allLines
if ($SinceLine -gt 0) {
$lines = @($lines | Select-Object -Skip $SinceLine)
}
if ($Tail -gt 0) {
$lines = @($lines | Select-Object -Last $Tail)
}
$items = New-Object System.Collections.Generic.List[object]
foreach ($line in $lines) {
if ($line -notlike "*upload.getFile*") {
continue
}
$method = Get-Field $line "method"
if ($method -notlike "upload.getFile*") {
continue
}
$client = Get-Field $line "client_type" "unknown"
$app = Get-Field $line "app_version" ""
$dur = Convert-DurationMs (Get-Field $line "dur" "0ms")
$items.Add([pscustomobject]@{
Client = $client
AppVersion = $app
DurationMs = $dur
Line = $line
}) | Out-Null
}
Write-Host "log=$ServerLogPath"
Write-Host "total_lines=$lineCount analyzed_lines=$($lines.Count) since_line=$SinceLine upload_get_file=$($items.Count)"
Write-Host ""
if ($items.Count -eq 0) {
Write-Host "No upload.getFile entries found."
exit 0
}
$groups = $items | Group-Object Client, AppVersion
foreach ($group in $groups) {
$values = @($group.Group | ForEach-Object { [double]$_.DurationMs })
$sum = 0.0
foreach ($v in $values) { $sum += $v }
$avg = $sum / [Math]::Max(1, $values.Count)
[pscustomobject]@{
Client = ($group.Group[0].Client)
AppVersion = ($group.Group[0].AppVersion)
Count = $values.Count
AvgMs = [Math]::Round($avg, 3)
P50Ms = [Math]::Round((Percentile $values 0.50), 3)
P95Ms = [Math]::Round((Percentile $values 0.95), 3)
P99Ms = [Math]::Round((Percentile $values 0.99), 3)
MaxMs = [Math]::Round((($values | Measure-Object -Maximum).Maximum), 3)
}
}
if ($ShowSamples) {
Write-Host ""
Write-Host "Samples:"
$items | Select-Object -Last 20 | ForEach-Object { Write-Host $_.Line }
}