Skip to content

Commit

Permalink
Merge pull request #2410 from hjoliver/custom-events
Browse files Browse the repository at this point in the history
Custom message event handlers.
  • Loading branch information
dvalters committed Sep 7, 2017
2 parents 6b0723d + 47f290e commit 2ed487f
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 89 deletions.
2 changes: 1 addition & 1 deletion bin/cylc-message
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def main():

parser.add_option(
"-p", "--priority", metavar="PRIORITY", type="choice",
choices=['NORMAL', 'WARNING', 'CRITICAL'],
choices=['NORMAL', 'WARNING', 'CRITICAL', 'CUSTOM'],
help="message priority: NORMAL, WARNING, or CRITICAL; default NORMAL.",
action="store", dest="priority", default="NORMAL")

Expand Down
99 changes: 50 additions & 49 deletions doc/src/cylc-user-guide/cug.tex
Original file line number Diff line number Diff line change
Expand Up @@ -5337,11 +5337,14 @@ \subsection{Inlined Tasks}
a few lines of code, however, we recommend using external shell scripts to allow
independent testing, re-use, and shell mode editing.
\subsection{Custom Task Messages}
\subsection{Task Messages}
Custom messages can be sent back to the suite daemon to report progress,
warnings, or critical events; and to trigger {\em warning} or {\em critical}
event handlers (see~\ref{EventHandling}).
Tasks messages can be sent back to the suite daemon to report completed
outputs and arbitrary messages of different priority levels.
Some types of message - in addition to events like task failure - can
optionally trigger execution of event handlers in the suite daemon
(see~\ref{EventHandling}).
Normal priority messages are printed to \lstinline=job.out= and logged by the
suite daemon:
Expand All @@ -5350,16 +5353,23 @@ \subsection{Custom Task Messages}
cylc message "Hello from ${CYLC_TASK_ID}"
\end{lstlisting}
Warning priority messages are printed to \lstinline=job.err=, logged by the
suite daemon, and can be passed to {\em warning} event handlers
(see~\ref{TaskEventHandling}):
CUSTOM priority messages are printed to \lstinline=job.out=, logged by the
suite daemon, and can be used to trigger {\em custom} event handlers:
\lstset{language=bash}
\begin{lstlisting}
cylc message -p CUSTOM "data available for ${CYLC_TASK_CYCLE_POINT}"
\end{lstlisting}
Task output messages, used for triggering other tasks, can also be sent with
custom priority if need be
WARNING priority messages are printed to \lstinline=job.err=, logged by the
suite daemon, and can be passed to {\em warning} event handlers:
\begin{lstlisting}
cylc message -p WARNING "Uh-oh, something's not right here."
\end{lstlisting}
Critical priority messages are printed to \lstinline=job.err=, logged by the
suite daemon, and can be passed to {\em critical} event handlers
(see~\ref{TaskEventHandling}):
CRITICAL priority messages are printed to \lstinline=job.err=, logged by the
suite daemon, and can be passed to {\em critical} event handlers:
\begin{lstlisting}
cylc message -p CRITICAL "ERROR occurred in process X!"
\end{lstlisting}
Expand Down Expand Up @@ -6600,22 +6610,21 @@ \subsection{Automatic Task Retry On Failure}
the next specified delay period expires. A usage example is shown in the
suite listed below under~\ref{EventHandling}.
\subsection{Suite And Task Event Handling}
\subsection{Task Event Handling}
\label{EventHandling}
See also~\ref{SuiteEventHandling} and~\ref{TaskEventHandling} in the {\em
Suite.rc Reference}.
Cylc can call nominated event handlers when certain suite or task events occur.
This is intended to facilitate centralized alerting and automated handling of
critical events. Event handlers can be used to send a message, call a pager,
and so on; or intervene in the operation of their own suite using cylc
commands.
Cylc can call nominated event handlers - to do whatever you like - when certain
suite or task events occur. This facilitates centralized alerting and automated
handling of critical events. Event handlers can be used to send a message, call
a pager, or whatever; they can even intervene in the operation of their own
suite using cylc commands.
To send an email, you can use the built-in setting
\lstinline=[[[events]]]mail events= to specify a list of events for which
notifications should be sent. E.g.\ to send an email on (submission) failed and
retry:
To send an email, use the built-in setting \lstinline=[[[events]]]mail events=
to specify a list of events for which notifications should be sent. E.g.\ to
send an email on (submission) failed and retry:
\lstset{language=suiterc}
\begin{lstlisting}
Expand Down Expand Up @@ -6647,15 +6656,14 @@ \subsection{Suite And Task Event Handling}
large group of tasks all fail at similar time.
See ~\ref{task-event-mail-interval} for details.
Event handler commands can be located in the suite \lstinline=bin/= directory,
Event handlers can be located in the suite \lstinline=bin/= directory;
otherwise it is up to you to ensure their location is in \lstinline=$PATH= (in
the shell in which cylc runs, on the suite host). The commands should require
very little resource to run and should return quickly. (Each event
handler is invoked by a child process in a finite process pool that is also
used to submit, poll and kill jobs. The child process will wait for the event
handler to complete before moving on to the next item in the queue. If the
process pool is saturated with long running event handlers, the suite will
appear to hang.)
the shell in which the suite daemon runs). They should require little
resource and return quickly - as each event handler is invoked by a child
process in a finite process pool that is also used to submit, poll and kill
jobs. The child process will wait for the event handler to complete before
moving on to the next item in the queue. If the process pool is saturated with
long running event handlers, the suite will appear to hang.
Task event handlers can be specified using the
\lstinline=[[[events]]]<event> handler= settings, where
Expand All @@ -6670,6 +6678,7 @@ \subsection{Suite And Task Event Handling}
\item `succeeded' - the task reported successful completion
\item `warning' - the task reported a WARNING priority message
\item `critical' - the task reported a CRITICAL priority message
\item `custom' - the task reported a CUSTOM priority message
\item `failed' - the task failed
\item `retry' - the task failed but will retry after a configured delay
\item `execution timeout' - task execution timed out
Expand All @@ -6683,26 +6692,19 @@ \subsection{Suite And Task Event Handling}
lines or command line templates (see below) and the latter is a list of events
for which these commands should be invoked.
A command line template may have any or all of these patterns which will be
substituted with actual values:
\begin{myitemize}
\item \%(event)s: event name
\item \%(suite)s: suite name
\item \%(point)s: cycle point
\item \%(name)s: task name
\item \%(submit\_num)s: submit number
\item \%(id)s: task ID (i.e.\ \%(name)s.\%(point)s)
\item \%(message)s: event message, if any
\end{myitemize}
Event handler arguments can be constructed from various templates
representing suite name; task ID, name, cycle point, message, and submit
number name; and any suite or task [meta] item. See~\ref{SuiteEventHandling}
and~\ref{TaskEventHandling} for options.
Otherwise, the command line will be called with the following command line
arguments:
If no template arguments are supplied the following default command line
will be used:
\begin{lstlisting}
<task-event-handler> %(event)s %(suite)s %(id)s %(message)s
\end{lstlisting}
Note: The substitution patterns should not be quoted in the template strings.
Where required, the values will be quoted automatically on substitution.
{\em Note: substitution patterns should not be quoted in the template strings.
This is done automatically where required.}
For an explanation of the substitution syntax, see
\href{https://docs.python.org/2/library/stdtypes.html#string-formatting}{String Formatting Operations}
Expand All @@ -6713,10 +6715,9 @@ \subsection{Suite And Task Event Handling}
The event handler will be called as soon as the task fails, not after
the retry delay period when it is resubmitted.
{\em Note that event handlers are called by cylc itself, not by the
running tasks} so if you wish to pass them additional information via
the environment you must use [cylc] \textrightarrow [[environment]],
not task runtime environments.
{\em Note that event handlers are called by the suite daemon, not by task jobs.}
If you wish to pass additional information to them use [cylc] \textrightarrow
[[environment]], not task runtime environment.
The following 2 \lstinline=suite.rc= snippets are examples on how to specify
event handlers using the alternate methods:
Expand All @@ -6742,8 +6743,8 @@ \subsection{Suite And Task Event Handling}
handlers = "echo '!!!!!EVENT!!!!!' "
handler events = retry, failed
\end{lstlisting}
Note: The handler command is called like this:
The handler command here - specified with no arguments - is called with the
default arguments, like this:
\begin{lstlisting}
echo '!!!!!EVENT!!!!!' %(event)s %(suite)s %(id)s %(message)s
\end{lstlisting}
Expand Down
67 changes: 32 additions & 35 deletions doc/src/cylc-user-guide/suiterc.tex
Original file line number Diff line number Diff line change
Expand Up @@ -340,22 +340,21 @@ \subsection{[cylc]}
\item \%(suite)s: suite name
\item \%(suite\_url)s: suite URL
\item \%(message)s: event message, if any
\item any suite [meta] item, e.g.:
\begin{myitemize}
\item \%(title)s: suite title
\item \%(importance)s: example custom suite metadata
\end{myitemize}
\end{myitemize}

It can also include the patterns from the [meta] section of the suite, for example:
\begin{myitemize}
\item \%(suite-priority)s: suite priority
\item \%(color)s: suite color
\end{myitemize}

Otherwise, the command line will be called with the following command line
Otherwise the command line will be called with the following default
arguments:
\begin{lstlisting}
<suite-event-handler> %(event)s %(suite)s %(message)s
\end{lstlisting}

Note: The substitution patterns should not be quoted in the template strings.
Where required, the values will be quoted automatically on substitution.
{\em Note: substitution patterns should not be quoted in the template strings.
This is done automatically where required.}

Additional information can be passed to event handlers via
[cylc] \textrightarrow [[environment]].
Expand Down Expand Up @@ -1612,50 +1611,47 @@ \subsection{[runtime]}
\label{TaskEventHandling}

Cylc can call nominated event handlers when certain task events occur. This
section configures specific task event handlers; see~\ref{SuiteEventHandling} for
suite event hooks.
section configures specific task event handlers; see~\ref{SuiteEventHandling}
for suite events.

Event handler commands can be located in the suite \lstinline=bin/= directory,
Event handlers can be located in the suite \lstinline=bin/= directory,
otherwise it is up to you to ensure their location is in \lstinline=$PATH= (in
the shell in which cylc runs, on the suite host). The commands should require
very little resource to run and should return quickly.
the shell in which the suite daemon runs). They should require little resource
to run and return quickly.

Each task event handler can be specified as a list of command lines or command
line templates.

A command line template may have any or all of these patterns which will be
substituted with actual values:
line templates. They can contain any or all of the following patterns, which
will be substituted with actual values:
\begin{myitemize}
\item \%(event)s: event name
\item \%(suite)s: suite name
\item \%(point)s: cycle point
\item \%(name)s: task name
\item \%(suite\_url)s: suite URL
\item \%(task\_url)s: task URL
\item \%(submit\_num)s: submit number
\item \%(id)s: task ID (i.e.\ \%(name)s.\%(point)s)
\item \%(message)s: event message, if any
\item any task [meta] item, e.g.:
\begin{myitemize}
\item \%(title)s: task title
\item \%(URL)s: task URL
\item \%(importance)s - example custom task metadata
\end{myitemize}
\item any suite [meta] item, prefixed with ``suite\_'', e.g.:
\begin{myitemize}
\item \%(suite\_title)s: suite title
\item \%(suite\_URL)s: suite URL
\item \%(suite\_rating)s - example custom suite metadata
\end{myitemize}
\end{myitemize}

The template can also include the patterns from [[[meta]]] section of the task, for example:
\begin{myitemize}
\item \%(importance)s: task priority
\item \%(color)s: task color
\end{myitemize}

Patterns from the [meta] section of the suite can also be used, for example:
\begin{myitemize}
\item \%(suite\_priority)s: suite priority
\item \%(suite\_color)s: suite color
\end{myitemize}

Otherwise, the command line will be called with the following arguments:
Otherwise, the command line will be called with the following default
arguments:
\begin{lstlisting}
<task-event-handler> %(event)s %(suite)s %(id)s %(message)s
\end{lstlisting}

Note: The substitution patterns should not be quoted in the template strings.
Where required, the values will be quoted automatically on substitution.
{\em Note: substitution patterns should not be quoted in the template strings.
This is done automatically where required.}

For an explanation of the substitution syntax, see String Formatting Operations
in the Python documentation:
Expand Down Expand Up @@ -1684,6 +1680,7 @@ \subsection{[runtime]}
\item {\bf execution timeout} - the task timed out after execution commenced
\item {\bf warning} - the task reported a WARNING priority message
\item {\bf critical} - the task reported a CRITICAL priority message
\item {\bf custom} - the task reported a CUSTOM priority message
\end{myitemize}

Item details:
Expand Down
1 change: 1 addition & 0 deletions lib/cylc/cfgspec/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ def _coerce_parameter_list(value, keys, _):
'submission retry handler': vdr(vtype='string_list'),
'execution timeout handler': vdr(vtype='string_list'),
'submission timeout handler': vdr(vtype='string_list'),
'custom handler': vdr(vtype='string_list'),
},
'suite state polling': {
'user': vdr(vtype='string'),
Expand Down
5 changes: 3 additions & 2 deletions lib/cylc/task_events_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,9 @@ def process_message(self, itask, priority, message, poll_event_time=None,
priority = getLevelName(priority)
self._db_events_insert(
itask, ("message %s" % str(priority).lower()), message)

if priority in [TaskMessage.WARNING, TaskMessage.CRITICAL]:
if priority == "CUSTOM":
self.setup_event_handlers(itask, "custom", message)
elif priority in [TaskMessage.WARNING, TaskMessage.CRITICAL]:
self.setup_event_handlers(itask, priority.lower(), message)

def setup_event_handlers(self, itask, event, message):
Expand Down
5 changes: 3 additions & 2 deletions lib/cylc/task_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class TaskMessage(object):
NORMAL = "NORMAL"
WARNING = "WARNING"
CRITICAL = "CRITICAL"
PRIORITIES = (NORMAL, WARNING, CRITICAL)
CUSTOM = "CUSTOM"
PRIORITIES = (NORMAL, WARNING, CRITICAL, CUSTOM)

MSG_RETRY_INTVL = 5.0
MSG_MAX_TRIES = 7
Expand Down Expand Up @@ -91,7 +92,7 @@ def send(self, messages):

def _print_messages(self, messages):
"""Print message to send."""
if self.priority == self.NORMAL:
if self.priority in [self.NORMAL, self.CUSTOM]:
handle = sys.stdout
else:
handle = sys.stderr
Expand Down
Loading

0 comments on commit 2ed487f

Please sign in to comment.