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

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