All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.eBusx.monitor.package-info Maven / Gradle / Ivy

The newest version!
//
// Copyright 2012 Charles W. Rapp
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/**
 * This package provides the ability to instrument
 * {@link net.sf.eBus.client.EObject 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 * {@link net.sf.eBusx.monitor.ActionLevel action level}. * This action level * informs administrators about the event severity. The need to * report * {@link net.sf.eBusx.monitor.ActionLevel#POSSIBLE_ACTION}, * {@link net.sf.eBusx.monitor.ActionLevel#ACTION_REQUIRED} and * {@link net.sf.eBusx.monitor.ActionLevel#FATAL_ERROR} events is * obvious: there is a problem occurring which must be corrected. * But there is debate about reporting * {@link net.sf.eBusx.monitor.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 to * {@link net.sf.eBusx.monitor.Monitor#openMonitor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, net.sf.eBus.messages.EField) open 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 * {@link net.sf.eBusx.monitor.Monitor#openMonitor(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, net.sf.eBus.messages.EField) Monitor.openMonitor} * for a detailed explanation for each of the parameters. *

* The next step in application instrumentation is to * {@link net.sf.eBusx.monitor.Monitor#register(net.sf.eBus.client.EObject) register your eBus objects} * with the {@code Monitor} instance. You obtain the * {@code Monitor} instance either from * {@code Monitor.openMonitor} or * {@link net.sf.eBusx.monitor.Monitor#getMonitor()} ( * note: {@code Monitor.getMonitor()} returns * {@code null} if monitor was not opened). * {@link net.sf.eBus.client.EObject#name() EObject.name()} is * used to uniquely identify this object. A newly registered * eBus object's initial on-going status is set to: *

*
    *
  • * Action level: {@link net.sf.eBusx.monitor.ActionLevel#NO_ACTION NO_ACTION} *
  • *
  • * Action name: Registered *
  • *
  • * Action message: "Registered with monitor subsystem" *
  • *
*

* Once registered, an object may * {@link net.sf.eBusx.monitor.Monitor#update(net.sf.eBusx.monitor.ActionLevel, String, String, net.sf.eBus.client.EObject) update} * its on-going (persistent) state and report * {@link net.sf.eBusx.monitor.Monitor#transientStatus(net.sf.eBusx.monitor.ActionLevel, String, String, net.sf.eBus.client.EObject) transient events} * via the {@code 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 * {@link net.sf.eBusx.monitor.Monitor#deregister(net.sf.eBus.client.EObject) deregistered}. * {@code Monitor} reports this de-registration by setting the * final on-going status to: *

*
    *
  • * Action level: {@code NO_ACTION} *
  • *
  • * Action name: Deregistered *
  • *
  • * Action message: "Deregistered from monitor subsystem" *
  • *
*

* Please note that {@code Monitor} maintains a weak reference to * the registered eBus object. If a registered eBus object is * garbage collected, then {@code Monitor} will automatically * de-register this eBus object. *

*

* {@code Monitor} reports object registration, on-going updates, * transient updates, and de-registration using * {@link net.sf.eBusx.monitor.MonitorUpdate MonitorUpdate} * notification message which contains: * {@link net.sf.eBusx.monitor.MonitorId} and * {@link net.sf.eBusx.monitor.MonitorUpdate.UpdateType}. *

*
    *
  • * host name ({@code String}), *
  • *
  • * application name ({@code String}), *
  • *
  • * monitor instance ({@link net.sf.eBusx.monitor.MonitorId MonitorId}), *
  • *
  • * update type ({@link net.sf.eBusx.monitor.MonitorUpdate.UpdateType UpdateType}) * which specifies if eBus object is registered, on-going * status changed, transient status, and de-registered, *
  • *
  • * action level ({@link net.sf.eBusx.monitor.ActionLevel ActionLevel}) *
  • *
  • * action name ({@code String}), and *
  • *
  • * action message ({@code String}). *
  • *
*

* These {@code 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 {@code Monitor} instance. {@code Monitor} also * replies to * {@link net.sf.eBusx.monitor.ApplicationInfoRequest ApplicationInfoRequest} * and * {@link net.sf.eBusx.monitor.MonitoredObjectRequest MonitoredObjectRequest} * messages. {@code ApplicationInfoRequest} sends a * {@link net.sf.eBusx.monitor.ApplicationInfoReply ApplicationInfoReply} * containing the application host name, application name, etc. * {@code MonitoredObjectRequest} sends a * {@link net.sf.eBusx.monitor.MonitoredObjectReply MonitoredObjectReply} * containing the latest * {@link net.sf.eBusx.monitor.PersistentStatusMessage PersistentStatusMessage} * for all currently registered eBus objects. *

*

* This leads to the next section. *

*

Monitoring eBus applications

*

1. Connect to Remote eBus Applications

*

* Establish a * {@link net.sf.eBus.client.ERemoteApp remote connection} to * all eBus applications which will be monitored. *

*

2. Subscribe to Monitor Updates

*

* As mentioned above, {@code Monitor} publishes * {@code ApplicationInfo} and {@code MonitorUpdate} messages on * a patterned subject * {@link net.sf.eBusx.monitor.Monitor#MONITOR_UPDATE_FORMAT MONITOR_UPDATE_FORMAT}. * If {@link net.sf.eBus.client.ESubscribeFeed 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: * {@link net.sf.eBus.client.EMultiSubscribeFeed EMultiSubscribeFeed} * using an {@link net.sf.eBus.util.regex.Pattern eBus pattern} * as the "subject". The following code demonstrates how to use * an {@code 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: * {@link net.sf.eBusx.monitor.Monitor#APP_INFO_REQUEST_SUBJECT APP_INFO_REQUEST_SUBJECT} * and * {@link net.sf.eBusx.monitor.Monitor#ONGOING_REQUEST_SUBJECT 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.
}
*/ package net.sf.eBusx.monitor;




© 2015 - 2024 Weber Informatics LLC | Privacy Policy