.. _60-events: Events ====== Four types of event are supported, at least for now. On Linux, `DBus `__ is the mechanism that handles the majority of the communication between the system and the applications, via a well described subscription mechanism. On Windows, on the other side, `WMI `__ is a WBEM based interface that allows for subscription to system events in a streamlined way, thus it has been implemented specifically for the Windows platform. WMI, of course, is not available on Linux, while DBus is optionally available on Windows. Other environments may expose interfaces that are not directly supported by **whenever**. One very specific case, which is also particularly useful, is the *notification* of changes in the filesystem for watched entities (files or directories), which is also implemented in **whenever** as one of the possible events that can fire conditions. The last kind of events supported by **whenever** relies on its *stdin* based :ref:`command interface <70-intcli-input-commands>`. These events are directly raised by issuing a ``trigger`` command followed by the event name: a wrapper, even possibly a platform specific one, can therefore notify **whenever** that a specific event took place, or that the user explicitly required to trigger it from the available user interface. This type of event is the simplest one to define, as it has no criteria to be specified. Note that if an event arises more that once within the tick interval, it is automatically *debounced* and a single occurrence is counted. All *event* definition sections must start with the TOML ``[[event]]`` header. An optional entry, namely ``tags``, is accepted in item configuration: this entry is ignored by **whenever** itself, however it is checked for correctness at startup and the configuration is refused if not set to an array (of strings) or a table. The associated conditions must exist, otherwise an error is raised and **whenever** aborts. .. _60-events-fschange: Filesystem changes ------------------ This type of event arises when there is a modification in the filesystems, regarding one of more monitored files and/or directories. **whenever** allows to monitor a list of items for each defined event of this type, and to associate an *event* based condition to the event itself. A sample configuration follows: .. code-block:: toml [[event]] name = "FilesystemChangeEventName" type = "fschange" condition = "AssignedConditionName" # optional parameters (if omitted, defaults are used) watch = [ "/path/to/resource", "/another/path/to/file.txt", ] recursive = false poll_seconds = 2 The configuration entries are: .. list-table:: :header-rows: 1 * - Entry - Default - Description * - ``name`` - N/A - the unique name of the event (mandatory) * - ``type`` - N/A - must be set to ``"fschange"`` (mandatory) * - ``condition`` - N/A - the name of the associated *event* based condition (mandatory) * - ``watch`` - (empty) - a list of items to be monitored: possibly expressed with their full path * - ``recursive`` - *false* - if *true*, listed directories will be monitored recursively * - ``poll_seconds`` - 2 - generally not used, can be needed on systems where the notification service is unavailable .. _60-events-dbus: DBus signals (optional) ----------------------- DBus provides signals that can be subscribed by applications, to receive information about various aspects of the system status in an asynchronous way. **whenever** offers the possibility to subscribe to these signals, so that when the *return parameters* match the provided constraints, then the event occurs and the associated condition is fired. .. note:: This type of item is only available when the ``dbus`` feature is enabled. Subscription is performed by providing a *watch expression* in the same form that is used by the `dbus-monitor ` utility. The criteria that the *signal parameters* must meet in order for the event to arise, are specified using the same format that is used for *return message parameter* checks in :ref:`DBus method based conditions <50-conditions-dbus>`. A sample configuration section follows: .. code-block:: toml [[event]] name = "DbusMessageEventName" type = "dbus" # mandatory value bus = ":session" # either ":session" or ":system" condition = "AssignedConditionName" rule = """\ type='signal',\ sender='org.freedesktop.DBus',\ interface='org.freedesktop.DBus',\ member='NameOwnerChanged',\ arg0='org.freedesktop.zbus.MatchRuleStreamTest42'\ """ # optional parameters (if omitted, defaults are used) parameter_check_all = false parameter_check = [ { index = 0, operator = "eq", value = false }, { index = [1, 5], operator = "neq", operator = "forbidden" }, { index = [2, "mapidx", 5], operator = "match", value = "^[A-Z][a-zA-Z0-9_]*$" }, ] and the details of the configuration entries are described in the table below: .. list-table:: :header-rows: 1 * - Entry - Default - Description * - ``name`` - N/A - the unique name of the event (mandatory) * - ``type`` - N/A - must be set to ``"dbus"`` (mandatory) * - ``condition`` - N/A - the name of the associated *event* based condition (mandatory) * - ``bus`` - N/A - the bus on which to listen for events: must be either ``":system"`` or ``":session"``, including the starting colon (mandatory) * - ``parameter_check_all`` - *false* - if *true*, all the provided criteria will have to be satisfied for the event to be fired, otherwise one is enough * - ``parameter_check`` - (empty) - a list of maps consisting of three fields each, each of which is a check to be performed on return parameters The considerations about indexes in return parameters are the same that have been seen for :ref:`DBus message based conditions <50-conditions-dbus>`. It is worth to remind that any errors that may arise during checks will cause the check itself to yield *false*. If no parameter checks are provided, the event arises simply when the signal is caught. .. _60-events-wmi: WMI (optional, Windows only) ---------------------------- On Windows, **whenever** can subscribe to *WMI* events using event specific `WML queries`_. This kind of query allows for an extremely precise determination of every aspect of the event that has to be caught, including the possibility to specify any criteria regarding the payload of an event in order to consider it verified. Thus **whenever** leaves to the *query* part of a *WMI* event definition the task of filtering the specific event for which it enables a listener. .. _WML queries: https://learn.microsoft.com/en-us/windows/win32/wmisdk/receiving-event-notifications .. note:: This type of item is only available when the ``wmi`` feature is enabled. As a result, the configuration of a *WMI* based event is much simpler than the one of *DBus signal* based ones, by only having to specify a mandatory ``query`` entry, whose syntax and semantic is similar to the one of the queries used in :ref:`WMI Query <50-conditions-dbus>` based conditions, but has to be expressly built for events. An example of *WMI* based event configuration follows: .. code-block:: toml [[event]] name = "WMIEventName" type = "wmi" # mandatory value condition = "AssignedConditionName" query = """ SELECT * FROM __InstanceModificationEvent WHERE TargetInstance ISA "Win32_LogicalDisk" AND TargetInstance.FreeSpace < 5000000000 """ which will occur every time the remaining space of a logical disk goes roughly under 5GB. The details of the configuration entries are described in the table below: .. list-table:: :header-rows: 1 * - Entry - Default - Description * - ``name`` - N/A - the unique name of the event (mandatory) * - ``type`` - N/A - must be set to ``"dbus"`` (mandatory) * - ``condition`` - N/A - the name of the associated *event* based condition (mandatory) * - ``query`` - N/A - the *WQL* query used specify what criteria must be satisfied for the event to occur As with DBus *match rules*, **whenever** does not do any parsing or check on the provided query: an incorrect query will only cause the event registration to fail and log an error message, at least in the *debug* log level. Every event returned by the system matches the criteria specified in the *query*, and will cause the assigned condition to fire. .. warning:: Some antimalware tools might detect event subscriptions as suspicious. .. _60-events-cli: Command line ------------ As said above, this type of event has no other parameters than the name, the type identifier, and the associated condition. All parameters are mandatory. The event is raised when a wrapper (or the user) passes a ``trigger`` :ref:`command <70-intcli-input-commands>` to **whenever** through the *stdin* stream of an active session. A sample configuration section follows: .. code-block:: toml name = "ManuallyTriggeredEvent" type = "cli" # mandatory value condition = "AssignedConditionName" and the details of the configuration entries are described in the table below: .. list-table:: :header-rows: 1 * - Entry - Default - Description * - ``name`` - N/A - the unique name of the event (mandatory) * - ``type`` - N/A - must be set to ``"cli"`` (mandatory) * - ``condition`` - N/A - the name of the associated *event* based condition (mandatory) No listening service is installed, so the impact on resource consumption and performance is almost unnoticeable.