Skip to content

Commit

Permalink
Add support for the Strimzi Metrics Reporter
Browse files Browse the repository at this point in the history
This patch adds support for the Strimzi Metrics Reporter.

Setting `bridge.metrics=jmxPrometheusExporter` enables the JMX Prometheus Exporter (equivalent to KAFKA_BRIDGE_METRICS_ENABLED=true).
Setting `bridge.metrics=strimziMetricsReporter` enables the new Strimzi Metrics Reporter as Kafka plugin.

When selecting the `strimziMetricsReporter`, you also need to add the plugin configuration as in the following example:

```sh
bridge.metrics=strimziMetricsReporter
kafka.metric.reporters=io.strimzi.kafka.metrics.KafkaPrometheusMetricsReporter
kafka.prometheus.metrics.reporter.listener.enable=false
kafka.prometheus.metrics.reporter.allowlist=.*
```

Signed-off-by: Federico Valeri <[email protected]>
  • Loading branch information
fvaleri committed Dec 17, 2024
1 parent 27007bf commit 909afb4
Show file tree
Hide file tree
Showing 25 changed files with 723 additions and 186 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
## 0.32.0

* Dependency updates (JMX exporter 1.1.0)
* Added support for the [Strimzi Metrics Reporter](https://github.com/strimzi/metrics-reporter) metrics.
This is a Kafka plugin that exports metrics in Prometheus format without passing through JMX, and can be enabled by setting `bridge.metrics=strimziMetricsReporter`.
The JMX Exporter metrics can still be enabled by setting `bridge.metrics=jmxPrometheusExporter`.

### Changes, deprecations and removals

* `KAFKA_BRIDGE_METRICS_ENABLED` has been deprecated.
The equivalent configuration is `bridge.metrics=jmxPrometheusExporter`.

## 0.31.1

Expand Down
4 changes: 4 additions & 0 deletions bin/docker/kafka_bridge_config_generator.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#!/usr/bin/env bash

if [ -n "$STRIMZI_METRICS" ]; then
BRIDGE_METRICS="bridge.metrics=${STRIMZI_METRICS}"
fi

if [ -n "$STRIMZI_TRACING" ]; then
BRIDGE_TRACING="bridge.tracing=${STRIMZI_TRACING}"
fi
Expand Down
10 changes: 10 additions & 0 deletions config/application.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
#Bridge related settings
bridge.id=my-bridge

# uncomment the following line to enable JMX Exporter metrics, check the documentation for more details
#bridge.metrics=jmxPrometheusExporter

# uncomment the following lines to enable Strimzi Reporter metrics, check the documentation for more details
#bridge.metrics=strimziMetricsReporter
#kafka.metric.reporters=io.strimzi.kafka.metrics.KafkaPrometheusMetricsReporter
#kafka.prometheus.metrics.reporter.listener.enable=false
#kafka.prometheus.metrics.reporter.allowlist=.*

# uncomment the following line (bridge.tracing) to enable OpenTelemetry tracing, check the documentation for more details
#bridge.tracing=opentelemetry

Expand Down
5 changes: 3 additions & 2 deletions documentation/assemblies/assembly-kafka-bridge-config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Distributed tracing allows you to track the progress of transactions between app
NOTE: Use the `KafkaBridge` resource to configure properties when you are xref:overview-components-running-kafka-bridge-cluster-{context}[running the Kafka Bridge on Kubernetes].

include::modules/proc-configuring-kafka-bridge.adoc[leveloffset=+1]
include::modules/proc-configuring-kafka-bridge-metrics.adoc[leveloffset=+1]
include::modules/proc-configuring-kafka-bridge-tracing.adoc[leveloffset=+1]
include::modules/proc-configuring-kafka-bridge-jmx-metrics.adoc[leveloffset=+1]
include::modules/proc-configuring-kafka-bridge-smr-metrics.adoc[leveloffset=+1]
include::modules/proc-configuring-kafka-bridge-tracing.adoc[leveloffset=+1]
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
[id='proc-configuring-kafka-bridge-metrics-{context}']
= Configuring metrics
[id='proc-configuring-kafka-bridge-jmx-metrics-{context}']
= Configuring JMX Exporter metrics

[role="_abstract"]
Enable metrics for the Kafka Bridge by setting the `KAFKA_BRIDGE_METRICS_ENABLED` environment variable.
Enable metrics for the Kafka Bridge by setting the `bridge.metrics` configuration.

.Prerequisites

* xref:proc-downloading-kafka-bridge-{context}[The Kafka Bridge installation archive is downloaded].

.Procedure

. Set the environment variable for enabling metrics to `true`.
. Set the `bridge.metrics` configuration to `jmxPrometheusExporter`.
+
.Environment variable for enabling metrics
.Configuration for enabling metrics

[source,properties]
----
KAFKA_BRIDGE_METRICS_ENABLED=true
bridge.metrics=jmxPrometheusExporter
----

. Run the Kafka Bridge script to enable metrics.
Expand All @@ -27,4 +27,4 @@ KAFKA_BRIDGE_METRICS_ENABLED=true
./bin/kafka_bridge_run.sh --config-file=<path>/application.properties
----
+
With metrics enabled, you can use `GET /metrics` with the `/metrics` endpoint to retrieve Kafka Bridge metrics in Prometheus format.
With metrics enabled, you can use `GET /metrics` with the `/metrics` endpoint to retrieve Kafka Bridge metrics in Prometheus format.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[id='proc-configuring-kafka-bridge-smr-metrics-{context}']
= Configuring Strimzi Metrics Reporter metrics

[role="_abstract"]
Enable metrics for the Kafka Bridge by setting the `bridge.metrics` configuration.

.Prerequisites

* xref:proc-downloading-kafka-bridge-{context}[The Kafka Bridge installation archive is downloaded].

.Procedure

. Set the `bridge.metrics` configuration to `strimziMetricsReporter` and related configuration.
+
.Configuration for enabling metrics

[source,properties]
----
bridge.metrics=strimziMetricsReporter
kafka.metric.reporters=io.strimzi.kafka.metrics.KafkaPrometheusMetricsReporter
kafka.prometheus.metrics.reporter.listener.enable=false
kafka.prometheus.metrics.reporter.allowlist=.*
----
+
See the https://github.com/strimzi/metrics-reporter[Strimzi Metrics Reporter documentation] for more details.

. Run the Kafka Bridge script to enable metrics.
+
.Running the Kafka Bridge to enable metrics
[source,shell]
----
./bin/kafka_bridge_run.sh --config-file=<path>/application.properties
----
+
With metrics enabled, you can use `GET /metrics` with the `/metrics` endpoint to retrieve Kafka Bridge metrics in Prometheus format.
37 changes: 32 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@
<kafka-env-var-config-provider.version>1.1.0</kafka-env-var-config-provider.version>
<maven.checkstyle.version>3.3.0</maven.checkstyle.version>
<checkstyle.version>10.12.2</checkstyle.version>
<hamcrest.version>2.2</hamcrest.version>
<junit.version>5.8.2</junit.version>
<hamcrest.version>2.2</hamcrest.version>
<mockito.version>4.11.0</mockito.version>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.0.0-M7</maven-failsafe-plugin.version>
Expand All @@ -126,14 +127,15 @@
<spotbugs.version>4.7.3</spotbugs.version>
<maven.spotbugs.version>4.7.3.0</maven.spotbugs.version>
<strimzi-oauth.version>0.15.0</strimzi-oauth.version>
<strimzi-metrics-reporter.version>0.1.0</strimzi-metrics-reporter.version>
<opentelemetry.version>1.34.1</opentelemetry.version>
<opentelemetry-alpha.version>1.34.1-alpha</opentelemetry-alpha.version>
<opentelemetry.instrumentation.version>1.32.0-alpha</opentelemetry.instrumentation.version>
<opentelemetry-semconv.version>1.21.0-alpha</opentelemetry-semconv.version>
<grpc-netty-shaded.version>1.61.0</grpc-netty-shaded.version>
<micrometer.version>1.12.3</micrometer.version>
<jmx-prometheus-collector.version>1.1.0</jmx-prometheus-collector.version>
<prometheus-client.version>1.3.4</prometheus-client.version>
<jmx-prometheus-collector.version>1.1.0</jmx-prometheus-collector.version>
<commons-cli.version>1.4</commons-cli.version>
<test-container.version>0.109.0</test-container.version>
<jakarta.version>2.3.2</jakarta.version>
Expand Down Expand Up @@ -291,20 +293,35 @@
<version>${micrometer.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus.jmx</groupId>
<artifactId>collector</artifactId>
<version>${jmx-prometheus-collector.version}</version>
<groupId>io.strimzi</groupId>
<artifactId>metrics-reporter</artifactId>
<version>${strimzi-metrics-reporter.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-model</artifactId>
<version>${prometheus-client.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-instrumentation-jvm</artifactId>
<version>${prometheus-client.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-exporter-httpserver</artifactId>
<version>${prometheus-client.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-exposition-textformats</artifactId>
<version>${prometheus-client.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus.jmx</groupId>
<artifactId>collector</artifactId>
<version>${jmx-prometheus-collector.version}</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
Expand Down Expand Up @@ -416,6 +433,12 @@
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.strimzi</groupId>
<artifactId>strimzi-test-container</artifactId>
Expand Down Expand Up @@ -579,6 +602,10 @@
<!-- OpenTelemetry - used via classpath configuration opentelemetry-exporter-sender-grpc is required at runtime to replace OKHTTP -->
<ignoredUnusedDeclaredDependency>io.grpc:grpc-netty-shaded:jar</ignoredUnusedDeclaredDependency>
<ignoredUnusedDeclaredDependency>com.google.guava:guava</ignoredUnusedDeclaredDependency>
<!-- Strimzi Metrics Reporter - used via classpath configuration -->
<ignoredUnusedDeclaredDependency>io.strimzi:metrics-reporter</ignoredUnusedDeclaredDependency>
<ignoredUnusedDeclaredDependency>io.prometheus:prometheus-metrics-instrumentation-jvm</ignoredUnusedDeclaredDependency>
<ignoredUnusedDeclaredDependency>io.prometheus:prometheus-metrics-exporter-httpserver</ignoredUnusedDeclaredDependency>
</ignoredUnusedDeclaredDependencies>
</configuration>
</execution>
Expand Down
99 changes: 54 additions & 45 deletions src/main/java/io/strimzi/kafka/bridge/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@

package io.strimzi.kafka.bridge;

import io.micrometer.core.instrument.MeterRegistry;
import io.strimzi.kafka.bridge.config.BridgeConfig;
import io.strimzi.kafka.bridge.config.ConfigRetriever;
import io.strimzi.kafka.bridge.http.HttpBridge;
import io.strimzi.kafka.bridge.metrics.JmxCollectorRegistry;
import io.strimzi.kafka.bridge.metrics.MetricsReporter;
import io.strimzi.kafka.bridge.metrics.MetricsType;
import io.strimzi.kafka.bridge.metrics.StrimziCollectorRegistry;
import io.strimzi.kafka.bridge.tracing.TracingUtil;
import io.vertx.core.Future;
import io.vertx.core.Promise;
Expand All @@ -18,7 +21,6 @@
import io.vertx.micrometer.MetricsDomain;
import io.vertx.micrometer.MicrometerMetricsOptions;
import io.vertx.micrometer.VertxPrometheusOptions;
import io.vertx.micrometer.backends.BackendRegistries;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
Expand Down Expand Up @@ -46,8 +48,6 @@
public class Application {
private static final Logger LOGGER = LogManager.getLogger(Application.class);

private static final String KAFKA_BRIDGE_METRICS_ENABLED = "KAFKA_BRIDGE_METRICS_ENABLED";

/**
* Bridge entrypoint
*
Expand All @@ -56,27 +56,12 @@ public class Application {
public static void main(String[] args) {
LOGGER.info("Strimzi Kafka Bridge {} is starting", Application.class.getPackage().getImplementationVersion());
try {
VertxOptions vertxOptions = new VertxOptions();
JmxCollectorRegistry jmxCollectorRegistry = null;
if (Boolean.parseBoolean(System.getenv(KAFKA_BRIDGE_METRICS_ENABLED))) {
LOGGER.info("Metrics enabled and exposed on the /metrics endpoint");
// setup Micrometer metrics options
vertxOptions.setMetricsOptions(metricsOptions());
jmxCollectorRegistry = getJmxCollectorRegistry();
}
Vertx vertx = Vertx.vertx(vertxOptions);
// MeterRegistry default instance is just null if metrics are not enabled in the VertxOptions instance
MeterRegistry meterRegistry = BackendRegistries.getDefaultNow();
MetricsReporter metricsReporter = new MetricsReporter(jmxCollectorRegistry, meterRegistry);


CommandLine commandLine = new DefaultParser().parse(generateOptions(), args);

Map<String, Object> config = ConfigRetriever.getConfig(absoluteFilePath(commandLine.getOptionValue("config-file")));
BridgeConfig bridgeConfig = BridgeConfig.fromMap(config);
LOGGER.info("Bridge configuration {}", bridgeConfig);

deployHttpBridge(vertx, bridgeConfig, metricsReporter).onComplete(done -> {
deployHttpBridge(bridgeConfig).onComplete(done -> {
if (done.succeeded()) {
// register tracing - if set, etc
TracingUtil.initialize(bridgeConfig);
Expand All @@ -88,40 +73,26 @@ public static void main(String[] args) {
}
}

/**
* Set up the Vert.x metrics options
*
* @return instance of the MicrometerMetricsOptions on Vert.x
*/
private static MicrometerMetricsOptions metricsOptions() {
Set<String> set = new HashSet<>();
set.add(MetricsDomain.NAMED_POOLS.name());
set.add(MetricsDomain.VERTICLES.name());
return new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
// define the labels on the HTTP server related metrics
.setLabels(EnumSet.of(Label.HTTP_PATH, Label.HTTP_METHOD, Label.HTTP_CODE))
// disable metrics about pool and verticles
.setDisabledMetricsCategories(set)
.setJvmMetricsEnabled(true)
.setEnabled(true);
}

/**
* Deploys the HTTP bridge into a new verticle
*
* @param vertx Vertx instance
* @param bridgeConfig Bridge configuration
* @param metricsReporter MetricsReporter instance for scraping metrics from different registries
* @return Future for the bridge startup
*/
private static Future<HttpBridge> deployHttpBridge(Vertx vertx, BridgeConfig bridgeConfig, MetricsReporter metricsReporter) {
private static Future<HttpBridge> deployHttpBridge(BridgeConfig bridgeConfig)
throws MalformedObjectNameException, IOException {
Promise<HttpBridge> httpPromise = Promise.promise();

Vertx vertx = createVertxInstance(bridgeConfig);
MetricsReporter metricsReporter = getMetricsReporter(bridgeConfig);
HttpBridge httpBridge = new HttpBridge(bridgeConfig, metricsReporter);

vertx.deployVerticle(httpBridge, done -> {
if (done.succeeded()) {
LOGGER.info("HTTP verticle instance deployed [{}]", done.result());
if (metricsReporter != null) {
LOGGER.info("Metrics of type '{}' enabled and exposed on /metrics endpoint", bridgeConfig.getMetrics());
}
httpPromise.complete(httpBridge);
} else {
LOGGER.error("Failed to deploy HTTP verticle instance", done.cause());
Expand All @@ -132,15 +103,54 @@ private static Future<HttpBridge> deployHttpBridge(Vertx vertx, BridgeConfig bri
return httpPromise.future();
}

private static Vertx createVertxInstance(BridgeConfig bridgeConfig) {
VertxOptions vertxOptions = new VertxOptions();
if (bridgeConfig.getMetrics() != null) {
vertxOptions.setMetricsOptions(metricsOptions()); // enable Vertx metrics
}
Vertx vertx = Vertx.vertx(vertxOptions);
return vertx;
}

/**
* Set up the Vert.x metrics options
*
* @return instance of the MicrometerMetricsOptions on Vert.x
*/
private static MicrometerMetricsOptions metricsOptions() {
Set<String> set = new HashSet<>();
set.add(MetricsDomain.NAMED_POOLS.name());
set.add(MetricsDomain.VERTICLES.name());
return new MicrometerMetricsOptions()
.setPrometheusOptions(new VertxPrometheusOptions().setEnabled(true))
// define the labels on the HTTP server related metrics
.setLabels(EnumSet.of(Label.HTTP_PATH, Label.HTTP_METHOD, Label.HTTP_CODE))
// disable metrics about pool and verticles
.setDisabledMetricsCategories(set)
.setJvmMetricsEnabled(true)
.setEnabled(true);
}

private static MetricsReporter getMetricsReporter(BridgeConfig bridgeConfig)
throws MalformedObjectNameException, IOException {
if (bridgeConfig.getMetrics() != null) {
if (bridgeConfig.getMetrics().equals(MetricsType.JMX_EXPORTER.toString())) {
return new MetricsReporter(getJmxCollectorRegistry());
} else if (bridgeConfig.getMetrics().equals(MetricsType.STRIMZI_REPORTER.toString())) {
return new MetricsReporter(new StrimziCollectorRegistry());
}
}
return null;
}

/**
* Return a JmxCollectorRegistry instance with the YAML configuration filters
*
* @return JmxCollectorRegistry instance
* @throws MalformedObjectNameException
* @throws IOException
*/
private static JmxCollectorRegistry getJmxCollectorRegistry()
throws MalformedObjectNameException, IOException {
private static JmxCollectorRegistry getJmxCollectorRegistry() throws MalformedObjectNameException, IOException {
InputStream is = Application.class.getClassLoader().getResourceAsStream("jmx_metrics_config.yaml");
if (is == null) {
return null;
Expand All @@ -160,7 +170,6 @@ private static JmxCollectorRegistry getJmxCollectorRegistry()
* @return command line options
*/
private static Options generateOptions() {

Option configFileOption = Option.builder()
.required(true)
.hasArg(true)
Expand Down
Loading

0 comments on commit 909afb4

Please sign in to comment.