Hi

I have an Apache server running mod_proxy to proxy requests to 3 nodes behind it. How can I monitor the status of each of those nodes?

mod_status doesn't provide this information.


Article Comments

Attention: This article is a record of a conversation with the Paessler support team. The information in this conversation is not updated to preserve the historical record. As a result, some of the information or recommendations in this conversation might be out of date.

Hello,

Thank you for your message.

To monitor the status of the servers behind the reverse proxy, you can :

  • Install a remote probe or Python probe in the same network, monitor the servers and send the data to PRTG.

Here is the GitLab page of the Python probe including its documentation: https://gitlab.com/paessler-labs/prtg-pyprobe

To install a remote probe, I invite you to have a look at our How-to page available here: https://www.paessler.com/support/how-to/remote-probe-installation

  • In case you can't install a probe there, you can also create a script on the reverse proxy which will check if the servers are available and then push the data to PRTG by using the HTTP Push Data / HTTP Push Data Advanced.

For this option, you will find the request and format of the data in the manual of the sensor as well as in this manual: https://www.paessler.com/manuals/prtg/custom_sensors

If you have questions, let us know.

Regards.


Sep, 2021 - Permalink

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 
    }  
}

Sep, 2021 - Permalink

Thank you for sharing the script!


Sep, 2021 - Permalink