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 ProvidingGauges. 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(); } }