Event interface

Protocol

The Supvisors Event Interface relies on a PyZMQ socket. To receive the Supvisors events, the client application must configure a socket with a SUBSCRIBE pattern and connect it on localhost using the event_port option defined in the rpcinterface extension point of the Supervisor configuration file. The event_link option must also be set to ZMQ.

Supvisors publishes the events in multi-parts messages.

Message header

The first part is a header that consists in an unicode string. This header identifies the type of the event, defined as follows in the supvisors.utils module:

SUPVISORS_STATUS_HEADER = u'supvisors'
INSTANCE_STATUS_HEADER = u'instance'
APPLICATION_STATUS_HEADER = u'application'
PROCESS_STATUS_HEADER = u'process'
PROCESS_EVENT_HEADER = u'event'

PyZMQ makes it possible to filter the messages received on the client side by subscribing to a part of them. To receive all messages, just subscribe using an empty string. For example, the following lines in python configure the PyZMQ socket so as to receive only the Supvisors and Process events:

socket.setsockopt(zmq.SUBSCRIBE, SUPVISORS_STATUS_HEADER.encode('utf-8'))
socket.setsockopt(zmq.SUBSCRIBE, PROCESS_STATUS_HEADER.encode('utf-8'))

Message data

The second part of the message is a dictionary serialized in JSON. Of course, the contents depends on the message type.

Supvisors status

Key

Value

‘fsm_statecode’

The state of Supvisors, in [0;6].

‘fsm_statename’

The string state of Supvisors, among { 'INITIALIZATION', 'DEPLOYMENT', 'OPERATION', 'CONCILIATION', 'RESTARTING', 'SHUTTING_DOWN', 'SHUTDOWN' }.

‘starting_jobs’

The list of Supvisors instances having starting jobs in progress.

‘stopping_jobs’

The list of Supvisors instances having stopping jobs in progress.

Supvisors instance status

Key

Value

‘identifier’

The deduced name of the Supvisors instance.

‘node_name’

The name of the node where the Supvisors instance is running.

‘port’

The HTTP port of the Supvisors instance.

‘statecode’

The Supvisors instance state, in [0;5].

‘statename’

The Supvisors instance state as string, among { 'UNKNOWN', 'CHECKING', 'RUNNING' 'SILENT', 'ISOLATING', 'ISOLATED' }.

‘remote_time’

The date of the last TICK event received from this node, in ms.

‘local_time’

The local date of the last TICK event received from this node, in ms.

‘loading’

The sum of the expected loading of the processes running on the node, in [0;100]%.

‘sequence_counter’

The TICK counter, i.e. the number of Tick events received since it is running.

Application status

Key

Value

‘application_name’

The Application name.

‘statecode’

The Application state, in [0;3].

‘statename’

The Application state as string, among { 'STOPPED', 'STARTING', 'RUNNING', 'STOPPING' }.

‘major_failure’

True if the application is running and at least one required process is not started.

‘minor_failure’

True if the application is running and at least one optional (not required) process is not started.

Process status

Key

Value

‘application_name’

The Application name.

‘process_name’

The Process name.

‘statecode’

The Process state, in {0, 10, 20, 30, 40, 100, 200, 1000}. A special value -1 means that the process has been deleted as a consequence of an XML-RPC update_numprocs.

‘statename’

The Process state as string, among { 'STOPPED', 'STARTING', 'RUNNING', 'BACKOFF', 'STOPPING', 'EXITED', 'FATAL', 'UNKNOWN' }. A special value DELETED means that the process has been deleted as a consequence of an XML-RPC update_numprocs.

‘expected_exit’

True if the exit status is expected (only when state is 'EXITED').

‘last_event_time’

The date of the last process event received for this process, regardless of the originating Supvisors instance.

‘identifiers’

The deduced names of the Supvisors instances where the process is running.

‘extra_args’

The additional arguments passed to the command line of the process.

Hint

The expected_exit information of this event provides an answer to the following Supervisor request:

Process event

Key

Value

‘group’

The Application name.

‘name’

The Process name.

‘state’

The Process state, in {0, 10, 20, 30, 40, 100, 200, 1000}. A special value -1 means that the process has been deleted as a consequence of an XML-RPC update_numprocs.

‘expected’

True if the exit status is expected (only when state is 100 - EXITED).

‘now’

The date of the event in the reference time of the node.

‘pid’

The UNIX process ID (only when state is 20 - RUNNING or 40 - STOPPING).

‘identifier’

The deduced name of the Supvisors instance that sent the initial event.

‘extra_args’

The additional arguments passed to the command line of the process.

‘disabled’

True if the process is disabled on the Supvisors instance.

Event Clients

This section explains how to use receive the Supvisors Events from a Python or JAVA client.

Python Client

The SupvisorsZmqEventInterface is designed to receive the Supvisors events from the local Supvisors instance. It requires PyZmq to be installed.

from supvisors.client.zmqsubscriber import *

# create the subscriber thread
subscriber = SupvisorsZmqEventInterface(zmq.Context.instance(), port, create_logger())
# subscribe to all messages
subscriber.subscribe_all()
# start the thread
subscriber.start()

JAVA Client

Each Supvisors release includes a JAR file that contains a JAVA client. It can be downloaded from the Supvisors releases.

The SupvisorsEventSubscriber of the org.supvisors.event package is designed to receive the Supvisors events from the local Supvisors instance. A SupvisorsEventListener with a specialization of the methods onXxxStatus must be attached to the SupvisorsEventSubscriber instance to receive the notifications.

It requires the following additional dependencies:

The binary JAR of JeroMQ 0.5.2 is available in the JeroMQ MAVEN repository.

The binary JAR of Google Gson 2.8.6 is available in the Gson MAVEN repository.

import org.supvisors.event.*;

// create ZeroMQ context
Context context = ZMQ.context(1);

// create and configure the subscriber
SupvisorsEventSubscriber subscriber = new SupvisorsEventSubscriber(60002, context);
subscriber.subscribeToAll();
subscriber.setListener(new SupvisorsEventListener() {

    @Override
    public void onSupvisorsStatus(final SupvisorsStatus status) {
        System.out.println(status);
    }

    @Override
    public void onInstanceStatus(final SupvisorsInstanceInfo status) {
        System.out.println(status);
    }

    @Override
    public void onApplicationStatus(final SupvisorsApplicationInfo status) {
        System.out.println(status);
    }

    @Override
    public void onProcessStatus(final SupvisorsProcessInfo status) {
        System.out.println(status);
    }

    @Override
    public void onProcessEvent(final SupvisorsProcessEvent event) {
        System.out.println(event);
    }
});

// start subscriber in thread
Thread t = new Thread(subscriber);
t.start();