这个神秘的 Scala 对象来自哪里?

Where is this mysterious Scala object coming from?

请注意:虽然这个问题与流行的 Dropwizard Metrics library and its Scala API analog, Metrics Scala 有关,但从本质上讲,这是一个严格的 Scala 问题。因此,我相信任何知识渊博的 Scala 开发人员都能回答这个问题!


我对 Scala 还很陌生,我正在尝试构建一个简单的应用程序来利用这个 Metrics-Scala 库(这又是用于 DW Metrics 的 Scala API)。我发现了一个非常有用的 GitHub 项目,展示了如何在现实世界中设置 Metrics-Scala,以及我在下面引用的源文件 can be found here.

我将该源文件剪切并切块成一个更小、更简单的版本来说明我的问题:

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
  }
}

我担心的是这个神秘的 metrics 对象及其用法。

我知道 RandomNumberGaugeExample 继承了一个 metricsRegistry 实例,因为它扩展了 Instrumented。但是我没有看到 metrics 实例的定义位置、它的类型以及 RandomNumberGaugeExample 如何访问它。难道 RandomNumberGaugeExample 不能访问 metricsRegistry 吗?!

还有这个恶魔是什么:

metrics.gauge("random-number") {
  Math.abs(new Random().nextInt() % 1000)
}.value

metrics.guagereturn如何取整数值?

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?!

metrics实例继承自InstrumentedBuilder trait,如源码所示。

trait InstrumentedBuilder extends BaseBuilder {
  protected lazy val metricBuilder = new MetricBuilder(metricBaseName, metricRegistry)

  /**
   * The MetricBuilder that can be used for creating timers, counters, etc.
   */
  def metrics: MetricBuilder = metricBuilder

  /**
   * The MetricRegistry where created metrics are registered.
   */
  val metricRegistry: MetricRegistry
}

Also what is this devilry...

Gauge对象定义了一个apply方法:

object Gauge {
  def apply[A](f: => A) = new Gauge[A](new DropwizardGauge[A] {
    def getValue: A = f
  })
}

这允许返回的 Gauge 对象被视为接受一个参数的函数,它本身就是一个 returns 一个值的函数。

为了进一步参考,我推荐 Scala tutorials 中的这些章节。

Instrumented 扩展 InstrumentedBuilder, which is where we find metrics. metrics is a MetricsBuilder.

至于metrics.gauge,我们来看gauge方法:

def gauge[A](name: String, scope: String = null)(f: => A): Gauge[A] = {
  wrapDwGauge(metricNameFor(name, scope), new DropwizardGauge[A] { def getValue: A = f })
}

这个方法有两个参数列表。第二个参数列表 (f: => A) 有一个名为 f 的按名称调用的参数,类型为 A。使用 f 创建一个新的 DropwizardGauge 并传递给 wrapDwGauge,这会创建一个新的 Gauge 实例。所以下面的恶魔...

metrics.gauge("random-number") {
  Math.abs(new Random().nextInt() % 1000)
}.value

...基本上是调用 gauge 方法,向它传递两个参数(String "random-number"Math.abs(new Random().nextInt() % 1000)Int 结果) ,然后对结果调用 .value.value returns 和 Int,因为我们可以看到 here.value 只是在创建的 [=22= 上调用了 getValue 方法].