Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Merge pull request #7 from stijndehaes/play-2.6
Browse files Browse the repository at this point in the history
Play 2.6
  • Loading branch information
stijndehaes authored Jul 21, 2017
2 parents eac3420 + c517e15 commit efa94bd
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 42 deletions.
8 changes: 7 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
language: scala
scala:
- 2.11.11
- 2.12.2
cache:
directories:
- $HOME/.m2/repository
- $HOME/.sbt
- $HOME/.ivy2
jdk:
- oraclejdk8
script:
- sbt clean coverage test coverageReport
- sbt ++$TRAVIS_SCALA_VERSION clean coverage test coverageReport
after_success:
- sbt coveralls
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,24 @@ Two of these filters are also compatible with the [lagom framework](https://gith
A simple hello world application using these filters can be found in the following repo:
https://github.com/stijndehaes/play-prometheus-filters-example-app

To use the library add the following to you build.sbt
To use the library add the following to you build.sbt:

```scala
libraryDependencies += "com.github.stijndehaes" %% "play-prometheus-filters" % "0.2.0"
libraryDependencies += "com.github.stijndehaes" %% "play-prometheus-filters" % "0.3.0"

```
This version only supports play 2.6.
For more info on play version compatibility see the releases matrix.


#Releases

| Release | Play version |
| :---------- | :----------- |
| 0.1.x | 2.5.x |
| 0.2.x | 2.5.x |
| 0.3.x | 2.6.x |


## The filters

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.github.stijndehaes.playprometheusfilters

import com.google.inject.AbstractModule
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}
import io.prometheus.client.CollectorRegistry

