The Toolkit #3

Back to the Source

In the last post, we discussed the concepts of Context and Instrument. This post explores the Source interface that the Context extends, an important interface for plugins and integrations with application code that aims to self-regulate its behavior based on events published by instruments. This is a key differentiator over other proposed standards in the Observability space.

Starting with the Source interface, we will then cover the supporting interfaces: Subscriber, Subscription, and Sink.

The Source Interface

The Source interface enables local application and service code routines to subscribe to measurement and model events published by an Instrument by way of Context, which is the primary implementation of the Source interface. The Source interface offers two ways to consume events via the registration of Subscriber or Sink.

Clients of the Substrates API, or one of the derived instrument APIs, use the Subscriber registration option when they wish to be selective in which named Instrument instances they wish to listen in on and dynamically unsubscribe from event consumption.

final var source =
  Gauges.context ();

// register a subscriber
final var subscription =
  source.subscribe (
    ( referent, registrar ) -> {
      /* .... */
    }
  );

// register a sink
source.consume (
  ( referent, operator ) -> {
    /* ... */
  }
);

The Subscriber Interface

The Subscriber interface is used to selectively register interest in events based on the Name provided in a callback from the Source where the Subscriber was registered. Whenever an underlying Named component, typically an Instrument, of the Source publishes an event, registered Subscriber instances are queried to determine whether they wish to receive the event and further events associated with the Name. If a Subscriber is interested in future events for a Name, it registers a Sink with the registrar provided in the callback.

 final var sink = ...

 final var subscription =
   source.subscribe (
     ( referent, registrar ) -> {
       if ( /** some condition **/ ) {
         registrar.register (
           sink
         );
       } 
     }
   );

The Sink Interface

The Sink interface is the ultimate consumer of events published by a Source. It is used at the client surface and within many Humainary instrument projects for internal event pipelining, including integrations across instrument libraries. For every published event forwarded to a Sink, a Name is provided along with the event payload, whose type is dependent on the Source and Instrument. A Sink can be hooked up to a Source via a Subscriber or directly where it effectively acts as a collect-all endpoint until termination.

source.consume (
  ( referent, operator ) -> {
    if ( operator == INC ) {
      /* ... */
    }
  }
);

The Subscription interface

The Subscription interface is used to end the communication between a Subscriber and a Source. A Subscription is returned by a Source when a Subscriber is registered. This result from the registration method should be held if the client (application or plugin) wishes to close the event consumption pipeline before the orderly shutdown of other components. In the future, this interface may be extended to include a callback on the closing of a source done elsewhere. This extension is currently under review for inclusion.