Index Changes

Difference between version and version     

Back to Fuji Message Tracing Apis, or Fuji Message Tracing Apis Info


At line 1 changed 1 line.
! Fuji Core and Component Message Tracing APIs
!!! Fuji Core and Component Message Tracing APIs
At line 3 added 1 line.
At line 5 changed 1 line.
In the course of working on tooling for Fuji we will eventually come (well, in fact we're already there) to the necessity of implementing some sort of message tracing functionality. This should satisfy four major tasks that the user will be able to perform from the tooling:
In the course of working on tooling for Fuji we will eventually come (well, in fact we're already there) to the necessity of implementing some sort of message tracing functionality. It should satisfy several major tasks that the user will be able to perform from the tooling (__note__: the changes described below are intended to provide the required infrastructure, not the complete "feature" providing support for these tasks. The latter is expected to be developed separately by the tooling engineers, or any third party):
At line 7 changed 1 line.
* "Monitoring". The tooling application "attaches" tot he runtime showing the user all messages that show up at the checkpoints of the currently active message flow.
* "Monitoring". The tooling application "attaches" to the runtime showing the user all messages that show up at the checkpoints of the currently active message flow.
At line 11 added 1 line.
* "Audit". The tooling application might want to record the messages as they flow through the system, providing a facility for a later retrieval. I would be beneficial to be able to reconstruct not only the path of a single message, but also the messages that are somehow related to the message in question. E.g. messages that resulted from this message having been processed by a certain component, or vice versa, messages that served as the "input" for the current one.
At line 11 changed 1 line.
A checkpoint is a certain location on the message flow that we consider to be interesting to inspect from the message state standpoint. Currently the checkpoints are located around each service present in the message flow, i.e. right after the message left the service and entered the NMR and right before the message leaves the NME and enters the service. Additionally we account for "raw" messages, that is, binding components (where applicable) have additional checkpoints: right after the binding received a message from the outside world (in binding-specific format) and right before the binding is about to send out a message to the OW (again in binding-specific format). A good example of these would be a an incoming or outgoing HTTP/SOAP request, contents of the file read by the file binding, JDBC result set of a database query, etc.
A checkpoint is a certain location on the message flow that we consider to be interesting to inspect from the message state standpoint. The standard checkpoints are located around each service present in the message flow, i.e. right after the message left the service and entered the NMR and right before the message leaves the NMR and enters the service. Additionally we account for "raw" messages, that is, binding components (where applicable) have additional checkpoints: right after the binding received a message from the outside world (in binding-specific format) and right before the binding is about to send out a message to the OW (again in binding-specific format). A good example of these would be a an incoming or outgoing HTTP/SOAP request, contents of the file read by the file binding, JDBC result set of a database query, etc.
Non-standard checkpoints are provided by the participating services and are component-type specific. E.g. a File BC (if equipped with an encoder) might want to provide access to the message as it was read from the filesystem, then as it was processed by an encoder and transformed into XML, etc.
At line 16 changed 1 line.
!! Things to consider in the future
!! Functionality requirements
At line 18 changed 1 line.
* Debugging of the component code itself. For the components whose "code" is exposed (e.g. BPEL, JRuby) it would be nice to be able to debug this code as well, thus introducing another action alongside with "Step by Message": "Step Into". We'd need a more or less common API for that as well, if we ever decide to pursue this direction.
To implement all of the above items we need the runtime to provide a mechanism to attach a listener, which would receive the events about messages passing through the checkpoints and be able to pause the execution of the message flow for debugging purposes.
Important things:
* When a listener is attached the should be a possibility to specify a filtering option:
** receive events about all messages are are passing through he system (might be useful for the monitoring scenario and is obviously the easiest to implement on the runtime side,)
** receive events about messages passing through the given message flow only (this is somewhat difficult to define right now, should that be an IFL file, or an application, or a certain namespace?) (again, this is useful for monitoring scenario,)
** receive events about messages that "appeared" as a result of the given message/set of messages (this will be used for testing and pure tracing scenarios,)
** receive events about messages only at specific checkpoints to be able to monitor, for example, only the encoding step,
** receive event only about specific types of messages: normal or fault, this would allow building some sort of maintenance solutions, allowing to "fix" faults as they occur and direct the fixed messages further along wire.
* There should be a way to "catch" faults and errors, as they appear. Additionally there should be an option to "fix" faults (see above).
* Ideally the events should be supplied in the more user-oriented fashion, than they are now, i.e. what we get now are the "raw" JBI objects like {{MessageExchange}}, etc. What we would like to get is probably just the event type (normal message, fault, error), message location (service and whether the message is "before" or "after" it) and the message itself as an {{Object}}.
* The requirement on being able to provide the "raw" message information should be optional for the bindings, though very desired.
* There should be a single interface for the whole set of the events (both NMs and the "raw" messages) that the tooling would attach to. The bindings that actually do provide the required functionality should somehow register or expose themselves in the overall events infrastructure.
!! API/SPI suggestions
The API/SPI should be provided by the core runtime and consist of two parts: the one facing the tooling and the one oriented towards the components.
The tooling part should consist of an OSGi service (exposing methods responsible for attaching/removing a listener and sending a message), the listener interface and the filter interface which would tell the runtime which events should be sent to this particular listener. The pause mechanism is to be realized via the listener's not returning till it is safe to continue execution.
{{{
/**
* Provides the functionality which enables the tooling applications to
* implement monitoring and debugging support for applications deployed
* to the Fuji runtime.
*/
public interface MessagesService {
/**
* Adds a listener, which will be notified of messages that are accepted
* by the provided filter.
*
* @param listener listener which will be receiving the events.
* @param filter filter object which will be used to decide whether the
* listener should receive the event.
* @throws IllegalStateException when this listener is already attached.
*/
void attachListener(
MessagesListener listener,
MessagesFilter filter);
/**
* Removes the previously attached listener.
*
* @param listener listener which should be removed from the listeners
* set.
* @throws IllegalStateException when this listener is not attached.
*/
void removeListener(
MessagesListener listener);
/**
* Sends (injects) a message to the specified point in the message flow.
* The concrete coordinates of this point are defined by the combination
* of the <kbd>service</kbd> and <kbd>location</kbd> parameters: the
* <kbd>service</kbd> one defines which service the message should go to,
* and the <kbd>location</kbd> specifies whether the message should be
* injected before the service, after it, or at some service-specific
* checkpoint.
*
* @param service service that the message should be injected into.
* @param location message injection location relative to the service.
* @param type type of the message which will be injected.
* @param message the message object.
* @param relations identifiers of the messages that are related to the
* current one. The keys in this map are relation types, the list in
* the map value lists the message identifiers.
* @throws IllegalArgumentException if the service cannot be found, or
* the service does not support such location (e.g. <kbd>INBOUND</kbd>
* for 'scheduler' services, or the supplied message object cannot be
* injected at the given coordinates (e.g. a normalized message before
* an inbound binding.)
*/
void sendMessage(
QName service,
String location,
String type,
Object message,
Map<String, List<String>> relations);
/**
* Standard checkpoint, identifying the location right before a message
* leaves the NMR and enters the service.
*/
public static final String INBOUND = "inbound"; // NOI18N
/**
* Standard checkpoint, identifying the location right after a message
* left the service and entered the NMR.
*/
public static final String OUTBOUND = "outbound"; // NOI18N
/**
* Standard message type, indicating that the message is a normal one.
*/
public static final String NORMAL = "normal"; // NOI18N
/**
* Standard message type, indicating that the message is a fault.
*/
public static final String FAULT = "fault"; // NOI18N
}
/**
* Listener which can be attached to the {@link MessagesService} and will be
* notified about messages as they pass through the Fuji runtime.
*/
public interface MessagesListener {
/**
* Invoked by the runtime when an event occurs, that is accepted by the
* filter which was supplied at listener attach time.
*
* @param service service that generated the event.
* @param location message location relative to the service.
* @param type type of the message.
* @param message the message object.
* @param relations identifiers of the messages that are related to the
* current one. The keys in this map are relation types, the list in
* the map value lists the message identifiers.
*/
void onMessage(
QName service,
String location,
String type,
Object message,
Map<String, List<String>> relations);
}
/**
* An instance of this class should be supplied when attaching a
* {@link MessagesListener} to the runtime, it will be used to define which
* events should be received by the listener and which should be skipped.
*/
public interface MessagesFilter {
/**
* Defines whether the given event should be passed through to the
* listener.
*
* @param service service that generated the event.
* @param location message location relative to the service.
* @param type type of the message.
* @param message the message object.
* @param relations identifiers of the messages that are related to the
* current one. The keys in this map are relation types, the list in
* the map value lists the message identifiers.
* @return <kbd>true</kbd> if the event should be passed to the listener,
* <kbd>false</kbd> otherwise.
*/
boolean accept(
QName service,
String location,
String type,
Object message,
Map<String, List<String>> relations);
}
}}}
The API oriented towards the components is very simple. It could be a single method in the {{MessagingService}}, or in a separate class:
{{{
/**
* Forwards the message event to the listeners attached to the Fuji runtime.
*
* @param service service that generated the event.
* @param location message location relative to the service.
* @param type type of the message.
* @param message the message object.
* @param relations identifiers of the messages that are related to the
* current one. The keys in this map are relation types, the list in
* the map value lists the message identifiers.
*/
void notifyListeners(
QName service,
MessageLocation location,
String type,
Object message,
Map<String, List<String>> relations);
}}}
! Questions
* Shouldn't we combine {{MessagesListener}} and {{MessagesFilter}}?
!! Known issues and questions
* There should be a way to somehow identify the implicit routes. Nothing is known about them at the tooling level, so for now we simply ignore these events. Whether we should continue to do so, or add some support for the implicit routes is an open question.
* Debugging of the component code itself. For the components whose "code" is exposed (e.g. BPEL, JRuby) it would be nice to be able to debug this code as well, thus introducing another action alongside with "Step by Message": "Step Into". We'd need a more or less common API for that as well, if we ever decide to pursue this direction. It is already partially possible with the service-specific checkpoints, but the overall API is too message-centric to be useful enough for this task. However, given that the message object is defined quite generically, it should be possible to pass in the internal service execution context.

JSPWiki v2.4.100
[RSS]
« Home Index Changes Prefs
This page (revision-5) was last changed on 25-Jul-09 15:52 PM, -0700 by KirillSorokin