diff --git a/jicoco-metrics-jetty/pom.xml b/jicoco-metrics-jetty/pom.xml
deleted file mode 100644
index f45ed952..00000000
--- a/jicoco-metrics-jetty/pom.xml
+++ /dev/null
@@ -1,217 +0,0 @@
-
-
-
-
- 4.0.0
-
-
- org.jitsi
- jicoco-parent
- 1.1-SNAPSHOT
-
-
- jicoco-metrics-jetty
- 1.1-SNAPSHOT
- jicoco-metrics-jetty
- Jitsi Common Components (Metrics Jetty)
-
-
-
- ${project.groupId}
- jicoco-metrics
- ${project.version}
-
-
- org.eclipse.jetty
- jetty-servlet
- ${jetty.version}
-
-
- org.eclipse.jetty
- jetty-servlets
- ${jetty.version}
-
-
- org.eclipse.jetty
- jetty-util
- ${jetty.version}
-
-
- org.glassfish.jersey.containers
- jersey-container-jetty-http
- ${jersey.version}
-
-
- org.glassfish.jersey.containers
- jersey-container-servlet
- ${jersey.version}
-
-
- org.glassfish.jersey.inject
- jersey-hk2
- ${jersey.version}
-
-
-
-
- org.junit.platform
- junit-platform-launcher
- 1.10.0
- test
-
-
- org.junit.jupiter
- junit-jupiter-api
- ${junit.version}
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- ${junit.version}
- test
-
-
- io.kotest
- kotest-runner-junit5-jvm
- ${kotest.version}
- test
-
-
- io.kotest
- kotest-assertions-core-jvm
- ${kotest.version}
- test
-
-
- org.glassfish.jersey.test-framework
- jersey-test-framework-core
- ${jersey.version}
- test
-
-
- junit
- junit
-
-
-
-
- org.glassfish.jersey.test-framework.providers
- jersey-test-framework-provider-jetty
- ${jersey.version}
- test
-
-
- junit
- junit
-
-
-
-
- org.junit.vintage
- junit-vintage-engine
- ${junit.version}
- test
-
-
-
-
-
-
- org.jetbrains.kotlin
- kotlin-maven-plugin
- ${kotlin.version}
-
-
- compile
- compile
-
- compile
-
-
-
- -opt-in=kotlin.ExperimentalStdlibApi
-
-
- ${project.basedir}/src/main/kotlin
- ${project.basedir}/src/main/java
-
-
-
-
- test-compile
- test-compile
-
- test-compile
-
-
-
- -opt-in=kotlin.ExperimentalStdlibApi
-
-
- ${project.basedir}/src/test/kotlin
- ${project.basedir}/src/test/java
-
-
-
-
-
- 11
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.10.1
-
-
-
- default-compile
- none
-
-
-
- default-testCompile
- none
-
-
- java-compile
- compile
-
- compile
-
-
-
- java-test-compile
- test-compile
-
- testCompile
-
-
-
-
- 11
-
- -Xlint:all
-
-
-
-
-
-
diff --git a/jicoco-metrics-jetty/src/main/java/org/jitsi/rest/prometheus/Prometheus.java b/jicoco-metrics-jetty/src/main/java/org/jitsi/rest/prometheus/Prometheus.java
deleted file mode 100644
index 83417306..00000000
--- a/jicoco-metrics-jetty/src/main/java/org/jitsi/rest/prometheus/Prometheus.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright @ 2022 - present 8x8, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.jitsi.rest.prometheus;
-
-import io.prometheus.client.exporter.common.*;
-import jakarta.ws.rs.*;
-import jakarta.ws.rs.core.*;
-import org.jetbrains.annotations.NotNull;
-import org.jitsi.metrics.*;
-
-/**
- * A REST endpoint exposing JVB stats for Prometheus.
- * Any scraper supporting Prometheus' text-based formats ({@code text/plain; version=0.0.4} or OpenMetrics)
- * is compatible with this {@code /metrics} endpoint.
- * JSON is provided when the client performs a request with the 'Accept' header set to {@code application/json}.
- * The response defaults to {@code text/plain; version=0.0.4} formatted output.
- *
- * @see
- * Prometheus' exposition formats
- */
-@Path("/metrics")
-public class Prometheus
-{
- @NotNull
- private final MetricsContainer metricsContainer;
-
- public Prometheus(@NotNull MetricsContainer metricsContainer)
- {
- this.metricsContainer = metricsContainer;
- }
-
- @GET
- @Produces(TextFormat.CONTENT_TYPE_004)
- public String getPrometheusPlainText()
- {
- return metricsContainer.getPrometheusMetrics(TextFormat.CONTENT_TYPE_004);
- }
-
- @GET
- @Produces(TextFormat.CONTENT_TYPE_OPENMETRICS_100)
- public String getPrometheusOpenMetrics()
- {
- return metricsContainer.getPrometheusMetrics(TextFormat.CONTENT_TYPE_OPENMETRICS_100);
- }
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- public String getJsonString()
- {
- return metricsContainer.getJsonString();
- }
-}
diff --git a/jicoco-metrics-jetty/src/test/kotlin/org/jitsi/rest/prometheus/PrometheusTest.kt b/jicoco-metrics-jetty/src/test/kotlin/org/jitsi/rest/prometheus/PrometheusTest.kt
deleted file mode 100644
index 6e587ab3..00000000
--- a/jicoco-metrics-jetty/src/test/kotlin/org/jitsi/rest/prometheus/PrometheusTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.jitsi.rest.prometheus
-
-import io.kotest.matchers.shouldBe
-import io.kotest.matchers.types.shouldBeInstanceOf
-import io.prometheus.client.CollectorRegistry
-import io.prometheus.client.exporter.common.TextFormat
-import jakarta.ws.rs.core.Application
-import jakarta.ws.rs.core.MediaType
-import jakarta.ws.rs.core.Response
-import org.eclipse.jetty.http.HttpStatus
-import org.glassfish.jersey.server.ResourceConfig
-import org.glassfish.jersey.test.JerseyTest
-import org.glassfish.jersey.test.TestProperties
-import org.jitsi.metrics.MetricsContainer
-import org.json.simple.JSONObject
-import org.json.simple.parser.JSONParser
-import org.junit.Test
-
-class PrometheusTest : JerseyTest() {
- private lateinit var metricsContainer: MetricsContainer
- private val baseUrl = "/metrics"
- private val mediaType004 = MediaType("text", "plain", mapOf("charset" to "utf-8", "version" to "0.0.4"))
- private val mediaTypeOpenMetrics =
- MediaType("application", "openmetrics-text", mapOf("charset" to "utf-8", "version" to "1.0.0"))
-
- override fun configure(): Application {
- metricsContainer = MetricsContainer(CollectorRegistry()).apply {
- checkForNameConflicts = false
- registerLongGauge("gauge", "A gauge", 50)
- registerBooleanMetric("boolean", "A boolean", true)
- }
-
- enable(TestProperties.LOG_TRAFFIC)
- enable(TestProperties.DUMP_ENTITY)
- return object : ResourceConfig() {
- init {
- register(Prometheus(metricsContainer))
- }
- }
- }
-
- @Test
- fun testGetJson() {
- val resp = target(baseUrl).request(MediaType.APPLICATION_JSON_TYPE).get()
- resp.status shouldBe HttpStatus.OK_200
- resp.mediaType shouldBe MediaType.APPLICATION_JSON_TYPE
- with(MetricsContainer(CollectorRegistry())) {
- registerLongGauge("gauge", "A gauge", 50)
- registerBooleanMetric("boolean", "A boolean", true)
- resp.getResultAsJson() shouldBe mapOf("gauge" to 50, "boolean" to true)
- }
- }
-
- @Test
- fun testGetPrometheus004() {
- val resp = target(baseUrl).request(TextFormat.CONTENT_TYPE_004).get()
- resp.status shouldBe HttpStatus.OK_200
- resp.mediaType shouldBe mediaType004
- with(MetricsContainer(CollectorRegistry())) {
- registerLongGauge("gauge", "A gauge", 50)
- registerBooleanMetric("boolean", "A boolean", true)
- val expected = getPrometheusMetrics(TextFormat.CONTENT_TYPE_004).split("\n").sorted()
- resp.getSortedLines() shouldBe expected
- }
- }
-
- @Test
- fun testGetPrometheusOpenMetrics() {
- val resp = target(baseUrl).request(TextFormat.CONTENT_TYPE_OPENMETRICS_100).get()
- resp.status shouldBe HttpStatus.OK_200
- resp.mediaType shouldBe mediaTypeOpenMetrics
- with(MetricsContainer(CollectorRegistry())) {
- registerLongGauge("gauge", "A gauge", 50)
- registerBooleanMetric("boolean", "A boolean", true)
- val expected = getPrometheusMetrics(TextFormat.CONTENT_TYPE_OPENMETRICS_100).split("\n").sorted()
- resp.getSortedLines() shouldBe expected
- }
- }
-
- private fun Response.getResultAsJson(): JSONObject {
- val obj = JSONParser().parse(readEntity(String::class.java))
- obj.shouldBeInstanceOf()
- return obj
- }
-
- private fun Response.getSortedLines(): List {
- return readEntity(String::class.java).split("\n").sorted()
- }
-}
diff --git a/jicoco-metrics/src/main/kotlin/org/jitsi/metrics/MetricsContainer.kt b/jicoco-metrics/src/main/kotlin/org/jitsi/metrics/MetricsContainer.kt
index 818af23e..70a35ef1 100644
--- a/jicoco-metrics/src/main/kotlin/org/jitsi/metrics/MetricsContainer.kt
+++ b/jicoco-metrics/src/main/kotlin/org/jitsi/metrics/MetricsContainer.kt
@@ -72,6 +72,41 @@ open class MetricsContainer @JvmOverloads constructor(
return writer.toString()
}
+ /**
+ * Gets metrics in a format based on the `Accept` header. Returns the content type as the second element of the
+ * pair. Defaults to OpenMetrics.
+ */
+ fun getMetrics(
+ /** List of accepted media types in order of preference */
+ accepts: List
+ ): Pair {
+ if (accepts.isEmpty()) {
+ return getPrometheusMetrics(
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ ) to TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ }
+ accepts.forEach {
+ when (it) {
+ "application/openmetrics-text" -> return getPrometheusMetrics(
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ ) to TextFormat.CONTENT_TYPE_OPENMETRICS_100
+
+ "text/plain" -> return getPrometheusMetrics(
+ TextFormat.CONTENT_TYPE_004
+ ) to TextFormat.CONTENT_TYPE_004
+
+ "application/json" -> return jsonString to "application/json"
+
+ "*/*" -> return getPrometheusMetrics(
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ ) to TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ }
+ }
+ throw NoSupportedMediaTypeException(
+ "Supported media types are application/openmetrics-text, text/plain and application/json"
+ )
+ }
+
/**
* Creates and registers a [BooleanMetric] with the given [name], [help] string and optional [initialValue].
*
@@ -217,4 +252,6 @@ open class MetricsContainer @JvmOverloads constructor(
fun resetAll() {
metrics.values.forEach { it.reset() }
}
+
+ class NoSupportedMediaTypeException(message: String) : Exception(message)
}
diff --git a/jicoco-metrics/src/test/kotlin/org/jitsi/metrics/MetricsContainerTest.kt b/jicoco-metrics/src/test/kotlin/org/jitsi/metrics/MetricsContainerTest.kt
index cfed1a13..aff570b5 100644
--- a/jicoco-metrics/src/test/kotlin/org/jitsi/metrics/MetricsContainerTest.kt
+++ b/jicoco-metrics/src/test/kotlin/org/jitsi/metrics/MetricsContainerTest.kt
@@ -21,6 +21,7 @@ import io.kotest.core.spec.style.ShouldSpec
import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.shouldBe
import io.prometheus.client.CollectorRegistry
+import io.prometheus.client.exporter.common.TextFormat
class MetricsContainerTest : ShouldSpec() {
@@ -85,5 +86,33 @@ class MetricsContainerTest : ShouldSpec() {
}
}
}
+ context("Getting metrics with different accepted content types") {
+ should("return the correct content type") {
+ mc.getMetrics(emptyList()).second shouldBe TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ mc.getMetrics(listOf("text/plain")).second shouldBe TextFormat.CONTENT_TYPE_004
+ mc.getMetrics(listOf("application/json")).second shouldBe "application/json"
+ mc.getMetrics(listOf("application/openmetrics-text")).second shouldBe
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ mc.getMetrics(listOf("application/openmetrics-text", "application/json")).second shouldBe
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ mc.getMetrics(listOf("application/json", "application/openmetrics-text")).second shouldBe
+ "application/json"
+ mc.getMetrics(
+ listOf(
+ "application/json",
+ "application/other",
+ "application/openmetrics-text"
+ )
+ ).second shouldBe
+ "application/json"
+ mc.getMetrics(listOf("application/json", "*/*", "application/openmetrics-text")).second shouldBe
+ "application/json"
+ mc.getMetrics(listOf("*/*", "application/json", "*/*", "application/openmetrics-text")).second shouldBe
+ TextFormat.CONTENT_TYPE_OPENMETRICS_100
+ shouldThrow {
+ mc.getMetrics(listOf("application/something", "application/something-else"))
+ }
+ }
+ }
}
}
diff --git a/pom.xml b/pom.xml
index 0df42ba1..f1a186be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -201,7 +201,6 @@
jicoco-config
jicoco-mediajson
jicoco-metrics
- jicoco-metrics-jetty
jicoco-test-kotlin
@@ -237,7 +236,6 @@
jicoco-config
jicoco-mediajson
jicoco-metrics
- jicoco-metrics-jetty
jicoco-test-kotlin