PRTG – Citrix ADM für zentrales ADC Performance Monitoring nutzen

Im einem der letzten Beiträge habe ich ein Powershell Modul vorgestellt, mit welchem man Daten vom Citrix ADM abgreifen kann.

Basierend auf diesem Modul habe ich bei uns einen PRTG Custom Sensor erstellt, welcher die wichtigsten Performance Daten aus dem ADM ausliest:

Dazu müssen erst einmal die Parameter von PRTG sowie das Modul selbst eingelesen und eine Verbindung zur Appliance hergestellt werden:

# Get parameter from PRTG
param (
[string]$server,
[string]$domain,
[string]$username,
[string]$password
)

# Import ADM PS module
$CustomSensors="C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\"
Import-Module $CustomSensors\PRTGCustomCitrixADM.psm1

# Create the ADM session
$ADMHost = "https://"+$server
$ADMSession = Connect-ADM -ADMHost $ADMHost -CredUser $username -CredPW $password

Damit dies funktioniert, muss der entsprechende Benutzer von PRTG auf dem ADM Leserechte haben. Weiter gehe ich nicht auf jede Zeile ein, dies kann im Script selbst nachgelesen werden. Hier beschreibe ich vor allem die wichtigsten Punkte, wie das auslesen der Performance-Daten sowie das Sortieren nach Appliance:

# Get the Instances from the ADM
$ADCInstance = Invoke-ADMNitro -ADMSession $ADMSession -OperationMethod GET -ResourceType ns
# Create the variable only with the NS parameters
$ADCInstance2 = $ADCInstance | Select-Object ns
# For troubleshooting
#$ADCInstance2.ns | FT hostname, ns_mgmt_cpu_usage, ns_cpu_usage, vm_memory_usage, diskperusage, disk0_used, disk1_used, ns_tx, model_id -AutoSize
$ADCInstances = $ADCInstance2.ns
# Sort output based on hostname
$ADCInstances2 = $ADCInstances | Sort-Object hostname

Da das Web GUI von PRTG nicht nach Channel ID sondern nach Alphabet sortiert, habe ich für die Channel-Namen jeweils noch einen eigenen Index erstellt. A0 ist reserviert für den „Overall Health“ Status (weiter unten beschrieben). Anschliessend kriegt jede Appliance einen eigenen Buchstaben und innerhalb einer Appliance wird hochgezählt:

$ChannelLetterIndex = 65    # Start index with 65 for ASCII 'A'
ForEach ($Instance in $ADCInstances2){

    #region returnvariables
    $ChannelLetterIndex = $ChannelLetterIndex + 1      # Increase letter index by one for each appliance instance
    $RetChannelLetter = [char]($ChannelLetterIndex)

Im PRTG werden Prozentwerte nur in ganzen Zahlen angezeigt, daher werden die entsprechenden Werte gerundet:

    $RetMgmtCPU = [math]::Round($Instance.ns_mgmt_cpu_usage)
    $RetCPU = [math]::Round($Instance.ns_cpu_usage)
    $RetRAM = [math]::Round($Instance.vm_memory_usage)

Die prozentuale Bandbreiten-Auslastung wird anhand der Werte sowie der Model ID berechnet. Da diese im Test oft exponentielle Werte lieferte und diese nicht gerundet werden können, musste dies via Umwandlung in einen String gemacht werden:

    #region bwcalculation
    # Calculate the percentage of the bandwidth usage
    # based on the license and the current bandwith
    # A conversation to string is needed because of the
    # exponential results which needed to be trimmed
    $BWPercentCalc = $null
    $BWPercent = $null

    $BWPercentCalc = $Instance.ns_tx*100/$Instance.model_id
    $BWPercentString = [String]$BWPercentCalc
    If ($BWPercentString.Length -ge 5){
        $SubLength = 5
    }
    Else {
        $SubLength = $BWPercentString.Length
    }
    $BWPercentStringShort = $BWPercentString.Substring(0,$SubLength)
    $BWPercentShort = [Decimal]$BWPercentStringShort
    $RetBWPercent = [math]::Round($BWPercentShort)
    #endregion bwcalculation

Im restlichen Skript wurden die einzelnen Daten mit einem vorgegebenen Wert gegen geprüft und die entsprechenden PRTG Ausgaben definiert.

Zu guter Letzt wird aus allen vorher berechneten Werten ein Channel mit einer Gesamtbewertung der Performance erstellt, welche mit dem hardcoded Index A0 auch ganz oben gelistet wird:

#region returnstring
# Determine return string depends on the several states
If ($returnState.State -contains 2) {
    $RetString = $AlertString
    $RetHealth = 0
}
ElseIf ($returnState.State -contains 1) {
    $RetString = $WarningString
    $RetHealth = 50    
}
Else {
    $RetString = "OK"
    $RetHealth = 100    
}
#endregion

#region health
# Channel for overall health
$retXml += "  <result>`n"
$retXml += "    <channel>A0 Overall health</channel>`n"
$retXml += "    <value>$RetHealth</value>`n"
$retXml += "    <unit>Count</unit>`n"
$retXml += "    <limitMode>1</limitMode>`n"
$retXml += "    <limitMinError>49</limitMinError>`n"
$retXml += "    <limitErrorMsg>$AlertString</limitErrorMsg>`n"
$retXml += "    <limitMinWarning>99</limitMinWarning>`n"
$retXml += "    <limitWarningMsg>$WarningString</limitWarningMsg>`n"
$retXml += "  </result>`n"
#endregion health

Das Script muss nun in den Custom Sensors Ordner von PRTG gelegt werden und der Sensor kann entsprechend eingerichtet werden:

Parameter gem. Script-Beschreibung, Securitykontext vom Gerät

Das Resultat sieht dann wie folgt aus:

Viel Spass beim Nachbauen :-)