【问题标题】:Where is this mysterious Scala object coming from?这个神秘的 Scala 物体来自哪里?
【发布时间】:2017-07-21 18:19:06
【问题描述】:

请注意:虽然这个问题与流行的 Dropwizard Metrics 库及其类似的 Scala API 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.guage如何返回整数值?

【问题讨论】:

    标签: scala dropwizard metrics


    【解决方案1】:

    Instrumented 扩展了InstrumentedBuilder,这是我们找到metrics 的地方。 metricsMetricsBuilder

    至于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 返回一个Int,因为我们可以看到here.value 只是在创建的DropwizardGauge 上调用getValue 方法。

    【讨论】:

      【解决方案2】:

      我了解 RandomNumberGaugeExample 继承了一个 metricsRegistry 实例,因为它扩展了 Instrumented。但是我没有看到该指标实例的定义位置,它是什么类型,以及 RandomNumberGaugeExample 如何访问它。 RandomNumberGaugeExample 不是只能访问 metricsRegistry 吗?!

      metrics 实例继承自 InstrumentedBuilder 特征,如源代码所示。

      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
      }
      

      这又是什么鬼……

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-04
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 2013-03-13
        • 1970-01-01
        • 2020-11-10
        • 2013-01-11
        相关资源
        最近更新 更多