Package net.sf.eBusx.monitor
eBus objects and to monitor
those objects' on-going state and transient events.
An on-going state is one that persists over time. An example is a disconnected connection. This state continues until either re-established or explicitly closed by the application. A transient event occurs in an instant, with no on-going impact to the application. An example of a transient event would be the application catching exception from which it immediately recovers. This exception is reported as a transient event so administrators are aware of the problem.
Both on-going status and transient events are reported with
a given
action level.
This action level
informs administrators about the event severity. The need to
report
ActionLevel.POSSIBLE_ACTION,
ActionLevel.ACTION_REQUIRED and
ActionLevel.FATAL_ERROR events is
obvious: there is a problem occurring which must be corrected.
But there is debate about reporting
ActionLevel.NO_ACTION,
information-only events. One view is that an application may
be considered to be operating correctly unless stated
otherwise. The opposing view is that,
"if it goes without saying, then it goes even better with
saying it." By reporting "no action" events, it is an
explicit statement of correct operation.
Instrumenting your Application
The starting point is toopen a monitor
with your host, application name, version, copyright,
description and optional name/value attributes. This method
should be called once at system start. See
Monitor.openMonitor
for a detailed explanation for each of the parameters.
The next step in application instrumentation is to
register your eBus objects
with the Monitor instance. You obtain the
Monitor instance either from
Monitor.openMonitor or
Monitor.getMonitor() (
note: Monitor.getMonitor() returns
null if monitor was not opened).
EObject.name() is
used to uniquely identify this object. A newly registered
eBus object's initial on-going status is set to:
-
Action level:
NO_ACTION - Action name: Registered
- Action message: "Registered with monitor subsystem"
Once registered, an object may
update
its on-going (persistent) state and report
transient events
via the Monitor instance. This is demonstrated in the
following code:
import net.sf.eBusx.monitor.ActionLevel;
import net.sf.eBusx.monitor.Monitor
// Note Monitor.getMonitor() returns null if Monitor was not opened.
final Monitor monitor = Monitor.getMonitor();
// This example assumes this eBus object is registered with Monitor.
// Note: this state is on-going until corrected.
monitor.update(ActionLevel.ACTION_REQUIRED,
"Market data feed",
"Ticker plant market data feed is DOWN.",
this);
// This is an example of a transient status report - not an on-going issue.
monitor.transientStatus(ActionLevel.ACTION_REQUIRED,
"Market data feed",
"Ticker plant market data feed down for " + downTimeInterval,
this);
// When the problem is resolved, then be sure to update the on-going status.
monitor.update(ActionLevel.NO_ACTION,
"Market data feed",
"Ticker plant market data feed is up.",
this);
If a registered object is to be discarded prior
to application termination, it should be
deregistered.
Monitor reports this de-registration by setting the
final on-going status to:
-
Action level:
NO_ACTION - Action name: Deregistered
- Action message: "Deregistered from monitor subsystem"
Please note that Monitor maintains a weak reference to
the registered eBus object. If a registered eBus object is
garbage collected, then Monitor will automatically
de-register this eBus object.
Monitor reports object registration, on-going updates,
transient updates, and de-registration using
MonitorUpdate
notification message which contains:
MonitorId and
MonitorUpdate.UpdateType.
-
host name (
String), -
application name (
String), -
monitor instance (
MonitorId), -
update type (
UpdateType) which specifies if eBus object is registered, on-going status changed, transient status, and de-registered, -
action level (
ActionLevel) -
action name (
String), and -
action message (
String).
These MonitorUpdate messages are published to the
subject
"/eBus/monitor/update/<host name>/<application name>"
where <host name> and
<application name> are those used to open the
application's Monitor instance. Monitor also
replies to
ApplicationInfoRequest
and
MonitoredObjectRequest
messages. ApplicationInfoRequest sends a
ApplicationInfoReply
containing the application host name, application name, etc.
MonitoredObjectRequest sends a
MonitoredObjectReply
containing the latest
PersistentStatusMessage
for all currently registered eBus objects.
This leads to the next section.
Monitoring eBus applications
1. Connect to Remote eBus Applications
Establish a
remote connection to
all eBus applications which will be monitored.
2. Subscribe to Monitor Updates
As mentioned above, Monitor publishes
ApplicationInfo and MonitorUpdate messages on
a patterned subject
MONITOR_UPDATE_FORMAT.
If ESubscribeFeed is
used receive monitor updates, then the subscriber must know
all host name, application name pairs. That is, the monitored
hosts and application is fixed and known a prior to
subscribing. It also means that there must be a way to add
or remove host, application name pairs if monitoring is
dynamic.
eBus provides a way to subscribe to all monitor update
subjects rather than each specific host, application name
pair:
EMultiSubscribeFeed
using an eBus pattern
as the "subject". The following code demonstrates how to use
an EMultiSubscribeFeed to receive monitor updates:
import static net.sf.eBus.client.EFeed.FeedScope;
import net.sf.eBus.client.EMultiSubscribeFeed;
import net.sf.eBus.client.IESubscribeFeed;
import net.sf.eBus.util.regex.Pattern;
import net.sf.eBusx.monitor.ApplicationInfo;
import net.sf.eBusx.monitor.Monitor;
import net.sf.eBusx.monitor.MonitorUpdate;
private EMultiSubscribeFeed mAppInfoFeed;
private EMultiSubscribeFeed mUpdateFeed;
@Override public void startup() {
final Pattern multiUpdateSubject =
Pattern.compile(
// Put ".+" in host and application name subject portions to accept
// updates from all hosts and applications.
String.format(Monitor.MONITOR_UPDATE_FORMAT, ".+", ".+"));
mAppInfoFeed =
(EMultiSubscribeFeed.builder()).target(this)
.messageClass(ApplicationInfo.class)
.scope(FeedScope.LOCAL_AND_REMOTE)
.query(multiUpdateSubject)
.statusCallback(this::onAppInfoFeedStatus)
.notifyCallback(this::onAppInfoUpdate)
.build();
mUpdateFeed =
(EMultiSubscribeFeed.builder()).target(this)
.messageClass(MonitorUpdate.class)
.scope(FeedScope.LOCAL_AND_REMOTE)
.query(multiUpdateSubject)
.statusCallback(this::onUpdateFeedStatus)
.notifyCallback(this::onMonitorUpdate)
.build();
}
private void onAppInfoFeedStatus(final EFeedState state, final IESubscribeFeed feed) {
...
}
private void onAppInfoUpdate(final ApplicationInfo info, final IESubscribeFeed feed) {
...
}
private void onUpdateFeedStatus(final EFeedState state, final IESubscribeFeed feed) {
...
}
private void onMonitorUpdate(final MonitorUpdate update, final IESubscribeFeed ffed) {
...
}
It is recommended that subscriptions be put into place before requesting latest monitor updates which is the next step.
3. Request Latest Monitor Updates
Unlike monitor notification subject, the monitor request
subjects are fixed:
APP_INFO_REQUEST_SUBJECT
and
ONGOING_REQUEST_SUBJECT.
It is recommended that these request subjects be put into
place on start-up but the requests themselves not be made
until the repliers are known to be up. The following code
demonstrates how to do this:
import static net.sf.eBus.client.EFeed.FeedScope;
import net.sf.eBus.client.ERequestFeed;
import net.sf.eBus.messages.EMessageKey;
import net.sf.eBusx.monitor.ApplicationInfoRequest;
import net.sf.eBusx.monitor.Monitor;
import net.sf.eBusx.monitor.MonitorObjectRequest;
private ERequestFeed mAppInfoRequestFeed;
private ERequestFeed.ERequest mAppInfoRequest;
private ERequestFeed mMonitorRequestFeed;
private ERequestFeed.ERequest mMonitorRequest;
@Override public void startup() {
final EMessageKey appInfoRequestKey =
new EMessageKey(
ApplicationInfoRequest.class, Monitor.APP_INFO_REQUEST_SUBJECT);
final EMessageKey ogRequestKey =
new EMessageKey(
MonitoredObjectRequest.class, Monitor.ONGOING_REQUEST_SUBJECT);
mAppInfoRequestFeed =
(ERequestFeed.builder()).target(this)
.messageKey(appInfoRequestKey)
.scope(FeedScope.LOCAL_AND_REMOTE)
.statusCallback(this::onAppInfoRequestFeedStatus)
.replyCallback(this::onAppInfoReply)
.build();
mAppInfoRequestFeed.subscribe();
mMonitorRequestFeed =
(ERequestFeed.builder()).target(this)
.messageKey(ogRequestKey)
.scope(FeedScope.LOCAL_AND_REMOTE)
.statusCallback(this::onMonitorFeedStatus)
.replyCallback(this::onMonitorStatusReply)
.build();
mMonitorRequestFeed.subscribe();
}
private void onAppInfoRequestFeedStatus(final EFeedState state, final IESubscribeFeed feed) {
if (state == EFeedState.UP) {
mAppInfoRequest =
mAppInfoRequestFeed.request(
(ApplicationInfoRequest.builder()).subject(Monitor.APP_INFO_REQUEST_SUBJECT)
.build());
}
}
private void onAppInfoReply(final int remaining, final EReplyMessage msg, final ERequestFeed.Request request) {
// Process application information reply.
}
private void onMonitorFeedStatus(final EFeedState state, final IESubscribeFeed feed) {
if (state == EFeedState.UP) {
mMonitorRequest =
mMonitorRequestFeed.request(
(MonitoredObjectRequest.builder()).subject(Monitor.ONGOING_REQUEST_SUBJECT)
.build());
}
}
private void onMonitorStatusReply(final int remaining, final EReplyMessage msg, final ERequestFeed.ERequest request) {
// Process monitored object status reply.
}
-
Class Summary Class Description ApplicationInfo Reports the application information.ApplicationInfo.Builder Builder class used to construct anApplicationInfoinstance.ApplicationInfoReply Returns application information currently registered withMonitor.ApplicationInfoReply.Builder Builder class used to create anApplicationInfoReplymessage.ApplicationInfoRequest Requests application information opened withMonitor.openMonitor(String, String, String, String, String, EField).ApplicationInfoRequest.Builder Builder class used to create anApplicationInfoRequestmessage.Monitor This class provides the ability to instrumenteBus objectsand monitor those instrumented object's status.MonitoredObjectReply Returns persistent status for all currently registered monitored objects within the eBus virtual machine, specified as an array ofPersistentStatusMessages.MonitoredObjectReply.Builder Builder class used to create aMonitoredObjectReplyinstance.MonitoredObjectRequest Requests persistent status all eBus objects registered withMonitor.MonitoredObjectRequest.Builder Builder class used to create anMonitoredObjectRequestmessage.MonitorId A passive, immutable class for storing a monitored object's type name, instance name and its assigned unique, 4-byte integer identifier.MonitorId.Builder Builder class used to create anMonitorIdfield.MonitorUpdate Reports theregistration,deregistration, an eBus object's change in on-going status, or an eBus object's transient event.MonitorUpdate.Builder Builder for creatingMonitorUpdatenotification.PersistentStatusMessage Reports a monitorable object's on-going status.PersistentStatusMessage.Builder Builder class used to construct apersistent status message.TransientStatusMessage Reports a monitored object's transient event.TransientStatusMessage.Builder Builder class used to create anTransientStatusMessagemessage. -
Enum Summary Enum Description ActionLevel The unique action levels reported inPersistentStatusMessageandTransientStatusMessagenotifications.MonitorUpdate.UpdateType MonitorUpdatehas four types: object registration, on-going status update, transient status update, and object de-registration.