Jvm Extra
A runnable to collect the various JVM metrics.
Instrumenting Your JVM Application
Add Dependency
Determine the latest version of the Java client in Maven Central.
Maven
Add a dependency to your pom:
<dependency>
<groupId>com.arpnetworking.metrics.extras</groupId>
<artifactId>jvm-extra</artifactId>
<version>VERSION</version>
</dependency>
The Maven Central repository is included by default.
Gradle
Add a dependency to your build.gradle:
compile group: 'com.arpnetworking.metrics.extras', name: 'jvm-extra', version: 'VERSION'
Add the Maven Central Repository into your build.gradle:
repositories {
mavenCentral()
}
SBT
Add a dependency to your project/Build.scala:
val appDependencies = Seq(
"com.arpnetworking.metrics" % "jvm-extra" % "VERSION"
)
The Maven Central repository is included by default.
Vertx
Users of Vertx need to also depend on the vertx-extra package. The vertx-extra provides the necessary wrappers around the standard Java metrics client to work with the shared data model in Vertx. Special thanks to Gil Markham for contributing this work. For more information please see metrics-vertx-extra/README.md.
JvmMetricsRunnable
The only dependency of the JvmMetricsRunnable is an instance of MetricsFactory from the Java metrics client. By default all defined JVM metrics are collected. Further, any exceptions encountered during collection are logged and swallowed. To instantiate a default JvmMetricsRunnable do the following:
JvmMetricsRunnable.Builder
.newInstance()
.setMetricsFactory(_metricsFactory)
.build();
If you prefer to handle exceptions then you will need to explicitly set the swallowException attribute to false. For example:
JvmMetricsRunnable.Builder
.newInstance()
.setMetricsFactory(metricsFactory)
.setSwallowException(false)
.build();
If you prefer to not collect some metrics then disable those collectors. For example:
JvmMetricsRunnable.Builder()
.newInstance()
.setMetricsFactory(metricsFactory)
.setCollectGarbageCollectionMetrics(false)
.setCollectThreadMetrics(false)
.setCollectPoolMemoryMetrics(false)
.setCollectHeapMemoryMetrics(false)
.build();
Executing with ScheduledExecutorService
Using ScheduledExecutorService, you will only need to schedule the JvmMetricsRunnable with an initial delay and a collection interval in the specified time unit.
import com.arpnetworking.metrics.MetricsFactory;
import com.arpnetworking.metrics.Sink;
import com.arpnetworking.metrics.impl.TsdMetricsFactory;
import com.arpnetworking.metrics.impl.TsdQueryLogSink;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class JvmMetricsCollector {
public static final void main(String[] args) {
// Instantiate a MetricsFactory
final MetricsFactory metricsFactory = TsdMetricsFactory.newInstance("MyService", "MyCluster");
// Create a default JvmMetricsRunnable
final Runnable runnable = new JvmMetricsRunnable.Builder()
.setMetricsFactory(metricsFactory)
.build();
// Schedule JVM metrics collection
final ScheduledExecutorService jvmMetricsCollector = Executors.newSingleThreadScheduledExecutor();
jvmMetricsCollector.scheduleAtFixedRate(
runnable,
0, // Initial delay
500, // Collection interval
TimeUnit.MILLISECONDS);
// Let the collector run for a while before shutting down
Thread.sleep(60000);
jvmMetricsCollector.shutdown();
}
}
Executing with Akka Actor
Create a new actor that inherits from the UntypedActor class. Next, schedule a message on the actor with an initial delay and a collection interval to trigger the metrics collection. One way to do this is to override the preStart hook. Finally, cancel the scheduling when the actor stops. In the example below, we use a String message "COLLECT" to trigger the JVM metrics collection by the actor.
import akka.actor.Cancellable;
import akka.actor.UntypedActor;
import com.arpnetworking.metrics.MetricsFactory;
import com.arpnetworking.metrics.jvm.JvmMetricsRunnable;
import com.arpnetworking.metrics.org.joda.time.Period;
import scala.concurrent.duration.FiniteDuration;
import scala.concurrent.duration.TimeUnit;
public class JvmMetricsCollector extends UntypedActor {
public JvmMetricsCollector(
final Period interval,
final MetricsFactory metricsFactory) {
interval = FiniteDuration.create(
interval.getMillis(),
TimeUnit.MILLISECONDS);
jvmMetricsRunnable = new JvmMetricsRunnable.Builder()
.setMetricsFactory(metricsFactory)
.setSwallowException(false) // Relying on the default akka supervisor strategy here.
.build();
}
@Override
public void preStart() {
cancellable = getContext().system().scheduler().schedule(
FiniteDuration.Zero(), // Initial delay
interval, // Collection interval
self(),
COLLECT_MESSAGE,
getContext().system().dispatcher(),
self());
}
@Override
public void postStop() {
cancellable.cancel();
}
@Override
public void onReceive(final Object message) throws Exception {
if (COLLECT_MESSAGE.equals(message)) {
jvmMetricsRunnable.run();
} else {
unhandled(message);
}
}
private Cancellable cancellable;
private final FiniteDuration interval;
private final Runnable jvmMetricsRunnable;
private static final String COLLECT_MESSAGE = "COLLECT";
}
Executing with Vert.x
Create a new verticle that inherits from the AbstractVerticle class. Next, schedule periodic with the desired collection interval to trigger the metrics collection. Execute the collection as blocking code because the underlying implementation uses JMX to gather JVM information it may perform blocking operations.
import com.arpnetworking.metrics.MetricsFactory;
import com.arpnetworking.metrics.impl.TsdMetricsFactory;
import com.arpnetworking.metrics.jvm.JvmMetricsRunnable;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
public final class MetricsVerticle extends AbstractVerticle {
@Override
public void start(final Future<Void> startFuture) {
// Instantiate a MetricsFactory
final MetricsFactory metricsFactory = TsdMetricsFactory.newInstance("MyService", "MyCluster");
// Create a default JvmMetricsRunnable
final Runnable runnable = new JvmMetricsRunnable.Builder()
.setMetricsFactory(metricsFactory)
.build();
// Schedule JVM metrics collection
this.getVertx().setPeriodic(
jvmMetricsCollectionDuration.toMillis(),
id -> vertx.executeBlocking(future -> {
try {
jvmMetricsRunnable.run();
} finally {
future.complete();
}
},
ignored -> {}));
}
}
Building
Prerequisites:
Building:
metrics-jvm-extra> ./mvnw verify
To use the local version you must first install it locally:
metrics-jvm-extra> ./mvnw install
You can determine the version of the local build from the pom file. Using the local version is intended only for testing or development.
You may also need to add the local repository to your build in order to pick-up the local version:
- Maven - Included by default.
- Gradle - Add mavenLocal() to build.gradle in the repositories block.
- SBT - Add resolvers += Resolver.mavenLocal into project/plugins.sbt.
License
Published under Apache Software License 2.0, see LICENSE
© Groupon Inc., 2015