Monitoring NetScaler with PRTG

PRTG has become my go to solution for monitoring when I need to monitor lots of different components like switches, servers and services.  PRTG provides a platform that’s easier to use than most, but still has a ton of power and flexibility.  It can monitor pretty much anything through generic interfaces (SNMP, WMI, Powershell, etc…).  There are also many robust built-in monitors for specific systems like Exchange, NetApp and vSphere.  Missing from that list, though, is NetScaler.

Fortunately, PRTG provides a very easy to use SDK.  I was able to write a collection of PRTG scripts leveraging NITRO through the NetScaler PowerShell Module.

Overview

Script download: https://github.com/xawen/PRTG-NetScaler/releases

There are a few scripts in the collection.  Each one can be created as a PRTG sensor to query a NetScaler instance.

  • NetScaler-AppliancePerformance.ps1 – Monitor general NetScaler perfomance stats.
    • CPU utlization
    • Packet engine CPU utilization
    • Management engine CPU utilization
    • Disk usage
    • Memory usage
    • Network throughput (RX/TX)
    • SSL transactions per second
  • NetScaler-AllvServer-State.ps1 – Monitor state and health of all instances of all vServer types.
    • Health % for each vServer
    • State (Up, down, maint) for each vServer
    • Note: includes Load Balancing, AAA, VPN (Gateway) and Content Switch vServers
  • NetScaler-LBvServer-State.ps1 – Monitor state and health of all instances of Load Balancer vServers.
    • Health % for each vServer
    • State (Up, down, maint) for each vServer
  • NetScaler-CertExpiration.ps1 – Monitor days until expiration for all SSL server certificates.
    • Days until next certificate expiration date
    • Days until expiration for each server type certificate
  • NetScaler-ConfigSavedState.ps1 – Monitor for unsaved configuration changes.
    • Unsaved configuration change status
    • Time since changes were saved

Each of these pulls the data from the NetScaler and feeds it to PRTG to make nice formatted charts and meters:

Configuration

Install the NetScaler Powershell Module on the PRTG server

On the PRTG Server open a Powershell (x86) prompt as admin and run:

Install-Module -Name NetScaler -scope AllUsers

Set-ExecutionPolicy Unrestricted

Note: This MUST be done in the (x86) version of powershell.

Create a NetScaler user

Create a new user on the NetScaler for PRTG to use.  Ideally, this user should be assigned the read-only Command Policy.  The user can be an Active Directory user, but it tends to work best with a local NetScaler user.

Load the scripts into PRTG

Copy all of the .ps1 files to the Custom Sesors\EXEXML directory (default location is: C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML).

Copy all of the .ovl files to the lookups\custom directory (default location is: C:\Program Files (x86)\PRTG Network Monitor\lookups\custom)

Reload the PRTG lookup tables.  In PRTG go to Setup > Administrative tools and choose Reload lookups.  If PRTG is unable to find the scripts, or doesn’t display the names for the sensor statuses, restart the core server.

Create the sensors

First, add a NetScaler device to PRTG.  Use the NSIP (or equivalent dns address) for the hostname.  After it’s created, edit the device settings and set the Linux credentials to the readonly account you created above.

Add a new sensor to the NetScaler device with the EXE/Script type.  Set the name to the display name you want to see in PRTG.  Set EXE/Script to the script you want.  Under parameters enter:

%host %linuxuser %linuxpassword

Notes

If you add/remove vServers to the NetScaler configuration after creating the sensor, they might not show up in PRTG.  This is due to the way channels are handled in PRTG sensors.  In this case, you’ll have to delete and recreate the sensor.

If you have IP Reputation enabled, the NetScaler will auto update the reputation database ever 5 minutes (default). When this happens, the “Last Config Changed Time” time will be updated. This will cause the “Time since changes were saved” counter in NetScaler-ConfigSavedState.ps1 to be inaccurate.  Don’t bother using this script if IP Reputation is enabled.

