Custom reporters
You can integrate custom reporters for Coda Hale Metrics. You do so by implementing a simple interface for the reporter lifecycle and enabling it through configuration. This section describes how to integrate custom reporters, and uses the SignalFx reporter as an example.
Cinnamon dependency
First make sure that your build is configured to use the Cinnamon Agent.
Add the Coda Hale Metrics plugin dependency to your build:
- sbt
-
libraryDependencies += Cinnamon.library.cinnamonCHMetrics
- Maven
-
<dependency> <groupId>com.lightbend.cinnamon</groupId> <artifactId>cinnamon-chmetrics</artifactId> <version>2.18.1</version> </dependency>
- Gradle
-
dependencies { implementation group: 'com.lightbend.cinnamon', name: 'cinnamon-chmetrics', version: '2.18.1' }
Example: SignalFx reporter
This section will describe how to set up the SignalFx reporter for your project.
Reporter dependency
The first thing you need to do is to include the reporter of your choice to the build file:
- sbt
-
libraryDependencies += "com.signalfx.public" % "signalfx-codahale" % "0.0.35"
- Maven
-
<dependency> <groupId>com.signalfx.public</groupId> <artifactId>signalfx-codahale</artifactId> <version>0.0.35</version> </dependency>
- Gradle
-
dependencies { implementation group: 'com.signalfx.public', name: 'signalfx-codahale', version: '0.0.35' }
Reporter interface
With the dependency in place the next step is to write the actual code that will be used to wire up the reporter. Lightbend Telemetry provides an API for this and the interface that you should implement is called Reporter
.
public interface Reporter {
/** Life cycle method called when telemetry is initiated. */
void start();
/** Life cycle method called when telemetry is stopped. */
void stop();
}
Reporter imports
First we need to ensure that the required classes are imported.
- Scala
-
import java.util.concurrent.TimeUnit import com.codahale.metrics.MetricRegistry import com.lightbend.cinnamon.chmetrics.reporter.{ Reporter, ReporterContext } import com.signalfx.codahale.reporter.SignalFxReporter
- Java
-
import com.codahale.metrics.MetricRegistry; import com.lightbend.cinnamon.chmetrics.reporter.Reporter; import com.lightbend.cinnamon.chmetrics.reporter.ReporterContext; import com.signalfx.codahale.reporter.SignalFxReporter; import java.util.concurrent.TimeUnit;
Imports explained:
Reporter
: the contract interface that is used by Lightbend Telemetry when loading the external reporterMetricRegistry
: the Coda Hale metric registry containing the data that the reporter will traverse and reportReporterContext
: context information that containscom.typesafe.config.Config
among other things (this is not a mandatory import - see constructors below)SignalFxReporter
: the reporter that you want to use - this will be different for each reporter
Reporter constructor
Lightbend Telemetry expects one of two constructors for a custom reporter. The constructor must accept a MetricRegistry
, and can optionally accept a ReporterContext
. In this example, the constructor uses both parameters:
- Scala
-
class SignalFxMetricReporter(registry: MetricRegistry, context: ReporterContext) extends Reporter {
- Java
-
public SignalFxMetricReporterJava(MetricRegistry registry, ReporterContext context) { init(registry, context); }
If no suitable constructor is available, an exception will be thrown and reporting will be disabled.
ReporterContext interface
The reporter context contains the following information that can come in handy when creating the reporter:
public interface ReporterContext {
LoggingProvider loggingProvider();
Config config();
MetricFilter filter();
ReporterMetadata metadata();
}
LoggingProvider
: a handle to get to logging functionalityConfig
: contains the configuration used when initiating the systemMetricFilter
: the filter associated with this reporter (the default filter if no filter has been defined in the configuration)
Initializing the reporter
As part of the initialization process you should set up the reporter. This section shows how to set up the SignalFx reporter, but how to go about will different for each reporter type.
- Scala
-
private final val period = context.config.getInt("period") private final val token = context.config.getString("auth-token") var reporter: SignalFxReporter = new SignalFxReporter.Builder(registry, token).setFilter(context.filter).build()
- Java
-
private void init(MetricRegistry registry, ReporterContext context) { period = context.config().getInt("period"); String token = context.config().getString("auth-token"); reporter = new SignalFxReporter.Builder(registry, token).setFilter(context.filter()).build(); }
Implementing the lifecycle methods
There are two lifecycle methods for the Reporter
interface that should be implemented. Here we call the corresponding start
and stop
methods on the SignalFx reporter.
- Scala
-
override def start(): Unit = { reporter.start(period, TimeUnit.SECONDS) } override def stop(): Unit = { reporter.stop() reporter = null }
- Java
-
@Override public void start() { reporter.start(period, TimeUnit.SECONDS); } @Override public void stop() { reporter.stop(); reporter = null; }
Full example
Here is the complete example for integrating a SignalFx reporter:
- Scala
-
package sample.reporter import java.util.concurrent.TimeUnit import com.codahale.metrics.MetricRegistry import com.lightbend.cinnamon.chmetrics.reporter.{ Reporter, ReporterContext } import com.signalfx.codahale.reporter.SignalFxReporter class SignalFxMetricReporter(registry: MetricRegistry, context: ReporterContext) extends Reporter { private final val period = context.config.getInt("period") private final val token = context.config.getString("auth-token") var reporter: SignalFxReporter = new SignalFxReporter.Builder(registry, token).setFilter(context.filter).build() override def start(): Unit = { reporter.start(period, TimeUnit.SECONDS) } override def stop(): Unit = { reporter.stop() reporter = null } }
- Java
-
package sample.reporter; import com.codahale.metrics.MetricRegistry; import com.lightbend.cinnamon.chmetrics.reporter.Reporter; import com.lightbend.cinnamon.chmetrics.reporter.ReporterContext; import com.signalfx.codahale.reporter.SignalFxReporter; import java.util.concurrent.TimeUnit; public class SignalFxMetricReporterJava implements Reporter { private SignalFxReporter reporter = null; private int period = 0; public SignalFxMetricReporterJava(MetricRegistry registry, ReporterContext context) { init(registry, context); } private void init(MetricRegistry registry, ReporterContext context) { period = context.config().getInt("period"); String token = context.config().getString("auth-token"); reporter = new SignalFxReporter.Builder(registry, token).setFilter(context.filter()).build(); } @Override public void start() { reporter.start(period, TimeUnit.SECONDS); } @Override public void stop() { reporter.stop(); reporter = null; } }
Wire the reporter in configuration
The last part is to instruct Lightbend Telemetry to use the reporter. You do so by adding it to the configuration file (normally application.conf
).
cinnamon.chmetrics {
reporters += signalfx-reporter
}
cinnamon.akka {
actors {
"/user/*" = {
report-by = class
}
}
}
signalfx-reporter {
reporter-class = "sample.reporter.SignalFxMetricReporter"
auth-token = "SIGNALFX_AUTH_TOKEN"
period = 5
}
Now start your application and it will use the provided reporter to report metrics gathered by Lightbend Telemetry.