Table of Contents
Table of Contents
Copyright © 2006-2007 Nicolas De Loof.
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.
You can get the latest version of this reference documentation as PDF at http://www.jmonit.org/pdf/Reference.pdf
Table of Contents
jMonit is composed by three architectural layers :
The
instrumentation
layer is included in the application code to extract the
datas. To avoid too much intrusion in your code, the
required classes are limited to the
org.jmonit
package, and many of them are simple interfaces.
The computation layer gathers those datas ands builds indicators, like statistics, history, or threshold warnings. The instrumentation and computation layers can collaborate using the feature API, that enable jMonit to accept custom code plugged at runtime.
The formating layer renders the indicators into a user interface. jMonit provides a web UI and a simple way to programmatically collect datas if you need to format them by yourself. The formating layer is based on the Visitor pattern, so the data may be formatted in any format (XML, CSV, PDF...) by simply creating the adequate renderer.
The
org.jmonit
package provides all required classes to instrument you
application code.
The
Monitor
class is used by application to expose state to the monitoring
infrastructure. A Monitor accepts new datas via the
add(long)
method. jMonit does not know the unit used by such data, so be
aware not to mix inconsistent values.
A monitor is identified by a name, that MUST be unique in the
application. A recommended usage is to use the full qualified
class name + some local name to identify a monitor. For example,
the monitor
"com.mycompany.ws.MyServiceEndPoint.doSomeBusiness()"
could be used to monitor the MyService web service endpoint
"doSomeBusiness" method execution. To also monitor SOAP message
weight, you can create another monitor
"com.mycompany.ws.MyServiceEndPoint.doSomeBusiness()-soap"
.
The
Monitoring
class is a utility class to acces jMonit classes. It provides
finders methods to retrieve a monitor by name, tag it, or create
a new Probe for performance computation. All Monitors are
attched to a repository. You can acces the repository from the
Monitoring class, or set a new instance if you want to use a
custom repository implementation.
The monitor can be tagged. A tag is used by the application to group monitors and refine the type of data that is monitored. Tags can reflect data type and units, component that uses the monitor, or whatever you need. For example, a monitor attached to a web service endpoint to gather incomming messages size can be tagged "soap", "ws", "bytes" and "received".
Performance is a main part of monitoring. For this purpose,
jMonit provides the dedicated
Probe
class. A new Probe is created by calling
Probe.start( monitor )
. The convenience static method
Monitoring.start( name )
can be used to get a starter probe in one line. The probe will
compute elapsed time until it gets stopped, after the monitored
code fragmentends. Using a probe automatically tags the monitor
as "perf".
Monitor
is an interface, an the implementation may provide many advanced
features. The default Monitor implementation is built as a
composite : it uses a set of sub-components to compute
indicators about the application state.
Those components MUST implement the interface
org.jmonit.spi.Aggregator
(or extend
org.jmonit.monitors.AbstractAggregator
). Before being used by the composite monitor, they receive the
composite via the
setComposite
initialization method. This method will be called any time a new
aggregator is added or removed to the monitor. The aggregator
may use the composite to acces other aggregators.
Each aggregator receives datas from the composite monitor in the
added(long)
method. They can use this data to compute any indicator or run
any process that can be usefull to monitor the application
state. The
clear()
method is used to reset the aggregator from a management
console. Be aware that some counters may not be set to null in
this method : for example, the
Concurrency
aggregator manages a counter of concurrent active threads that
use the monitor. Also be aware when creating custom aggreagtors
that they are used in a concurrent context. synchronize the
required methods or use
java.util.concurrent
classes to assume thread-safety and data consistency.
Custom aggregators are managed by a
org.jmonit.spi.FeatureManager
implementation (see later section about features). The
default-one uses a properties files in classpath root :
jmonit-features.properties
. This file lists class name of Factories used to create the
aggregators instances. The factory (
org.jmonit.spi.Factory
) is used by jMonit to create new aggregators instance for
monitors on demand.
To avoid your application to depend on jMonit implementation
code, jMonit provides the feature API : Any aggregator of the
composite Monitor can expose a public interface, that we call
"Feature". The instrumented application can use those features
when the default
add(long)
method is not sufficient to expose it's state. This API class is
used as the identifier for aggregators factories.
The
monitor.getFeature(class)
method is used to acces a feature. This method MAY return null,
so allways check the returned object. The class argument is the
expected feature API interface. Thanks to Java5 constructs, the
returned object is safelly casted. The default Monitor
implementation will anto-enhance it's composite to add the
requested feature.
The following code sample demonstrates the feature API usage. Based on an existing monitor, we ask for a feature, dedicated to HTTP status monitoring. The returned object is then used to monitor the current request.
HttpStatus status = monitor.getFeature( HttpStatus.class ); if ( status != null ) { status.setHttpStatus( sc ); }
In many case, the aggregator code is simple and we can use a single class for aggregator and feature (feature is not required to be an interface).
Computed indicators must be rendered to the application administrator. jMonit uses the Visitor pattern to expose the monitor (and its aggregators) datas.
An Aggregator MAY implement the
org.jmonit.reporting.Visitable
interface. In such case, it is reponsible to compute a Map
representation of its state and pass it to the visitor. Some
aggregators may not be visitable, and in such case are ignored.
This can be used for example to create an aggregator that stores
application state on shutdown, but has no data to report.
The Visitor pattern can be used by custom application code to
build a report on the monitoring state, by simply binding a
org.jmonit.reporting.Visitor
implementation to the adequate formatting methods. jMonit uses a
second level of abstraction via the
Renderer
interface. This one is used by the RestServlet to provide
web-oriented rendering.
The RestServlet accepts REST style URIs. The request path is composed as :
/monitors[/tag/.*]/Feature[+Feature]*
/monitors
: all monitors, but only name and tags are returned
/monitors/tag/web
: all monitors tagged as "web"
/monitors/tag/web/Statistics
: all monitors tagged as "web" AND supporting the
"Statistics" feature. The feature datas are also returned
/monitors/tag/web/Statistics+Concurrency
: all monitors tagged as "web" AND supporting both the
"Statistics" and "Concurrency" features.
The data formatting depends on the request "accept" header. It
also considers the request path extension. Based on this, a
renderer instance is used. For example, request to
/monitors/Statistics
with accept header set to
"application/json"
will use the JsonRenderer. Based on this, we can render the
monitored datas in many formats, like XML, CSV, PDF...
jMonit provides a web UI built over the REST+json facility. It uses the prototype js library to parse the JSON result and render datas in a grid. Point your browser to http://myserver/myapp/jMonit/performances.html to see it in action.