Skip to content
This repository was archived by the owner on Mar 16, 2025. It is now read-only.

Commit 1152ffe

Browse files
authored
Split dropwizard v4 and v5 (#85)
* Split dropwizard v4 and v5 * Ignre dimensions and log warning
1 parent 8eaedf8 commit 1152ffe

File tree

20 files changed

+628
-61
lines changed

20 files changed

+628
-61
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Split dropwizard v4 and v5. v4 being the default.
56
- Fix bug when HttpEntity.Default is used with HTTP/1.0 protocol
67

78
## 1.4.1 (2020-12-14)

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,18 +233,21 @@ See datadog's [documentation](https://github.com/dataDog/java-dogstatsd-client)
233233
| connections | connections |
234234
| connections active | connections.active |
235235

236-
**Important**: The `DropwizardRegistry` works with tags. This feature is only supported since dropwizard `v5`.
236+
**Important**: The `DropwizardRegistry` does not support labels.
237+
This feature will be available with dropwizard `v5`, which development is paused at the moment.
237238

238239
Add to your `build.sbt`:
239240

240241
```scala
241242
libraryDependencies += "fr.davit" %% "akka-http-metrics-dropwizard" % <version>
243+
// or for dropwizard v5
244+
libraryDependencies += "fr.davit" %% "akka-http-metrics-dropwizard-v5" % <version>
242245
```
243246

244247
Create your registry
245248

246249
```scala
247-
import io.dropwizard.metrics5.MetricRegistry
250+
import com.codahale.metrics.MetricRegistry
248251
import fr.davit.akka.http.metrics.core.HttpMetricsSettings
249252
import fr.davit.akka.http.metrics.dropwizard.{DropwizardRegistry, DropwizardSettings}
250253

@@ -263,15 +266,15 @@ val route = (get & path("metrics"))(metrics(registry))
263266
```
264267

265268
All metrics from the dropwizard metrics registry will be exposed.
266-
You can find some external exporters [here](https://github.com/dropwizard/metrics/tree/5.0-development). For instance,
269+
You can find some external exporters [here](https://github.com/dropwizard/metrics/). For instance,
267270
to expose some JVM metrics, you have to add the dedicated dependency and register the metrics set into your collector registry:
268271

269272
```sbt
270-
libraryDependencies += "io.dropwizard.metrics5" % "metrics-jvm" % <version>
273+
libraryDependencies += "com.codahale.metrics" % "metrics-jvm" % <version>
271274
```
272275

273276
```scala
274-
import io.dropwizard.metrics5.jvm._
277+
import com.codahale.metrics.jvm._
275278

276279
val dropwizard: MetricRegistry = ... // your dropwizard registry
277280
dropwizard.register("jvm.gc", new GarbageCollectorMetricSet())

build.sbt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ lazy val commonSettings = Defaults.itSettings ++
2323
Seq(
2424
organization := "fr.davit",
2525
organizationName := "Michel Davit",
26-
version := "1.4.2-SNAPSHOT",
26+
version := "1.5.0-SNAPSHOT",
2727
crossScalaVersions := (ThisBuild / crossScalaVersions).value,
2828
scalaVersion := crossScalaVersions.value.head,
2929
scalacOptions ~= filterScalacOptions,
@@ -102,6 +102,7 @@ lazy val `akka-http-metrics-dropwizard` = (project in file("dropwizard"))
102102
libraryDependencies ++= Seq(
103103
Dependencies.dropwizardCore,
104104
Dependencies.dropwizardJson,
105+
Dependencies.scalaLogging,
105106
Dependencies.Provided.akkaStream,
106107
Dependencies.Test.akkaHttpJson,
107108
Dependencies.Test.akkaHttpTestkit,
@@ -115,6 +116,27 @@ lazy val `akka-http-metrics-dropwizard` = (project in file("dropwizard"))
115116
)
116117
)
117118

119+
lazy val `akka-http-metrics-dropwizard-v5` = (project in file("dropwizard-v5"))
120+
.configs(IntegrationTest)
121+
.dependsOn(`akka-http-metrics-core`)
122+
.settings(commonSettings: _*)
123+
.settings(
124+
libraryDependencies ++= Seq(
125+
Dependencies.dropwizardV5Core,
126+
Dependencies.dropwizardV5Json,
127+
Dependencies.Provided.akkaStream,
128+
Dependencies.Test.akkaHttpJson,
129+
Dependencies.Test.akkaHttpTestkit,
130+
Dependencies.Test.akkaSlf4j,
131+
Dependencies.Test.akkaStreamTestkit,
132+
Dependencies.Test.akkaTestkit,
133+
Dependencies.Test.dropwizardV5Jvm,
134+
Dependencies.Test.logback,
135+
Dependencies.Test.scalaCollectionCompat,
136+
Dependencies.Test.scalaTest
137+
)
138+
)
139+
118140
lazy val `akka-http-metrics-graphite` = (project in file("graphite"))
119141
.configs(IntegrationTest)
120142
.dependsOn(`akka-http-metrics-core`)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
akka {
2+
loggers = ["akka.event.slf4j.Slf4jLogger"]
3+
loglevel = "DEBUG"
4+
logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
5+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<configuration debug="false">
4+
<appender name="file" class="ch.qos.logback.core.FileAppender">
5+
<file>./target/akka-http-metrics-dropwizard.it-test.log</file>
6+
<append>false</append>
7+
<encoder>
8+
<pattern>%date{HH:mm:ss} %-5level %logger{0} {%class %method} - %msg%n</pattern>
9+
</encoder>
10+
</appender>
11+
12+
<root level="DEBUG">
13+
<appender-ref ref="file"/>
14+
</root>
15+
</configuration>
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2019 Michel Davit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package fr.davit.akka.http.metrics.dropwizard
18+
19+
import java.util.concurrent.TimeUnit
20+
21+
import akka.actor.ActorSystem
22+
import akka.http.scaladsl.Http
23+
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
24+
import akka.http.scaladsl.model.{HttpRequest, StatusCodes, Uri}
25+
import akka.http.scaladsl.server.Directives._
26+
import akka.http.scaladsl.server.Route
27+
import akka.http.scaladsl.unmarshalling.Unmarshal
28+
import akka.testkit.TestKit
29+
import fr.davit.akka.http.metrics.core.HttpMetrics._
30+
import fr.davit.akka.http.metrics.core.scaladsl.server.HttpMetricsDirectives._
31+
import fr.davit.akka.http.metrics.dropwizard.marshalling.DropwizardMarshallers._
32+
import io.dropwizard.metrics5.MetricRegistry
33+
import io.dropwizard.metrics5.jvm.{CachedThreadStatesGaugeSet, GarbageCollectorMetricSet, MemoryUsageGaugeSet}
34+
import org.scalatest.BeforeAndAfterAll
35+
import org.scalatest.concurrent.ScalaFutures
36+
import org.scalatest.flatspec.AnyFlatSpecLike
37+
import org.scalatest.matchers.should.Matchers
38+
import org.scalatest.time.{Millis, Seconds, Span}
39+
import spray.json.{DefaultJsonProtocol, JsValue}
40+
41+
import scala.concurrent.duration._
42+
43+
class DropwizardMetricsItSpec
44+
extends TestKit(ActorSystem("DropwizardMetricsItSpec"))
45+
with AnyFlatSpecLike
46+
with Matchers
47+
with ScalaFutures
48+
with BeforeAndAfterAll
49+
with SprayJsonSupport
50+
with DefaultJsonProtocol {
51+
52+
implicit val defaultPatience = PatienceConfig(timeout = Span(10, Seconds), interval = Span(500, Millis))
53+
54+
private case class JsonResponse(metrics: Map[String, JsValue])
55+
implicit private val metricsFormat = jsonFormat1(JsonResponse)
56+
57+
override def afterAll(): Unit = {
58+
Http().shutdownAllConnectionPools()
59+
TestKit.shutdownActorSystem(system)
60+
}
61+
62+
"DropwizardMetrics" should "expose external metrics" in {
63+
val settings = DropwizardSettings.default
64+
val dropwizard: MetricRegistry = new MetricRegistry()
65+
dropwizard.register("jvm.gc", new GarbageCollectorMetricSet())
66+
dropwizard.register("jvm.threads", new CachedThreadStatesGaugeSet(10, TimeUnit.SECONDS))
67+
dropwizard.register("jvm.memory", new MemoryUsageGaugeSet())
68+
69+
val registry = DropwizardRegistry(dropwizard, settings)
70+
71+
val route: Route = (get & path("metrics"))(metrics(registry))
72+
73+
val binding = Http()
74+
.newMeteredServerAt("localhost", 0, registry)
75+
.bindFlow(route)
76+
.futureValue
77+
78+
val uri = Uri("/metrics")
79+
.withScheme("http")
80+
.withAuthority(binding.localAddress.getHostString, binding.localAddress.getPort)
81+
val request = HttpRequest().withUri(uri)
82+
83+
val response = Http()
84+
.singleRequest(request)
85+
.futureValue
86+
87+
response.status shouldBe StatusCodes.OK
88+
val body = Unmarshal(response).to[JsonResponse].futureValue
89+
90+
body.metrics.keys.filter(_.startsWith("jvm.gc")) should not be empty
91+
body.metrics.keys.filter(_.startsWith("jvm.memory")) should not be empty
92+
body.metrics.keys.filter(_.startsWith("jvm.threads")) should not be empty
93+
94+
binding.terminate(30.seconds).futureValue
95+
}
96+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2019 Michel Davit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package fr.davit.akka.http.metrics.dropwizard
18+
19+
import fr.davit.akka.http.metrics.core.{Counter, Dimension, Gauge, Histogram, Timer}
20+
import io.dropwizard.metrics5.{MetricName, MetricRegistry}
21+
22+
import scala.concurrent.duration.FiniteDuration
23+
24+
object DropwizardMetrics {
25+
26+
implicit class RichMetricsName(val metricName: MetricName) extends AnyVal {
27+
28+
def tagged(dimensions: Seq[Dimension]): MetricName =
29+
metricName.tagged(dimensions.flatMap(d => Seq(d.key, d.value)): _*)
30+
31+
}
32+
}
33+
34+
abstract class DropwizardMetrics(namespace: String, name: String) {
35+
protected lazy val metricName: MetricName = MetricName.build(namespace, name)
36+
}
37+
38+
class DropwizardCounter(namespace: String, name: String)(implicit registry: MetricRegistry)
39+
extends DropwizardMetrics(namespace, name)
40+
with Counter {
41+
42+
import DropwizardMetrics._
43+
44+
override def inc(dimensions: Seq[Dimension] = Seq.empty): Unit = {
45+
registry.counter(metricName.tagged(dimensions)).inc()
46+
}
47+
}
48+
49+
class DropwizardGauge(namespace: String, name: String)(implicit registry: MetricRegistry)
50+
extends DropwizardMetrics(namespace, name)
51+
with Gauge {
52+
53+
import DropwizardMetrics._
54+
55+
override def inc(dimensions: Seq[Dimension] = Seq.empty): Unit = {
56+
registry.counter(metricName.tagged(dimensions)).inc()
57+
}
58+
59+
override def dec(dimensions: Seq[Dimension] = Seq.empty): Unit = {
60+
registry.counter(metricName.tagged(dimensions)).dec()
61+
}
62+
}
63+
64+
class DropwizardTimer(namespace: String, name: String)(implicit registry: MetricRegistry)
65+
extends DropwizardMetrics(namespace, name)
66+
with Timer {
67+
68+
import DropwizardMetrics._
69+
70+
override def observe(duration: FiniteDuration, dimensions: Seq[Dimension] = Seq.empty): Unit = {
71+
registry.timer(metricName.tagged(dimensions)).update(duration.length, duration.unit)
72+
}
73+
}
74+
75+
class DropwizardHistogram(namespace: String, name: String)(implicit registry: MetricRegistry)
76+
extends DropwizardMetrics(namespace, name)
77+
with Histogram {
78+
79+
import DropwizardMetrics._
80+
81+
override def update[T](value: T, dimensions: Seq[Dimension] = Seq.empty)(implicit numeric: Numeric[T]): Unit = {
82+
registry.histogram(metricName.tagged(dimensions)).update(numeric.toLong(value))
83+
}
84+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2019 Michel Davit
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package fr.davit.akka.http.metrics.dropwizard
18+
19+
import fr.davit.akka.http.metrics.core.{HttpMetricsSettings, _}
20+
import io.dropwizard.metrics5.MetricRegistry
21+
22+
object DropwizardRegistry {
23+
24+
def apply(
25+
registry: MetricRegistry = new MetricRegistry(),
26+
settings: HttpMetricsSettings = DropwizardSettings.default
27+
): DropwizardRegistry = {
28+
new DropwizardRegistry(settings)(registry)
29+
}
30+
}
31+
32+
class DropwizardRegistry(settings: HttpMetricsSettings)(implicit val underlying: MetricRegistry)
33+
extends HttpMetricsRegistry(settings) {
34+
35+
lazy val requests: Counter = new DropwizardCounter(settings.namespace, settings.metricsNames.requests)
36+
lazy val requestsActive: Gauge = new DropwizardGauge(settings.namespace, settings.metricsNames.requestsActive)
37+
lazy val requestsFailures: Counter = new DropwizardCounter(settings.namespace, settings.metricsNames.requestsFailures)
38+
lazy val requestsSize: Histogram = new DropwizardHistogram(settings.namespace, settings.metricsNames.requestsSize)
39+
lazy val responses: Counter = new DropwizardCounter(settings.namespace, settings.metricsNames.responses)
40+
lazy val responsesErrors: Counter = new DropwizardCounter(settings.namespace, settings.metricsNames.responsesErrors)
41+
lazy val responsesDuration: Timer = new DropwizardTimer(settings.namespace, settings.metricsNames.responsesDuration)
42+
lazy val responsesSize: Histogram = new DropwizardHistogram(settings.namespace, settings.metricsNames.responsesSize)
43+
lazy val connections: Counter = new DropwizardCounter(settings.namespace, settings.metricsNames.connections)
44+
lazy val connectionsActive: Gauge = new DropwizardGauge(settings.namespace, settings.metricsNames.connectionsActive)
45+
}

0 commit comments

Comments
 (0)