I instead opted for a custom sensor, using a Powershell script:
<#
.Synopsis
Custom PRTG script for monitoring Apache mod_proxy balancer members.
.Description
Scrapes the page served by Apache's mod_status for metrics regarding BalancerMembers and
returns data in a JSON format for consumption by PRTG.
.Example
.\ApacheLoadBalancerNodeSensor.ps1 -Url https://my.load.balancer/balancer-manager
-Route route1
.Parameter Url
(Mandatory) The Url of the page served by mod_status.
.Parameter Route
(Mandatory) The specific balancer member to return info for.
#>
param(
[Parameter(Mandatory=$true)]
[string] $Route,
[Parameter(Mandatory=$true)]
[string] $Url
)
# Need to import this module to have access to ConvertTo-Json
Import-Module Microsoft.PowerShell.Utility
# Since we need to parse the result of a WebRequest (which uses IE), and this script may run
# in a service account, the FirstRunCustomize setting needs to be disabled.
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Internet Explorer\Main" `
-Name "DisableFirstRunCustomize" `
-Value 2
# Get the page
$WebRequest = Invoke-WebRequest $Url
# Get the second table on that page (the one containing information about the balancer
# members)
$tables = @($WebRequest.ParsedHtml.getElementsByTagName("TABLE"))
$table = $tables[1]
$titles = @()
$rows = @($table.Rows)
# Iterate through the rows
foreach($row in $rows)
{
$cells = @($row.Cells)
# Get the headers
if($cells[0].tagName -eq "TH")
{
$titles = @($cells | % { ("" + $_.InnerText).Trim() })
continue
}
# Get the contents
$resultObject = [Ordered] @{}
for($counter = 0; $counter -lt $cells.Count; $counter++)
{
$title = $titles[$counter]
if(-not $title) { continue }
$resultObject[$title] = ("" + $cells[$counter].InnerText).Trim()
}
# If the current row contains the Route we asked for, build a JSON object with the
# results.
if($resultObject.Route -eq $Route)
{
# If the Status is Init Ok, return 1. Otherwise return 0.
# NOTE: This can be interpreted through a custom lookup in PRTG to display a
# textual result
$statusAsInt = 0
if($resultObject.Status -eq 'Init Ok')
{
$statusAsInt = 1
}
# Break the From and To values down to its base byte values
# The PRTG channel can then be configured to display as Kbytes or Mbytes
[int]$toAsInt = 0
if($resultObject.To -like "*K")
{
$toAsInt = [int]([decimal]($resultObject.To.replace('K', '')) * 1024)
}
if($resultObject.To -like "*M")
{
$toAsInt = [int]([decimal]($resultObject.To.replace('M', '')) * 1024 * 1024)
}
[int]$fromAsInt = 0
if($resultObject.From -like "*K")
{
$fromAsInt = [int]([decimal]($resultObject.From.replace('K', '')) * 1024)
}
if($resultObject.From -like "*M")
{
$fromAsInt = [int]([decimal]($resultObject.From.replace('M', '')) * 1024 * 1024)
}
$jsonBase = @{}
$array = @{}
# Build the JSON object. This section can benefit from a cleaner design.
$jsonResult = @{
result = @(
@{
channel = 'Factor'
value = $resultObject.Factor
float = 1
unit = 'Percent'
},
@{
channel = 'Status'
value = $statusAsInt
limitminerror = '0'
limiterrormessage = 'Heartbeat failed.'
limitmode = 1
},
@{
channel = 'Elected'
value = $resultObject.Elected
},
@{
channel = 'Busy'
value = $resultObject.Busy
},
@{
channel = 'Load'
value = $resultObject.Load
},
@{
channel = 'From'
value = $fromAsInt
unit = 'BytesBandwidth'
volumesize = 'Kilo'
},
@{
channel = 'To'
value = $toAsInt
unit = 'BytesBandwidth'
volumesize = 'Kilo'
}
)
}
$jsonBase.Add("prtg",$jsonResult)
# Return the JSON object that PRTG expects
Write-Output $jsonBase | ConvertTo-Json -Depth 10
}
}
Add comment