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 anApplicationInfo
instance.ApplicationInfoReply Returns application information currently registered withMonitor
.ApplicationInfoReply.Builder Builder class used to create anApplicationInfoReply
message.ApplicationInfoRequest Requests application information opened withMonitor.openMonitor(String, String, String, String, String, EField)
.ApplicationInfoRequest.Builder Builder class used to create anApplicationInfoRequest
message.Monitor This class provides the ability to instrumenteBus objects
and 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 ofPersistentStatusMessage
s.MonitoredObjectReply.Builder Builder class used to create aMonitoredObjectReply
instance.MonitoredObjectRequest Requests persistent status all eBus objects registered withMonitor
.MonitoredObjectRequest.Builder Builder class used to create anMonitoredObjectRequest
message.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 anMonitorId
field.MonitorUpdate Reports theregistration
,deregistration
, an eBus object's change in on-going status, or an eBus object's transient event.MonitorUpdate.Builder Builder for creatingMonitorUpdate
notification.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 anTransientStatusMessage
message. -
Enum Summary Enum Description ActionLevel The unique action levels reported inPersistentStatusMessage
andTransientStatusMessage
notifications.MonitorUpdate.UpdateType MonitorUpdate
has four types: object registration, on-going status update, transient status update, and object de-registration.