Schedule
Many software systems have self-regulation routines that must be scheduled regularly. Observability libraries and toolkits are no different in this regard, with the sampling of metric values or resource states being notable examples; another less common one would be the status snapshotting of inflight workflow constructs such as requests, transactions, tasks, threads, pools, and queues. It is not enough to know what has happened, the typical use case for most metrics, but also what is in progress and at what stage.
Commercial vendor-led open-source projects of proposed instrumentation standards offer little in this regard; there is no support for developers of instrumentation agents to schedule work and no instruments that focus on capturing circadian behavioral aspects separate from request-triggered ones, such as traces and logs. Today, instrumentation developers are forced to implement scheduling external to toolkits, leaving toolkits ignorant of such cyclic work and unable to distinguish it from the regular service execution. With the Substrates API, an important step is finally being made to correct this significant omission.
Clock
In the Substrates API, the Clock interface is a Circuit Component that emits time Instants at different time unit boundaries, referred to as a Cycle. The Clock interface being an extension of Component, an extension of Context, provides a means to subscribe to a Source of Instant boundary Events. It uses the same Event pipeline processing of Conduit and Adjunct via the Circuit.
1 2 3 4 5 6 7 8 9 10 11 |
var circuit = cortex.circuit ( "clocks" ); var clock = circuit.clock ( "clock" ); |
Cycle
The Clock’s source method provides access to a Source for Event subscribing. Subscribing an Outlet with a Source without specifying a Subject’s Name, generated from a Cycle, will result in the same Instant being delivered multiple times if it crosses multiple time unit boundaries. The boundaries are currently MILLISECOND, SECOND, and MINUTE, with a Subject for each enum value. The Clock interface also offers a convenient method called consume that restricts Event delivery to a single time unit boundary, a Cycle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var subcription = clock.consume ( SECOND, event -> out.printf ( "%s : %s%n", event .subject () .reference () .name () .value (), event .emission () ) ); |
Running the above code, the following is printed to a terminal.
>_
SECOND : 2023-04-05T11:01:54.426Z
SECOND : 2023-04-05T11:01:55.426Z
SECOND : 2023-04-05T11:01:56.426Z
SECOND : 2023-04-05T11:01:57.426Z
SECOND : 2023-04-05T11:01:58.426Z
SECOND : 2023-04-05T11:01:59.426Z
SECOND : 2023-04-05T11:02:00.426Z
SECOND : 2023-04-05T11:02:01.426Z
SECOND : 2023-04-05T11:02:02.426Z
SECOND : 2023-04-05T11:02:03.426Z