Checked with Get-MarsCollectorDiagnostics.ps1 output from MARS agent 2.0.9274 (VA-FS-01): - JobStatus.StartTime/EndTime are UTC values not marked as UTC (DisplayTime is the local one); they were read as local, putting runs 6 hours off. Lookback filtering now compares in UTC too - ErrorInfo is always present with ErrorCode 0 on success; every completed backup would have been a warning. Only non-zero error codes count - Schedule times are TimeSpans; casting them to DateTime failed, so next_run_at was always empty - DatasourceStatus.Datasource is an object; use its DataSourceName - Also report FileProgress.Failed file counts and FailedFileLog - Mock rebuilt on the real shapes; diagnostics handle no System State policy Co-Authored-By: Claude Opus 5.5 <[email protected]>
103 lines
3.7 KiB
PowerShell
103 lines
3.7 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Read-only dump of what the MARS agent's cmdlets return, for troubleshooting the collector.
|
|
|
|
.DESCRIPTION
|
|
The collector reads properties of Get-OBJob / Get-OBPolicy / Get-OBSchedule results whose names
|
|
aren't documented. This prints those objects' real structure (property names, types and values,
|
|
a few levels deep) so mismatches can be fixed. Nothing is changed. Output is also saved to a
|
|
text file.
|
|
|
|
.EXAMPLE
|
|
.\Get-MarsCollectorDiagnostics.ps1
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[int]$Jobs = 3,
|
|
[string]$OutFile = (Join-Path $env:TEMP 'mars-collector-diagnostics.txt')
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$MaxDepth = 6
|
|
|
|
if (-not (Get-Command Get-OBJob -ErrorAction SilentlyContinue)) {
|
|
if (Get-Module -ListAvailable -Name MSOnlineBackup) {
|
|
Import-Module MSOnlineBackup
|
|
} else {
|
|
Import-Module (Join-Path $env:ProgramFiles 'Microsoft Azure Recovery Services Agent\bin\Modules\MSOnlineBackup')
|
|
}
|
|
}
|
|
|
|
function Test-Scalar($Value) {
|
|
return $null -eq $Value -or $Value -is [string] -or $Value -is [ValueType] -or $Value -is [guid]
|
|
}
|
|
|
|
# Recursive "name (type) = value" listing. Collections show their first 3 items.
|
|
function Show-Object($Value, [string]$Indent = ' ', [int]$Depth = 0) {
|
|
if (Test-Scalar $Value) { return }
|
|
if ($Depth -ge $MaxDepth) { "$Indent..."; return }
|
|
if ($Value -is [Collections.IEnumerable]) {
|
|
$items = @($Value)
|
|
"$Indent[$($items.Count) item(s)]"
|
|
$i = 0
|
|
foreach ($item in $items | Select-Object -First 3) {
|
|
"$Indent[$i] ($($item.GetType().FullName))$(if (Test-Scalar $item) { " = $item" })"
|
|
Show-Object $item "$Indent " ($Depth + 1)
|
|
$i++
|
|
}
|
|
return
|
|
}
|
|
foreach ($p in $Value.PSObject.Properties) {
|
|
try { $v = $p.Value } catch { "$Indent$($p.Name) = <error: $($_.Exception.Message)>"; continue }
|
|
$type = if ($null -eq $v) { 'null' } else { $v.GetType().FullName }
|
|
if (Test-Scalar $v) {
|
|
"$Indent$($p.Name) ($type) = $v"
|
|
} else {
|
|
$text = [string]$v
|
|
if ($text.Length -gt 100) { $text = $text.Substring(0, 97) + '...' }
|
|
"$Indent$($p.Name) ($type) = $text"
|
|
Show-Object $v "$Indent " ($Depth + 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
function Show-Section([string]$Title, [scriptblock]$Get) {
|
|
"== $Title"
|
|
try {
|
|
$result = @(& $Get)
|
|
if ($result.Count -eq 0 -or ($result.Count -eq 1 -and $null -eq $result[0])) { ' (nothing returned)' }
|
|
$n = 0
|
|
foreach ($item in $result) {
|
|
if ($null -eq $item) { continue }
|
|
" [$n] ($($item.GetType().FullName))"
|
|
Show-Object $item ' '
|
|
$n++
|
|
}
|
|
} catch {
|
|
" error: $($_.Exception.Message)"
|
|
}
|
|
''
|
|
}
|
|
|
|
$report = & {
|
|
$agent = try {
|
|
(Get-Item (Join-Path $env:ProgramFiles 'Microsoft Azure Recovery Services Agent\bin\cbengine.exe')).VersionInfo.ProductVersion
|
|
} catch { 'unknown' }
|
|
"Generated $(Get-Date -Format o) on $env:COMPUTERNAME, MARS agent $agent, PowerShell $($PSVersionTable.PSVersion)"
|
|
''
|
|
Show-Section 'Get-OBJob (in progress)' { Get-OBJob }
|
|
Show-Section "Get-OBJob -Previous $Jobs" { Get-OBJob -Previous $Jobs }
|
|
Show-Section 'Get-OBPolicy' { Get-OBPolicy }
|
|
Show-Section 'Get-OBPolicy | Get-OBSchedule' { Get-OBSchedule -Policy (Get-OBPolicy) }
|
|
if (Get-Command Get-OBSystemStatePolicy -ErrorAction SilentlyContinue) {
|
|
Show-Section 'Get-OBSystemStatePolicy | Get-OBSchedule' {
|
|
$ssPolicy = Get-OBSystemStatePolicy
|
|
if ($ssPolicy) { Get-OBSchedule -Policy $ssPolicy } else { '(no System State policy configured)' }
|
|
}
|
|
}
|
|
} | Out-String -Width 300
|
|
|
|
$report
|
|
$report | Set-Content -Path $OutFile -Encoding UTF8
|
|
Write-Host "Saved to $OutFile"
|