---
layout: "docs"
page_title: "Event Handler Router Recipe"
sidebar_current: "docs-recipes"
description: |-
Typically you must configure a handler for each type of event you expect to
encounter (more about events and handlers here).
To change handler configuration, one must update the Serf configuration and reload
the agent with a SIGHUP or a restart.
Thanks to the flexibility and open-endedness Serf offers for configuring and
executing handlers, it is possible to achieve similar functionality by
configuring only a single "router" handler, which never needs to be updated.
This removes the orchestration work of reloading the agents by allowing one to
simply drop new executables with predictable names into a directory.
Handler executables must be named by event type for this recipe to work
(e.g. member-join
). User events get prefixed with "user-", and queries with
"query-" (user-deploy
, query-uptime
, etc.).
What you will end up with is a directory structure that looks like this:
$ tree /etc/serf
/etc/serf
└── handlers
├── member-failed
├── member-join
├── member-leave
├── member-update
├── user-deploy
└── query-uptime
The following code must be configured as the only handler for this recipe to
work. It will act as a catch-all this way and be able to make decisions on what
script handler to invoke based on the Serf environment variables.
#!/bin/sh
HANDLER_DIR="/etc/serf/handlers"
if [ "$SERF_EVENT" = "user" ]; then
EVENT="user-$SERF_USER_EVENT"
elif [ "$SERF_EVENT" = "query" ]; then
EVENT="query-$SERF_QUERY_NAME"
else
EVENT=$SERF_EVENT
fi
HANDLER="$HANDLER_DIR/$EVENT"
[ -f "$HANDLER" -a -x "$HANDLER" ] && exec "$HANDLER" || :
The pluginhook project offers
an alternative way that enables multiple plugins to handle a hook, instead
of only a single handler.
Using this enables a tree structure that looks like:
$ tree /etc/serf
/etc/serf
└── handlers
├── a-1st-plugin
| ├── member-failed
| ├── member-join
| ├── member-leave
| └── member-update
├── a-2nd-plugin
| ├── member-update
| ├── user-deploy
| └── query-uptime
└── an-nth-plugin
├── member-join
└── member-leave
Using this requires only requires minor modifications to our handler script
above:
#!/bin/sh
HANDLER_DIR="/etc/serf/handlers"
if [ "$SERF_EVENT" = "user" ]; then
EVENT="user-$SERF_USER_EVENT"
elif [ "$SERF_EVENT" = "query" ]; then
EVENT="query-$SERF_QUERY_NAME"
else
EVENT=$SERF_EVENT
fi
cd $HANDLER_DIR
pluginhook $EVENT
The serf-master project provides the same functionality but allows you to write handlers strictly in Python. Using serf-master might be a better approach if you are more comfortable with Python than Bash.