Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial draft for statsD metrics #771

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ val server = project.in(file("cosmos-server"))
libraryDependencies ++=
Deps.bijectionUtil ++
Deps.logback ++
Deps.metrics ++
Deps.metricsStatsD ++
Deps.slf4j ++
Deps.twitterCommons ++
Deps.twitterServer
Expand Down
2 changes: 1 addition & 1 deletion cosmos-server/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %d [%thread] %logger{36}: %msg%n</pattern>
<pattern>%-5level %d [%thread] %logger{36}.%M\(%line\): %msg%n</pattern>
</encoder>
</appender>

Expand Down
26 changes: 22 additions & 4 deletions cosmos-server/src/main/scala/com/mesosphere/cosmos/Cosmos.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.mesosphere.cosmos.handler.ResourceProxyHandler
import com.mesosphere.cosmos.handler.ServiceDescribeHandler
import com.mesosphere.cosmos.handler.ServiceUpdateHandler
import com.mesosphere.cosmos.handler.UninstallHandler
import com.mesosphere.cosmos.metrics.MetricsWrapper
import com.mesosphere.cosmos.repository.PackageCollection
import com.mesosphere.cosmos.repository.PackageSourcesStorage
import com.mesosphere.cosmos.repository.UniverseClient
Expand All @@ -37,6 +38,7 @@ import com.mesosphere.cosmos.service.CustomPackageManagerRouter
import com.mesosphere.cosmos.service.ServiceUninstaller
import com.mesosphere.universe
import com.mesosphere.util.UrlSchemeHeader
import com.readytalk.metrics.StatsDReporter
import io.lemonlabs.uri.Uri
import com.twitter.app.App
import com.twitter.finagle.Http
Expand All @@ -54,6 +56,7 @@ import com.twitter.server.Lifecycle
import com.twitter.server.Stats
import com.twitter.util.Await
import com.twitter.util.Try
import java.util.concurrent.TimeUnit
import org.apache.curator.framework.CuratorFramework
import shapeless.:+:
import shapeless.CNil
Expand All @@ -74,8 +77,11 @@ trait CosmosApp

private[this] lazy val logger = org.slf4j.LoggerFactory.getLogger(getClass)

implicit final val sr: StatsReceiver = new MetricsWrapper()

override def statsReceiver: StatsReceiver = sr

protected final def buildComponents(): Components = {
implicit val sr = statsReceiver

val adminRouter = configureDcosClients().get

Expand All @@ -90,6 +96,21 @@ trait CosmosApp

val universeClient = UniverseClient(adminRouter)
val packageCollection = new PackageCollection(sourcesStorage, universeClient)

// Start the STATSD Reporter.
(statsDHost(), statsDPort(), statsDInterval()) match {
case (Some(statsDHostValue), Some(statsDPortValue), Some(statsDIntervalValue)) =>
StatsDReporter
.forRegistry(MetricsWrapper.metrics)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build(statsDHostValue, statsDPortValue)
.start(statsDIntervalValue.inSeconds.toLong, TimeUnit.SECONDS)
case (None, None, None) => logger.warn("Disabling StatsD reporting")
case (host, port, interval) => throw new IllegalArgumentException(s"Illegal StatsD config : " +
s"Host [$host] Port [$port] Interval [$interval]")
}

new Components(
adminRouter,
zkClient,
Expand All @@ -106,8 +127,6 @@ trait CosmosApp
final def buildHandlers(components: Components): Handlers = {
import components._

implicit val sr = statsReceiver

new Handlers(
// Keep alphabetized
capabilities = new CapabilitiesHandler,
Expand Down Expand Up @@ -156,7 +175,6 @@ trait CosmosApp
tr: ToResponse.Aux[A, Application.Json]
): Unit = {
HttpProxySupport.configureProxySupport()
implicit val sr = statsReceiver

val service = CustomLoggingFilter.andThen(buildService(allEndpoints))
val maybeHttpServer = startServer(service.map { request: Request =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.mesosphere.cosmos.metrics

import com.codahale.metrics.MetricRegistry
import com.twitter.finagle.stats.Counter
import com.twitter.finagle.stats.Gauge
import com.twitter.finagle.stats.Stat
import com.twitter.finagle.stats.StatsReceiver
import com.twitter.finagle.stats.Verbosity

class MetricsWrapper extends StatsReceiver {
import MetricsWrapper._

final val appender = "."

override def repr: AnyRef = this

override def counter(verbosity: Verbosity, name: String*): Counter =
DCounter(name.mkString(appender))

override def stat(verbosity: Verbosity, name: String*): Stat =
DStat(name.mkString(appender))

override def addGauge(verbosity: Verbosity, name: String*)(f: => Float): Gauge = ???
}

object MetricsWrapper {
final val metrics: MetricRegistry = new MetricRegistry

case class DStat(name: String) extends Stat {
final val histogram = metrics.histogram(name)

override def add(value: Float): Unit = histogram.update(value.toLong)
}

case class DCounter(name: String) extends Counter {
final val meter = metrics.meter(name.toString)

override def incr(delta: Long): Unit = meter.mark(delta)
}

}
12 changes: 12 additions & 0 deletions cosmos-server/src/main/scala/com/mesosphere/cosmos/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,17 @@ package cosmos {
3,
"Maximum number of retries on HTTP upstreams (repositories & /resource endpoints)"
)

object statsDHost extends GlobalFlag[Option[String]](
"The StatsD host that can be used to publish StatsD metrics"
)

object statsDPort extends GlobalFlag[Option[Int]](
"The StatsD port that can be used to publish StatsD metrics"
)

object statsDInterval extends GlobalFlag[Option[Duration]](
"Interval to emit StatsD Metrics"
)
// scalastyle:on object.name
}
22 changes: 17 additions & 5 deletions project/Deps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import sbt._

object Deps {

// APLv2.0
val apacheCommons = Seq(
"commons-codec" % "commons-codec" % "1.11"
)

// APLv2.0
val bijection = Seq(
"com.twitter" %% "bijection-core" % V.bijection
Expand Down Expand Up @@ -38,6 +43,16 @@ object Deps {
ExclusionRule("jline", "jline")
))

// APLv2.0
val metrics = Seq(
"io.dropwizard.metrics" % "metrics-core" % V.metrics
)

// APLv2.0
val metricsStatsD = Seq(
"com.readytalk" % "metrics3-statsd" % V.metricsStatsD
)

// MIT
val fastparse = Seq(
"com.lihaoyi" %% "fastparse" % V.fastparse
Expand Down Expand Up @@ -131,11 +146,6 @@ object Deps {
"com.twitter.common" % "quantity" % "0.0.100"
)

// APLv2.0
val apacheCommons = Seq(
"commons-codec" % "commons-codec" % "1.11"
)

}

object V {
Expand All @@ -151,6 +161,8 @@ object V {
val jackson = "2.11.0"
val jsonSchema = "2.2.14"
val logback = "1.2.3"
val metrics = "4.0.5"
val metricsStatsD = "4.2.0"
val mockito = "2.16.0"
val mustache = "0.9.6"
val scalaCheck = "1.14.0"
Expand Down
5 changes: 4 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import sbt.Resolver

resolvers ++= Seq(
Resolver.sbtPluginRepo("releases"),
Resolver.sonatypeRepo("snapshots")
Resolver.sonatypeRepo("snapshots"),
Resolver.bintrayRepo("readytalk", "maven")
)

addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.1")
Expand Down