What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general.

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
More than 500,000 users rely on Paessler PRTG every day. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags


View all Tags

Nginx status monitor sensor

Votes:

0

Is there a way we can create a custom monitor from nginx_status? The output can be like:

Active connections: 1 server accepts handled requests 19 19 28 Reading: 0 Writing: 1 Waiting: 0

nginx prtg webserver

Created on Apr 10, 2014 9:36:03 PM



Best Answer

Accepted Answer

Votes:

0

This article applies to PRTG Network Monitor 14 or later

Using PRTG to Monitor Nginx Status

You can monitor the status page of nginx and see the corresponding values by creating an EXE/Script Advanced sensor which uses the PowerShell script given below.

Note: The script might not properly work with newer versions of Nginx and probably requires some modifications. As an alternative, you can try the REST Custom sensor with an appropriate template.

Set up Monitoring of Nginx Status

  • Open a text editor.
  • Copy the following code and paste it into the editor:
Param([string]$url)
$warningpreference = "silentlyContinue"


    $global:resultText = "OK"

# create a table to store the information 
    $table = New-Object system.Data.DataTable "result"
    $col1 = New-Object system.Data.DataColumn channel,string
    $col2 = New-Object system.Data.DataColumn value,string
    $col3 = New-Object system.Data.DataColumn unit,string
    $col4 = New-Object system.Data.DataColumn customUnit,string
    $col5 = New-Object system.Data.DataColumn warning,string
    $col6 = New-Object system.Data.DataColumn float,string
    $col7 = New-Object system.Data.DataColumn mode, string
    
    $table.columns.add($($col1))
    $table.columns.add($($col2))
    $table.columns.add($($col3))
    $table.columns.add($($col4))
    $table.columns.add($($col5))
    $table.columns.add($($col6))
    $table.columns.add($($col7))
    
# To get this script running with PRTGNetworkMonitor you need to enable RemoteSigned-scripting for 32bit-processes. 
# This can be done with running 'c:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy RemoteSigned"' on a system with default paths

# this function produces a well-formated xml-output out of a given table
function New-Xml
{
    param($RootTag="ROOT",$ItemTag="ITEM", $ChildItems="*", $TextTag="OK", $Attributes=$Null)

    Begin {
        $xml = "<$RootTag>`n"
    }

    Process {
        $xml += "  <$ItemTag>`n"
        
    foreach ($child in $_ | Get-Member -Type *Property $childItems)
    {
        $Name = $child.Name
        if (-not "$($_.$name)" -eq "")  {
            $xml += "    <$Name>$($_.$Name)</$Name>`n"
        }
    }
        $xml += "  </$ItemTag>`n"
    }

    End {
        $xml += "  <text>$TextTag</text>`n" 
        $xml += "</$RootTag>`n"
        $xml
    }
} 


    $web = New-Object Net.WebClient
    Try {
        $response = $web.DownloadString($url)
    } 
    Catch {
        Write-Warning "$($error[0])"
    }
    # Stubbing input for development:
    #$response="Active connections: 291`r`n
