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.

def setup():    argparser = argparse.ArgumentParser(        description="The script provides the result of rolling of an n-sided die.",        exit_on_error=False,    )    argparser.add_argument(        "--sides", type=int, default=6, help="The number of sides the die has."    )    try:      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) 

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 die 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 die rolled {result}.",        "channels": [            {                "id": 10,                "name": "Last Roll",                "type": "integer",                "value": result,            }        ],    }

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.

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