Please note: Although this question has to do with the popular Dropwizard Metrics library and its Scala API analog, Metrics Scala, this is -- at its core -- strictly a Scala question. As such, I believe any knowledgeable Scala dev can answer this!
I am fairly new to Scala and am trying to build a simple app that will leverage this Metrics-Scala library (which again is the Scala API for DW Metrics). I found a very useful GitHub project showing how to setup Metrics-Scala in the real world, and the source file I'm referencing below can be found here.
I cut and diced that source file into a much smaller, simpler version to illustrate my question:
object Metrics extends App {
val metricRegistry = new com.codahale.metrics.MetricRegistry()
val healthCheckRegistry = new com.codahale.metrics.health.HealthCheckRegistry()
ConsoleReporter.forRegistry(metricRegistry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build().start(10, TimeUnit.SECONDS)
run()
while(true){}
def run() {
new TimerExample().longRunningInstrumentedMethod()
spawn {
val gaugeExample = new RandomNumberGaugeExample()
while (true) {
Thread.sleep(500)
gaugeExample.fetchingRandomNumber()
}
}
}
}
trait Instrumented extends InstrumentedBuilder {
val metricRegistry = Metrics.metricRegistry
}
class RandomNumberGaugeExample() extends Instrumented {
def fetchingRandomNumber(): Int = {
metrics.gauge("random-number") {
Math.abs(new Random().nextInt() % 1000)
}.value
}
}
My concerns are with this mysterious metrics
object and its usage.
I understand that RandomNumberGaugeExample
inherits a metricsRegistry
instance because it extends Instrumented
. But I'm not seeing where that metrics
instance is defined, what type it is, and how RandomNumberGaugeExample
gets asscess to it. Wouldn't RandomNumberGaugeExample
just have access to a metricsRegistry
?!
Also what is this devilry:
metrics.gauge("random-number") {
Math.abs(new Random().nextInt() % 1000)
}.value
How does metrics.guage
return an integral value?
Instrumented
extends InstrumentedBuilder
, which is where we find metrics
. metrics
is a MetricsBuilder
.
As for metrics.gauge
, let's look at the gauge
method:
def gauge[A](name: String, scope: String = null)(f: => A): Gauge[A] = {
wrapDwGauge(metricNameFor(name, scope), new DropwizardGauge[A] { def getValue: A = f })
}
This method has two parameter lists. The second parameter list, (f: => A)
has a call-by-name argument named f
that is of type A
. A new DropwizardGauge
is created with f
and passed to wrapDwGauge
, which creates a new Gauge
instance. So the following devilry...
metrics.gauge("random-number") {
Math.abs(new Random().nextInt() % 1000)
}.value
...is basically calling the gauge
method, passing it two arguments (the String
"random-number"
and the Int
result of Math.abs(new Random().nextInt() % 1000)
), then calling .value
on the result. The .value
returns an Int
, because as we can see here, .value
just calls the getValue
method on the created DropwizardGauge
.