38 Comments on Monitoring NetScaler with PRTG

  1. If you want to run the NetScaler-ConfigSavedState script on a non English system, change the Script as follows:
    Add line:
    $Culture = [System.Globalization.CultureInfo]::InvariantCulture
    Change line 20 to:
    $LastConfigChangedTime = [datetime]::ParseExact($LastConfigChangedTime, “ddd MMM d HH:mm:ss yyyy”, $Culture)

  2. Reto, that’s an awesome suggestion. I’ll take a look at the scripts and see if this should be applied anywhere else. Thanks!

  3. Kim Laurits Kristensen | July 12, 2018 at 7:03 am | Reply

    Awsome 🙂 Easy to setup and gives valuable information.

    I got one issue. When I use the script “NetScaler-LBvServer-State” – it doesn’t seem to like vServers that are non-adressable and used in a content-switch.
    In value it writes “configered lookup prtg.networklookups.rest.netscalervserverstatus is empty or not available”.

    • That’s really odd. Most of my LB vServers are non-addressable and behind content switches as well. That error means that the status script returned a code that isn’t defined in the lookup file. Would you be able to create a sensor log and post the output of the script so I can see what’s missing?

  4. Hi Guys
    I tried several times to put this sensor to work in my PRTG env. but I’m getting this error I’ve followed all the instruction but is not use, maybe I;m doing something wrong
    XML: The returned XML does not match the expected schema. (code: PE233) — JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231)

  5. Hi, we are quite new to PRTG, and we are looking to integrate our Netscalers as well into PRTG. Currently we use PRTG version 19.1 and Netscalers in version 12.0 and 11.0.

    The Powershell scripts are executed, but I always get the Response is not well formatted: PE132.

    Response not well-formed: “( CPU Usage 2 Percent Packet CPU Usage 2 Percent Management CPU Usage 1 Percent Memory Usage 18 Percent Memory MB Usage 176160768 BytesMemory Disk 0 Usage 16 Percent Disk 1 Usage 30 Percent SSL Transactions/sec 1 Custom Transactions RX Bandwidth 1038375 BytesBandwidth KiloBits TX Bandwidth 1047593 BytesBandwidth KiloBits )” (code: PE132)

    Does someone have an idea how to fix that? The scripts are from the latest github version.

    Thx, Norman

  6. -> solved it by my own. I had choosen the wrong sensor type. After choosing Custom EXE/Script ADVANCED sensor -> it works.

  7. How can I exclude a LB vServer that is allways down? Would be great if I can use a Text file where the excluded vserver are listet

    • I will look at adding a variable that can be passed from the sensor settings screen to exclude a vServer. In the mean time though, you can disable the error/warning thresholds on individual channels in the sensor channel settings screen in PRTG. This won’t hide the down vServer, but it will ignore it when PRTG determines if the sensor is up or down. That effectively ignores that vServer for alerts.

  8. Hi I have 3 VPX configured and one of them has the (Code:PE231) Error. This is NS 12.1.50.31 Version.
    Can this be the Problem? I have disabled the Cert Check:
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    and also set HTTPS:$true

    $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru -Https:$true

    • Can you upload a the sensor logs to a location where I can look at them? There are a lot of possible reasons for that error, but the logs will show exactly what’s happening.

  9. Marcel Ammann | March 4, 2019 at 3:40 am | Reply

    Hi Jason I found the issue on this NS the nsroot password was changed…

    Sorry for that.

  10. Marcel Ammann | March 4, 2019 at 3:42 am | Reply

    I filter the LB right now directly in the script but so I have to create a script for each VPX.

    $vServerResults = Get-NSLBVirtualServer -session $Session | ? { $_.Name -notlike “lb_testltprd.XXX.local_capi_internal”}

  11. Marcel Ammann | March 6, 2019 at 3:06 pm | Reply

    Param(
    [String]$Nsip,
    [String]$Username,
    [String]$Password,
    [Parameter(ValueFromRemainingArguments=$true)][string[]]$excludeVserver

    )

    $listOfLBvservers = @($excludeVserver)

    $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword)

    $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru

    ## $vServerResults = Get-NSLBVirtualServer -session $Session
    ## $vServerResults = Get-NSLBVirtualServer -session $Session | ? { $_.Name -notlike “lb_valvconsultdev.violabor.local_delivery_internal” -and $_.Name -notlike “lb_valvconsultdev.violabor.local_router_internal”}

    $vServerResults = Get-NSLBVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    Write-Host “”
    $listOfLBvservers

    foreach ($Result in $vServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State:” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”

    Write-Host “”
    Write-Host (“Health: ” + $Result.name + “”)
    Write-Host (“” + $Result.health + “”)
    Write-Host “Percent”
    Write-Host “”
    }

    Write-Host “”

    Disconnect-Netscaler

  12. Marcel Ammann | March 6, 2019 at 3:09 pm | Reply

    This is my Script that is working fine:

    PRTG Parameters:
    %host %linuxuser %linuxpassword LBvServer1 LBvServer2 LBvServer3 …

    Param(
    [String]$Nsip,
    [String]$Username,
    [String]$Password,
    [Parameter(ValueFromRemainingArguments=$true)][string[]]$excludeVserver

    )

    $listOfLBvservers = @($excludeVserver)

    $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword)

    $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru

    ## $vServerResults = Get-NSLBVirtualServer -session $Session
    ## $vServerResults = Get-NSLBVirtualServer -session $Session | ? { $_.Name -notlike “lb_valvconsultdev.violabor.local_delivery_internal” -and $_.Name -notlike “lb_valvconsultdev.violabor.local_router_internal”}

    $vServerResults = Get-NSLBVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    Write-Host “”
    $listOfLBvservers

    foreach ($Result in $vServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State:” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”

    Write-Host “”
    Write-Host (“Health: ” + $Result.name + “”)
    Write-Host (“” + $Result.health + “”)
    Write-Host “Percent”
    Write-Host “”
    }

    Write-Host “”

    Disconnect-Netscaler

  13. Marcel Ammann | March 6, 2019 at 4:04 pm | Reply

    This is for the All vServer Script

    PRTG Parameters:
    %host %linuxuser %linuxpassword LBvServer1 LBvServer2 LBvServer3 …
    You have to set at least one vServer Name like test or so

    Param(
    [String]$Nsip,
    [String]$Username,
    [String]$Password,
    [Parameter(ValueFromRemainingArguments=$true)][string[]]$excludeVserver

    )

    $listOfLBvservers = @($excludeVserver)

    $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword)

    $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru

    $LBvServerResults = Get-NSLBVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    $VPNvServerResults = Get-NSVPNVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    $AAAvServerResults = Get-NSAAAVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    $CSvServerResults = Get-NSCSVirtualServer -session $Session |
    where { $_.Name -notmatch (
    ‘(‘ + [string]::Join(‘)|(‘, $listOfLBvservers) + ‘)’) }

    Write-Host “”

    foreach ($Result in $CSvServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State CS: ” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”
    }

    foreach ($Result in $LBvServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State LB: ” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”

    Write-Host “”
    Write-Host (“Health LB: ” + $Result.name + “”)
    Write-Host (“” + $Result.health + “”)
    Write-Host “Percent”
    Write-Host “”
    }

    foreach ($Result in $VPNvServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State VPN: ” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”
    }

    foreach ($Result in $AAAvServerResults) {
    switch ($Result.curstate)
    {
    “UP” {$CurState = 1}
    “DOWN” {$CurState = 2}
    “OUT OF SERVICE” {$CurState = 3}
    }
    Write-Host “”
    Write-Host (“State AAA: ” + $Result.name + “”)
    Write-Host (“” + $CurState + “”)
    Write-Host “Custom”
    Write-Host “Status”
    Write-Host “prtg.networklookups.REST.NetscalerVserverStatus”
    Write-Host “”
    }

    Write-Host “”

    Disconnect-Netscaler

  14. Hi,

    the CertExpiration PS script doesn’t update automatically.
    It shows expired certificates that have already been renewed.

    What can I do?

  15. Hi,
    nice script, thank you.
    I have a problem setting the parameters in PRTG. It seems like the parameters are sent wrong.
    If I start the script in powershell, with the needed parameters, it works.
    Do you have any idea what the problem is?

  16. I am also getting the JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231) error.

    I modified the script to $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru -Https:$true without success. What else needs to be done?

    • I run into the same issue. Make sure you install the “NetScaler” module with the PowerShell x86 version! Otherwise it will not work. Looks like PRTG is always using the x86-version of PowerShell. Thanks for sharing the scripts. My customer is happy 🙂

  17. Hi there,
    I have the same Problem as some of the other Users but i used every Workaround and i’am still expieriencing the Error: Pe233 and Pe231

    Could someone please help me?

    Kind Regards

  18. Are there any plans for a script for tracking the current number of connected sessions for the NetScaler Gateway?

  19. Hi I am still getting this error

    XML: The returned XML does not match the expected schema. (code: PE233) — JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231)

  20. Hi, I get the same error: XML: Das zurückgelieferte XML entspricht nicht dem erwarteten Schema. (Code: PE233) — JSON: Das zurückgelieferte JSON entspricht nicht der erwarteten Struktur (No mapping for the Unicode character exists in the target multi-byte code page). (Code: PE231)
    Could someone help. It looks like that there is a problem with the https connection.
    I have put the -https:true and
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $AllProtocols = [System.Net.SecurityProtocolType]’Tls11,Tls12′
    [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
    but it not works!
    Could someone please help?

  21. I am also getting the following message:

    XML: Das zurückgelieferte XML entspricht nicht dem erwarteten Schema. (Code: PE233) — JSON: Das zurückgelieferte JSON entspricht nicht der erwarteten Struktur (Invalid JSON.). (Code: PE231)

    So is there any solution yet?

  22. The error is located within the “Connect-Netscaler.ps1” file, i guess.
    While executing the Netscaler-AllvServer-State.ps1 script in the PowerShell ISE (x86) i get the following error message:

    C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\NetScaler-AllvServer-State.ps1
    Invoke-RestMethod : Die Verbindung mit dem Remoteserver kann nicht hergestellt werden.
    In C:\Program Files (x86)\WindowsPowerShell\Modules\NetScaler\1.7.0\Public\Connect-NetScaler.ps1:115 Zeichen:21
    + $response = Invoke-RestMethod @params
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : System.Net.WebException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    I tried the options with deactiving the SSL Check and lots of other URL combinations of the POST and GET methods, but they do not seem to work.

    Does anyone have got a solution for this?

    • Has anyone found the solution for this problem?
      we have the same problem and it seems that there is a problem with ssl.

      • we are getting this message:

        Invoke-RestMethod : The underlying connection was closed: Could not establish
        trust relationship for the SSL/TLS secure channel.
        At C:\Program
        Files\WindowsPowerShell\Modules\NetScaler\Public\Connect-NetScaler.ps1:115
        char:21
        + $response = Invoke-RestMethod @params
        + ~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:Htt
        pWebRequest) [Invoke-RestMethod], WebException
        + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShe
        ll.Commands.InvokeRestMethodCommand

        • These three lines fixed the problem for us:

          [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
          $AllProtocols = [System.Net.SecurityProtocolType]’Tls11,Tls12′
          [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols

          Just add in each script before:
          $Session = Connect-Netscaler -Hostname $Nsip -Credential $Credential -PassThru -Https:$true

  23. If you get the error “XML: The returned XML does not match the expected schema. (code: PE233) — JSON: The returned JSON does not match the expected structure (invalid JSON). (code:PE231)” after installing the NetScaler module then go to the folder where the PS1 are installed, right click and unblock the file and apply. This fixed my issue.

  24. if you get the XML schema error, your Netscaler powershell module is probably only installed for the user that first installed it. PRTG executes scripts mostly as SYSTEM User so you need to drop the Netscaler Module Folder from C:\Windows\System32\WindowsPowerShell\v1.0\Modules
    in
    C:\Program Files (x86)\WindowsPowerShell\Modules
    worked for me after I did that

  25. Brian Markussen | April 15, 2021 at 5:02 am | Reply

    Hi.

    Thx for scripts.

    It took me a while to get it to work.
    In parameters I had to write.
    -Nsip “%Host” -Username “%linuxuser” -Password “%linuxpassword”

    I have a problem with LBvserverstate:
    “configered lookup prtg.networklookups.rest.netscalervserverstatus is empty or not available”.

    Could you make a script showing services?

    /nitro/V1/stat/Service

    Brian

1 Trackbacks & Pingbacks

  1. PRTG – Citrix ADC überwachen – PIT – Power of IT

Leave a comment

Your email address will not be published.


*