In the world of enterprise IT, there’s always a fancy solution for every problem—usually with an equally fancy price tag. But let’s face it: not everyone has the budget to splurge on shiny tools with all the bells and whistles. Sometimes, you need to get scrappy, roll up your sleeves, and make magic happen with what you’ve got. Enter the “Poor Man’s VMware Aria Operations Integration” for monitoring HAProxy.
This is the tale of a humble PowerShell script that doesn’t have a six-figure sticker price or a logo worthy of a TED Talk but gets the job done. Let’s dive in.
Monitoring HAProxy Without Spending a Fortune!!!
HAProxy is like the unsung hero of your IT stack—a rock-solid load balancer and proxy server that keeps your web services humming along. But monitoring it? That’s another story. Sure, there are premium tools out there that promise to make HAProxy’s status page look like a Monet painting in your analytics dashboard, but what if you’re working with a ramen-budget IT team?
Enter this PowerShell script: a no-frills, homegrown solution that scrapes HAProxy’s status page and uploads the data to VMware Aria Operations. Is it flashy? No. Does it work? Absolutely.
Step 1: Scrape the HAProxy Status Page
First, the script sidles up to HAProxy’s status page like it’s trying to borrow a cup of sugar and scrapes all the juicy metrics. Think response times, connection rates, and session counts—everything you’d want to know to keep tabs on your load balancer.
It’s not glamorous. There are no SDKs or integrations here—just raw scraping power, a little XML wizardry, and some elbow grease.
Step 2: Format the Data for VMware Aria Operations
Once the script has the goods, it packages them up into XML. Why XML? Because that’s what VMware Aria Operations understands. It’s like writing a love letter in a language only your monitoring tool can read.
The script painstakingly maps each metric to the right stat key, adding timestamps, values, and units. Here’s a snippet of the love letter:
Step 3: Upload to VMware Aria Operations
Finally, the script sends this carefully crafted data bundle to VMware Aria Operations. It uses the API, but not in a “developer conference keynote” kind of way—more like a “here’s my token, just take the data” kind of way. The script manages authentication, creates an object for HAProxy, and uploads metrics faster than you can say “enterprise-grade monitoring.”
#Powershell collector script for HAProxy API to vRops Suite-api
<#
.SYNOPSIS
Collecting metric / state data HAProxy and pushes it into vRops for monitoring as a new ResourceKind.
Run the command below to store user and pass in secure credential XML for each environment
$cred = Get-Credential
$cred | Export-Clixml -Path "C:\Scripts\vROPS\config\creds\vropsApi.xml"
Usage .\HAProxy2vRops.ps1 -vRopsAddress '192.168.16.100' -vRopsCreds 'vropsApi' -HAproxyAddress '192.168.50.100' -HAProxyPort '2041' -HAProxyfilter ''
#>
param
(
[String]$vRopsAddress,
[String]$vRopsCreds,
[String]$HAproxyAddress,
[String]$HAProxyPort,
[String]$HAProxyfilter
)
##Vars
$ScriptPath = (Get-Item -Path ".\" -Verbose).FullName
#Get Date / Time for vRops
[DateTime]$NowDate = (Get-date)
[int64]$NowDateEpoc = (([DateTimeOffset](Get-Date)).ToUniversalTime().ToUnixTimeMilliseconds())
#Cred
####### Get vCenter Stored Credentials #######
if($vRopsCreds -gt ""){
$vRopsCred = Import-Clixml -Path "$ScriptPath\config\creds\$vRopsCreds.xml"
}
else
{
Write-host "Credentials missing, terminating script" -ForegroundColor Magenta
Exit
}
#JobControl used to limit how hard the machine's CPU and memory is used.
$maxJobCount = 12
$sleepTimer = 15
$jobQueue = New-Object System.Collections.ArrayList
Function New-vRopsToken {
[CmdletBinding()]param(
[PSCredential]$credentialFile,
[string]$vROPSServer
)
if ($vROPSServer -eq $null -or $vROPSServer -eq '') {
$vROPSServer = ""
}
$vROPSUser = $credentialFile.UserName
$vROPSPassword = $credentialFile.GetNetworkCredential().Password
if ("TrustAllCertsPolicy" -as [type]) {} else {
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
}
$BaseURL = "https://" + $vROPsServer + "/suite-api/api/"
$BaseAuthURL = "https://" + $vROPsServer + "/suite-api/api/auth/token/acquire"
$Type = "application/json"
$AuthJSON =
"{
""username"": ""$vROPSUser"",
""password"": ""$vROPsPassword""
}"
Try { $vROPSSessionResponse = Invoke-RestMethod -Method POST -Uri $BaseAuthURL -Body $AuthJSON -ContentType $Type }
Catch {
$_.Exception.ToString()
$error[0] | Format-List -Force
}
$vROPSSessionHeader = @{"Authorization"="vRealizeOpsToken "+$vROPSSessionResponse.'auth-token'.token
"Accept"="application/xml"}
$vROPSSessionHeader.add("X-vRealizeOps-API-use-unsupported","true")
return $vROPSSessionHeader
}
#Take all certs.
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#Generate vRops Token
$vRopsAdminToken = New-vRopsToken $vRopsCred $vRopsAddress
#Connect to HA Proxy and Dump Deetz
$HAproxyData = Invoke-RestMethod -Uri "http://$($HAproxyAddress):$($HAProxyPort)/stats/?scope=$($HAProxyfilter);csv"
$HAproxyData = $HAproxyData.Replace(',,',',0,')
$HAproxyData = $HAproxyData.Replace(',,',',0,')
$HAproxyData = $HAproxyData.Replace('#','') | ConvertFrom-Csv -Delimiter ','
$HAproxyDataGrouped = $HAproxyData | Group-Object -Property pxname
#Generate Lookup table
[xml]$ResourceList = Invoke-RestMethod -Method GET -Uri "https://$vRopsAddress/suite-api/api/resources?resourceKind=HAProxyPool&pageSize=5000" -ContentType "application/xml" -Headers $vRopsAdminToken
$ObjectLookupTable = @()
$resourceIdLookupTable = @{}
ForEach ($Resource in $ResourceList.resources.resource){
$ObjectLookupTable += New-Object PSObject -Property @{
Id = $Resource.identifier
Name = $Resource.resourceKey.Name
}
}
$ObjectLookupTable | Sort-Object -Property Name | ForEach-Object -Begin {
$resourceIdLookupTable = @{}
} -Process {
$resourceIdLookupTable.Add($_.Name,$_.Id)
}
$scriptBlock = {
param
(
$vRopsAddress,
$vRopsAdminToken,
$HAproxyValueGroup,
$HAproxyResourceId,
$NowDateEpoc
)
#Function to create new vRops HAProxyNode
Function CreatevRopsObject([String]$vRopsServer, $CreateRopsObject, $vRopsToken){
[xml]$CreateXML = @('<ops:resource xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ops:description>HA Proxy Pool</ops:description>
<ops:resourceKey>
<ops:name>{0}</ops:name>
<ops:adapterKindKey>HAPROXY</ops:adapterKindKey>
<ops:resourceKindKey>HAProxyPool</ops:resourceKindKey>
<ops:resourceIdentifiers>
<ops:resourceIdentifier>
<ops:identifierType name="entityName" dataType="STRING" isPartOfUniqueness="true" />
<ops:value>{0}</ops:value>
</ops:resourceIdentifier>
</ops:resourceIdentifiers>
</ops:resourceKey>
<ops:resourceStatusStates />
<ops:dtEnabled>true</ops:dtEnabled>
</ops:resource>' -f $CreateRopsObject
)
#Create URL string for voke-RestMethod
$Createurl = 'https://'+$vRopsServer+'/suite-api/api/resources/adapterkinds/OPENAPI'
#Send Attribute data to vRops.
$ContentType = "application/xml;charset=utf-8"
$header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$header.Add("Accept", 'application/xml')
try {
$result = Invoke-RestMethod -Method POST -uri $Createurl -Body $CreateXML -ContentType $ContentType -Headers $vRopsToken
}
catch {
$result = $_.Exception.Response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($result)
$reader.BaseStream.Position = 0
$reader.DiscardBufferedData()
$responseBody = $reader.ReadToEnd();
}
}
#Take all certs.
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
#Stuff for Invoke-RestMethod
$ContentType = "application/xml"
$header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$header.Add("Accept", 'application/xml')
$header.Add("User-Agent", 'HAProxyHealthExtractor/1.0')
Function GetObject([String]$vRopsObjName, [String]$resourceKindKey, [String]$vRopsServer, $vRopsToken){
$vRopsObjName = $vRopsObjName -replace ' ','%20'
[xml]$Checker = Invoke-RestMethod -Method GET -Uri "https://$vRopsServer/suite-api/api/resources?resourceKind=$resourceKindKey&name=$vRopsObjName" -ContentType "application/xml" -Headers $vRopsToken
# Check if we get more than 1 result and apply some logic
If ([Int]$Checker.resources.pageInfo.totalCount -gt '1') {
$DataReceivingCount = $Checker.resources.resource.resourceStatusStates.resourceStatusState.resourceStatus -eq 'DATA_RECEIVING'
If ($DataReceivingCount.count -gt 1){
If ($Checker.resources.resource.ResourceKey.name -eq $vRopsObjName){
ForEach ($Result in $Checker.resources.resource){
IF ($Result.resourceStatusStates.resourceStatusState.resourceStatus -eq 'DATA_RECEIVING'){
$CheckerOutput = New-Object PsObject -Property @{Name=$vRopsObjName; resourceId=$Result.identifier; resourceKindKey=$Result.resourceKey.resourceKindKey}
Return $CheckerOutput
}
}
}
}
Else
{
ForEach ($Result in $Checker.resources.resource){
IF ($Result.resourceStatusStates.resourceStatusState.resourceStatus -eq 'DATA_RECEIVING'){
$CheckerOutput = New-Object PsObject -Property @{Name=$vRopsObjName; resourceId=$Result.identifier; resourceKindKey=$Result.resourceKey.resourceKindKeY}
Return $CheckerOutput
}
}
}
}
else
{
IF ($Checker.resources.resource.ResourceKey.name -eq $vRopsObjName ) {
$CheckerOutput = New-Object PsObject -Property @{Name=$vRopsObjName; resourceId=$Checker.resources.resource.identifier; resourceKindKey=$Checker.resources.resource.resourceKey.resourceKindKey}
}
Return $CheckerOutput
}
}
Write-Host "Pushing data for $($HAproxyValueGroup.name)"
If (!$HAproxyResourceId){
Write-Host $Name 'Object does not exist in vRops, creating it now'
CreatevRopsObject $vRopsAddress $($HAproxyValueGroup.name) $vRopsAdminToken
$resourceLookup = GetObject $($HAproxyValueGroup.name) 'HAProxyPool' $vRopsAddress $vRopsAdminToken
$resourceLookup = $resourceLookup.Resourceid
Write-host 'Found it' $resourceLookup
} else {$resourceLookup = $HAproxyResourceId}
$HAproxyValueStatsXML = @('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ops:stat-contents xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">')
$HAproxyValuePropsXML = @('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ops:property-contents xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ops="http://webservice.vmware.com/vRealizeOpsMgr/1.0/">')
ForEach ($HAproxyValue in $HAproxyValueGroup.Group){
$HAproxyValueStatsXML += @('<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|qcur">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.qcur+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|qmax">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.qmax+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|scur">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.scur+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|smax">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.smax+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|slim">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.slim+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|stot">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.stot+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|bin">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.bin+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|bout">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.bout+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|dreq">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.dreq+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|dresp">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.dresp+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|ereq">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.ereq+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|econ">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.econ+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|eresp">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.eresp+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|wretr">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.wretr+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|wredis">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.wredis+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|act">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.act+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|bck">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.bck+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|chkfail">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.chkfail+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|chkdown">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.chkdown+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|lastchg">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.lastchg+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|downtime">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.downtime+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|qlimit">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.qlimit+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|pid">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.pid+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|iid">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.iid+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|sid">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.sid+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|throttle">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.throttle+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|lbtot">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.lbtot+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|tracked">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.tracked+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|type">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.type+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|rate">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.rate+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|rate_lim">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.rate_lim+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|rate_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.rate_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_code">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.check_code+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_1xx">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_1xx+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_2xx">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_2xx+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_3xx">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_3xx+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_4xx">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_4xx+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_5xx">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_5xx+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hrsp_other">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hrsp_other+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|hanafail">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.hanafail+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|req_rate">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.req_rate+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|req_rate_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.req_rate_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|req_tot">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.req_tot+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|cli_abrt">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.cli_abrt+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|srv_abrt">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.srv_abrt+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|comp_in">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.comp_in+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|comp_out">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.comp_out+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|comp_byp">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.comp_byp+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|comp_rsp">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.comp_rsp+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|lastsess">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.lastsess+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|last_agt">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.last_agt+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|qtime">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.qtime+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|ctime">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.ctime+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|rtime">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.rtime+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|ttime">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.ttime+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_status">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_status+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_code">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_code+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_duration">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_duration+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_rise">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.check_rise+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_fall">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.check_fall+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_health">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.check_health+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_rise">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_rise+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_fall">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_fall+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_health">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_health+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|agent_fall">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.agent_fall+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|conn_rate">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.conn_rate+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|conn_rate_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.conn_rate_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|conn_tot">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.conn_tot+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|intercepted">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.intercepted+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|dcon">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.dcon+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|dses">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.dses+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|wrew">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.wrew+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|connect">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.connect+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|reuse">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.reuse+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|cache_lookups">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.cache_lookups+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|cache_hits">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.cache_hits+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|srv_icur">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.srv_icur+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|src_ilim">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.src_ilim+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|qtime_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.qtime_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|ctime_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.ctime_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|rtime_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.rtime_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>
<ops:stat-content statKey="MEMBER|'+$HAproxyValue.svname+'|ttime_max">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:data>'+$HAproxyValue.ttime_max+'</ops:data>
<ops:unit>num</ops:unit>
</ops:stat-content>')
$HAproxyValuePropsXML += @('<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_status">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.check_status+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|check_desc">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.check_desc+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|addr">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.addr+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|cookie">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.cookie+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|mode">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.mode+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|last_chk">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.last_chk+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|algo">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.algo+']]></ops:values>
</ops:property-content>
<ops:property-content statKey="MEMBER|'+$HAproxyValue.svname+'|status">
<ops:timestamps>'+$NowDateEpoc+'</ops:timestamps>
<ops:values><![CDATA['+$HAproxyValue.status+']]></ops:values>
</ops:property-content>')
Remove-Variable HAproxyValue -ErrorAction SilentlyContinue
}
$HAproxyValueStatsXML += @('</ops:stat-contents>')
$HAproxyValuePropsXML += @('</ops:property-contents>')
[xml]$HAproxyValueStatsXML = $HAproxyValueStatsXML
[xml]$HAproxyValuePropsXML = $HAproxyValuePropsXML
$vRopsHAproxyeStatsURL = 'https://' + $vRopsAddress + '/suite-api/api/resources/'+$resourceLookup+'/stats'
$vRopsHAproxyePropsURL = 'https://' + $vRopsAddress + '/suite-api/api/resources/'+$resourceLookup+'/properties'
Invoke-RestMethod -Method POST -uri $vRopsHAproxyeStatsURL -Body $HAproxyValueStatsXML -ContentType "application/xml;charset=utf-8" -Headers $vRopsAdminToken
Invoke-RestMethod -Method POST -uri $vRopsHAproxyePropsURL -Body $HAproxyValuePropsXML -ContentType "application/xml;charset=utf-8" -Headers $vRopsAdminToken
Remove-Variable HAproxyValueStatsXML -ErrorAction SilentlyContinue
Remove-Variable HAproxyValuePropsXML -ErrorAction SilentlyContinue
Remove-Variable HAproxyValueGroup -ErrorAction SilentlyContinue
}
If ($HAproxyDataGrouped){
ForEach ($HAproxyValueGroup in $HAproxyDataGrouped){
# Wait until job queue has a slot available.
while ($jobQueue.count -ge $maxJobCount) {
#echo "Waiting for jobs to finish before adding more."
foreach ($jobObject in $jobQueue.toArray()) {
if ($jobObject.job.state -eq 'Completed') {
#echo "jobQueue count is $($jobQueue.count): Removing job"
$jobQueue.remove($jobObject)
}
}
Start-sleep -milliseconds $sleepTimer
}
echo "jobQueue count is $($jobQueue.count): Adding new job: $($HAproxyValueGroup.Name)"
$job = Start-Job -name $HAproxyValueGroup.Name -ScriptBlock $scriptBlock -ArgumentList $vRopsAddress, $vRopsAdminToken, $HAproxyValueGroup, $($resourceIdLookupTable.Item($HAproxyValueGroup.Name)), $NowDateEpoc
$jobObject = "" | select Element, job
$jobObject.Element = $Element
$jobObject.job = $job
$jobQueue.add($jobObject) | Out-Null
}
Get-Job | Wait-Job | Out-Null
Remove-Variable HAproxyDataGrouped -ErrorAction SilentlyContinue
}
Is this the perfect solution? No. It’s not going to win any design awards or make your CIO gush during the next board meeting. But it’s practical, functional, and—most importantly—it works.
It’s the duct tape of HAProxy monitoring solutions. Not fancy, but dependable.
Hope it was helpful
vMan
Recent Comments