Edi Weissmann

I code for fun /* and profit */

Yammer Metrics and Playframework

Yammer metrics logo

I love the Yammer metrics library. It’s so handy easy to use and comes with friendly scala wrappers.

Typically I would setup access to a web application’s metrics by dropping the default MetricsServlets into web.xml and mapping them to an unsecured /metricsFtw! url.

With Playframework this servlet/web.xml approach would not work, so here’s the alternative setup I found to work nicely for me.

First, we add the dependencies to Build.scala

1
2
3
4
5
6
7
  val metricsVersion = "2.1.2"
  val metricsCore = "com.yammer.metrics" % "metrics-core" % metricsVersion
  val metricsScala = "com.yammer.metrics" %% "metrics-scala" % metricsVersion

  val appDependencies = Seq(
    /* other deps */ metricsCore, metricsScala
  )

Second, we add code to our components to gather runtime metrics:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package controllers

import play.mvc.Controller
import play.api.mvc.Action
import com.yammer.metrics.scala.Instrumented

object DownloadController extends Controller with Instrumented {

  // measure downloads
  val downloadsCounter = metrics.counter("downloads")

  def download(uuid: String) = Action {
  
  downloadsCounter += 1
  /* actual downloading */
  }
}

Now, we should be able to see the metrics by connecting with jconsole to the sbt-launch.jar run process locally.

To access the metrics data via HTTP, we’ll create a MetricsController that reports the metrics by using the provided ConsoleReporter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package controllers

import play.api.mvc._
import com.yammer.metrics.reporting.ConsoleReporter
import java.io.{PrintStream, ByteArrayOutputStream}

object MetricsController extends Controller {

  def index = Action {

    def metricsAsString() = {
      val baos = new ByteArrayOutputStream()
      val ps = new PrintStream(baos)
      new ConsoleReporter(ps).run()

      ps.flush()
      ps.close()

      new String(baos.toByteArray)
    }

    Ok(metricsAsString())
  }
}

And registered this url in routes.conf

1
2
# Metrics
GET     /metricsFtw!/                   controllers.MetricsController.index()

And that’s it.