Producers
Producers allow for custom metrics and events to be added to the Cinnamon Backends. The constructor of a Producer should accept a Backends
parameter. The Backends
interface exposes methods with which it is possible to dynamically add and remove metrics and events via the methods MetricFactory metricsFor(Identity identity)
and EventFactory eventsFor(Identity identity)
. This means that it is possible to create and delete metrics and events in runtime and that these are added to all configured backends.
An alternative to using a Producer is to use a Registrant. Registrant is for when you specifically have existing Coda Hale Metrics MetricSets
. If you’re producing or importing metrics yourself, i.e. not an existing MetricSet
or MetricRegistry
, then Producer is a better choice.
Implementing a Producer
To implement a Producer, complete the steps here below.
Import
Import the Backends
and Producer
interfaces:
- Scala
-
import com.lightbend.cinnamon.backend.Backends import com.lightbend.cinnamon.producer.Producer
- Java
-
import com.lightbend.cinnamon.backend.Backends; import com.lightbend.cinnamon.producer.Producer;
Extend and construct
Extend the Producer
abstract class. The constructor should accept a Backends
parameter, to be able to add metrics and events to Cinnamon:
- Scala
-
class SampleProducer(backends: Backends) extends Producer {
- Java
-
public class SampleProducerJava extends Producer { public SampleProducerJava(Backends backends) { }
Implement stop method
Implement the stop
method to clean up any resources and destroy created metrics:
- Scala
-
override def stop() = { someResource.cleanUp() someLongGauge.destroy() someDoubleGauge.destroy() }
- Java
-
@Override public void stop() { someResource.cleanUp(); someLongGauge.destroy(); someDoubleGauge.destroy(); }
Enable via configuration
Enable the Producer
by adding a configuration section to cinnamon.producers
which contains a producer-class
setting for the fully qualified class name:
- Scala
-
cinnamon { producers += sample-producer sample-producer { producer-class = "sample.producer.SampleProducer" } }
- Java
-
cinnamon { producers += sample-producer sample-producer { producer-class = "sample.producer.SampleProducerJava" } }
Full example
The example below is naive in that it does not provide a whole lot of information in the form of metrics. It does, however, showcase a couple of important parts; the first one being how to write a complete implementation of a Producer, and the second important part is the use of ProvidingGauge
s. The latter means that the value will be fetched when data is being reported, and this frequency is related to how the reporter(s) have been configured. It alleviates you from having to set up any internal scheduler to push data to the metrics backend(s), which, of course, also is a possible solution.
- Scala
-
package sample.producer import com.lightbend.cinnamon.backend.Backends import com.lightbend.cinnamon.producer.Producer import com.lightbend.cinnamon.meta.{ Descriptor, Identity } import com.lightbend.cinnamon.metric.{ DoubleValueProvider, LongValueProvider } class SampleProducer(backends: Backends) extends Producer { val someResource = new SomeResource val resourceIdentity = Identity .createFor("resources", "resource") // category and key .withName("some-resource") .withParent(backends.getCinnamonMeta().getApplicationIdentity()) .build() val metricFactory = backends.metricsFor(resourceIdentity) val someLongGauge = metricFactory.createProvidingGaugeLong( new Descriptor.Builder().withKey("some-long-value").build(), new LongValueProvider { override def currentValue(): Long = someResource.getLongValue } ) val someDoubleGauge = metricFactory.createProvidingGaugeDouble( new Descriptor.Builder().withKey("some-double-value").build(), new DoubleValueProvider { override def currentValue(): Double = someResource.getDoubleValue } ) override def stop() = { someResource.cleanUp() someLongGauge.destroy() someDoubleGauge.destroy() } }
- Java
-
package sample.producer; import com.lightbend.cinnamon.backend.Backends; import com.lightbend.cinnamon.producer.Producer; import com.lightbend.cinnamon.meta.Descriptor; import com.lightbend.cinnamon.meta.Identity; import com.lightbend.cinnamon.metric.MetricFactory; import com.lightbend.cinnamon.metric.ProvidingGaugeDouble; import com.lightbend.cinnamon.metric.ProvidingGaugeLong; public class SampleProducerJava extends Producer { private final SomeResource someResource; private final ProvidingGaugeLong someLongGauge; private final ProvidingGaugeDouble someDoubleGauge; public SampleProducerJava(Backends backends) { this.someResource = new SomeResource(); Identity resourceIdentity = Identity.createFor("resources", "resource") // category and key .withName("some-resource") .withParent(backends.getCinnamonMeta().getApplicationIdentity()) .build(); MetricFactory metricFactory = backends.metricsFor(resourceIdentity); this.someLongGauge = metricFactory.createProvidingGaugeLong( new Descriptor.Builder().withKey("some-long-value").build(), () -> someResource.getLongValue()); this.someDoubleGauge = metricFactory.createProvidingGaugeDouble( new Descriptor.Builder().withKey("some-double-value").build(), () -> someResource.getDoubleValue()); } @Override public void stop() { someResource.cleanUp(); someLongGauge.destroy(); someDoubleGauge.destroy(); } }