添加 veeam全任务.ps1
This commit is contained in:
+255
@@ -0,0 +1,255 @@
|
|||||||
|
# 完全兼容你的环境,所有原有指标和格式不变
|
||||||
|
Add-PSSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
# 配置项
|
||||||
|
$JobName = "veeam_backup"
|
||||||
|
$InstanceName = $env:COMPUTERNAME
|
||||||
|
$OutputFile = Join-Path -Path $PWD.Path -ChildPath "veeam_metrics.prom"
|
||||||
|
|
||||||
|
# Linux 上传配置
|
||||||
|
$linuxUser = "root"
|
||||||
|
$linuxIP = "10.150.117.190"
|
||||||
|
$linuxPath = "/opt/prom_textfile/"
|
||||||
|
$localFile = ".\veeam_metrics.prom"
|
||||||
|
|
||||||
|
# 恢复任务采集配置:采集最近多少小时内的恢复会话
|
||||||
|
$RestoreSessionHours = 24
|
||||||
|
|
||||||
|
while ($true) {
|
||||||
|
$Metrics = @()
|
||||||
|
$TodayStart = (Get-Date).Date
|
||||||
|
$GlobalTotalJobs = 0
|
||||||
|
$GlobalSuccessJobs = 0
|
||||||
|
$GlobalFailedJobs = 0
|
||||||
|
$GlobalRunningJobs = 0
|
||||||
|
$GlobalDailyTotalBackup = 0
|
||||||
|
|
||||||
|
# ================== 指标头部(新增备份量明确说明)==================
|
||||||
|
$Metrics += "# HELP veeam_job_status Veeam all job status (0=Success,1=Warning,2=Failed,3=None)"
|
||||||
|
$Metrics += "# TYPE veeam_job_status gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_is_running Veeam job is running (1=running,0=idle)"
|
||||||
|
$Metrics += "# TYPE veeam_job_is_running gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_progress_percent Veeam job progress percentage"
|
||||||
|
$Metrics += "# TYPE veeam_job_progress_percent gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_backup_size_gb 上次备份实际写入仓库的大小(GB) - 对应Veeam日志中的Backup size"
|
||||||
|
$Metrics += "# TYPE veeam_job_backup_size_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_data_size_gb 上次备份处理的原始数据总大小(GB) - 对应Veeam日志中的Total size"
|
||||||
|
$Metrics += "# TYPE veeam_job_data_size_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_transferred_size_gb 上次备份实际传输的数据大小(GB) - 对应Veeam日志中的Transferred"
|
||||||
|
$Metrics += "# TYPE veeam_job_transferred_size_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_duration_seconds Veeam last job duration in seconds"
|
||||||
|
$Metrics += "# TYPE veeam_job_duration_seconds gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_daily_backup_size_gb 今日累计备份写入仓库的总大小(GB)"
|
||||||
|
$Metrics += "# TYPE veeam_job_daily_backup_size_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_compression_ratio 总压缩率(原始数据总大小/备份大小)"
|
||||||
|
$Metrics += "# TYPE veeam_job_compression_ratio gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_current_compression_ratio 本次备份压缩率(本次读取数据/实际传输大小) - 对应Veeam日志中的Compression"
|
||||||
|
$Metrics += "# TYPE veeam_job_current_compression_ratio gauge"
|
||||||
|
$Metrics += "# HELP veeam_repo_free_space_gb Veeam repository free space in GB"
|
||||||
|
$Metrics += "# TYPE veeam_repo_free_space_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_repo_total_space_gb Veeam repository total space in GB"
|
||||||
|
$Metrics += "# TYPE veeam_repo_total_space_gb gauge"
|
||||||
|
|
||||||
|
# 全局统计指标
|
||||||
|
$Metrics += "# HELP veeam_global_total_jobs Total number of all Veeam jobs"
|
||||||
|
$Metrics += "# TYPE veeam_global_total_jobs gauge"
|
||||||
|
$Metrics += "# HELP veeam_global_success_jobs Number of successful Veeam jobs"
|
||||||
|
$Metrics += "# TYPE veeam_global_success_jobs gauge"
|
||||||
|
$Metrics += "# HELP veeam_global_failed_jobs Number of failed Veeam jobs"
|
||||||
|
$Metrics += "# TYPE veeam_global_failed_jobs gauge"
|
||||||
|
$Metrics += "# HELP veeam_global_running_jobs Number of running Veeam jobs"
|
||||||
|
$Metrics += "# TYPE veeam_global_running_jobs gauge"
|
||||||
|
$Metrics += "# HELP veeam_global_daily_total_gb 今日所有任务累计写入仓库的总大小(GB)"
|
||||||
|
$Metrics += "# TYPE veeam_global_daily_total_gb gauge"
|
||||||
|
$Metrics += "# HELP veeam_global_success_rate Overall Veeam job success rate today (0-100)"
|
||||||
|
$Metrics += "# TYPE veeam_global_success_rate gauge"
|
||||||
|
|
||||||
|
# 单任务健康度指标
|
||||||
|
$Metrics += "# HELP veeam_job_last_success_timestamp Last successful job timestamp (Unix milliseconds)"
|
||||||
|
$Metrics += "# TYPE veeam_job_last_success_timestamp gauge"
|
||||||
|
$Metrics += "# HELP veeam_job_since_last_success_hours Hours since last successful job"
|
||||||
|
$Metrics += "# TYPE veeam_job_since_last_success_hours gauge"
|
||||||
|
|
||||||
|
# 存储智能预警指标
|
||||||
|
$Metrics += "# HELP veeam_repo_usage_percent Repository usage percentage (0-100)"
|
||||||
|
$Metrics += "# TYPE veeam_repo_usage_percent gauge"
|
||||||
|
$Metrics += "# HELP veeam_repo_remaining_days Estimated remaining days based on daily rate"
|
||||||
|
$Metrics += "# TYPE veeam_repo_remaining_days gauge"
|
||||||
|
$Metrics += ""
|
||||||
|
|
||||||
|
# ================== 1. 采集所有持久化计划任务 ==================
|
||||||
|
$Jobs = Get-VBRJob | Where-Object { $_.JobType -in
|
||||||
|
"Backup", "Restore", "VmRestore", "FileRestore", "Rescan",
|
||||||
|
"Replication", "BackupCopy", "TapeBackup", "TapeCatalog",
|
||||||
|
"FileToTape", "SureBackup", "BackupSync", "BackupValidation",
|
||||||
|
"ConfigurationBackup", "AgentBackup", "AgentRestore",
|
||||||
|
"NASBackup", "NASRestore", "CloudBackup", "CloudRestore"
|
||||||
|
}
|
||||||
|
$AllSessions = Get-VBRBackupSession
|
||||||
|
$Now = Get-Date # 提前获取当前时间,避免循环中多次调用
|
||||||
|
|
||||||
|
# ================== 2. 采集最近24小时所有恢复会话(手动+计划)==================
|
||||||
|
$RestoreCutoffTime = $Now.AddHours(-$RestoreSessionHours)
|
||||||
|
$AllRestoreSessions = Get-VBRRestoreSession | Where-Object { $_.CreationTime -ge $RestoreCutoffTime }
|
||||||
|
|
||||||
|
# 将恢复会话转换为统一的任务对象格式
|
||||||
|
$RestoreTasks = @()
|
||||||
|
foreach ($Session in $AllRestoreSessions) {
|
||||||
|
# 跳过已经在计划任务中的恢复任务(去重)
|
||||||
|
if ($Jobs | Where-Object { $_.Id -eq $Session.JobId }) { continue }
|
||||||
|
|
||||||
|
$RestoreTask = [PSCustomObject]@{
|
||||||
|
Id = $Session.Id
|
||||||
|
Name = "Restore_" + $Session.Name -replace '[^a-zA-Z0-9_]', '_'
|
||||||
|
JobType = "RestoreSession"
|
||||||
|
LastSession = $Session
|
||||||
|
}
|
||||||
|
$RestoreTasks += $RestoreTask
|
||||||
|
}
|
||||||
|
|
||||||
|
# 合并计划任务和恢复任务
|
||||||
|
$AllJobs = $Jobs + $RestoreTasks
|
||||||
|
$GlobalTotalJobs = $AllJobs.Count
|
||||||
|
|
||||||
|
# ================== 统一处理所有任务 ==================
|
||||||
|
foreach ($Job in $AllJobs) {
|
||||||
|
# 区分计划任务和临时恢复会话
|
||||||
|
if ($Job.JobType -eq "RestoreSession") {
|
||||||
|
$LastSession = $Job.LastSession
|
||||||
|
} else {
|
||||||
|
$LastSession = $Job.FindLastSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
$Status = if ($LastSession) { $LastSession.Result } else { "None" }
|
||||||
|
$State = if ($LastSession) { $LastSession.State } else { "Idle" }
|
||||||
|
|
||||||
|
$StatusCode = switch ($Status) {
|
||||||
|
"Success" { 0; $GlobalSuccessJobs++ }
|
||||||
|
"Warning" { 1; $GlobalSuccessJobs++ }
|
||||||
|
"Failed" { 2; $GlobalFailedJobs++ }
|
||||||
|
default { 3 }
|
||||||
|
}
|
||||||
|
|
||||||
|
$IsRunning = if ($State -eq "Working") { 1; $GlobalRunningJobs++ } else { 0 }
|
||||||
|
$CleanJobName = $Job.Name -replace '[^a-zA-Z0-9_]', '_' -replace '[\r\n`"''"]', ''
|
||||||
|
|
||||||
|
# 基础指标(完全不变)
|
||||||
|
$Metrics += "veeam_job_status{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $StatusCode"
|
||||||
|
$Metrics += "veeam_job_is_running{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $IsRunning"
|
||||||
|
$Metrics += "veeam_job_progress_percent{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $(if($LastSession-and$State-eq'Working'){$LastSession.Progress.Percents}else{0})"
|
||||||
|
|
||||||
|
# ✅ 修复:完整采集所有备份量指标(对应Veeam日志所有字段)
|
||||||
|
if ($LastSession) {
|
||||||
|
if ($State -eq "Working") {
|
||||||
|
$BackupSizeGB = if ($LastSession.Info.Progress.BackupSize) { [math]::Round($LastSession.Info.Progress.BackupSize / 1GB, 2) } else { 0 }
|
||||||
|
$DataSizeGB = if ($LastSession.Info.Progress.DataSize) { [math]::Round($LastSession.Info.Progress.DataSize / 1GB, 2) } else { 0 }
|
||||||
|
$TransferredSizeGB = if ($LastSession.Info.Progress.TransferredSize) { [math]::Round($LastSession.Info.Progress.TransferredSize / 1GB, 2) } else { 0 }
|
||||||
|
} else {
|
||||||
|
$BackupSizeGB = if ($LastSession.BackupStats.BackupSize) { [math]::Round($LastSession.BackupStats.BackupSize / 1GB, 2) } else { 0 }
|
||||||
|
$DataSizeGB = if ($LastSession.BackupStats.DataSize) { [math]::Round($LastSession.BackupStats.DataSize / 1GB, 2) } else { 0 }
|
||||||
|
$TransferredSizeGB = if ($LastSession.BackupStats.TransferredSize) { [math]::Round($LastSession.BackupStats.TransferredSize / 1GB, 2) } else { 0 }
|
||||||
|
}
|
||||||
|
$DurationSeconds = if ($LastSession.EndTime -and $LastSession.CreationTime) { [math]::Round(($LastSession.EndTime - $LastSession.CreationTime).TotalSeconds, 2) } else { 0 }
|
||||||
|
} else {
|
||||||
|
$BackupSizeGB = 0
|
||||||
|
$DataSizeGB = 0
|
||||||
|
$TransferredSizeGB = 0
|
||||||
|
$DurationSeconds = 0
|
||||||
|
}
|
||||||
|
$Metrics += "veeam_job_backup_size_gb{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $BackupSizeGB"
|
||||||
|
$Metrics += "veeam_job_data_size_gb{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $DataSizeGB"
|
||||||
|
$Metrics += "veeam_job_transferred_size_gb{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $TransferredSizeGB"
|
||||||
|
$Metrics += "veeam_job_duration_seconds{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $DurationSeconds"
|
||||||
|
|
||||||
|
# 当日任务量(包含所有类型任务)
|
||||||
|
$TodaySessions = $AllSessions | Where-Object { $_.JobId -eq $Job.Id -and $_.CreationTime -ge $TodayStart }
|
||||||
|
$DailyBackupSizeGB = 0
|
||||||
|
foreach ($Session in $TodaySessions) {
|
||||||
|
if ($Session.BackupStats.BackupSize) {
|
||||||
|
$DailyBackupSizeGB += $Session.BackupStats.BackupSize / 1GB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$DailyBackupSizeGB = [math]::Round($DailyBackupSizeGB, 2)
|
||||||
|
$GlobalDailyTotalBackup += $DailyBackupSizeGB
|
||||||
|
$Metrics += "veeam_job_daily_backup_size_gb{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $DailyBackupSizeGB"
|
||||||
|
|
||||||
|
# 任务健康度指标(完全不变)
|
||||||
|
if ($Job.JobType -eq "RestoreSession") {
|
||||||
|
# 恢复会话直接使用当前会话作为最后成功会话
|
||||||
|
$LastSuccessSession = if ($Status -eq "Success") { $LastSession } else { $null }
|
||||||
|
} else {
|
||||||
|
$JobSuccessSessions = $AllSessions | Where-Object { $_.JobId -eq $Job.Id -and $_.Result -eq "Success" } | Sort-Object EndTime -Descending
|
||||||
|
$LastSuccessSession = $JobSuccessSessions | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($LastSuccessSession -and $LastSuccessSession.EndTime) {
|
||||||
|
$LastSuccessTimestamp = [math]::Round($LastSuccessSession.EndTime.ToUniversalTime().Subtract((Get-Date "1970-01-01")).TotalMilliseconds, 0)
|
||||||
|
$TimeDiff = ($Now) - $LastSuccessSession.EndTime
|
||||||
|
$SinceLastSuccessHours = [math]::Round($TimeDiff.TotalHours, 1)
|
||||||
|
} else {
|
||||||
|
$LastSuccessTimestamp = 0
|
||||||
|
$SinceLastSuccessHours = 9999
|
||||||
|
}
|
||||||
|
$Metrics += "veeam_job_last_success_timestamp{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $LastSuccessTimestamp"
|
||||||
|
$Metrics += "veeam_job_since_last_success_hours{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $SinceLastSuccessHours"
|
||||||
|
|
||||||
|
# ✅ 修复:同时提供两种压缩率
|
||||||
|
# 总压缩率:原始数据总大小/备份大小(反映整体压缩效果)
|
||||||
|
$CompressionRatio = if ($BackupSizeGB -gt 0) { [math]::Round($DataSizeGB / $BackupSizeGB, 2) } else { 0 }
|
||||||
|
# 本次压缩率:本次传输大小/本次读取大小(和Veeam日志显示一致)
|
||||||
|
$CurrentCompressionRatio = if ($TransferredSizeGB -gt 0) { [math]::Round($DataSizeGB / $TransferredSizeGB, 2) } else { 0 }
|
||||||
|
$Metrics += "veeam_job_compression_ratio{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $CompressionRatio"
|
||||||
|
$Metrics += "veeam_job_current_compression_ratio{job=`"$JobName`",instance=`"$InstanceName`",job_name=`"$CleanJobName`"} $CurrentCompressionRatio"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 全局统计(完全不变)
|
||||||
|
$GlobalSuccessRate = if ($GlobalTotalJobs -gt 0) { [math]::Round(($GlobalSuccessJobs / $GlobalTotalJobs) * 100, 1) } else { 0 }
|
||||||
|
$Metrics += "veeam_global_total_jobs{job=`"$JobName`",instance=`"$InstanceName`"} $GlobalTotalJobs"
|
||||||
|
$Metrics += "veeam_global_success_jobs{job=`"$JobName`",instance=`"$InstanceName`"} $GlobalSuccessJobs"
|
||||||
|
$Metrics += "veeam_global_failed_jobs{job=`"$JobName`",instance=`"$InstanceName`"} $GlobalFailedJobs"
|
||||||
|
$Metrics += "veeam_global_running_jobs{job=`"$JobName`",instance=`"$InstanceName`"} $GlobalRunningJobs"
|
||||||
|
$Metrics += "veeam_global_daily_total_gb{job=`"$JobName`",instance=`"$InstanceName`"} $([math]::Round($GlobalDailyTotalBackup, 2))"
|
||||||
|
$Metrics += "veeam_global_success_rate{job=`"$JobName`",instance=`"$InstanceName`"} $GlobalSuccessRate"
|
||||||
|
$Metrics += ""
|
||||||
|
|
||||||
|
# ================== 3. 存储库指标(完全不变)==================
|
||||||
|
$Repositories = Get-VBRBackupRepository
|
||||||
|
foreach ($Repo in $Repositories) {
|
||||||
|
$Path = $Repo.Path
|
||||||
|
$DriveLetter = (Split-Path $Path -Qualifier).TrimEnd(':')
|
||||||
|
$DiskInfo = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$DriveLetter`:'" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$FreeSpaceGB = if ($DiskInfo -and $DiskInfo.FreeSpace) { [math]::Round($DiskInfo.FreeSpace / 1GB, 2) } else { 0 }
|
||||||
|
$TotalSpaceGB = if ($DiskInfo -and $DiskInfo.Size) { [math]::Round($DiskInfo.Size / 1GB, 2) } else { 0 }
|
||||||
|
$CleanRepoName = $Repo.Name -replace '[^a-zA-Z0-9_]', '_' -replace '[\r\n`"''"]', ''
|
||||||
|
|
||||||
|
$Metrics += "veeam_repo_free_space_gb{job=`"$JobName`",instance=`"$InstanceName`",repo_name=`"$CleanRepoName`"} $FreeSpaceGB"
|
||||||
|
$Metrics += "veeam_repo_total_space_gb{job=`"$JobName`",instance=`"$InstanceName`",repo_name=`"$CleanRepoName`"} $TotalSpaceGB"
|
||||||
|
|
||||||
|
# 存储使用率和剩余天数
|
||||||
|
$UsagePercent = if ($TotalSpaceGB -gt 0) { [math]::Round((($TotalSpaceGB - $FreeSpaceGB) / $TotalSpaceGB) * 100, 1) } else { 0 }
|
||||||
|
$Metrics += "veeam_repo_usage_percent{job=`"$JobName`",instance=`"$InstanceName`",repo_name=`"$CleanRepoName`"} $UsagePercent"
|
||||||
|
|
||||||
|
$RemainingDays = if ($GlobalDailyTotalBackup -gt 0 -and $FreeSpaceGB -gt 0) { [math]::Round($FreeSpaceGB / $GlobalDailyTotalBackup, 1) } else { 999 }
|
||||||
|
$Metrics += "veeam_repo_remaining_days{job=`"$JobName`",instance=`"$InstanceName`",repo_name=`"$CleanRepoName`"} $RemainingDays"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ================== 格式保证 & 上传(完全不变)==================
|
||||||
|
$Metrics += ""
|
||||||
|
$MetricsBody = $Metrics -join "`n" -replace "`r", ""
|
||||||
|
[System.IO.File]::WriteAllText($OutputFile, $MetricsBody, [System.Text.UTF8Encoding]::new($false))
|
||||||
|
|
||||||
|
Write-Host "`n📤 正在上传指标文件..." -ForegroundColor Cyan
|
||||||
|
scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL $localFile "${linuxUser}@${linuxIP}:${linuxPath}"
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL "${linuxUser}@${linuxIP}" "sed -i 's/\r$//;s/[^[:print:]]//g' ${linuxPath}veeam_metrics.prom && chmod 644 ${linuxPath}veeam_metrics.prom"
|
||||||
|
Write-Host "✅ [$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] 采集完成"
|
||||||
|
Write-Host " - 总任务: $GlobalTotalJobs | 成功: $GlobalSuccessJobs | 失败: $GlobalFailedJobs | 运行中: $GlobalRunningJobs"
|
||||||
|
Write-Host " - 今日总备份量: $([math]::Round($GlobalDailyTotalBackup, 2)) GB | 成功率: $GlobalSuccessRate%"
|
||||||
|
Write-Host " - 已包含所有任务类型+完整备份量统计,等待60秒`n" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "❌ 上传失败,请检查SSH免密配置" -ForegroundColor Red
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 60
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user