All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.co.unclealex.diagnostics.DiagnosticsComponents.scala Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package uk.co.unclealex.diagnostics

import java.net.InetSocketAddress
import java.time.Clock
import java.util.concurrent.TimeUnit

import com.codahale.metrics.MetricFilter
import com.codahale.metrics.graphite.{Graphite, GraphiteReporter}
import com.codahale.metrics.health.{HealthCheck, HealthCheckRegistry}
import com.kenshoo.play.metrics._
import com.typesafe.scalalogging.StrictLogging
import play.api.http.HttpErrorHandler
import play.api.mvc.EssentialFilter
import play.api.{ApplicationLoader, BuiltInComponents, BuiltInComponentsFromContext}
import play.filters.gzip.GzipFilter
import uk.co.unclealex.diagnostics.ConfigurationExtensions._

import scala.concurrent.duration.FiniteDuration
import scala.concurrent.{Await, Future}

trait DiagnosticsComponents extends BuiltInComponents {

  def metricsBearerToken: String = {
    configuration.getOrEnv[String]("metrics token", "metrics.token", "METRICS_TOKEN")
  }

  def healthCheckBearerToken: String = {
    configuration.getOrEnv[String]("health check token", "healthcheck.token", "HEALTHCHECK_TOKEN")
  }

  def clock: Clock

  // Provided

  def secureMetricsController: SecureMetricsController


}

abstract class DiagnosticsFromContext(
                                       context: ApplicationLoader.Context,
                                       val name: String) extends BuiltInComponentsFromContext(context) with StrictLogging
  with DiagnosticsComponents {

  private lazy val metrics: Metrics = new MetricsImpl(applicationLifecycle, configuration)

  private lazy val healthCheckRegistry: HealthCheckRegistry = new HealthCheckRegistry()

  applicationLifecycle.addStopHook(() => Future.successful(healthCheckRegistry.shutdown()))

  def registerHealthCheck(healthCheckName: String, healthCheck: HealthCheck): Unit = {
    logger.info(s"Registering health check $healthCheckName")
    healthCheckRegistry.register(healthCheckName, healthCheck)
  }

  def registerHealthCheck(healthCheckName: String, healthCheck: () => Future[String], duration: FiniteDuration): Unit = {
    val actualHealthCheck: HealthCheck = () => {
      try {
        HealthCheck.Result.healthy(Await.result(healthCheck(), duration))
      }
      catch {
        case exception: Throwable => HealthCheck.Result.unhealthy(exception)
      }
    }
    registerHealthCheck(healthCheckName, actualHealthCheck)
  }

  val maybeGraphiteHost: Option[String] =
    configuration.getOptional[String]("metrics.graphite.host")
  maybeGraphiteHost.foreach { graphiteHost =>
    val graphitePort: Int =
      configuration.getOptional[Int]("metrics.graphite.port").getOrElse(2003)
    logger.info(s"Sending metrics to $graphiteHost:$graphitePort")
    val graphite = new Graphite(new InetSocketAddress(graphiteHost, graphitePort))
    val reporter: GraphiteReporter = GraphiteReporter.
      forRegistry(metrics.defaultRegistry).
      prefixedWith(name).
      convertRatesTo(TimeUnit.SECONDS).
      convertDurationsTo(TimeUnit.MILLISECONDS).
      filter(MetricFilter.ALL).
      build(graphite)
    reporter.start(1, TimeUnit.MINUTES)
    applicationLifecycle.addStopHook(() => Future.successful(reporter.stop()))
  }

  lazy val secureMetricsController: SecureMetricsController = {
    val metricsController: MetricsController = new MetricsController(metrics, controllerComponents)
    new SecureMetricsController(metricsController, metricsBearerToken, controllerComponents)
  }

  lazy val healthCheckController =
    new HealthCheckController(healthCheckRegistry, healthCheckBearerToken, controllerComponents)

  override def httpFilters: Seq[EssentialFilter] = {
    val metricsFilter: MetricsFilter = new MetricsFilterImpl(metrics) {
      override def labelPrefix: String = DiagnosticsFromContext.this.name
    }
    val accessLoggingFilter = new AccessLoggingFilter(clock)
    Seq(accessLoggingFilter, metricsFilter, new GzipFilter())
  }

  override lazy val httpErrorHandler: HttpErrorHandler = new JsonErrorHandler(environment)

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy