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

How can I make my Python scripts work with the Script v2 sensor?

Votes:

0

I currently use the Python Script Advanced sensor for monitoring. I want to use the same scripts in the Script v2 sensors. What do I have to do to so that I can use my same scripts in the Script v2 sensor?

deprecation migration prtg python-script-advanced script-v2 scripts sensor

Created on Nov 4, 2024 9:29:25 AM by  Jacqueline Conforti [Paessler Support]

Last change on Nov 21, 2024 9:15:13 AM by  Jacqueline Conforti [Paessler Support]



2 Replies

Accepted Answer

Votes:

0

This article applies to as of PRTG 24

Python scripts for the Script v2

With the upcoming discontinuation of the Python Script Advanced sensor, we created a script breakdown to help the transition to Python scripts that you can use with the Script v2 sensor.

The script breakdown covers the following topics:

  • Parse input parameters: setup()
  • Script logic: work()
  • Error argument: fail()
  • Main function

If you follow the example script in this article without making any changes, the resulting script accepts a parameter from PRTG and outputs one channel with a random value.

This script is based on the Script v2 example script: Example python script. In this example, we use a script that mimics rolling an n-sided die.

Parse input parameters: setup()

To parse the input parameters for our script, we use the argparse package from the standard python library.

In our case, we define the setup() function which contains the input handling where we define all required parameters.

ArgumentDescription
ArgumentParserThis sets the description displayed when invoking the script using --help.
add_argumentThis adds the --sides parameter with a default value. You can set the parameter on the Command Line Interface (CLI), for example, '--sides 20'.
argparser = setup()Calls the setup function to handle the script input.
if sys.stdin.isatty()Checks if the script is executed interactively.
args = argparser.parse_args()If the script is interactive, the script places the extracted data in a argparse.Namespace object.
pipestring = sys.stdin.read().rstrip()If there is no terminal detected, the script falls backs to read from sys.stdin.
args = argparser.parse_args(shlex.split(pipestring))Parses stdin with argparse.
except argparse.ArgumentErrorIn case of an argparse.Argument error, we suspect something is wrong with the parameters on invocation.

Example

def setup(): argparser = argparse.ArgumentParser( description="The script provides the result of rolling of an n-sided die." ) argparser.add_argument( "--sides", type=int, default=6, help="The number of sides the dice has." ) args = argparser.parse_args() try: argparser = setup() if sys.stdin.isatty(): args = argparser.parse_args() else: pipestring = sys.stdin.read().rstrip() args = argparser.parse_args(shlex.split(pipestring)) except argparse.ArgumentError: fail( "Could not parse input parameter. Check configured parameters." ) return vars(args)

2. Script logic: work()

The work() function defines the sensor logic and returns the result for the sensor. It accepts the parsed arguments defined in setup() and returns the result as a python dictionary.

The returned result adheres to the Script v2 JSON Schema. The Script v2 validates the result against the schema version specified.

Here, you define the result variable of your dice roll and how the sensor behaves as a result.

Return parameters

ParameterDescription
verisonThe script output schema version
statusThe sensor status
You can use any of the sensor states.
Be aware that ok = Up and error = Down.
messageThe sensor message
Hint: Use an f-string to be able to use placeholders.
channelsThe sensors channels
Define the channel ID, name, type, and value.
def work(args: argparse.Namespace):
    result = random.randrange(1, args["sides"] + 1)
    return {
        "version": 2,
        "status": "ok",
        "message": f"The dice rolled {result}.",
        "channels": [
            {
                "id": 10,
                "name": "Last Roll",
                "type": "integer",
                "value": result,
            }
        ],
    }

3. Error argument: fail()

The fail() function takes a message and prints out a result that only contains an error and a sensor message. Use this function to handle error cases and stop your script early.

Best practices

  • Only create errors and error messages for situations that a user can act on immediately. By default, allow all exceptions and use the sensor debug log for detailed error analysis.
  • Do not include sensitive information in the message parameter. All messages defined in this script appear as the sensor message and you could potentially leak sensitive data if you pass an unfiltered exception.
  • Make useful error messages. It does not help the user if the sensor message displays just the exception that triggered the error.
  • Use fail() to define common ways for the script to fail. This reduces repetitive code.

def fail(message: str): print( json.dumps( { "version": 2, "status": "error", "message": message, } ) ) exit(0)

Note: Scripts always need to exit with EXITCODE=0. Otherwise, the sensor fails to recognize the script output and interprets the sensor run as failed.

4. Main function

Finally, the last part of the script defines the main function, or entry point, of the script.

Main function breakdown

The script runs through the functions in the order defined in the main function. In this example, the script first checks the setup function. If there is no error, the script executes the work function and finally prints the result. Then, the script closes on the exit code.

if __name__ == "__main__":
    # Retrieve script arguments
    args = setup()

    # Execute sensor logic
    sensor_result = work(args)

    # Format the result to JSON and print them to stdout.
    print(json.dumps(sensor_result))

    # Scripts always need to exit with EXITCODE=0.
    exit(0)

More

Python Documentation

Created on Nov 4, 2024 10:13:50 AM by  Jacqueline Conforti [Paessler Support]

Last change on Dec 3, 2024 1:54:17 PM by  Felix Seethaler [Paessler Support]



Votes:

0

Example python script without comments

You can put this script into C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\scripts and create a Script v2 sensor using this python script.

#!/usr/bin/env python3
"""This is an example Python script for the Script v2 sensor.
The script provides the result of rolling of an n-sided die.
The script uses the integer parameter '--sides' to determine the number of sides of the die.
If the parameter is omitted, the number of sides default to 6.
"""
import argparse  # needed to parse the script arguments
import json  # needed to construct the result message
import random  # needed for the random dice roll
import shlex  # needed to parse arguments passed via pipe to stdin (PRTG uses this invocation style)
import sys  # needed to check if script is invoked from a tty or through a pipe
def fail(message: str):
    """
    Return error message to PRTG and abort the sensor script.
    This function can be used to reduce code duplication by having a common way to fail the sensor script
    Be careful with the message you pass here. As the message will be shown in PRTG as the Sensor message.
    You could potentially leak sensitive data in the sensor message if you pass an unfiltered exception.
    It is recommended only catch errors on which the user immediately can act on.
    In general exceptions should not be caught and the sensor debug log on the probe should be checked for the detailed error.
    """
    print(
        json.dumps(
            {
                "version": 2,
                "status": "error",
                "message": message,
            }
        )
    )
""" Scripts always need to exit with EXITCODE=0.
   Otherwise the Sensor will fail to recognize your script output and interpret the sensor run as failed.
   """
exit(0)
def setup():
    """
    Parse the arguments from stdin or cli when running interactive and return them
    as a dict.
   Construct the ArgumentParser without `exit_on_error`. This allows us to forward the error to PRTG.
   """
    argparser = argparse.ArgumentParser(
        description="The script provides the result of rolling of an n-sided die",
        exit_on_error=False,
    )

    """ Define your arguments here.""""
    argparser.add_argument(
        "--sides", type=int, default=6, help="The number of sides the dice has."
    )
    try:
        """Check if script is executed interactively first. Otherwise expect arguments from stdin."""
        if sys.stdin.isatty():
            args = argparser.parse_args()
        else:
            pipestring = sys.stdin.read().rstrip()
            args = argparser.parse_args(shlex.split(pipestring))
    """ In case of an argparse.Argument error we suspect something wrong with the parameters on invocation"""
    except argparse.ArgumentError:
        fail(
            "Could not parse input parameter. Check configured `Parameters` in `Script Settings`"
        )

    return vars(args)
def work(args: dict):
    """
    The work function implements the sensor logic and returns the sensor result as a dict.
    Implement your sensor logic here.
    Read the sides parameter from args. This is the work the sensor performs.
     """ 
     result = random.randrange(1, args["sides"] + 1)
     """ 
     Construct your sensor result here
     Create a dict adhering to the expected JSON output format
     """"
    return {
        "version": 2,  # The script output schema version to use
        "status": "ok",  # The sensor status
        "message": f"The dice rolled {result}",  # The sensor message
        "channels": [
            {
                "id": 10,
                "name": "Last Roll",
                "type": "integer",
                "value": result,
            }
        ],
    }
if __name__ == "__main__":
    args = setup()  # Retrieve script arguments  
    sensor_result = work(args)  # Execute sensor logic
    print(json.dumps(sensor_result))  # Format the result to JSON and print them to stdout.
    exit(0)

Created on Dec 2, 2024 11:00:39 AM by  Jacqueline Conforti [Paessler Support]

Last change on Dec 3, 2024 11:48:02 AM by  Jacqueline Conforti [Paessler Support]




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.