#server accepts handled requests`r`n
#  16630948 16630949 31070465`r`n
#Reading: 6 Writing: 179 Waiting: 106"

    $responseArray = $response.split(“`r`n”)

    ForEach ($responseLine in $responseArray){
      if ($responseLine.startswith('Active')) {
        $keyval = $responseLine.split(":") 
        $row = $table.NewRow();
        $row.channel = "$($keyval[0])";
        $row.value = $keyval[1]
        $row.unit  = "Count"
        $row.mode  = "absolute"
        $table.Rows.Add($row)
      }
      if ($responseLine.startswith('Reading:')) {
        ($responseLine -match "Reading: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
        ($responseLine -match "Writing: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
        ($responseLine -match "Waiting: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
      }
      if (!$responseLine.length -eq 0 -and ! $responseLine.startswith('Active connections:') -and ! $responseLine.startswith('server') -and ! $responseLine.startswith('Reading:')) {
        $values = $responseLine.trim().split(" ")
        $row = $table.NewRow();
          $row.channel = "Accepts";
          $row.value = "$($values[0])"
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
        $row = $table.NewRow();
          $row.channel = "Handled";
          $row.value = $values[1]
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
          $row = $table.NewRow();
        $row.channel = "Requests";
          $row.value = $values[2]
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
      }
    }

# forward the generated table to xml-generator and store the result
    $retval = $table | New-Xml -RootTag prtg -ItemTag result -ChildItems Channel,Value,Unit,CustomUnit,Warning,Float,Mode -TextTag $resultText

# return the result
    write-host $retval
  • Save the file and name it, e.g., nginx_status.ps1
  • Place the script in the \Custom Sensors\EXEXML sub-directory of your PRTG installation to ensure that the EXE/Script Advanced sensor can pick up the same.
  • Create a new EXE/Script Advanced Sensor .
    • Choose nginx_status.ps1 as executable.
    • As Parameter, pass the URL to the nginx status page to the sensor.

The sensor will now read the status page and you should see the values reflected in the sensor's channels.

Best regards

Created on Apr 14, 2014 11:21:27 AM by  Konstantin Wolff [Paessler Support]

Last change on Dec 21, 2017 11:11:40 AM by  Gerald Schoch [Paessler Support]



15 Replies

Votes:

0

Is there a way we can create a custom monitor for nginx from nginx_status? The output of http://ip/nginx_status is:

Active connections: 1 server accepts handled requests 19 19 28 Reading: 0 Writing: 1 Waiting: 0

Is there a way to monitor above values from the page?

Created on Apr 11, 2014 7:27:37 AM



Accepted Answer

Votes:

0

This article applies to PRTG Network Monitor 14 or later

Using PRTG to Monitor Nginx Status

You can monitor the status page of nginx and see the corresponding values by creating an EXE/Script Advanced sensor which uses the PowerShell script given below.

Note: The script might not properly work with newer versions of Nginx and probably requires some modifications. As an alternative, you can try the REST Custom sensor with an appropriate template.

Set up Monitoring of Nginx Status

  • Open a text editor.
  • Copy the following code and paste it into the editor:
Param([string]$url)
$warningpreference = "silentlyContinue"


    $global:resultText = "OK"

# create a table to store the information 
    $table = New-Object system.Data.DataTable "result"
    $col1 = New-Object system.Data.DataColumn channel,string
    $col2 = New-Object system.Data.DataColumn value,string
    $col3 = New-Object system.Data.DataColumn unit,string
    $col4 = New-Object system.Data.DataColumn customUnit,string
    $col5 = New-Object system.Data.DataColumn warning,string
    $col6 = New-Object system.Data.DataColumn float,string
    $col7 = New-Object system.Data.DataColumn mode, string
    
    $table.columns.add($($col1))
    $table.columns.add($($col2))
    $table.columns.add($($col3))
    $table.columns.add($($col4))
    $table.columns.add($($col5))
    $table.columns.add($($col6))
    $table.columns.add($($col7))
    
# To get this script running with PRTGNetworkMonitor you need to enable RemoteSigned-scripting for 32bit-processes. 
# This can be done with running 'c:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe "Set-ExecutionPolicy RemoteSigned"' on a system with default paths

# this function produces a well-formated xml-output out of a given table
function New-Xml
{
    param($RootTag="ROOT",$ItemTag="ITEM", $ChildItems="*", $TextTag="OK", $Attributes=$Null)

    Begin {
        $xml = "<$RootTag>`n"
    }

    Process {
        $xml += "  <$ItemTag>`n"
        
    foreach ($child in $_ | Get-Member -Type *Property $childItems)
    {
        $Name = $child.Name
        if (-not "$($_.$name)" -eq "")  {
            $xml += "    <$Name>$($_.$Name)</$Name>`n"
        }
    }
        $xml += "  </$ItemTag>`n"
    }

    End {
        $xml += "  <text>$TextTag</text>`n" 
        $xml += "</$RootTag>`n"
        $xml
    }
} 


    $web = New-Object Net.WebClient
    Try {
        $response = $web.DownloadString($url)
    } 
    Catch {
        Write-Warning "$($error[0])"
    }
    # Stubbing input for development:
    #$response="Active connections: 291`r`n
#server accepts handled requests`r`n
#  16630948 16630949 31070465`r`n
#Reading: 6 Writing: 179 Waiting: 106"

    $responseArray = $response.split(“`r`n”)

    ForEach ($responseLine in $responseArray){
      if ($responseLine.startswith('Active')) {
        $keyval = $responseLine.split(":") 
        $row = $table.NewRow();
        $row.channel = "$($keyval[0])";
        $row.value = $keyval[1]
        $row.unit  = "Count"
        $row.mode  = "absolute"
        $table.Rows.Add($row)
      }
      if ($responseLine.startswith('Reading:')) {
        ($responseLine -match "Reading: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
        ($responseLine -match "Writing: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
        ($responseLine -match "Waiting: [0-9]+") | out-null 
          $keyval = $matches[0].split(": ")
          $row = $table.NewRow();
          $row.channel = "$($keyval[0])";
          $row.value = $keyval[2]
          $row.unit  = "Count"
          $row.mode  = "absolute"
          $table.Rows.Add($row)
      }
      if (!$responseLine.length -eq 0 -and ! $responseLine.startswith('Active connections:') -and ! $responseLine.startswith('server') -and ! $responseLine.startswith('Reading:')) {
        $values = $responseLine.trim().split(" ")
        $row = $table.NewRow();
          $row.channel = "Accepts";
          $row.value = "$($values[0])"
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
        $row = $table.NewRow();
          $row.channel = "Handled";
          $row.value = $values[1]
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
          $row = $table.NewRow();
        $row.channel = "Requests";
          $row.value = $values[2]
          $row.unit  = "Count"
          $row.mode  = "difference"
          $table.Rows.Add($row)
      }
    }

# forward the generated table to xml-generator and store the result
    $retval = $table | New-Xml -RootTag prtg -ItemTag result -ChildItems Channel,Value,Unit,CustomUnit,Warning,Float,Mode -TextTag $resultText

# return the result
    write-host $retval
  • Save the file and name it, e.g., nginx_status.ps1
  • Place the script in the \Custom Sensors\EXEXML sub-directory of your PRTG installation to ensure that the EXE/Script Advanced sensor can pick up the same.
  • Create a new EXE/Script Advanced Sensor .
    • Choose nginx_status.ps1 as executable.
    • As Parameter, pass the URL to the nginx status page to the sensor.

The sensor will now read the status page and you should see the values reflected in the sensor's channels.

Best regards

Created on Apr 14, 2014 11:21:27 AM by  Konstantin Wolff [Paessler Support]

Last change on Dec 21, 2017 11:11:40 AM by  Gerald Schoch [Paessler Support]



Votes:

4

If you're merely interested in recording the connection information from the status page, you can use the embedded variables that the status module exposes, and format them for consumption by the HTTP Content sensor directly in the NGINX configuration:

location /prtg {
    return 200 [$connections_active][$connections_reading][$connections_writing][$connections_waiting];
    access_log off;
    allow x.x.x.x/y;
    deny all;
}

Reference:

Created on Jun 15, 2018 3:00:15 AM

Last change on Nov 27, 2018 6:43:17 AM by  Luciano Lingnau [Paessler]



Votes:

0

Thanks for your suggestion to return the module variables, Luciano.

I am reading the values with a http content sensor, but I can not rename the names of the created channels - making the connected values rather useless.

Did I overlook something in the setup, or is it not possible to change the channel names during setup or after creation?

Created on Nov 26, 2018 12:58:44 PM

Last change on Nov 27, 2018 6:43:30 AM by  Luciano Lingnau [Paessler]



Votes:

0

Hello jkrem,
thank you for your reply.

It was actually ek's suggestion, I just adjusted the formatting of the reply a bit. :)

Can you place the variables in a XML-Like (or JSON-like) document that looks like this?

<?xml version="1.0" encoding="utf-8" ?>
<prtg>
	<result>
		<channel>Connections Active</channel>
		<value>[$connections_active]</value>
	</result>
	<result>
		<channel>Connections Reading</channel>
		<value>[$connections_reading]</value>
	</result>
	<text>The sensor's message</text>
</prtg>

This example shows only two channels, but in theory it could be up to 50. For a more complex example, please refer to:

The full API documentation for Custom Sensors is available in PRTG itself under Setup > PRTG API

If the above is an option, you can define the name of the channels in advance and use the HTTP Data Advanced Sensor. Otherwise, the issue with not being able to rename the channels is a known bug in PRTG, that we hope to fix very soon.

Best Regards,
Luciano Lingnau [Paessler Support]

Created on Nov 27, 2018 6:50:03 AM by  Luciano Lingnau [Paessler]

Last change on Nov 27, 2018 6:52:24 AM by  Luciano Lingnau [Paessler]



Votes:

2

Just an FYI, the channel rename bug is fixed with 18.4.47.1962 :)


PRTG Scheduler | PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Jan 9, 2019 12:06:42 PM by  Stephan Linke [Paessler Support]



Votes:

1

For anyone that is copy/pasting Paessler's script and is unable to get it to work, there is a strange character on line 71 that PowerShell will not recognise. This line can be modified to: $responseArray = $response.split("`r`n")

Created on Mar 26, 2020 12:35:38 PM



Votes:

1

If you're still seeing errors with the script referencing $responseArray = $response.split("`r`n")

Make sure your nginx status page is enabled

Link: https://easyengine.io/tutorials/nginx/status-page/

Created on Apr 21, 2020 4:01:47 PM



Votes:

1

I had this script working and then it crashed a few weeks later, turns out that Powershell defaults to using TLS 1.0 and we had recently removed that from our endpoints. To change this, just add the following to Line 3 of the script to set it for the duration of the script:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Created on Jun 9, 2020 11:26:29 PM



Votes:

0

Cool, thanks for sharing!

Created on Jun 10, 2020 6:57:21 AM by  Stephan Linke [Paessler Support]



Votes:

1

Here is a simple working example for NGINX using the HTTP Advanced Sensor:

        location /prtg {
                default_type application/json;
                return 200 '{"prtg":{"result":[{"channel":"Active","value":$connections_active},{"channel":"Reading","value":$connections_reading},{"channel":"Writing","value":$connections_writing},{"channel":"Waiting">
                access_log off;
                allow 192.168.0.10; #PRTG's Probe IP
                deny all;
        }

Created on Nov 6, 2020 8:12:48 PM



Votes:

0

Awesome little "hack" :) Thanks!

Created on Nov 8, 2020 6:02:43 PM by  Stephan Linke [Paessler Support]



Votes:

0

Hi All,

Could you help me check what causing this error from the script above?

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)

The error was encountered when I upgrade our prtg to latest version,

Created on Jun 11, 2021 5:40:37 AM



Votes:

0

Hello,

Thank you for your message.

Regarding the issue with the sensor, I invite you to make sure that the response returned by it follows the corresponding format, indicated here: https://www.paessler.com/manuals/prtg/custom_sensors#advanced_sensors

To check the data returned by the script, I invite you to enable the option Store result in its Settings tab and then execute a manual scan. The sensor log files should then be generated by default under "C:\ProgramData\Paessler\PRTG Network Monitor\Logs\sensors".

If other EXE/Script sensors are affected, I invite you to disable the PowerShell Security Enhancement feature under Setup > System Administration > Monitoring (/systemsetup.htm?tabid=2) > Experimental Features.

Regards.

Created on Jun 14, 2021 5:20:06 AM by  Florian Lesage [Paessler Support]



Votes:

0

When you've properly configured your webserver, TLS1.2 should be enabled in the script. Powershell does TLS1.0 by default

You can add:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Created on Mar 30, 2023 2:46:38 PM




Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.