class PrometheusModule extends AbstractModule {
class PrometheusModule extends Module {

override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = Seq(
bind[CollectorRegistry].to(CollectorRegistry.defaultRegistry)
)

override def configure(): Unit = {
bind(classOf[CollectorRegistry]).toInstance(CollectorRegistry.defaultRegistry)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package com.github.stijndehaes.playprometheusfilters.controllers

import akka.util.ByteString
import com.github.stijndehaes.playprometheusfilters.utils.WriterAdapter
import com.google.inject.Inject
import javax.inject._
import play.api.mvc._
import io.prometheus.client.CollectorRegistry
import io.prometheus.client.exporter.common.TextFormat
import play.api.http.HttpEntity
import play.api.mvc._

class PrometheusController @Inject()(registry: CollectorRegistry) extends Controller {
class PrometheusController @Inject()(registry: CollectorRegistry, cc: ControllerComponents) extends AbstractController(cc) {

def getMetrics = Action {
val samples = new StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import akka.stream.Materializer
import com.google.inject.{Inject, Singleton}
import io.prometheus.client.{CollectorRegistry, Histogram}
import play.api.mvc.{Filter, RequestHeader, Result}
import play.api.routing.Router.Tags
import play.api.routing.Router

import scala.concurrent.{ExecutionContext, Future}

Expand All @@ -19,7 +19,11 @@ class RouteLatencyFilter @Inject()(registry: CollectorRegistry) (implicit val ma

def apply(nextFilter: RequestHeader => Future[Result])
(requestHeader: RequestHeader): Future[Result] = {
val requestTimer = requestLatency.labels(requestHeader.tags.getOrElse(Tags.RouteActionMethod, RouteLatencyFilter.unmatchedRoute)).startTimer
val routeLabel = requestHeader.attrs
.get(Router.Attrs.HandlerDef)
.map(_.method)
.getOrElse(RouteLatencyFilter.unmatchedRoute)
val requestTimer = requestLatency.labels(routeLabel).startTimer
nextFilter(requestHeader).map { result =>
requestTimer.observeDuration()
result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import akka.stream.Materializer
import com.google.inject.Inject
import io.prometheus.client.{Collector, CollectorRegistry, Histogram}
import play.api.mvc.{Filter, RequestHeader, Result}
import play.api.routing.Router.Tags
import play.api.routing.Router

import scala.concurrent.{ExecutionContext, Future}

Expand All @@ -24,7 +24,10 @@ class StatusAndRouteLatencyFilter @Inject()(registry: CollectorRegistry) (implic
nextFilter(requestHeader).map { result =>
val endTime = System.nanoTime
val requestTime = endTime - startTime / Collector.NANOSECONDS_PER_SECOND
val routeLabel = requestHeader.tags.getOrElse(Tags.RouteActionMethod, RouteLatencyFilter.unmatchedRoute)
val routeLabel = requestHeader.attrs
.get(Router.Attrs.HandlerDef)
.map(_.method)
.getOrElse(RouteLatencyFilter.unmatchedRoute)
val statusLabel = result.header.status.toString
requestLatency.labels(routeLabel, statusLabel).observe(requestTime)
result
Expand Down
9 changes: 6 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name := "play-prometheus-filters"
organization := "com.github.stijndehaes"

version := "0.2.0"
version := "0.3.0-SNAPSHOT"

lazy val root = (project in file("."))
.enablePlugins(PlayScala)
Expand Down Expand Up @@ -38,14 +38,17 @@ lazy val root = (project in file("."))
</developers>

)
scalaVersion := "2.11.11"
scalaVersion := "2.12.2"

crossScalaVersions := Seq(scalaVersion.value, "2.11.11")

libraryDependencies ++= Seq(
guice,
"io.prometheus" % "simpleclient" % "0.0.23",
"io.prometheus" % "simpleclient_servlet" % "0.0.23"
)

libraryDependencies ++= Seq(
"org.scalatestplus.play" %% "scalatestplus-play" % "2.0.0" % Test,
"org.scalatestplus.play" %% "scalatestplus-play" % "3.0.0" % Test,
"org.mockito" % "mockito-core" % "2.7.22" % Test
)
4 changes: 2 additions & 2 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.15")
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.2")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1")

addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.3.5")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.0")

addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.1.0")
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PrometheusControllerSpec extends PlaySpec with Results with MockitoSugar {
val metricsFamilySample = new MetricFamilySamples("test", Collector.Type.COUNTER, "help", Collections.emptyList())
when(collectorRegistry.metricFamilySamples()).thenReturn(new java.util.Vector(Collections.singleton(metricsFamilySample)).elements)

val client = new PrometheusController(collectorRegistry)
val client = new PrometheusController(collectorRegistry, stubControllerComponents())

val request = FakeRequest(GET, "/metrics")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
package com.github.stijndehaes.playprometheusfilters.filters

import akka.stream.Materializer
import com.github.stijndehaes.playprometheusfilters.mocks.MockController
import io.prometheus.client.CollectorRegistry
import org.mockito.ArgumentMatchers._
import org.mockito.Mockito._
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{MustMatchers, WordSpec}
import org.scalatestplus.play.PlaySpec
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc._
import play.api.test.Helpers._
import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits}

class LatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite {
import scala.concurrent.ExecutionContext.Implicits.global

class LatencyFilterSpec extends PlaySpec with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite {

"Filter constructor" should {
"Add a histogram to the prometheus registry" in {
implicit val mat = app.materializer
val collectorRegistry = mock[CollectorRegistry]
new LatencyFilter(collectorRegistry)(mock[Materializer], defaultContext)
new LatencyFilter(collectorRegistry)
verify(collectorRegistry).register(any())
}
}
Expand All @@ -26,7 +29,7 @@ class LatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar wit
implicit val mat = app.materializer
val filter = new LatencyFilter(mock[CollectorRegistry])
val rh = FakeRequest()
val action = Action(Ok("success"))
val action = new MockController(stubControllerComponents()).ok

await(filter(action)(rh).run())

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package com.github.stijndehaes.playprometheusfilters.filters

import com.github.stijndehaes.playprometheusfilters.mocks.MockController
import io.prometheus.client.CollectorRegistry
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.verify
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{MustMatchers, WordSpec}
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.{Action, _}
import play.api.routing.Router.Tags
import play.api.libs.typedmap.TypedMap
import play.api.mvc._
import play.api.routing.{HandlerDef, Router}
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits}

import scala.concurrent.ExecutionContext.Implicits.global

class RouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite {

private implicit val mat = app.materializer
Expand All @@ -26,8 +30,10 @@ class RouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSuga
"Apply method" should {
"Measure the latency" in {
val filter = new RouteLatencyFilter(mock[CollectorRegistry])
val rh = FakeRequest().withTag(Tags.RouteActionMethod, "test")
val action = Action(Ok("success"))
val rh = FakeRequest().withAttrs( TypedMap(
Router.Attrs.HandlerDef -> HandlerDef(null, null, null, "test", null, null ,null ,null ,null)
))
val action = new MockController(stubControllerComponents()).ok

await(filter(action)(rh).run())

Expand All @@ -44,7 +50,7 @@ class RouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSuga
"Measure the latency for an unmatched route" in {
val filter = new RouteLatencyFilter(mock[CollectorRegistry])
val rh = FakeRequest()
val action = Action(NotFound("error"))
val action = new MockController(stubControllerComponents()).error

await(filter(action)(rh).run())

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package com.github.stijndehaes.playprometheusfilters.filters

import com.github.stijndehaes.playprometheusfilters.mocks.MockController
import io.prometheus.client.CollectorRegistry
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.verify
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{MustMatchers, WordSpec}
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.{Action, Results}
import play.api.routing.Router.Tags
import play.api.libs.typedmap.TypedMap
import play.api.mvc.Results
import play.api.routing.{HandlerDef, Router}
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits}

import scala.concurrent.ExecutionContext.Implicits.global

class StatusAndRouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite {

private implicit val mat = app.materializer
Expand All @@ -26,8 +30,10 @@ class StatusAndRouteLatencyFilterSpec extends WordSpec with MustMatchers with Mo
"Apply method" should {
"Measure the latency" in {
val filter = new StatusAndRouteLatencyFilter(mock[CollectorRegistry])
val rh = FakeRequest().withTag(Tags.RouteActionMethod, "test")
val action = Action(Ok("success"))
val rh = FakeRequest().withAttrs( TypedMap(
Router.Attrs.HandlerDef -> HandlerDef(null, null, null, "test", null, null ,null ,null ,null)
))
val action = new MockController(stubControllerComponents()).ok

await(filter(action)(rh).run())

Expand All @@ -45,7 +51,7 @@ class StatusAndRouteLatencyFilterSpec extends WordSpec with MustMatchers with Mo
"Measure the latency for an unmatched route" in {
val filter = new StatusAndRouteLatencyFilter(mock[CollectorRegistry])
val rh = FakeRequest()
val action = Action(NotFound("error"))
val action = new MockController(stubControllerComponents()).error

await(filter(action)(rh).run())

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.github.stijndehaes.playprometheusfilters.filters

import com.github.stijndehaes.playprometheusfilters.mocks.MockController
import io.prometheus.client.CollectorRegistry
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.verify
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{MustMatchers, WordSpec}
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.{Action, Results}
import play.api.mvc.Results
import play.api.test.Helpers.stubControllerComponents
import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits}

import scala.concurrent.ExecutionContext.Implicits.global

class StatusCounterFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite {

private implicit val mat = app.materializer
Expand All @@ -26,7 +29,7 @@ class StatusCounterFilterSpec extends WordSpec with MustMatchers with MockitoSug
"Count the requests with status" in {
val filter = new StatusCounterFilter(mock[CollectorRegistry])
val rh = FakeRequest()
val action = Action(Ok("success"))
val action = new MockController(stubControllerComponents()).ok

await(filter(action)(rh).run())

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.stijndehaes.playprometheusfilters.mocks

import javax.inject.Inject

import play.api.mvc.{AbstractController, ControllerComponents}

class MockController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {

def ok = Action {
Ok("ok")
}

def error = Action {
NotFound("error")
}

}

0 comments on commit efa94bd

Please sign in to comment.