1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
| function Invoke-DataEtlPipeline { [CmdletBinding()] param( [string]$OutputPath = './etl-output', [switch]$IncludeSummary )
Write-Host "[Extract] 从 CSV 提取服务器资产数据..." -ForegroundColor Yellow $serverCsv = @' Hostname,IP,OS,CPU_CORES,RAM_GB,STATUS WEB-01,192.168.1.10,Ubuntu 22.04,4,16,Running WEB-02,192.168.1.11,Ubuntu 22.04,4,16,Running DB-01,192.168.1.20,CentOS 7,8,64,Running DB-02,192.168.1.21,CentOS 7,8,64,Stopped CACHE-01,192.168.1.30,Ubuntu 22.04,2,8,Running '@
$servers = $serverCsv | ConvertFrom-Csv Write-Host " 提取 $($servers.Count) 条服务器记录"
Write-Host "[Extract] 从 JSON 提取监控指标数据..." -ForegroundColor Yellow $metricsJson = @' [ {"host": "WEB-01", "cpu_pct": 45.2, "mem_pct": 62.1, "disk_pct": 33.7, "timestamp": "2026-02-23T08:00:00Z"}, {"host": "WEB-02", "cpu_pct": 12.8, "mem_pct": 45.3, "disk_pct": 28.9, "timestamp": "2026-02-23T08:00:00Z"}, {"host": "DB-01", "cpu_pct": 78.5, "mem_pct": 85.2, "disk_pct": 71.4, "timestamp": "2026-02-23T08:00:00Z"}, {"host": "CACHE-01", "cpu_pct": 23.1, "mem_pct": 91.5, "disk_pct": 15.2, "timestamp": "2026-02-23T08:00:00Z"} ] '@
$metrics = $metricsJson | ConvertFrom-Json Write-Host " 提取 $($metrics.Count) 条监控指标"
Write-Host "[Extract] 从 XML 提取告警配置..." -ForegroundColor Yellow $alertXml = @' <alerts> <rule name="cpu_high" threshold="70" severity="critical" target_pattern="DB-*"/> <rule name="mem_warning" threshold="80" severity="warning" target_pattern="*"/> <rule name="disk_high" threshold="60" severity="warning" target_pattern="DB-*"/> </alerts> '@
[xml]$xmlDoc = $alertXml $alertRules = $xmlDoc.alerts.rule | ForEach-Object { [PSCustomObject]@{ RuleName = $_.name Threshold = [int]$_.threshold Severity = $_.severity TargetPattern = $_.target_pattern } } Write-Host " 提取 $($alertRules.Count) 条告警规则"
Write-Host "`n[Transform] 关联服务器资产与监控指标..." -ForegroundColor Green
$enriched = foreach ($srv in $servers) { $metric = $metrics | Where-Object { $_.host -eq $srv.Hostname } $triggeredAlerts = @()
foreach ($rule in $alertRules) { $pattern = $rule.TargetPattern -replace '\*', '.*' if ($srv.Hostname -match "^$pattern$") { $violated = $false $fieldMap = @{ 'cpu_high' = 'cpu_pct' 'mem_warning' = 'mem_pct' 'disk_high' = 'disk_pct' } $fieldName = $fieldMap[$rule.RuleName] if ($fieldName -and $metric -and $metric.$fieldName -gt $rule.Threshold) { $violated = $true } if ($violated) { $triggeredAlerts += "[{0}] {1} ({2}% > {3}%)" -f $rule.Severity, $rule.RuleName, $metric.$fieldName, $rule.Threshold } } }
[PSCustomObject][ordered]@{ Hostname = $srv.Hostname IPAddress = $srv.IP OS = $srv.OS CPU_Cores = [int]$srv.CPU_CORES RAM_GB = [int]$srv.RAM_GB Status = $srv.STATUS CPU_Usage = if ($metric) { $metric.cpu_pct } else { $null } MEM_Usage = if ($metric) { $metric.mem_pct } else { $null } DISK_Usage = if ($metric) { $metric.disk_pct } else { $null } AlertCount = $triggeredAlerts.Count Alerts = if ($triggeredAlerts) { $triggeredAlerts -join '; ' } else { '无' } } }
$null = New-Item -ItemType Directory -Path $OutputPath -Force -ErrorAction SilentlyContinue
Write-Host "`n[Load] 导出为 CSV 报表..." -ForegroundColor Magenta $csvFile = Join-Path $OutputPath 'server-report.csv' $enriched | ConvertTo-Csv -NoTypeInformation | Out-File $csvFile -Encoding utf8 Write-Host " 已写入: $csvFile"
Write-Host "[Load] 导出为 JSON..." -ForegroundColor Magenta $jsonFile = Join-Path $OutputPath 'server-report.json' $enriched | ConvertTo-Json -Depth 5 | Out-File $jsonFile -Encoding utf8 Write-Host " 已写入: $jsonFile"
Write-Host "[Load] 导出为 HTML 报表..." -ForegroundColor Magenta $htmlFile = Join-Path $OutputPath 'server-report.html' $htmlParams = @{ Title = '服务器状态报表' Body = '<h1>服务器状态报表</h1>' + '<p>生成时间: {0}</p>' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') Head = '<style>table { border-collapse: collapse; } ' + 'td, th { border: 1px solid #ccc; padding: 6px; } ' + '.critical { color: red; font-weight: bold; }</style>' } $enriched | ConvertTo-Html @htmlParams | Out-File $htmlFile -Encoding utf8 Write-Host " 已写入: $htmlFile"
if ($IncludeSummary) { Write-Host "`n=== ETL 汇总 ===" -ForegroundColor Cyan Write-Host (" 服务器总数: {0}" -f $enriched.Count) Write-Host (" 运行中: {0}" -f ($enriched | Where-Object Status -eq 'Running').Count) Write-Host (" 已停机: {0}" -f ($enriched | Where-Object Status -eq 'Stopped').Count) Write-Host (" 触发告警的服务器: {0}" -f ($enriched | Where-Object AlertCount -gt 0).Count) Write-Host (" 平均 CPU 使用率: {0:N1}%" -f ( ($enriched | Where-Object CPU_Usage | Measure-Object -Property CPU_Usage -Average).Average )) Write-Host (" 平均内存使用率: {0:N1}%" -f ( ($enriched | Where-Object MEM_Usage | Measure-Object -Property MEM_Usage -Average).Average )) }
return $enriched }
$result = Invoke-DataEtlPipeline -IncludeSummary
Write-Host "`n=== 最终报表 ===" -ForegroundColor Cyan $result | Format-Table Hostname, IPAddress, OS, Status, @{N='CPU%';E={'{0:N1}' -f $_.CPU_Usage}}, @{N='MEM%';E={'{0:N1}' -f $_.MEM_Usage}}, @{N='DISK%';E={'{0:N1}' -f $_.DISK_Usage}}, AlertCount -AutoSize
|