Sync all scripts from website downloads — 352 scripts total

Includes updated JS challenge scripts with Claude-User whitelist,
same-site referer bypass, Blackbox-Exporter allowed bot, and all
new exporters, cheat sheets, and automation scripts.
This commit is contained in:
2026-05-25 03:31:08 +02:00
parent dbd6bf0324
commit a1a17e81a1
332 changed files with 174509 additions and 1106 deletions
+713
View File
@@ -0,0 +1,713 @@
<#
.SYNOPSIS
Windows Event Log Prometheus Metrics Exporter
.DESCRIPTION
Prometheus exporter for Windows Event Log critical and error events. Scans
System, Application, and Security event logs for errors, warnings, and
critical events. Exports counts, rates, and recent event details as
Prometheus-compatible text format for windows_exporter textfile collector.
.PARAMETER Mode
Output mode: 'stdout' (default), 'textfile', or 'http'
.PARAMETER Port
HTTP port for http mode (default: 9199)
.PARAMETER TextfileDir
Directory for textfile collector output (default: C:\ProgramData\node_exporter)
.PARAMETER OutputFile
Custom output file path
.PARAMETER InstallScheduledTask
Switch to create a scheduled task for auto-start on system boot
.PARAMETER TaskIntervalMinutes
Interval in minutes for the scheduled task (default: 5)
.NOTES
Author: Phil Connor
Contact: contact@mylinux.work
Website: https://mylinux.work
License: MIT
Version: 1.0
Metrics Exported:
Core Status:
- windows_eventlog_up
- windows_eventlog_exporter_info{version}
System Log:
- windows_eventlog_system_critical_total_1h
- windows_eventlog_system_critical_total_6h
- windows_eventlog_system_critical_total_24h
- windows_eventlog_system_error_total_1h
- windows_eventlog_system_error_total_6h
- windows_eventlog_system_error_total_24h
- windows_eventlog_system_warning_total_1h
- windows_eventlog_system_warning_total_6h
- windows_eventlog_system_warning_total_24h
- windows_eventlog_system_top_source_count{source}
- windows_eventlog_system_events_per_hour
Application Log:
- windows_eventlog_application_critical_total_1h
- windows_eventlog_application_critical_total_6h
- windows_eventlog_application_critical_total_24h
- windows_eventlog_application_error_total_1h
- windows_eventlog_application_error_total_6h
- windows_eventlog_application_error_total_24h
- windows_eventlog_application_warning_total_1h
- windows_eventlog_application_warning_total_6h
- windows_eventlog_application_warning_total_24h
- windows_eventlog_application_top_source_count{source}
- windows_eventlog_application_events_per_hour
- windows_eventlog_application_crash_total_24h
- windows_eventlog_application_dotnet_error_total_24h
Security Log (requires admin):
- windows_eventlog_security_failed_logon_total_24h
- windows_eventlog_security_account_lockout_total_24h
- windows_eventlog_security_privilege_escalation_total_24h
- windows_eventlog_security_audit_policy_change_total_24h
Service Failures:
- windows_eventlog_service_stopped_autostart{service}
- windows_eventlog_service_crash_total_24h
Disk Events:
- windows_eventlog_disk_error_total_24h{source}
System Stability:
- windows_eventlog_unexpected_shutdown_total_24h
- windows_eventlog_bugcheck_total_24h
Summary:
- windows_eventlog_total_critical_error_all_logs
- windows_eventlog_newest_event_timestamp{log}
Exporter:
- windows_eventlog_exporter_duration_seconds
- windows_eventlog_exporter_last_run_timestamp
#>
param(
[ValidateSet('stdout', 'textfile', 'http')]
[string]$Mode = 'stdout',
[int]$Port = 9199,
[string]$TextfileDir = 'C:\ProgramData\node_exporter',
[string]$OutputFile,
[switch]$InstallScheduledTask,
[int]$TaskIntervalMinutes = 5
)
# Create a scheduled task to run this script every $TaskIntervalMinutes minutes
# The task will run as SYSTEM and will be set to run at startup
if ($InstallScheduledTask) {
$taskName = "WindowsEventLogExporter"
$existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
if (-not $existingTask) {
$taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`" -Mode textfile"
if (-not $TaskIntervalMinutes -or $TaskIntervalMinutes -le 0) {
throw "TaskIntervalMinutes must be a positive integer"
}
$taskTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes $TaskIntervalMinutes) -RepetitionDuration (New-TimeSpan -Days 365)
$taskPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
try {
Write-Host "Creating scheduled task: $taskName"
Register-ScheduledTask -TaskName $taskName -Action $taskAction -Trigger $taskTrigger -Principal $taskPrincipal -Description "Exports Windows event log metrics for Prometheus every $TaskIntervalMinutes minutes"
$createdTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
if (-not $createdTask) {
throw "Failed to verify scheduled task creation"
}
Write-Host "Successfully created scheduled task: $taskName" -ForegroundColor Green
} catch {
Write-Error "Failed to create auto-start task: $($_.Exception.Message)"
throw
}
} else {
Write-Host "Scheduled task '$taskName' already exists, skipping creation"
}
}
$ErrorActionPreference = 'SilentlyContinue'
# ============================================================================
# HELPER FUNCTIONS
# ============================================================================
function Get-UnixTimestamp {
[int][double]::Parse((Get-Date -UFormat '%s'))
}
function Format-MetricValue {
param([double]$Value, [int]$Decimals = 2)
[math]::Round($Value, $Decimals)
}
function Get-EventCount {
param(
[string]$LogName,
[int[]]$Level,
[int[]]$Id,
[string[]]$ProviderName,
[int]$Hours = 24
)
$filter = @{
LogName = $LogName
StartTime = (Get-Date).AddHours(-$Hours)
}
if ($Level) { $filter['Level'] = $Level }
if ($Id) { $filter['Id'] = $Id }
if ($ProviderName) { $filter['ProviderName'] = $ProviderName }
try {
$events = Get-WinEvent -FilterHashtable $filter -ErrorAction Stop
return @($events).Count
} catch {
return 0
}
}
function Get-EventCountToTimestamp {
param(
[string]$LogName,
[int[]]$Level
)
try {
$events = Get-WinEvent -FilterHashtable @{
LogName = $LogName
Level = $Level
} -MaxEvents 1 -ErrorAction Stop
if ($events -and $events.Count -gt 0) {
return [int][double]::Parse($events[0].TimeCreated.ToUniversalTime().ToString('yyyyMMddHHmmss').Substring(0,10))
}
} catch {}
try {
$events = Get-WinEvent -FilterHashtable @{
LogName = $LogName
} -MaxEvents 1 -ErrorAction Stop
if ($events -and $events.Count -gt 0) {
$epoch = [datetime]'1970-01-01'
return [int]($events[0].TimeCreated.ToUniversalTime() - $epoch).TotalSeconds
}
} catch {}
return 0
}
# ============================================================================
# SYSTEM LOG EVENTS
# ============================================================================
function Get-SystemLogMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Critical events (Level 1)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'System' -Level 1 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_system_critical_total_$($window.Suffix) System log critical events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_system_critical_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_system_critical_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Error events (Level 2)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'System' -Level 2 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_system_error_total_$($window.Suffix) System log error events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_system_error_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_system_error_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Warning events (Level 3)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'System' -Level 3 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_system_warning_total_$($window.Suffix) System log warning events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_system_warning_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_system_warning_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Top event sources
try {
$systemEvents = Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1, 2
StartTime = (Get-Date).AddHours(-24)
} -ErrorAction Stop
$topSources = $systemEvents | Group-Object ProviderName |
Sort-Object Count -Descending |
Select-Object -First 5
[void]$sb.AppendLine('# HELP windows_eventlog_system_top_source_count Event count for top sources in System log')
[void]$sb.AppendLine('# TYPE windows_eventlog_system_top_source_count gauge')
foreach ($source in $topSources) {
$sourceName = $source.Name -replace '"', ''
[void]$sb.AppendLine("windows_eventlog_system_top_source_count{source=`"$sourceName`"} $($source.Count)")
}
[void]$sb.AppendLine('')
} catch {
[void]$sb.AppendLine('# HELP windows_eventlog_system_top_source_count Event count for top sources in System log')
[void]$sb.AppendLine('# TYPE windows_eventlog_system_top_source_count gauge')
[void]$sb.AppendLine('')
}
# Events per hour
$total24h = Get-EventCount -LogName 'System' -Level 1, 2 -Hours 24
$perHour = Format-MetricValue ($total24h / 24)
[void]$sb.AppendLine('# HELP windows_eventlog_system_events_per_hour System log error/critical event rate per hour')
[void]$sb.AppendLine('# TYPE windows_eventlog_system_events_per_hour gauge')
[void]$sb.AppendLine("windows_eventlog_system_events_per_hour $perHour")
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect system log metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# APPLICATION LOG EVENTS
# ============================================================================
function Get-ApplicationLogMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Critical events (Level 1)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'Application' -Level 1 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_application_critical_total_$($window.Suffix) Application log critical events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_application_critical_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_application_critical_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Error events (Level 2)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'Application' -Level 2 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_application_error_total_$($window.Suffix) Application log error events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_application_error_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_application_error_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Warning events (Level 3)
foreach ($window in @(@{Suffix='1h'; Hours=1}, @{Suffix='6h'; Hours=6}, @{Suffix='24h'; Hours=24})) {
$count = Get-EventCount -LogName 'Application' -Level 3 -Hours $window.Hours
[void]$sb.AppendLine("# HELP windows_eventlog_application_warning_total_$($window.Suffix) Application log warning events in last $($window.Suffix)")
[void]$sb.AppendLine("# TYPE windows_eventlog_application_warning_total_$($window.Suffix) gauge")
[void]$sb.AppendLine("windows_eventlog_application_warning_total_$($window.Suffix) $count")
[void]$sb.AppendLine('')
}
# Top event sources
try {
$appEvents = Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Level = 1, 2
StartTime = (Get-Date).AddHours(-24)
} -ErrorAction Stop
$topSources = $appEvents | Group-Object ProviderName |
Sort-Object Count -Descending |
Select-Object -First 5
[void]$sb.AppendLine('# HELP windows_eventlog_application_top_source_count Event count for top sources in Application log')
[void]$sb.AppendLine('# TYPE windows_eventlog_application_top_source_count gauge')
foreach ($source in $topSources) {
$sourceName = $source.Name -replace '"', ''
[void]$sb.AppendLine("windows_eventlog_application_top_source_count{source=`"$sourceName`"} $($source.Count)")
}
[void]$sb.AppendLine('')
} catch {
[void]$sb.AppendLine('# HELP windows_eventlog_application_top_source_count Event count for top sources in Application log')
[void]$sb.AppendLine('# TYPE windows_eventlog_application_top_source_count gauge')
[void]$sb.AppendLine('')
}
# Events per hour
$total24h = Get-EventCount -LogName 'Application' -Level 1, 2 -Hours 24
$perHour = Format-MetricValue ($total24h / 24)
[void]$sb.AppendLine('# HELP windows_eventlog_application_events_per_hour Application log error/critical event rate per hour')
[void]$sb.AppendLine('# TYPE windows_eventlog_application_events_per_hour gauge')
[void]$sb.AppendLine("windows_eventlog_application_events_per_hour $perHour")
[void]$sb.AppendLine('')
# Application crash events (WER)
$crashCount = Get-EventCount -LogName 'Application' -ProviderName 'Application Error', 'Windows Error Reporting' -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_application_crash_total_24h Application crash events (WER) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_application_crash_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_application_crash_total_24h $crashCount")
[void]$sb.AppendLine('')
# .NET runtime errors
$dotnetCount = Get-EventCount -LogName 'Application' -ProviderName '.NET Runtime' -Level 1, 2 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_application_dotnet_error_total_24h .NET runtime errors in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_application_dotnet_error_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_application_dotnet_error_total_24h $dotnetCount")
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect application log metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# SECURITY LOG EVENTS (requires admin)
# ============================================================================
function Get-SecurityLogMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Failed logon attempts (Event ID 4625)
$failedLogons = Get-EventCount -LogName 'Security' -Id 4625 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_security_failed_logon_total_24h Failed logon attempts (4625) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_security_failed_logon_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_security_failed_logon_total_24h $failedLogons")
[void]$sb.AppendLine('')
# Account lockouts (Event ID 4740)
$lockouts = Get-EventCount -LogName 'Security' -Id 4740 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_security_account_lockout_total_24h Account lockout events (4740) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_security_account_lockout_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_security_account_lockout_total_24h $lockouts")
[void]$sb.AppendLine('')
# Privilege escalation (Event IDs 4672, 4673)
$privEsc = Get-EventCount -LogName 'Security' -Id 4672, 4673 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_security_privilege_escalation_total_24h Privilege escalation events (4672/4673) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_security_privilege_escalation_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_security_privilege_escalation_total_24h $privEsc")
[void]$sb.AppendLine('')
# Audit policy changes (Event ID 4719)
$auditChanges = Get-EventCount -LogName 'Security' -Id 4719 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_security_audit_policy_change_total_24h Audit policy change events (4719) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_security_audit_policy_change_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_security_audit_policy_change_total_24h $auditChanges")
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect security log metrics (admin required): $_"
}
$sb.ToString()
}
# ============================================================================
# SERVICE FAILURES
# ============================================================================
function Get-ServiceFailureMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Auto-start services that are stopped
$stoppedAutoStart = Get-Service | Where-Object {
$_.StartType -eq 'Automatic' -and $_.Status -ne 'Running'
}
[void]$sb.AppendLine('# HELP windows_eventlog_service_stopped_autostart Auto-start services currently in stopped state')
[void]$sb.AppendLine('# TYPE windows_eventlog_service_stopped_autostart gauge')
if ($stoppedAutoStart) {
foreach ($svc in $stoppedAutoStart) {
$svcName = $svc.Name -replace '"', ''
[void]$sb.AppendLine("windows_eventlog_service_stopped_autostart{service=`"$svcName`"} 1")
}
}
[void]$sb.AppendLine('')
# Service crash events (SCM Event IDs 7031, 7034)
$crashCount = Get-EventCount -LogName 'System' -ProviderName 'Service Control Manager' -Id 7031, 7034 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_service_crash_total_24h Service crash events in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_service_crash_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_service_crash_total_24h $crashCount")
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect service failure metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# DISK EVENTS
# ============================================================================
function Get-DiskEventMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
$diskSources = @('disk', 'ntfs', 'volmgr', 'Ntfs', 'Disk', 'volsnap')
[void]$sb.AppendLine('# HELP windows_eventlog_disk_error_total_24h Disk errors in last 24 hours by source')
[void]$sb.AppendLine('# TYPE windows_eventlog_disk_error_total_24h gauge')
foreach ($source in $diskSources) {
$count = Get-EventCount -LogName 'System' -ProviderName $source -Level 1, 2, 3 -Hours 24
if ($count -gt 0) {
[void]$sb.AppendLine("windows_eventlog_disk_error_total_24h{source=`"$source`"} $count")
}
}
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect disk event metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# SYSTEM STABILITY
# ============================================================================
function Get-SystemStabilityMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Unexpected shutdown events (Event ID 6008)
$unexpectedShutdowns = Get-EventCount -LogName 'System' -Id 6008 -Hours 24
[void]$sb.AppendLine('# HELP windows_eventlog_unexpected_shutdown_total_24h Unexpected shutdown events (6008) in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_unexpected_shutdown_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_unexpected_shutdown_total_24h $unexpectedShutdowns")
[void]$sb.AppendLine('')
# Bugcheck events
$bugchecks = 0
try {
$bugcheckEvents = Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Microsoft-Windows-WER-SystemErrorReporting', 'BugCheck'
StartTime = (Get-Date).AddHours(-24)
} -ErrorAction Stop
$bugchecks = @($bugcheckEvents).Count
} catch {}
[void]$sb.AppendLine('# HELP windows_eventlog_bugcheck_total_24h Bugcheck events in last 24 hours')
[void]$sb.AppendLine('# TYPE windows_eventlog_bugcheck_total_24h gauge')
[void]$sb.AppendLine("windows_eventlog_bugcheck_total_24h $bugchecks")
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect system stability metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# SUMMARY
# ============================================================================
function Get-SummaryMetrics {
$sb = [System.Text.StringBuilder]::new()
try {
# Total critical+error across all logs
$sysCritErr = Get-EventCount -LogName 'System' -Level 1, 2 -Hours 24
$appCritErr = Get-EventCount -LogName 'Application' -Level 1, 2 -Hours 24
$total = $sysCritErr + $appCritErr
[void]$sb.AppendLine('# HELP windows_eventlog_total_critical_error_all_logs Total critical and error events across all logs (24h)')
[void]$sb.AppendLine('# TYPE windows_eventlog_total_critical_error_all_logs gauge')
[void]$sb.AppendLine("windows_eventlog_total_critical_error_all_logs $total")
[void]$sb.AppendLine('')
# Newest event timestamp per log
[void]$sb.AppendLine('# HELP windows_eventlog_newest_event_timestamp Unix timestamp of newest event per log')
[void]$sb.AppendLine('# TYPE windows_eventlog_newest_event_timestamp gauge')
foreach ($logName in @('System', 'Application', 'Security')) {
try {
$newestEvent = Get-WinEvent -LogName $logName -MaxEvents 1 -ErrorAction Stop
if ($newestEvent) {
$epoch = [datetime]'1970-01-01'
$ts = [int]($newestEvent.TimeCreated.ToUniversalTime() - $epoch).TotalSeconds
[void]$sb.AppendLine("windows_eventlog_newest_event_timestamp{log=`"$logName`"} $ts")
}
} catch {}
}
[void]$sb.AppendLine('')
}
catch {
Write-Warning "Failed to collect summary metrics: $_"
}
$sb.ToString()
}
# ============================================================================
# COLLECT ALL METRICS
# ============================================================================
function Get-AllMetrics {
$scriptStart = Get-Date
$sb = [System.Text.StringBuilder]::new()
# Exporter up
[void]$sb.AppendLine('# HELP windows_eventlog_up Exporter status (1=up, 0=down)')
[void]$sb.AppendLine('# TYPE windows_eventlog_up gauge')
[void]$sb.AppendLine('windows_eventlog_up 1')
[void]$sb.AppendLine('')
# Exporter info
[void]$sb.AppendLine('# HELP windows_eventlog_exporter_info Exporter version information')
[void]$sb.AppendLine('# TYPE windows_eventlog_exporter_info gauge')
[void]$sb.AppendLine('windows_eventlog_exporter_info{version="1.0"} 1')
[void]$sb.AppendLine('')
# Collect all sections
[void]$sb.Append((Get-SystemLogMetrics))
[void]$sb.Append((Get-ApplicationLogMetrics))
[void]$sb.Append((Get-SecurityLogMetrics))
[void]$sb.Append((Get-ServiceFailureMetrics))
[void]$sb.Append((Get-DiskEventMetrics))
[void]$sb.Append((Get-SystemStabilityMetrics))
[void]$sb.Append((Get-SummaryMetrics))
# Exporter runtime
$scriptEnd = Get-Date
$duration = Format-MetricValue ($scriptEnd - $scriptStart).TotalSeconds
$timestamp = Get-UnixTimestamp
[void]$sb.AppendLine('# HELP windows_eventlog_exporter_duration_seconds Time to generate all metrics')
[void]$sb.AppendLine('# TYPE windows_eventlog_exporter_duration_seconds gauge')
[void]$sb.AppendLine("windows_eventlog_exporter_duration_seconds $duration")
[void]$sb.AppendLine('')
[void]$sb.AppendLine('# HELP windows_eventlog_exporter_last_run_timestamp Unix timestamp of last successful run')
[void]$sb.AppendLine('# TYPE windows_eventlog_exporter_last_run_timestamp gauge')
[void]$sb.AppendLine("windows_eventlog_exporter_last_run_timestamp $timestamp")
[void]$sb.AppendLine('')
$sb.ToString()
}
# ============================================================================
# HTTP SERVER MODE
# ============================================================================
function Start-HttpServer {
param([int]$ListenPort)
$prefix = "http://+:$ListenPort/"
$listener = [System.Net.HttpListener]::new()
$listener.Prefixes.Add($prefix)
try {
$listener.Start()
Write-Host "Starting Windows event log exporter on port $ListenPort..." -ForegroundColor Green
Write-Host "Metrics available at http://localhost:$ListenPort/metrics"
while ($listener.IsListening) {
$context = $listener.GetContext()
$request = $context.Request
$response = $context.Response
if ($request.Url.AbsolutePath -eq '/metrics') {
$metrics = Get-AllMetrics
$buffer = [System.Text.Encoding]::UTF8.GetBytes($metrics)
$response.ContentType = 'text/plain; version=0.0.4; charset=utf-8'
}
else {
$html = @"
<!DOCTYPE html>
<html>
<head><title>Windows Event Log Exporter v1.0</title></head>
<body>
<h1>Windows Event Log Exporter v1.0</h1>
<p><a href="/metrics">Metrics</a></p>
<h2>Sections</h2>
<ul>
<li>System log events (critical, error, warning counts)</li>
<li>Application log events (crashes, .NET runtime errors)</li>
<li>Security log events (failed logons, lockouts, privilege escalation)</li>
<li>Service failures (stopped auto-start services, crash events)</li>
<li>Disk events (disk, ntfs, volmgr errors)</li>
<li>System stability (unexpected shutdowns, bugchecks)</li>
<li>Summary (total events, newest timestamps per log)</li>
</ul>
</body>
</html>
"@
$buffer = [System.Text.Encoding]::UTF8.GetBytes($html)
$response.ContentType = 'text/html; charset=utf-8'
}
$response.ContentLength64 = $buffer.Length
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.OutputStream.Close()
}
}
catch {
Write-Error "HTTP server error: $_"
Write-Error "If access denied, run: netsh http add urlacl url=http://+:$ListenPort/ user=Everyone"
}
finally {
if ($listener.IsListening) {
$listener.Stop()
}
}
}
# ============================================================================
# MAIN EXECUTION
# ============================================================================
switch ($Mode) {
'http' {
Start-HttpServer -ListenPort $Port
}
'textfile' {
if (-not $OutputFile) {
$OutputFile = Join-Path $TextfileDir 'windows_eventlog.prom'
}
$outputDir = Split-Path $OutputFile -Parent
if (-not (Test-Path $outputDir)) {
New-Item -Path $outputDir -ItemType Directory -Force | Out-Null
}
$tempFile = Join-Path $outputDir ".windows_eventlog_metrics.$PID.tmp"
try {
$metrics = Get-AllMetrics
$metrics | Out-File -FilePath $tempFile -Encoding utf8 -NoNewline
$lineCount = ($metrics -split "`n").Count
if ($lineCount -lt 10) {
Remove-Item -Path $tempFile -Force -ErrorAction SilentlyContinue
Write-Error "Metrics file too small ($lineCount lines), keeping previous"
exit 1
}
Move-Item -Path $tempFile -Destination $OutputFile -Force
Write-Host "Metrics written to $OutputFile ($lineCount lines)" -ForegroundColor Green
}
catch {
Remove-Item -Path $tempFile -Force -ErrorAction SilentlyContinue
Write-Error "Failed to generate metrics: $_"
exit 1
}
}
default {
Get-AllMetrics | Write-Output
}
}