Skip to content

Commit

Permalink
Merge pull request #288 from MAIF/issue-282-prometheus
Browse files Browse the repository at this point in the history
Additional prometheus metrics
  • Loading branch information
larousso authored Sep 20, 2019
2 parents 330ca2d + 098e468 commit cab32cd
Show file tree
Hide file tree
Showing 15 changed files with 215 additions and 22 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ReleaseTransformations._

name := """izanami"""
organization := "fr.maif"
scalaVersion := "2.12.8"
scalaVersion := "2.12.9"

lazy val root = (project in file("."))
.aggregate(
Expand Down
2 changes: 1 addition & 1 deletion example/example-play/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ lazy val `example-play` = (project in file("."))
.enablePlugins(NoPublish)
.disablePlugins(BintrayPlugin)

scalaVersion := "2.12.8"
scalaVersion := "2.12.9"

val akkaVersion = "2.5.21"

Expand Down
2 changes: 1 addition & 1 deletion example/example-spring/build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
organization := "fr.maif"
name := "example-spring"

scalaVersion := "2.12.8"
scalaVersion := "2.12.9"

mainClass := Some("izanami.example.Application")

Expand Down
2 changes: 1 addition & 1 deletion izanami-clients/jvm/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ val disabledPlugins = if (sys.env.get("TRAVIS_TAG").filterNot(_.isEmpty).isDefin
Seq(RevolverPlugin, BintrayPlugin)
}

scalaVersion := "2.12.8"
scalaVersion := "2.12.9"

val akkaVersion = "2.5.23"
val akkaHttpVersion = "10.1.8"
Expand Down
2 changes: 1 addition & 1 deletion izanami-documentation/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sbt.project

scalaVersion := "2.12.8"
scalaVersion := "2.12.9"

lazy val `izanami-documentation` = (project in file("."))
.enablePlugins(ParadoxPlugin, DitaaPlugin)
Expand Down
5 changes: 5 additions & 0 deletions izanami-server/app/IzanamiLoader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class IzanamiLoader extends ApplicationLoader {
}

package object modules {
import scala.concurrent.Future

class IzanamiComponentsInstances(context: Context)
extends BuiltInComponentsFromContext(context)
Expand Down Expand Up @@ -129,6 +130,10 @@ package object modules {
*> patchs.run().ignore
)

applicationLifecycle.addStopHook { () =>
Future(globalContext.prometheusRegistry.clear())
}

lazy val homeController: HomeController = wire[HomeController]
lazy val globalScripController: GlobalScriptController = wire[GlobalScriptController]
lazy val configController: ConfigController = wire[ConfigController]
Expand Down
2 changes: 1 addition & 1 deletion izanami-server/app/controllers/MetricController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class MetricController(AuthAction: ActionBuilder[AuthContext, AnyContent], cc: C
req match {
case Accepts.Json =>
Ok(metrics.jsonExport).withHeaders("Content-Type" -> "application/json")
case Prometheus =>
case Prometheus() =>
Ok(metrics.prometheusExport)
case _ =>
Ok(metrics.defaultHttpFormat)
Expand Down
7 changes: 6 additions & 1 deletion izanami-server/app/domains/feature/feature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import store._
import zio.{RIO, ZIO}
import domains.{AuthInfo, AuthInfoModule}
import java.time.LocalTime
import metrics.Metrics
import metrics.MetricsService

sealed trait Strategy

Expand Down Expand Up @@ -149,6 +151,7 @@ object FeatureService {
feature <- jsResultToError(created.validate[Feature])
authInfo <- AuthInfo.authInfo
_ <- EventStore.publish(FeatureCreated(id, feature, authInfo = authInfo))
_ <- MetricsService.incFeatureCreated(id.key)
} yield feature

def update(oldId: FeatureKey, id: FeatureKey, data: Feature): ZIO[FeatureContext, IzanamiErrors, Feature] =
Expand All @@ -159,6 +162,7 @@ object FeatureService {
feature <- jsResultToError(updated.validate[Feature])
authInfo <- AuthInfo.authInfo
_ <- EventStore.publish(FeatureUpdated(id, oldValue, feature, authInfo = authInfo))
_ <- MetricsService.incFeatureUpdated(id.key)
} yield feature

def delete(id: FeatureKey): ZIO[FeatureContext, IzanamiErrors, Feature] =
Expand All @@ -167,10 +171,11 @@ object FeatureService {
feature <- jsResultToError(deleted.validate[Feature])
authInfo <- AuthInfo.authInfo
_ <- EventStore.publish(FeatureDeleted(id, feature, authInfo = authInfo))
_ <- MetricsService.incFeatureDeleted(id.key)
} yield feature

def deleteAll(query: Query): ZIO[FeatureContext, IzanamiErrors, Unit] =
FeatureDataStore.deleteAll(query)
FeatureDataStore.deleteAll(query) <* MetricsService.incFeatureCreated(query.toString())

def getById(id: FeatureKey): RIO[FeatureContext, Option[Feature]] =
for {
Expand Down
6 changes: 4 additions & 2 deletions izanami-server/app/domains/feature/instances.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import zio.{IO, Task, ZIO}

import scala.util.hashing.MurmurHash3
import java.time.LocalTime
import metrics.MetricsService

object DefaultFeatureInstances {

Expand Down Expand Up @@ -320,7 +321,9 @@ object FeatureInstances {
case f: ReleaseDateFeature => ReleaseDateFeatureInstances.isActive.isActive(f, context)
case f: PercentageFeature => PercentageFeatureInstances.isActive.isActive(f, context)
case f: HourRangeFeature => HourRangeFeatureInstances.isActive.isActive(f, context)
})
}) >>= { checked =>
MetricsService.incFeatureCheckCount(feature.id.key, checked) *> ZIO.succeed(checked)
}
}

implicit val isActive: IsActive[Feature] =
Expand Down Expand Up @@ -355,7 +358,6 @@ object FeatureInstances {
GlobalScriptFeatureInstances.format.reads(o)
case o if (o \ "activationStrategy").asOpt[String].contains(PERCENTAGE) =>
PercentageFeatureInstances.format.reads(o)
GlobalScriptFeatureInstances.format.reads(o)
case o if (o \ "activationStrategy").asOpt[String].contains(HOUR_RANGE) =>
HourRangeFeatureInstances.format.reads(o)
case _ =>
Expand Down
47 changes: 46 additions & 1 deletion izanami-server/app/filters/IzanamiDefaultFilter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,51 @@ import zio.{DefaultRuntime, Runtime, ZIO}

import scala.concurrent.{ExecutionContext, Future}
import scala.util._
import io.prometheus.client.Gauge
import io.prometheus.client.Counter
import metrics.MetricsContext
import metrics.Metrics
import metrics.MetricsService
import io.prometheus.client.Histogram

object PrometheusMetricsHolder {

val prometheursRequestCounter = io.prometheus.client.Counter
.build()
.name("request_count")
.labelNames("http_method", "request_path", "request_status")
.help("Count of http request")
.create()

val prometheursRequestHisto = io.prometheus.client.Histogram
.build()
.name("request_duration_details")
.labelNames("http_method", "request_path")
.help("Duration of http request")
.create()

prometheursRequestCounter.register()
prometheursRequestHisto.register()
}

class IzanamiDefaultFilter[F[_]: Effect](env: Env,
izanamiConfig: IzanamiConfig,
config: DefaultFilter,
apikeyConfig: ApikeyConfig)(
implicit ec: ExecutionContext,
runtime: Runtime[ApiKeyContext],
runtime: Runtime[ApiKeyContext with MetricsContext],
val mat: Materializer
) extends Filter {

import cats.effect.implicits._
import scala.collection.JavaConverters._

private val logger = Logger("filter")
private val decoder = Base64.getDecoder
// private val knownQueryParams = Seq("active", "clientId", "configs", "domains", "experiments", "features", "flat", "name_only", "newLevel",
// "page", "pageSize", "pattern", "patterns", "render", "scripts")

//private val labelNames = Seq("http_method", "request_path", "query_params").sorted.toArray

private val allowedPath: Seq[String] = izanamiConfig.contextPath match {
case "/" => config.allowedPaths
Expand Down Expand Up @@ -70,6 +101,11 @@ class IzanamiDefaultFilter[F[_]: Effect](env: Env,
val startTime: Long = System.currentTimeMillis
val maybeClaim = Try(requestHeader.cookies.get(config.cookieClaim).get.value).toOption

val histoWithLabels =
PrometheusMetricsHolder.prometheursRequestHisto
.labels(requestHeader.method, requestHeader.path)
.startTimer()

val maybeAuthorization = requestHeader.headers
.get("Authorization")
.map(_.replace("Basic ", ""))
Expand Down Expand Up @@ -244,12 +280,21 @@ class IzanamiDefaultFilter[F[_]: Effect](env: Env,
timer.stop()
timerMethod.foreach(_.stop())
timerMethodPath.stop()

PrometheusMetricsHolder.prometheursRequestCounter
.labels(requestHeader.method, requestHeader.path, s"${resp.header.status}")
.inc()
histoWithLabels.observeDuration()

case Failure(e) =>
logger.error(s"Error for request ${requestHeader.method} ${requestHeader.uri}", e)
env.metricRegistry.meter(name("request", "500", "rate")).mark()
timer.stop()
timerMethod.foreach(_.stop())
timerMethodPath.stop()

PrometheusMetricsHolder.prometheursRequestCounter.labels(requestHeader.method, requestHeader.path, "500").inc()
histoWithLabels.observeDuration()
}
result
}
Expand Down
Loading

0 comments on commit cab32cd

Please sign in to comment.