Parfait is a performance monitoring library for Java which extracts metrics and makes them available in a variety of ways (including JMX beans and the open-source cross-platform Performance Co-Pilot).
Parfait requires Java 8.
Parfait consists of several modules:
- A core monitoring subsytem, which defines a series of monitorable values and counters (which can be of any Java type) and some basic operations on these
- Interfaces for exporting these values to various 'data sinks' as they change over time. The parfait project defines a few common data sinks for monitoring the current state of these values, exporting them to JMX and the Performance Co-Pilot (PCP) monitoring system.
- A number of modules built on top of this core system, which enable the collection of metrics from common data sources (such as JDBC drivers and other JMX beans) to provide easy monitoring of existing Java subsystems.
For a rapid deployment, the parfait-agent can be used in unmodified applications using the Java "-javaagent" command line option.
This mode uses many of the parfait modules described below, internally, so that you don't have to use the API right away. It accesses JMX and other metric values available from within the JVM and exports those as PCP Memory Mapped Value (MMV) metrics. This instrumentation mechanism is designed for use in production applications - it is proven, robust and very lightweight.
To build the standalone parfait-agent module, the Maven build contains an extra step:
$ mvn clean package install
$ pushd parfait-agent
$ mvn assembly:single
$ popd
Install to a well-known place:
$ mkdir lib
$ cp parfait-agent/target/parfait-agent-jar-with-dependencies.jar lib/parfait.jar
Ensure the target directory for memory-mapped files has been created according to the security model you wish to use.
Then, to run an application with the parfait-agent loaded:
$ java -javaagent:./lib/parfait.jar MyApplication
Or use the helper script provided:
$ export PARFAIT_HOME=`pwd`
$ ./bin/parfait [.sh|.bat] -- MyApplication
New PCP mmv metrics will then appear automatically for the duration of the instrumented Java application - these metrics can be recorded, charted, used for automated live and historical analysis, and so on, using PCP tools.
$ pminfo --desc --fetch --helptext mmv.MyApplication.java.jvm.compilation
mmv.MyApplication.java.jvm.compilation
Data Type: 64-bit int InDom: PM_INDOM_NULL 0xffffffff
Semantics: counter Units: millisec
Help:
Time spent in the JVM doing Java bytecode compilation
value 489
parfait is, like an ogre, made up of many layers. parfait provides several modules assisting with the various stages of metrics collection and performance monitoring (integration, collection, output), and each module is a separate Maven subproject (and hence, separate .jar artifact). The following diagram illustrates the provided core modules, along with their key responsibilities and some interactions between them:
parfait-core is the main module of parfait. Fundamentally, it defines two things: a set of basic types used to encapsulate monitored values (such as the number of active user sessions, total database query execution count, and so on), and a very simple output mechanism for same. This provides a simple, powerful, and flexible way of collecting values from a variety of sources and collating them to different monitoring systems.
A MonitorableRegistry is merely a collection of monitorable values: a 'suite' of metrics which can be output to a particular source. Most output views on your metrics will take a single MonitorableRegistry as their metric source, and operate on all the metrics within that registry. Think of this as a related group of metrics for a single application; multiple applications in the same JVM, for example, may have completely disparate MonitorableRegistry objects.
Note that most metric values are aware of the default MonitorableRegistry, a singleton for use in situations with a single globally-accessible MonitorableRegistry context.
The most important class in parfait is Monitorable. This encapsulates all the key metadata for an observable monitored value, and can be used by the various output subsystems to display, log, or otherwise use the value in an appropriate way.
A Monitorable has a few important key properties:
-
name
- A machine-readable name for the metric.
- This is freeform text, but is typically of a log4j-style dotted hierarchical String (e.g. java.vm.gc.count). It is recommended to follow this format as later work will likely enable conditional output etc. for different branches of the hierarchy.
-
description
- A human-readable description of the metric's meaning and origin.
-
unit
- A JSR-363 measurement unit for the metric.
- This may or may not be used by various output formats, but is intended to provide additional context and comparisons between units (e.g. between B/s and KB/s)
-
valueSemantics
- The semantics of the individual unit value -- is it a free-running point-in-time value, a constant, or a monotonically increasing counter?
In reality, it is unlikely that you will need to implement Monitorable directly. There are a few simple classes which cover the vast majority of your needs:
-
MonitoredCounter
-
A Monitorable which covers values with increasing-counter semantics.
-
An example is a metric for 'total number of user logins since app startup'.
-
A MonitoredCounter may not be decremented, and should only ever increase over time:
MonitoredCounter counter = new MonitoredCounter("user.logins", "# of user logins since app startup");
// ... more ...
public void logUserOn() { counter.inc(); // ... more ... }
-
-
MonitoredValue
-
A Monitorable which is used for free-running point-in-time values which can be set arbitrarily.
-
For the common cases of integer and long values, the subclasses MonitoredIntValue and MonitoredLongValue are useful shortcuts, and provide increment and decrement methods.
MonitoredIntValue inProgress = new MonitoredIntValue("emails.inprogress", "# of email sends currently in progress", 0);
// ... more ...
public synchronized void sendEmail() { inProgress.inc(); // ... more ... inProgress.dec(); }
public synchronized void cancelInProgressEmails() { // ... more ... inProgress.set(0); }
-
-
PollingMonitoredValue
- Uses a Timer and a callback mechanism to poll for Monitorable values from sources which do not provide asynchronous notifications.
A MonitoringView is the bridge between the core parfait libraries and the various possible output mechanisms.
A particular parfait output library will typically implement its own MonitoringView, which is responsible for initializing the monitoring output and being notified (via a Monitor) of any changes to the Monitorable objects it obtains from the provided MonitorableRegistry.
All binary versions of parfait are synced to the Maven central repository. If you're using Maven for your project, you can automatically add dependencies to your project with no further configuration required. For example, to include the parfait-core library, simply use the POM snippet:
<project>
...
<dependencies>
...
<dependency>
<groupId>io.pcp.parfait</groupId>
<artifactId>parfait-core</artifactId>
<version>0.5.1</version>
</dependency>
...
<dependencies>
...
<project>
If you are not using Maven for your project, the JAR files (including source and Javadoc) may be downloaded from the appropriate subdirectory of the repository's parfait folder.