Metrics

This functionality is available starting in Scalatra 2.4.

Scalatra supports metrics via the metrics and metrics-scala projects.

Setup

In order to make use of this functionality, add scalatra-metrics to your build.sbt:

// for javax
"org.scalatra" %% "scalatra-metrics-javax" % "3.0.0"

// for jakarta
"org.scalatra" %% "scalatra-metrics-jakarta" % "3.0.0"

and mix in the MetricsBootstrap trait into ScalatraBootstrap:

class ScalatraBootstrap extends LifeCycle with MetricsBootstrap {
  override def init(context: ServletContext) =
  {
    // ...
  }
}

Mixing in MetricsBootstrap will provide a default instance of both a MetricRegistry and a HealthCheckRegistry to your application. You can also choose to override one or both if the defaults don’t suit your purpose.

class ScalatraBootstrap extends LifeCycle with MetricsBootstrap {
  override val metricRegistry = ???
  override val healthCheckRegistry = ???
  override def init(context: ServletContext) =
  {
  }
}

Metrics Servlets

Convenience methods to mount the metrics servlets at a specified path from the init method are provided in MetricsSupportExtensions.

import org.scalatra.metrics.MetricsSupportExtensions._

class ScalatraBootstrap extends LifeCycle with MetricsBootstrap {
  override def init(context: ServletContext) =
  {
    context.mountMetricsAdminServlet("/metrics-admin")
    context.mountHealthCheckServlet("/health")
    context.mountMetricsServlet("/metrics")
    context.mountThreadDumpServlet("/thread-dump")
    context.installInstrumentedFilter("/test/*")
  }
}

Details for what each servlet does are provided in the Metrics Servlets Documentation

Metrics Filter

A convenience method is also provided to mount a servlet filter to aggregate response code counts and timings. The parameter passed will specify where to apply the filter. To apply it globally, use /*

class ScalatraBootstrap extends LifeCycle with MetricsBootstrap {
  override def init(context: ServletContext) =
  {
    context.installInstrumentedFilter("/test/*")
  }
}
In its current state, this filter does not handle AsyncContext correctly and will be inaccurate if you are using Futures.

Measuring

In order to record metrics in your servlets, mix in the MetricsSupport trait and call the provided methods:

class TestServlet extends ScalatraServlet with MetricsSupport {
  get("/") {
    timer("timer") {
      // Code that's timed by a timer named "timer"
    }

    // Increments a counter called "counter"
    counter("counter") += 1

    // Increments a histogram called "histogram"
    histogram("histogram") += 1

    // Sets a gauge called "gauge"
    gauge("gauge") {
      "gauge"
    }

    // Sets a meter named "meter"
    meter("meter").mark(1)
  }
}

Health Checks

In order to make use of health checks, mix in the HealthChecksSupport trait and define your health checks:

class TestServlet extends ScalatraServlet with HealthChecksSupport {
  get("/") {
    healthCheck("basic") {
      true
    }

    healthCheck("withMessage", unhealthyMessage = "DEADBEEF") {
      true
    }
  }
}

Advanced

In addition to the provided convenience methods, the full metrics-core, metrics-servlet, metrics-servlets, and metrics-scala libraries are available for import. The default registries are exposed as implicit vals, and so can be accessed directly if needed.