## Event Handlers

Introduction

Event handlers are optional commands that are executed whenever a host or service state change occurs. An obvious use for event handlers (especially with services) is the ability for NetSaint to proactively fix problems before anyone is notified. Another use for event handlers is to log service or host events to an external database.

Event Handler Types

There are two main types of event handlers than can be defined - service event handlers and host event handlers. Event handler commands are (optionally) defined in each host and service definition. Because these event handlers are only associated with particular services or hosts, I will call these "local" event handlers. If a local event handler has been defined for a service or host, it will be executed when that host or service changes state.

You may also specify global event handlers that should be run for every host or service state change by using the global_host_event_handler and global_service_event_handler options in your main configuration file. Global event handlers are run immediately prior to running a local service or host event handler.

When Are Event Handler Commands Executed?

Service and host event handler commands are executed when a service or host:

- is in a "soft" error state
- initially goes into a "hard" error state
- recovers from a "soft" or "hard" error state

What are "soft" and "hard" states you ask? They are described here .

Event Handler Execution Order

Global event handlers are executed before any local event handlers that you have configured for specific hosts or services.

Writing Event Handler Commands

In most cases, event handler commands will be shell or perl scripts. At a minimum, the scripts should take the following macros as arguments:

Service event handler macros: $SERVICESTATE$, $STATETYPE$, $SERVICEATTEMPT$
Host event handler macros: $HOSTSTATE$, $STATETYPE$, $HOSTATTEMPT$

The scripts should examine the values of the arguments passed in and take any necessary action based upon those values. The best way to understand how event handlers should work is to see and example. Lucky for you, one is provided below. There are also some sample event handler scripts included in the eventhandlers/ subdirectory of the NetSaint distribution. Some of these sample scripts demonstrate the use of external commands to implement redundant monitoring hosts.

Permissions For Event Handler Commands

Any event handler commands you configure will execute with the same permissions as the user under which NetSaint is running on your machine. This presents a problem with scripts that attempt to restart system services, as root privileges are generally required to do these sorts of tasks.

Ideally you should evaluate the types of event handlers you will be implementing and grant just enough permissions to the NetSaint user for executing the necessary system commands. I'll leave the details of how to do that up to you...

Debugging Event Handler Commands

When you are debugging event handler commands, I would highly recommend that you enable logging of service retries, host retries, and event handler commands. All of these logging options are configured in the main configuration file. Enabling logging for these options will allow you to see exactly when and why event handler commands are being executed.

When you're done debugging your event handler commands you'll probably want to disable logging of service and host retries. They can fill up your log file fast, but if you have enabled log rotation you might not care.

Service Event Handler Example

The example below assumes that you are monitoring the HTTP server on the local machine and have specified restart-httpd as the event handler command for the HTTP service definition. Also, I will be assuming that you have set the <max_attempts> option for the service to be a value of 4 or greater (i.e. the service is checked 4 times before it is considered to have a real problem).

First off, we must define the event handler as a command. Notice the macros that I am passing to the event handler command - these are important!

command[restart-httpd]=/usr/local/netsaint/restart-httpd $SERVICESTATE$ $STATETYPE$ $SERVICEATTEMPT$

Now, let's actually write the event handler script (this is the /usr/local/netsaint/restart-httpd file).

    #!/bin/sh
    #
    # Event handler script for restarting the web server on the local machine
    #
    # Note: This script will only restart the web server if the service is
    #       retried 3 times (in a "soft" state) or if the web service somehow
    #       manages to fall into a "hard" error state.
    #

    # What state is the HTTP service in?
    case "$1" in
    OK)
    	# The service just came back up, so don't do anything...
    	;;
    WARNING)
    	# We don't really care about warning states, since the service is probably still running...
    	;;
    UNKNOWN)
    	# We don't know what might be causing an unknown error, so don't do anything...
    	;;
    CRITICAL)
    	# Aha!  The HTTP service appears to have a problem - perhaps we should restart the server...

    	# Is this a "soft" or a "hard" state?
    	case "$2" in

    	# We're in a "soft" state, meaning that NetSaint is in the middle of retrying the
    	# check before it turns into a "hard" state and contacts get notified...
    	SOFT)

    		# What check attempt are we on?  We don't want to restart the web server on the first
    		# check, because it may just be a fluke!
    		case "$3" in

    		# Wait until the check has been tried 3 times before restarting the web server.
    		# If the check fails on the 4th time (after we restart the web server), the state
    		# type will turn to "hard" and contacts will be notified of the problem.
    		# Hopefully this will restart the web server successfully, so the 4th check will
    		# result in a "soft" recovery.  If that happens no one gets notified because we
    		# fixed the problem!
    		3)
    			echo -n "Restarting HTTP service (3rd soft critical state)..."
    			# Call the init script to restart the HTTPD server
    			/etc/rc.d/init.d/httpd restart
    			;;
    			esac
    		;;

    	# The HTTP service somehow managed to turn into a hard error without getting fixed.
    	# It should have been restarted by the code above, but for some reason it didn't.
    	# Let's give it one last try, shall we?
    	# Note: Contacts have already been notified of a problem with the service at this
    	# point (unless you disabled notifications for this service)
    	HARD)
    		echo -n "Restarting HTTP service..."
    		# Call the init script to restart the HTTPD server
    		/etc/rc.d/init.d/httpd restart
    		;;
    	esac
    	;;
    esac
    exit 0

The sample script provided above will attempt to restart the web server on the local machine in two different instances - after the HTTP service is being retried for the 3rd time (in an "soft" error state) and after the service falls into a "hard" state. The "hard" state situation shouldn't really occur, since the script should restart the service when its still in a "soft" state (i.e. the 3rd check retry), but its left as a fallback anyway.

It should be noted that the service event handler will only be execute the first time that the service falls into a "hard" state. This will prevent NetSaint from continuously executing the script to restart the web server when it is in a "hard" state.