diff --git a/CHANGELOG.md b/CHANGELOG.md index 1039c8ccccd..359289ba825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Support for MirrorMaker 1 has been removed * Added support to configure `dnsPolicy` and `dnsConfig` using the `template` sections. * Store Kafka node certificates in separate Secrets, one Secret per pod. +* Added support for Strimzi Metrics Reporter to the Kafka component. ### Major changes, deprecations and removals diff --git a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/JmxPrometheusExporterMetrics.java b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/JmxPrometheusExporterMetrics.java index 404442e97c7..726f8c15de6 100644 --- a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/JmxPrometheusExporterMetrics.java +++ b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/JmxPrometheusExporterMetrics.java @@ -5,7 +5,6 @@ package io.strimzi.api.kafka.model.common.metrics; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import io.strimzi.api.kafka.model.common.Constants; import io.strimzi.api.kafka.model.common.ExternalConfigurationReference; @@ -31,7 +30,6 @@ public class JmxPrometheusExporterMetrics extends MetricsConfig { private ExternalConfigurationReference valueFrom; @Description("ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ") - @JsonProperty(required = true) public ExternalConfigurationReference getValueFrom() { return valueFrom; } diff --git a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/MetricsConfig.java b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/MetricsConfig.java index fc37bf6cd01..ed6ffb6e84c 100644 --- a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/MetricsConfig.java +++ b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/MetricsConfig.java @@ -23,6 +23,7 @@ property = "type") @JsonSubTypes({ @JsonSubTypes.Type(name = JmxPrometheusExporterMetrics.TYPE_JMX_EXPORTER, value = JmxPrometheusExporterMetrics.class), + @JsonSubTypes.Type(name = StrimziMetricsReporter.TYPE_STRIMZI_METRICS_REPORTER, value = StrimziMetricsReporter.class) }) @JsonInclude(JsonInclude.Include.NON_NULL) @EqualsAndHashCode @@ -30,7 +31,10 @@ public abstract class MetricsConfig implements UnknownPropertyPreserving { private Map additionalProperties; - @Description("Metrics type. Only 'jmxPrometheusExporter' supported currently.") + @Description("Metrics type. " + + "The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. " + + "Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. " + + "Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint.") public abstract String getType(); @Override @@ -45,5 +49,4 @@ public void setAdditionalProperty(String name, Object value) { } this.additionalProperties.put(name, value); } -} - +} \ No newline at end of file diff --git a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporter.java b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporter.java new file mode 100644 index 00000000000..99c065a27ee --- /dev/null +++ b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporter.java @@ -0,0 +1,46 @@ +/* + * Copyright Strimzi authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.strimzi.api.kafka.model.common.metrics; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.strimzi.api.kafka.model.common.Constants; +import io.strimzi.crdgenerator.annotations.Description; +import io.sundr.builder.annotations.Buildable; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * Strimzi Metrics Reporter. + */ +@Buildable( + editableEnabled = false, + builderPackage = Constants.FABRIC8_KUBERNETES_API +) +@JsonPropertyOrder({"type", "values"}) +@JsonInclude(JsonInclude.Include.NON_NULL) +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class StrimziMetricsReporter extends MetricsConfig { + public static final String TYPE_STRIMZI_METRICS_REPORTER = "strimziMetricsReporter"; + + private StrimziMetricsReporterValues values; + + @Description("Must be `" + TYPE_STRIMZI_METRICS_REPORTER + "`") + @JsonInclude(JsonInclude.Include.NON_NULL) + @Override + public String getType() { + return TYPE_STRIMZI_METRICS_REPORTER; + } + + @Description("Configuration values for the Strimzi Metrics Reporter.") + public StrimziMetricsReporterValues getValues() { + return values; + } + + public void setValues(StrimziMetricsReporterValues values) { + this.values = values; + } +} diff --git a/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporterValues.java b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporterValues.java new file mode 100644 index 00000000000..3c2b83bb7e1 --- /dev/null +++ b/api/src/main/java/io/strimzi/api/kafka/model/common/metrics/StrimziMetricsReporterValues.java @@ -0,0 +1,59 @@ +/* + * Copyright Strimzi authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.strimzi.api.kafka.model.common.metrics; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import io.strimzi.api.kafka.model.common.Constants; +import io.strimzi.api.kafka.model.common.UnknownPropertyPreserving; +import io.strimzi.crdgenerator.annotations.Description; +import io.sundr.builder.annotations.Buildable; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Strimzi Metrics Reporter configuration. + */ +@Buildable( + editableEnabled = false, + builderPackage = Constants.FABRIC8_KUBERNETES_API +) +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({"allowList"}) +@EqualsAndHashCode() +@ToString +public class StrimziMetricsReporterValues implements UnknownPropertyPreserving { + private static final String DEFAULT_REGEX = ".*"; + + private List allowList = List.of(DEFAULT_REGEX); + private Map additionalProperties; + + @Description("A comma separated list of regex patterns to specify the metrics to collect. Default: `" + DEFAULT_REGEX + "`.") + @JsonInclude(value = JsonInclude.Include.NON_NULL) + public List getAllowList() { + return allowList; + } + + public void setAllowList(List allowList) { + this.allowList = allowList; + } + + @Override + public Map getAdditionalProperties() { + return this.additionalProperties != null ? this.additionalProperties : Map.of(); + } + + @Override + public void setAdditionalProperty(String name, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap<>(2); + } + this.additionalProperties.put(name, value); + } +} \ No newline at end of file diff --git a/api/src/main/java/io/strimzi/api/kafka/model/kafka/KafkaClusterSpec.java b/api/src/main/java/io/strimzi/api/kafka/model/kafka/KafkaClusterSpec.java index 42d15fff693..3cd396667c6 100644 --- a/api/src/main/java/io/strimzi/api/kafka/model/kafka/KafkaClusterSpec.java +++ b/api/src/main/java/io/strimzi/api/kafka/model/kafka/KafkaClusterSpec.java @@ -62,7 +62,8 @@ public class KafkaClusterSpec implements HasConfigurableMetrics, HasConfigurable + "cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, " + "node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, " // KRaft options + "client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, " - + "client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list"; + + "client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list, " + + "kafka.metric.reporters, prometheus.metrics.reporter."; public static final String FORBIDDEN_PREFIX_EXCEPTIONS = "zookeeper.connection.timeout.ms, sasl.server.max.receive.size, " + "ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, " diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/ConfigMapUtils.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/ConfigMapUtils.java index 6aa4e5ea44a..6ad1cfe96ee 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/ConfigMapUtils.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/ConfigMapUtils.java @@ -67,7 +67,7 @@ public static Map generateMetricsAndLogConfigMapData(Reconciliat data.put(supportsLogging.logging().configMapKey(), supportsLogging.logging().loggingConfiguration(reconciliation, metricsAndLogging.loggingCm())); } - if (model instanceof SupportsMetrics supportMetrics) { + if (model instanceof SupportsMetrics supportMetrics && supportMetrics.metrics() != null) { String parseResult = supportMetrics.metrics().metricsJson(reconciliation, metricsAndLogging.metricsCm()); if (parseResult != null) { data.put(MetricsModel.CONFIG_MAP_KEY, parseResult); diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/CruiseControl.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/CruiseControl.java index f81ca159936..0071feb4051 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/CruiseControl.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/CruiseControl.java @@ -21,6 +21,8 @@ import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyIngressRule; import io.fabric8.kubernetes.api.model.networking.v1.NetworkPolicyPeer; import io.strimzi.api.kafka.model.common.JvmOptions; +import io.strimzi.api.kafka.model.common.metrics.JmxPrometheusExporterMetrics; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; import io.strimzi.api.kafka.model.common.template.DeploymentTemplate; import io.strimzi.api.kafka.model.common.template.InternalServiceTemplate; import io.strimzi.api.kafka.model.common.template.PodTemplate; @@ -45,6 +47,7 @@ import io.strimzi.operator.common.Annotations; import io.strimzi.operator.common.Reconciliation; import io.strimzi.operator.common.Util; +import io.strimzi.operator.common.model.InvalidResourceException; import io.strimzi.operator.common.model.Labels; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlApiProperties; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlConfigurationParameters; @@ -95,7 +98,7 @@ public class CruiseControl extends AbstractModel implements SupportsMetrics, Sup */ public static final String API_AUTH_CREDENTIALS_FILE = API_AUTH_CONFIG_VOLUME_MOUNT + CruiseControlApiProperties.AUTH_FILE_KEY; - protected static final String ENV_VAR_CRUISE_CONTROL_METRICS_ENABLED = "CRUISE_CONTROL_METRICS_ENABLED"; + protected static final String ENV_VAR_CRUISE_CONTROL_JMX_EXPORTER_ENABLED = "CRUISE_CONTROL_JMX_EXPORTER_ENABLED"; /** * Annotation for rolling a cluster whenever the server configuration has changed. @@ -118,7 +121,7 @@ public class CruiseControl extends AbstractModel implements SupportsMetrics, Sup @SuppressFBWarnings({"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"}) // This field is initialized in the fromCrd method protected Capacity capacity; @SuppressFBWarnings({"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"}) // This field is initialized in the fromCrd method - private MetricsModel metrics; + private MetricsModel jmxExporterMetrics; private LoggingModel logging; /* test */ CruiseControlConfiguration configuration; @@ -217,7 +220,15 @@ public static CruiseControl fromCrd( result.livenessProbeOptions = ProbeUtils.extractLivenessProbeOptionsOrDefault(ccSpec, ProbeUtils.DEFAULT_HEALTHCHECK_OPTIONS); result.gcLoggingEnabled = ccSpec.getJvmOptions() == null ? JvmOptions.DEFAULT_GC_LOGGING_ENABLED : ccSpec.getJvmOptions().isGcLoggingEnabled(); result.jvmOptions = ccSpec.getJvmOptions(); - result.metrics = new MetricsModel(ccSpec); + + if (ccSpec.getMetricsConfig() instanceof JmxPrometheusExporterMetrics) { + result.jmxExporterMetrics = new MetricsModel(ccSpec); + } else if (ccSpec.getMetricsConfig() instanceof StrimziMetricsReporter) { + // Cruise Control own metrics are only exported through JMX + LOGGER.errorCr(reconciliation, "The Strimzi Metrics Reporter is not supported for Cruise Control"); + throw new InvalidResourceException("The Strimzi Metrics Reporter is not supported for Cruise Control"); + } + result.logging = new LoggingModel(ccSpec, result.getClass().getSimpleName(), true, false); result.resources = ccSpec.getResources(); @@ -306,7 +317,7 @@ protected List getContainerPortList() { portList.add(ContainerUtils.createContainerPort(REST_API_PORT_NAME, REST_API_PORT)); - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { portList.add(ContainerUtils.createContainerPort(MetricsModel.METRICS_PORT_NAME, MetricsModel.METRICS_PORT)); } @@ -394,7 +405,8 @@ public Deployment generateDeployment(Map annotations, boolean is protected List getEnvVars() { List varList = new ArrayList<>(); - varList.add(ContainerUtils.createEnvVar(ENV_VAR_CRUISE_CONTROL_METRICS_ENABLED, String.valueOf(metrics.isEnabled()))); + String jmxMetricsEnabled = jmxExporterMetrics != null && jmxExporterMetrics.isEnabled() ? Boolean.TRUE.toString() : Boolean.FALSE.toString(); + varList.add(ContainerUtils.createEnvVar(ENV_VAR_CRUISE_CONTROL_JMX_EXPORTER_ENABLED, jmxMetricsEnabled)); varList.add(ContainerUtils.createEnvVar(ENV_VAR_STRIMZI_KAFKA_BOOTSTRAP_SERVERS, KafkaResources.bootstrapServiceName(cluster) + ":" + KafkaCluster.REPLICATION_PORT)); varList.add(ContainerUtils.createEnvVar(ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED, String.valueOf(gcLoggingEnabled))); @@ -475,7 +487,7 @@ public NetworkPolicy generateNetworkPolicy(String operatorNamespace, Labels oper rules.add(NetworkPolicyUtils.createIngressRule(REST_API_PORT, peers)); // Everyone can access metrics - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { rules.add(NetworkPolicyUtils.createIngressRule(MetricsModel.METRICS_PORT, List.of())); } @@ -500,7 +512,7 @@ public HashLoginServiceApiCredentials apiCredentials() { * @return Metrics Model instance for configuring Prometheus metrics */ public MetricsModel metrics() { - return metrics; + return jmxExporterMetrics; } /** diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilder.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilder.java index 5850b95eb24..77d7354b4da 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilder.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilder.java @@ -30,6 +30,7 @@ import io.strimzi.kafka.oauth.server.ServerConfig; import io.strimzi.kafka.oauth.server.plain.ServerPlainConfig; import io.strimzi.operator.cluster.model.cruisecontrol.CruiseControlMetricsReporter; +import io.strimzi.operator.cluster.model.metrics.StrimziMetricsReporterModel; import io.strimzi.operator.common.Reconciliation; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlConfigurationParameters; @@ -59,7 +60,6 @@ public class KafkaBrokerConfigurationBuilder { // Names of environment variables expanded through config providers inside the Kafka node private final static String PLACEHOLDER_CERT_STORE_PASSWORD = "${strimzienv:CERTS_STORE_PASSWORD}"; private final static String PLACEHOLDER_OAUTH_CLIENT_SECRET = "${strimzienv:STRIMZI_%s_OAUTH_CLIENT_SECRET}"; - private final StringWriter stringWriter = new StringWriter(); private final PrintWriter writer = new PrintWriter(stringWriter); private final Reconciliation reconciliation; @@ -134,6 +134,26 @@ public KafkaBrokerConfigurationBuilder withCruiseControl(String clusterName, Cru return this; } + /** + * Configures the Strimzi Metrics Reporter. It is set only if user enabled Strimzi Metrics Reporter. + * + * @param model Strimzi Metrics Reporter configuration + * + * @return Returns the builder instance + */ + public KafkaBrokerConfigurationBuilder withStrimziMetricsReporter(StrimziMetricsReporterModel model) { + if (model != null && model.isEnabled()) { + printSectionHeader("Strimzi Metrics Reporter configuration"); + writer.println("kafka.metrics.reporters=io.strimzi.kafka.metrics.YammerPrometheusMetricsReporter"); + writer.println("prometheus.metrics.reporter.listener.enable=true"); + writer.println("prometheus.metrics.reporter.listener=http://0.0.0.0:" + StrimziMetricsReporterModel.METRICS_PORT); + model.getAllowList().ifPresent(allowList -> writer.println("prometheus.metrics.reporter.allowlist=" + allowList)); + writer.println(); + } + + return this; + } + /** * Adds the template for the {@code rack.id}. The rack ID will be set in the container based on the value of the * {@code STRIMZI_RACK_ID} env var. It is set only for broker nodes and only if user enabled the rack awareness. @@ -286,7 +306,6 @@ public KafkaBrokerConfigurationBuilder withListeners( //////////////////// // Shared configurations with values dependent on all listeners //////////////////// - // configure OAuth principal builder for all the nodes - brokers, controllers, and mixed configureOAuthPrincipalBuilderIfNeeded(writer, kafkaListeners); @@ -787,28 +806,33 @@ private void configProviders(KafkaConfiguration userConfig) { /** * Configures the configuration options passed by the user in the Kafka CR. * - * @param userConfig The User configuration - Kafka broker configuration options specified by the user in the Kafka custom resource - * @param injectCcMetricsReporter Inject the Cruise Control Metrics Reporter into the configuration + * @param userConfig The User configuration - Kafka broker configuration options specified by the user in the Kafka custom resource + * @param injectCcMetricsReporter Inject the Cruise Control Metrics Reporter into the configuration + * @param injectStrimziMetricsReporter Inject the Strimzi Metrics Reporter into the configuration * * @return Returns the builder instance */ - public KafkaBrokerConfigurationBuilder withUserConfiguration(KafkaConfiguration userConfig, boolean injectCcMetricsReporter) { + public KafkaBrokerConfigurationBuilder withUserConfiguration(KafkaConfiguration userConfig, boolean injectCcMetricsReporter, boolean injectStrimziMetricsReporter) { if (userConfig != null && !userConfig.getConfiguration().isEmpty()) { - // We have to create a copy of the configuration before we modify it + // We have to create a copy of the configuration before we modify it, to avoid modifying the original input. userConfig = new KafkaConfiguration(userConfig); // Configure the configuration providers => we have to inject the Strimzi ones configProviders(userConfig); - if (injectCcMetricsReporter) { - // We configure the Cruise Control Metrics Reporter is needed - if (userConfig.getConfigOption(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD) != null) { - if (!userConfig.getConfigOption(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD).contains(CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER)) { - userConfig.setConfigOption(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD, userConfig.getConfigOption(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD) + "," + CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER); - } - } else { - userConfig.setConfigOption(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD, CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER); - } + // Handle all combinations of metric.reporters + String metricReporters = userConfig.getConfigOption(KafkaCluster.KAFKA_METRIC_REPORTERS_CONFIG_FIELD); + + // If the injectCcMetricsReporter / injectStrimziMetricsReporter flag is set to true, it is appended to the list of metric reporters + if (injectCcMetricsReporter) { + metricReporters = appendMetricReporter(metricReporters, CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER); + } + if (injectStrimziMetricsReporter) { + metricReporters = appendMetricReporter(metricReporters, StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER); + } + if (metricReporters != null) { + // update the userConfig with the new list of metric reporters + userConfig.setConfigOption(KafkaCluster.KAFKA_METRIC_REPORTERS_CONFIG_FIELD, metricReporters); } printSectionHeader("User provided configuration"); @@ -818,10 +842,17 @@ public KafkaBrokerConfigurationBuilder withUserConfiguration(KafkaConfiguration // Configure the configuration providers => we have to inject the Strimzi ones configProviders(userConfig); - if (injectCcMetricsReporter) { - // There is no user provided configuration. But we still need to inject the Cruise Control Metrics Reporter - printSectionHeader("Cruise Control Metrics Reporter"); - writer.println(CruiseControlMetricsReporter.KAFKA_METRIC_REPORTERS_CONFIG_FIELD + "=" + CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER); + // There is no user provided configuration + if (injectCcMetricsReporter || injectStrimziMetricsReporter) { + printSectionHeader("CruiseControl Metrics Reporters and Strimzi Metrics Reporters"); + String metricReporters = null; + if (injectCcMetricsReporter) { + metricReporters = CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER; + } + if (injectStrimziMetricsReporter) { + metricReporters = appendMetricReporter(metricReporters, StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER); + } + writer.println(KafkaCluster.KAFKA_METRIC_REPORTERS_CONFIG_FIELD + "=" + metricReporters); writer.println(); } } @@ -829,6 +860,21 @@ public KafkaBrokerConfigurationBuilder withUserConfiguration(KafkaConfiguration return this; } + /** + * Appends a new metric reporter to the existing list of metric reporters. + * + * @param existingReporters The existing list of metric reporters, as a comma-separated string. + * @param newReporter The new metric reporter to add to the list. + * @return A comma-separated string containing the existing metric reporters and the new metric reporter. + */ + private String appendMetricReporter(String existingReporters, String newReporter) { + if (existingReporters == null || existingReporters.isEmpty()) { + return newReporter; + } else { + return existingReporters + "," + newReporter; + } + } + /** * Configures the log dirs used by the Kafka brokers. The log dirs contain a broker ID in the path. This is passed * as template and filled in only in the Kafka container. diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaCluster.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaCluster.java index e8cb5fd19e8..d1cbe353ee6 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaCluster.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaCluster.java @@ -41,6 +41,8 @@ import io.strimzi.api.kafka.model.common.CertAndKeySecretSource; import io.strimzi.api.kafka.model.common.Condition; import io.strimzi.api.kafka.model.common.Rack; +import io.strimzi.api.kafka.model.common.metrics.JmxPrometheusExporterMetrics; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; import io.strimzi.api.kafka.model.common.template.ContainerTemplate; import io.strimzi.api.kafka.model.common.template.ExternalTrafficPolicy; import io.strimzi.api.kafka.model.common.template.InternalServiceTemplate; @@ -75,6 +77,7 @@ import io.strimzi.operator.cluster.model.logging.LoggingModel; import io.strimzi.operator.cluster.model.logging.SupportsLogging; import io.strimzi.operator.cluster.model.metrics.MetricsModel; +import io.strimzi.operator.cluster.model.metrics.StrimziMetricsReporterModel; import io.strimzi.operator.cluster.model.metrics.SupportsMetrics; import io.strimzi.operator.cluster.model.securityprofiles.ContainerSecurityProviderContextImpl; import io.strimzi.operator.cluster.model.securityprofiles.PodSecurityProviderContextImpl; @@ -114,7 +117,7 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp public static final String COMPONENT_TYPE = "kafka"; protected static final String ENV_VAR_KAFKA_INIT_EXTERNAL_ADDRESS = "EXTERNAL_ADDRESS"; - private static final String ENV_VAR_KAFKA_METRICS_ENABLED = "KAFKA_METRICS_ENABLED"; + private static final String ENV_VAR_KAFKA_JMX_EXPORTER_ENABLED = "KAFKA_JMX_EXPORTER_ENABLED"; private static final String ENV_VAR_STRIMZI_OPA_AUTHZ_TRUSTED_CERTS = "STRIMZI_OPA_AUTHZ_TRUSTED_CERTS"; private static final String ENV_VAR_STRIMZI_KEYCLOAK_AUTHZ_TRUSTED_CERTS = "STRIMZI_KEYCLOAK_AUTHZ_TRUSTED_CERTS"; @@ -128,6 +131,12 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp protected static final String REPLICATION_PORT_NAME = "tcp-replication"; protected static final int KAFKA_AGENT_PORT = 8443; protected static final String KAFKA_AGENT_PORT_NAME = "tcp-kafkaagent"; + + /** + * The configuration field name for Kafka metric reporters. + */ + public static final String KAFKA_METRIC_REPORTERS_CONFIG_FIELD = "metric.reporters"; + /** * Port number used for control plane */ @@ -228,7 +237,8 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp private String clusterId; private JmxModel jmx; private CruiseControlMetricsReporter ccMetricsReporter; - private MetricsModel metrics; + private MetricsModel jmxExporterMetrics; + private StrimziMetricsReporterModel strimziMetricsReporter; private LoggingModel logging; private QuotasPlugin quotas; /* test */ KafkaConfiguration configuration; @@ -289,6 +299,7 @@ private KafkaCluster(Reconciliation reconciliation, HasMetadata resource, Shared * * @return Kafka cluster instance */ + @SuppressWarnings("NPathComplexity") public static KafkaCluster fromCrd(Reconciliation reconciliation, Kafka kafka, List pools, @@ -298,9 +309,7 @@ public static KafkaCluster fromCrd(Reconciliation reconciliation, SharedEnvironmentProvider sharedEnvironmentProvider) { KafkaSpec kafkaSpec = kafka.getSpec(); KafkaClusterSpec kafkaClusterSpec = kafkaSpec.getKafka(); - KafkaCluster result = new KafkaCluster(reconciliation, kafka, sharedEnvironmentProvider); - result.clusterId = clusterId; result.nodePools = pools; @@ -333,7 +342,12 @@ public static KafkaCluster fromCrd(Reconciliation reconciliation, } result.initImage = initImage; - result.metrics = new MetricsModel(kafkaClusterSpec); + if (kafkaClusterSpec.getMetricsConfig() instanceof JmxPrometheusExporterMetrics) { + result.jmxExporterMetrics = new MetricsModel(kafkaClusterSpec); + } else if (kafkaClusterSpec.getMetricsConfig() instanceof StrimziMetricsReporter) { + result.strimziMetricsReporter = new StrimziMetricsReporterModel(kafkaClusterSpec); + } + result.logging = new LoggingModel(kafkaClusterSpec, result.getClass().getSimpleName(), false, true); result.jmx = new JmxModel( @@ -1312,8 +1326,10 @@ private List getContainerPortList(KafkaPool pool) { } // Metrics port is enabled on all node types regardless their role - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { ports.add(ContainerUtils.createContainerPort(MetricsModel.METRICS_PORT_NAME, MetricsModel.METRICS_PORT)); + } else if (strimziMetricsReporter != null && strimziMetricsReporter.isEnabled()) { + ports.add(ContainerUtils.createContainerPort(StrimziMetricsReporterModel.METRICS_PORT_NAME, StrimziMetricsReporterModel.METRICS_PORT)); } // JMX port is enabled on all node types regardless their role @@ -1507,12 +1523,12 @@ private List getVolumeMounts(Storage storage, ContainerTemplate con if (authorization instanceof KafkaAuthorizationKeycloak keycloakAuthz) { CertUtils.createTrustedCertificatesVolumeMounts(volumeMountList, keycloakAuthz.getTlsTrustedCertificates(), TRUSTED_CERTS_BASE_VOLUME_MOUNT + "/authz-keycloak-certs/", "authz-keycloak"); } - + TemplateUtils.addAdditionalVolumeMounts(volumeMountList, containerTemplate); return volumeMountList; } - + private List getInitContainerVolumeMounts(KafkaPool pool) { List volumeMountList = new ArrayList<>(); volumeMountList.add(VolumeUtils.createVolumeMount(INIT_VOLUME_NAME, INIT_VOLUME_MOUNT)); @@ -1627,7 +1643,8 @@ private Container createContainer(ImagePullPolicy imagePullPolicy, KafkaPool poo */ private List getEnvVars(KafkaPool pool) { List varList = new ArrayList<>(); - varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_METRICS_ENABLED, String.valueOf(metrics.isEnabled()))); + String jmxMetricsEnabled = jmxExporterMetrics != null && jmxExporterMetrics.isEnabled() ? Boolean.TRUE.toString() : Boolean.FALSE.toString(); + varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_JMX_EXPORTER_ENABLED, jmxMetricsEnabled)); varList.add(ContainerUtils.createEnvVar(ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED, String.valueOf(pool.gcLoggingEnabled))); JvmOptionUtils.heapOptions(varList, 50, 5L * 1024L * 1024L * 1024L, pool.jvmOptions, pool.resources); @@ -1739,8 +1756,10 @@ public NetworkPolicy generateNetworkPolicy(String operatorNamespace, Labels oper } // The Metrics port (if enabled) is opened to all by default - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { rules.add(NetworkPolicyUtils.createIngressRule(MetricsModel.METRICS_PORT, List.of())); + } else if (strimziMetricsReporter != null && strimziMetricsReporter.isEnabled()) { + rules.add(NetworkPolicyUtils.createIngressRule(StrimziMetricsReporterModel.METRICS_PORT, List.of())); } // The JMX port (if enabled) is opened to all by default @@ -1839,9 +1858,10 @@ private String generatePerBrokerConfiguration(NodeRef node, KafkaPool pool, Map< ) .withAuthorization(cluster, authorization) .withCruiseControl(cluster, ccMetricsReporter, node.broker()) + .withStrimziMetricsReporter(strimziMetricsReporter) .withTieredStorage(cluster, tieredStorage) .withQuotas(cluster, quotas) - .withUserConfiguration(configuration, node.broker() && ccMetricsReporter != null) + .withUserConfiguration(configuration, node.broker() && ccMetricsReporter != null, strimziMetricsReporter != null && strimziMetricsReporter.isEnabled()) .build() .trim(); } @@ -1856,8 +1876,11 @@ private String generatePerBrokerConfiguration(NodeRef node, KafkaPool pool, Map< * * @return ConfigMap with the shared configuration. */ - public List generatePerBrokerConfigurationConfigMaps(MetricsAndLogging metricsAndLogging, Map> advertisedHostnames, Map> advertisedPorts) { - String parsedMetrics = metrics.metricsJson(reconciliation, metricsAndLogging.metricsCm()); + public List generatePerBrokerConfigurationConfigMaps(MetricsAndLogging metricsAndLogging, Map> advertisedHostnames, Map> advertisedPorts) { + String parsedMetrics = null; + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { + parsedMetrics = jmxExporterMetrics.metricsJson(reconciliation, metricsAndLogging.metricsCm()); + } String parsedLogging = logging().loggingConfiguration(reconciliation, metricsAndLogging.loggingCm()); List configMaps = new ArrayList<>(); @@ -1931,7 +1954,14 @@ public JmxModel jmx() { * @return Metrics Model instance for configuring Prometheus metrics */ public MetricsModel metrics() { - return metrics; + return jmxExporterMetrics; + } + + /** + * @return Strimzi Metrics Reporter Model instance for configuring Prometheus metrics + */ + public StrimziMetricsReporterModel strimziMetricsReporter() { + return strimziMetricsReporter; } /** diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaConnectCluster.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaConnectCluster.java index cfb8c5eb8f9..467bfb2c856 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaConnectCluster.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/KafkaConnectCluster.java @@ -38,6 +38,8 @@ import io.strimzi.api.kafka.model.common.ProbeBuilder; import io.strimzi.api.kafka.model.common.Rack; import io.strimzi.api.kafka.model.common.authentication.KafkaClientAuthentication; +import io.strimzi.api.kafka.model.common.metrics.JmxPrometheusExporterMetrics; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; import io.strimzi.api.kafka.model.common.template.ContainerTemplate; import io.strimzi.api.kafka.model.common.template.DeploymentStrategy; import io.strimzi.api.kafka.model.common.template.DeploymentTemplate; @@ -69,6 +71,7 @@ import io.strimzi.operator.cluster.model.securityprofiles.PodSecurityProviderContextImpl; import io.strimzi.operator.common.Reconciliation; import io.strimzi.operator.common.Util; +import io.strimzi.operator.common.model.InvalidResourceException; import io.strimzi.operator.common.model.Labels; import io.strimzi.operator.common.model.OrderedProperties; @@ -106,7 +109,7 @@ public class KafkaConnectCluster extends AbstractModel implements SupportsMetric // Kafka Connect configuration keys (EnvVariables) protected static final String ENV_VAR_PREFIX = "KAFKA_CONNECT_"; protected static final String ENV_VAR_KAFKA_CONNECT_CONFIGURATION = "KAFKA_CONNECT_CONFIGURATION"; - protected static final String ENV_VAR_KAFKA_CONNECT_METRICS_ENABLED = "KAFKA_CONNECT_METRICS_ENABLED"; + protected static final String ENV_VAR_KAFKA_CONNECT_JMX_EXPORTER_ENABLED = "KAFKA_CONNECT_JMX_EXPORTER_ENABLED"; protected static final String ENV_VAR_KAFKA_CONNECT_BOOTSTRAP_SERVERS = "KAFKA_CONNECT_BOOTSTRAP_SERVERS"; protected static final String ENV_VAR_KAFKA_CONNECT_TLS = "KAFKA_CONNECT_TLS"; protected static final String ENV_VAR_KAFKA_CONNECT_TRUSTED_CERTS = "KAFKA_CONNECT_TRUSTED_CERTS"; @@ -139,7 +142,7 @@ public class KafkaConnectCluster extends AbstractModel implements SupportsMetric protected List externalVolumes = Collections.emptyList(); protected Tracing tracing; protected JmxModel jmx; - protected MetricsModel metrics; + protected MetricsModel jmxExporterMetrics; protected LoggingModel logging; protected AbstractConfiguration configuration; @@ -252,7 +255,14 @@ protected static C fromSpec(Reconciliation recon result.gcLoggingEnabled = spec.getJvmOptions() == null ? JvmOptions.DEFAULT_GC_LOGGING_ENABLED : spec.getJvmOptions().isGcLoggingEnabled(); result.jvmOptions = spec.getJvmOptions(); - result.metrics = new MetricsModel(spec); + + if (spec.getMetricsConfig() instanceof JmxPrometheusExporterMetrics) { + result.jmxExporterMetrics = new MetricsModel(spec); + } else if (spec.getMetricsConfig() instanceof StrimziMetricsReporter) { + LOGGER.errorCr(reconciliation, "The Strimzi Metrics Reporter is not supported for this component"); + throw new InvalidResourceException("The Strimzi Metrics Reporter is not supported for this component"); + } + result.logging = new LoggingModel(spec, result.getClass().getSimpleName(), false, true); result.jmx = new JmxModel( reconciliation.namespace(), @@ -358,7 +368,7 @@ public Service generateHeadlessService() { protected List getContainerPortList() { List portList = new ArrayList<>(2); portList.add(ContainerUtils.createContainerPort(REST_API_PORT_NAME, REST_API_PORT)); - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { portList.add(ContainerUtils.createContainerPort(MetricsModel.METRICS_PORT_NAME, MetricsModel.METRICS_PORT)); } @@ -611,7 +621,8 @@ protected String getCommand() { protected List getEnvVars() { List varList = new ArrayList<>(); varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_CONNECT_CONFIGURATION, configuration.getConfiguration())); - varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_CONNECT_METRICS_ENABLED, String.valueOf(metrics.isEnabled()))); + String jmxMetricsEnabled = jmxExporterMetrics != null && jmxExporterMetrics.isEnabled() ? Boolean.TRUE.toString() : Boolean.FALSE.toString(); + varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_CONNECT_JMX_EXPORTER_ENABLED, jmxMetricsEnabled)); varList.add(ContainerUtils.createEnvVar(ENV_VAR_KAFKA_CONNECT_BOOTSTRAP_SERVERS, bootstrapServers)); varList.add(ContainerUtils.createEnvVar(ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED, String.valueOf(gcLoggingEnabled))); @@ -759,7 +770,7 @@ public NetworkPolicy generateNetworkPolicy(boolean connectorOperatorEnabled, rules.add(NetworkPolicyUtils.createIngressRule(REST_API_PORT, List.of(connectPeer, clusterOperatorPeer))); // The Metrics port (if enabled) is opened to all by default - if (metrics.isEnabled()) { + if (jmxExporterMetrics != null && jmxExporterMetrics.isEnabled()) { rules.add(NetworkPolicyUtils.createIngressRule(MetricsModel.METRICS_PORT, List.of())); } @@ -871,7 +882,7 @@ public JmxModel jmx() { * @return Metrics Model instance for configuring Prometheus metrics */ public MetricsModel metrics() { - return metrics; + return jmxExporterMetrics; } /** diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/cruisecontrol/CruiseControlMetricsReporter.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/cruisecontrol/CruiseControlMetricsReporter.java index b895c831e44..53a1eed3807 100644 --- a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/cruisecontrol/CruiseControlMetricsReporter.java +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/cruisecontrol/CruiseControlMetricsReporter.java @@ -22,10 +22,6 @@ public record CruiseControlMetricsReporter(String topicName, Integer numPartitio private static final String KAFKA_NUM_PARTITIONS_CONFIG_FIELD = "num.partitions"; private static final String KAFKA_REPLICATION_FACTOR_CONFIG_FIELD = "default.replication.factor"; - /** - * Kafka configuration option for configuring metrics reporters - */ - public static final String KAFKA_METRIC_REPORTERS_CONFIG_FIELD = "metric.reporters"; /** * Class of the Cruise Control Metrics reporter */ diff --git a/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModel.java b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModel.java new file mode 100644 index 00000000000..ea9606f379e --- /dev/null +++ b/cluster-operator/src/main/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModel.java @@ -0,0 +1,99 @@ +/* + * Copyright Strimzi authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.strimzi.operator.cluster.model.metrics; + +import io.strimzi.api.kafka.model.common.HasConfigurableMetrics; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; +import io.strimzi.operator.common.model.InvalidResourceException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Represents a model for components with configurable metrics using Strimzi Reporter + */ +public class StrimziMetricsReporterModel { + /** + * Fully Qualified Class Name of the Strimzi Kafka Prometheus Metrics Reporter. + */ + public static final String KAFKA_PROMETHEUS_METRICS_REPORTER = "io.strimzi.kafka.metrics.KafkaPrometheusMetricsReporter"; + + /** + * Name of the Strimzi metrics port + */ + public static final String METRICS_PORT_NAME = "tcp-prometheus"; + + /** + * Number of the Strimzi metrics port + */ + public static final int METRICS_PORT = 9404; + private final boolean isEnabled; + private final List allowList; + + /** + * Constructs the StrimziMetricsReporterModel for managing configurable metrics with Strimzi Reporter + * + * @param spec StrimziReporterMetrics object containing the metrics configuration + */ + public StrimziMetricsReporterModel(HasConfigurableMetrics spec) { + if (spec.getMetricsConfig() != null) { + if (spec.getMetricsConfig() instanceof StrimziMetricsReporter config) { + validate(config); + this.isEnabled = true; + this.allowList = config.getValues() != null && + config.getValues().getAllowList() != null + ? config.getValues().getAllowList() : null; + } else { + throw new InvalidResourceException("Unsupported metrics type " + spec.getMetricsConfig().getType()); + } + } else { + this.isEnabled = false; + this.allowList = null; + } + } + + /** + * @return True if metrics are enabled. False otherwise. + */ + public boolean isEnabled() { + return isEnabled; + } + + /** + * Validates the Strimzi Metrics Reporter configuration + * + * @param config StrimziReporterMetrics configuration to validate + */ + /* test */ static void validate(StrimziMetricsReporter config) { + List errors = new ArrayList<>(); + if (config.getValues() != null && config.getValues().getAllowList() != null) { + if (config.getValues().getAllowList().isEmpty()) { + errors.add("Allowlist should contain at least one element"); + } + for (String regex : config.getValues().getAllowList()) { + try { + Pattern.compile(regex); + } catch (PatternSyntaxException e) { + errors.add(String.format("Invalid regex: %s, %s", regex, e.getDescription())); + } + } + } + if (!errors.isEmpty()) { + throw new InvalidResourceException("Metrics configuration is invalid: " + errors); + } + } + + /** + * Returns the allowlist as a comma-separated string wrapped in an Optional. + * + * @return an Optional containing the comma-separated allowlist if it is not null, otherwise an empty Optional + */ + public Optional getAllowList() { + return allowList != null ? Optional.of(String.join(",", allowList)) : Optional.empty(); + } +} diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/CruiseControlTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/CruiseControlTest.java index 01758211180..86ce08a76d5 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/CruiseControlTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/CruiseControlTest.java @@ -61,6 +61,7 @@ import io.strimzi.operator.cluster.model.cruisecontrol.CpuCapacity; import io.strimzi.operator.common.Annotations; import io.strimzi.operator.common.Reconciliation; +import io.strimzi.operator.common.model.InvalidResourceException; import io.strimzi.operator.common.model.Labels; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlApiProperties; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlConfigurationParameters; @@ -101,6 +102,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasProperty; +import static org.junit.jupiter.api.Assertions.assertThrows; @SuppressWarnings({ "checkstyle:ClassDataAbstractionCoupling", @@ -1093,10 +1095,27 @@ public void testMetricsParsingFromConfigMap() { @ParallelTest public void testMetricsParsingNoMetrics() { CruiseControl cc = createCruiseControl(KAFKA, NODES, STORAGE, Map.of()); + assertThat(cc.metrics(), is(nullValue())); + } + + @ParallelTest + public void testStrimziReporterMetricsConfig() { + Kafka kafka = new KafkaBuilder(KAFKA) + .editSpec() + .withNewCruiseControl() + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList(List.of("kafka_log.*", "kafka_network.*")) + .endValues() + .endStrimziMetricsReporterConfig() + .endCruiseControl() + .endSpec() + .build(); + + InvalidResourceException ex = assertThrows(InvalidResourceException.class, + () -> createCruiseControl(kafka, NODES, STORAGE, Map.of())); - assertThat(cc.metrics().isEnabled(), is(false)); - assertThat(cc.metrics().getConfigMapName(), is(nullValue())); - assertThat(cc.metrics().getConfigMapKey(), is(nullValue())); + assertThat(ex.getMessage(), is("The Strimzi Metrics Reporter is not supported for Cruise Control")); } @ParallelTest @@ -1204,7 +1223,7 @@ private Map expectedLabels() { private List getExpectedEnvVars() { List expected = new ArrayList<>(); - expected.add(new EnvVarBuilder().withName(CruiseControl.ENV_VAR_CRUISE_CONTROL_METRICS_ENABLED).withValue(Boolean.toString(CruiseControl.DEFAULT_CRUISE_CONTROL_METRICS_ENABLED)).build()); + expected.add(new EnvVarBuilder().withName(CruiseControl.ENV_VAR_CRUISE_CONTROL_JMX_EXPORTER_ENABLED).withValue(Boolean.toString(CruiseControl.DEFAULT_CRUISE_CONTROL_METRICS_ENABLED)).build()); expected.add(new EnvVarBuilder().withName(CruiseControl.ENV_VAR_STRIMZI_KAFKA_BOOTSTRAP_SERVERS).withValue(KafkaResources.bootstrapServiceName(CLUSTER_NAME) + ":" + KafkaCluster.REPLICATION_PORT).build()); expected.add(new EnvVarBuilder().withName(CruiseControl.ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED).withValue(Boolean.toString(JvmOptions.DEFAULT_GC_LOGGING_ENABLED)).build()); expected.add(new EnvVarBuilder().withName(CruiseControl.ENV_VAR_API_SSL_ENABLED).withValue(Boolean.toString(CruiseControlConfigurationParameters.DEFAULT_WEBSERVER_SSL_ENABLED)).build()); diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilderTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilderTest.java index d65b5ab30d1..35398f0c672 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilderTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaBrokerConfigurationBuilderTest.java @@ -7,12 +7,15 @@ import io.strimzi.api.kafka.model.common.CertSecretSource; import io.strimzi.api.kafka.model.common.CertSecretSourceBuilder; import io.strimzi.api.kafka.model.common.Rack; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporterBuilder; import io.strimzi.api.kafka.model.kafka.EphemeralStorageBuilder; import io.strimzi.api.kafka.model.kafka.JbodStorageBuilder; import io.strimzi.api.kafka.model.kafka.KafkaAuthorization; import io.strimzi.api.kafka.model.kafka.KafkaAuthorizationKeycloakBuilder; import io.strimzi.api.kafka.model.kafka.KafkaAuthorizationOpaBuilder; import io.strimzi.api.kafka.model.kafka.KafkaAuthorizationSimpleBuilder; +import io.strimzi.api.kafka.model.kafka.KafkaClusterSpecBuilder; import io.strimzi.api.kafka.model.kafka.PersistentClaimStorageBuilder; import io.strimzi.api.kafka.model.kafka.SingleVolumeStorage; import io.strimzi.api.kafka.model.kafka.Storage; @@ -32,6 +35,7 @@ import io.strimzi.kafka.oauth.server.ServerConfig; import io.strimzi.operator.cluster.KafkaVersionTestUtils; import io.strimzi.operator.cluster.model.cruisecontrol.CruiseControlMetricsReporter; +import io.strimzi.operator.cluster.model.metrics.StrimziMetricsReporterModel; import io.strimzi.operator.common.Reconciliation; import io.strimzi.operator.common.model.cruisecontrol.CruiseControlConfigurationParameters; import io.strimzi.test.annotations.ParallelSuite; @@ -62,6 +66,7 @@ import static org.hamcrest.Matchers.equalTo; @ParallelSuite +@SuppressWarnings("checkstyle:classdataabstractioncoupling") public class KafkaBrokerConfigurationBuilderTest { private final static NodeRef NODE_REF = new NodeRef("my-cluster-kafka-2", 2, "kafka", false, true); @@ -154,6 +159,27 @@ public void testNoCruiseControl() { assertThat(configuration, isEquivalent("node.id=2")); } + @ParallelTest + public void testStrimziMetricsReporter() { + StrimziMetricsReporter config = new StrimziMetricsReporterBuilder() + .withNewValues() + .withAllowList("kafka_log.*", "kafka_network.*") + .endValues() + .build(); + StrimziMetricsReporterModel model = new StrimziMetricsReporterModel(new KafkaClusterSpecBuilder() + .withMetricsConfig(config).build()); + + String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) + .withStrimziMetricsReporter(model) + .build(); + + assertThat(configuration, isEquivalent("node.id=2", + "kafka.metrics.reporters=io.strimzi.kafka.metrics.YammerPrometheusMetricsReporter", + "prometheus.metrics.reporter.listener.enable=true", + "prometheus.metrics.reporter.listener=http://0.0.0.0:9404", + "prometheus.metrics.reporter.allowlist=kafka_log.*,kafka_network.*")); + } + @ParallelTest public void testCruiseControl() { CruiseControlMetricsReporter ccMetricsReporter = new CruiseControlMetricsReporter("strimzi.cruisecontrol.metrics", 1, 1, 1); @@ -467,7 +493,7 @@ public void testOpaAuthorizationWithTls() { @ParallelTest public void testNullUserConfiguration() { String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(null, false) + .withUserConfiguration(null, false, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -481,9 +507,9 @@ public void testNullUserConfiguration() { } @ParallelTest - public void testNullUserConfigurationAndCCReporter() { + public void testNullUserConfigurationWithCcMetricsReporter() { String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(null, true) + .withUserConfiguration(null, true, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -497,13 +523,48 @@ public void testNullUserConfigurationAndCCReporter() { "metric.reporters=com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter")); } + @ParallelTest + public void testNullUserConfigurationWithStrimziMetricsReporter() { + String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) + .withUserConfiguration(null, false, true) + .build(); + + assertThat(configuration, isEquivalent("node.id=2", + "config.providers=strimzienv,strimzifile,strimzidir", + "config.providers.strimzienv.class=org.apache.kafka.common.config.provider.EnvVarConfigProvider", + "config.providers.strimzienv.param.allowlist.pattern=.*", + "config.providers.strimzifile.class=org.apache.kafka.common.config.provider.FileConfigProvider", + "config.providers.strimzifile.param.allowed.paths=/opt/kafka", + "config.providers.strimzidir.class=org.apache.kafka.common.config.provider.DirectoryConfigProvider", + "config.providers.strimzidir.param.allowed.paths=/opt/kafka", + "metric.reporters=" + StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER)); + } + + @ParallelTest + public void testNullUserConfigurationWithCcAndStrimziMetricsReporters() { + String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) + .withUserConfiguration(null, true, true) + .build(); + + assertThat(configuration, isEquivalent("node.id=2", + "config.providers=strimzienv,strimzifile,strimzidir", + "config.providers.strimzienv.class=org.apache.kafka.common.config.provider.EnvVarConfigProvider", + "config.providers.strimzienv.param.allowlist.pattern=.*", + "config.providers.strimzifile.class=org.apache.kafka.common.config.provider.FileConfigProvider", + "config.providers.strimzifile.param.allowed.paths=/opt/kafka", + "config.providers.strimzidir.class=org.apache.kafka.common.config.provider.DirectoryConfigProvider", + "config.providers.strimzidir.param.allowed.paths=/opt/kafka", + "metric.reporters=" + CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER + + "," + StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER)); + } + @ParallelTest public void testEmptyUserConfiguration() { Map userConfiguration = new HashMap<>(); KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(kafkaConfiguration, false) + .withUserConfiguration(kafkaConfiguration, false, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -527,7 +588,7 @@ public void testUserConfiguration() { KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(kafkaConfiguration, false) + .withUserConfiguration(kafkaConfiguration, false, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -549,12 +610,11 @@ public void testUserConfigurationWithConfigProviders() { Map userConfiguration = new HashMap<>(); userConfiguration.put("config.providers", "env"); userConfiguration.put("config.providers.env.class", "org.apache.kafka.common.config.provider.EnvVarConfigProvider"); - KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); // Broker String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(kafkaConfiguration, false) + .withUserConfiguration(kafkaConfiguration, false, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -569,7 +629,7 @@ public void testUserConfigurationWithConfigProviders() { // Controller configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, new NodeRef("my-cluster-kafka-3", 3, "kafka", true, false)) - .withUserConfiguration(kafkaConfiguration, false) + .withUserConfiguration(kafkaConfiguration, false, false) .build(); assertThat(configuration, isEquivalent("node.id=3", @@ -580,7 +640,7 @@ public void testUserConfigurationWithConfigProviders() { } @ParallelTest - public void testUserConfigurationWithCCMetricsReporter() { + public void testUserConfigurationWithCcMetricsReporter() { Map userConfiguration = new HashMap<>(); userConfiguration.put("auto.create.topics.enable", "false"); userConfiguration.put("offsets.topic.replication.factor", 3); @@ -590,7 +650,7 @@ public void testUserConfigurationWithCCMetricsReporter() { KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(kafkaConfiguration, true) + .withUserConfiguration(kafkaConfiguration, true, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -605,18 +665,18 @@ public void testUserConfigurationWithCCMetricsReporter() { "offsets.topic.replication.factor=3", "transaction.state.log.replication.factor=3", "transaction.state.log.min.isr=2", - "metric.reporters=com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter")); + KafkaCluster.KAFKA_METRIC_REPORTERS_CONFIG_FIELD + "=com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter")); } @ParallelTest - public void testUserConfigurationWithCCMetricsReporterAndOtherMetricReporters() { + public void testUserConfigurationWithCcAndOtherMetricsReporters() { Map userConfiguration = new HashMap<>(); userConfiguration.put("metric.reporters", "my.domain.CustomMetricReporter"); KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) - .withUserConfiguration(kafkaConfiguration, true) + .withUserConfiguration(kafkaConfiguration, true, false) .build(); assertThat(configuration, isEquivalent("node.id=2", @@ -630,6 +690,48 @@ public void testUserConfigurationWithCCMetricsReporterAndOtherMetricReporters() "metric.reporters=my.domain.CustomMetricReporter,com.linkedin.kafka.cruisecontrol.metricsreporter.CruiseControlMetricsReporter")); } + @ParallelTest + public void testUserConfigurationWithStrimziAndOtherMetricsReporters() { + Map userConfiguration = new HashMap<>(); + userConfiguration.put("metric.reporters", "my.domain.CustomMetricReporter"); + KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); + String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) + .withUserConfiguration(kafkaConfiguration, false, true) + .build(); + + assertThat(configuration, isEquivalent("node.id=2", + "config.providers=strimzienv,strimzifile,strimzidir", + "config.providers.strimzienv.class=org.apache.kafka.common.config.provider.EnvVarConfigProvider", + "config.providers.strimzienv.param.allowlist.pattern=.*", + "config.providers.strimzifile.class=org.apache.kafka.common.config.provider.FileConfigProvider", + "config.providers.strimzifile.param.allowed.paths=/opt/kafka", + "config.providers.strimzidir.class=org.apache.kafka.common.config.provider.DirectoryConfigProvider", + "config.providers.strimzidir.param.allowed.paths=/opt/kafka", + "metric.reporters=my.domain.CustomMetricReporter," + StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER)); + } + + @ParallelTest + public void testUserConfigurationWithCcAndStrimziAndOtherMetricsReporters() { + Map userConfiguration = new HashMap<>(); + userConfiguration.put("metric.reporters", "my.domain.CustomMetricReporter"); + KafkaConfiguration kafkaConfiguration = new KafkaConfiguration(Reconciliation.DUMMY_RECONCILIATION, userConfiguration.entrySet()); + String configuration = new KafkaBrokerConfigurationBuilder(Reconciliation.DUMMY_RECONCILIATION, NODE_REF) + .withUserConfiguration(kafkaConfiguration, true, true) + .build(); + + assertThat(configuration, isEquivalent("node.id=2", + "config.providers=strimzienv,strimzifile,strimzidir", + "config.providers.strimzienv.class=org.apache.kafka.common.config.provider.EnvVarConfigProvider", + "config.providers.strimzienv.param.allowlist.pattern=.*", + "config.providers.strimzifile.class=org.apache.kafka.common.config.provider.FileConfigProvider", + "config.providers.strimzifile.param.allowed.paths=/opt/kafka", + "config.providers.strimzidir.class=org.apache.kafka.common.config.provider.DirectoryConfigProvider", + "config.providers.strimzidir.param.allowed.paths=/opt/kafka", + "metric.reporters=my.domain.CustomMetricReporter," + + CruiseControlMetricsReporter.CRUISE_CONTROL_METRIC_REPORTER + "," + + StrimziMetricsReporterModel.KAFKA_PROMETHEUS_METRICS_REPORTER)); + } + @ParallelTest public void testEphemeralStorageLogDirs() { Storage storage = new EphemeralStorageBuilder() diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaClusterTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaClusterTest.java index adde95c0e1b..0e742923e31 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaClusterTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaClusterTest.java @@ -80,6 +80,7 @@ import io.strimzi.operator.cluster.model.jmx.JmxModel; import io.strimzi.operator.cluster.model.logging.LoggingModel; import io.strimzi.operator.cluster.model.metrics.MetricsModel; +import io.strimzi.operator.cluster.model.metrics.StrimziMetricsReporterModel; import io.strimzi.operator.cluster.model.nodepools.NodePoolUtils; import io.strimzi.operator.common.Annotations; import io.strimzi.operator.common.Reconciliation; @@ -302,6 +303,57 @@ public void testMetricsConfigMap() { } } + @ParallelTest + public void testStrimziMetricsReporterConfigs() { + Kafka kafkaAssembly = new KafkaBuilder(KAFKA) + .editSpec() + .editKafka() + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList("kafka_log.*", "kafka_network.*") + .endValues() + .endStrimziMetricsReporterConfig() + .endKafka() + .endSpec() + .build(); + + List pools = NodePoolUtils.createKafkaPools(Reconciliation.DUMMY_RECONCILIATION, kafkaAssembly, List.of(POOL_CONTROLLERS, POOL_MIXED, POOL_BROKERS), Map.of(), KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, SHARED_ENV_PROVIDER); + KafkaCluster kc = KafkaCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, kafkaAssembly, pools, VERSIONS, KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, null, SHARED_ENV_PROVIDER); + + List cms = kc.generatePerBrokerConfigurationConfigMaps(new MetricsAndLogging(null, null), ADVERTISED_HOSTNAMES, ADVERTISED_PORTS); + assertThat(cms.size(), is(8)); + + for (ConfigMap cm : cms) { + assertThat(cm.getData().toString(), containsString("kafka.metrics.reporters=io.strimzi.kafka.metrics.YammerPrometheusMetricsReporter")); + assertThat(cm.getData().toString(), containsString("prometheus.metrics.reporter.listener.enable=true")); + assertThat(cm.getData().toString(), containsString("prometheus.metrics.reporter.listener=http://0.0.0.0:9404")); + assertThat(cm.getData().toString(), containsString("allowlist=kafka_log.*,kafka_network.*")); + } + } + + @ParallelTest + public void testStrimziMetricsReporterNetworkPolicy() { + Kafka kafkaAssembly = new KafkaBuilder(KAFKA) + .editSpec() + .editKafka() + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList("kafka_log.*", "kafka_network.*") + .endValues() + .endStrimziMetricsReporterConfig() + .endKafka() + .endSpec() + .build(); + + List pools = NodePoolUtils.createKafkaPools(Reconciliation.DUMMY_RECONCILIATION, kafkaAssembly, List.of(POOL_CONTROLLERS, POOL_MIXED, POOL_BROKERS), Map.of(), KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, SHARED_ENV_PROVIDER); + KafkaCluster kc = KafkaCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, kafkaAssembly, pools, VERSIONS, KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, null, SHARED_ENV_PROVIDER); + + NetworkPolicy np = kc.generateNetworkPolicy(null, null); + List rules = np.getSpec().getIngress().stream().filter(ing -> ing.getPorts().get(0).getPort().equals(new IntOrString(StrimziMetricsReporterModel.METRICS_PORT))).collect(Collectors.toList()); + + assertThat(rules.size(), is(1)); + } + @ParallelTest public void testJavaSystemProperties() { Kafka kafka = new KafkaBuilder(KAFKA) @@ -951,7 +1003,7 @@ public void testExposesJmxContainerPortWhenJmxEnabled() { } @ParallelTest - public void testContainerPorts() { + public void testWithJmxMetricsExporterContainerPorts() { Kafka kafka = new KafkaBuilder(KAFKA) .editSpec() .editKafka() @@ -966,6 +1018,29 @@ public void testContainerPorts() { .endSpec() .build(); + assertExpectedContainerPortsAreSet(kafka); + } + + @ParallelTest + public void testWithStrimziMetricsReporterContainerPorts() { + Kafka kafka = new KafkaBuilder(KAFKA) + .editSpec() + .editKafka() + .withListeners(new GenericKafkaListenerBuilder().withName("tls").withPort(9093).withType(KafkaListenerType.INTERNAL).withTls().build(), + new GenericKafkaListenerBuilder().withName("external").withPort(9094).withType(KafkaListenerType.NODEPORT).withTls().build()) + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList("kafka_log.*", "kafka_network.*") + .endValues() + .endStrimziMetricsReporterConfig() + .endKafka() + .endSpec() + .build(); + + assertExpectedContainerPortsAreSet(kafka); + } + + private void assertExpectedContainerPortsAreSet(Kafka kafka) { List pools = NodePoolUtils.createKafkaPools(Reconciliation.DUMMY_RECONCILIATION, kafka, List.of(POOL_CONTROLLERS, POOL_MIXED, POOL_BROKERS), Map.of(), KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, SHARED_ENV_PROVIDER); KafkaCluster kc = KafkaCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, kafka, pools, VERSIONS, KafkaVersionTestUtils.DEFAULT_KRAFT_VERSION_CHANGE, null, SHARED_ENV_PROVIDER); List podSets = kc.generatePodSets(true, null, null, node -> Map.of()); @@ -1970,9 +2045,8 @@ public void testMetricsParsingFromConfigMap() { @ParallelTest public void testMetricsParsingNoMetrics() { - assertThat(KC.metrics().isEnabled(), is(false)); - assertThat(KC.metrics().getConfigMapName(), is(nullValue())); - assertThat(KC.metrics().getConfigMapKey(), is(nullValue())); + assertThat(KC.metrics(), is(nullValue())); + assertThat(KC.strimziMetricsReporter(), is(nullValue())); } @ParallelTest diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaConnectClusterTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaConnectClusterTest.java index 26e0b32238c..525a025fb8e 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaConnectClusterTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaConnectClusterTest.java @@ -196,7 +196,7 @@ private Map expectedLabels() { protected List getExpectedEnvVars() { List expected = new ArrayList<>(); expected.add(new EnvVarBuilder().withName(KafkaConnectCluster.ENV_VAR_KAFKA_CONNECT_CONFIGURATION).withValue(expectedConfiguration.asPairs()).build()); - expected.add(new EnvVarBuilder().withName(KafkaConnectCluster.ENV_VAR_KAFKA_CONNECT_METRICS_ENABLED).withValue(String.valueOf(true)).build()); + expected.add(new EnvVarBuilder().withName(KafkaConnectCluster.ENV_VAR_KAFKA_CONNECT_JMX_EXPORTER_ENABLED).withValue(String.valueOf(true)).build()); expected.add(new EnvVarBuilder().withName(KafkaConnectCluster.ENV_VAR_KAFKA_CONNECT_BOOTSTRAP_SERVERS).withValue(bootstrapServers).build()); expected.add(new EnvVarBuilder().withName(KafkaConnectCluster.ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED).withValue(Boolean.toString(JvmOptions.DEFAULT_GC_LOGGING_ENABLED)).build()); expected.add(new EnvVarBuilder().withName(AbstractModel.ENV_VAR_KAFKA_HEAP_OPTS).withValue(kafkaHeapOpts).build()); @@ -2101,10 +2101,24 @@ public void testMetricsParsingFromConfigMap() { @ParallelTest public void testMetricsParsingNoMetrics() { KafkaConnectCluster kc = KafkaConnectCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, this.resource, VERSIONS, SHARED_ENV_PROVIDER); + assertThat(kc.metrics(), is(nullValue())); + } + + @ParallelTest + public void testStrimziMetricsReporterConfig() { + KafkaConnect resourceWithMetrics = new KafkaConnectBuilder(resource) + .editSpec() + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList(List.of("kafka_log.*", "kafka_network.*")) + .endValues() + .endStrimziMetricsReporterConfig() + .endSpec() + .build(); + InvalidResourceException ex = assertThrows(InvalidResourceException.class, + () -> KafkaConnectCluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, resourceWithMetrics, VERSIONS, SHARED_ENV_PROVIDER)); - assertThat(kc.metrics().isEnabled(), is(false)); - assertThat(kc.metrics().getConfigMapName(), is(nullValue())); - assertThat(kc.metrics().getConfigMapKey(), is(nullValue())); + assertThat(ex.getMessage(), is("The Strimzi Metrics Reporter is not supported for this component")); } @ParallelTest diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaMirrorMaker2ClusterTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaMirrorMaker2ClusterTest.java index 0261e922ceb..eea6c97b2d2 100644 --- a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaMirrorMaker2ClusterTest.java +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/KafkaMirrorMaker2ClusterTest.java @@ -198,7 +198,7 @@ private Map expectedLabels() { protected List getExpectedEnvVars() { List expected = new ArrayList<>(); expected.add(new EnvVarBuilder().withName(KafkaMirrorMaker2Cluster.ENV_VAR_KAFKA_CONNECT_CONFIGURATION).withValue(expectedConfiguration.asPairs()).build()); - expected.add(new EnvVarBuilder().withName(KafkaMirrorMaker2Cluster.ENV_VAR_KAFKA_CONNECT_METRICS_ENABLED).withValue(String.valueOf(true)).build()); + expected.add(new EnvVarBuilder().withName(KafkaMirrorMaker2Cluster.ENV_VAR_KAFKA_CONNECT_JMX_EXPORTER_ENABLED).withValue(String.valueOf(true)).build()); expected.add(new EnvVarBuilder().withName(KafkaMirrorMaker2Cluster.ENV_VAR_KAFKA_CONNECT_BOOTSTRAP_SERVERS).withValue(bootstrapServers).build()); expected.add(new EnvVarBuilder().withName(KafkaMirrorMaker2Cluster.ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED).withValue(Boolean.toString(JvmOptions.DEFAULT_GC_LOGGING_ENABLED)).build()); expected.add(new EnvVarBuilder().withName(AbstractModel.ENV_VAR_KAFKA_HEAP_OPTS).withValue(kafkaHeapOpts).build()); @@ -2236,10 +2236,25 @@ public void testJmxSecretCustomLabelsAndAnnotations() { @ParallelTest public void testMetricsParsingNoMetrics() { KafkaMirrorMaker2Cluster kmm = KafkaMirrorMaker2Cluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, this.resource, VERSIONS, SHARED_ENV_PROVIDER); + assertThat(kmm.metrics(), is(nullValue())); + } + + @ParallelTest + public void testStrimziMetricsReporterConfig() { + KafkaMirrorMaker2 resourceWithMetrics = new KafkaMirrorMaker2Builder(resource) + .editSpec() + .withNewStrimziMetricsReporterConfig() + .withNewValues() + .withAllowList(List.of("kafka_log.*", "kafka_network.*")) + .endValues() + .endStrimziMetricsReporterConfig() + .endSpec() + .build(); + + InvalidResourceException ex = assertThrows(InvalidResourceException.class, + () -> KafkaMirrorMaker2Cluster.fromCrd(Reconciliation.DUMMY_RECONCILIATION, resourceWithMetrics, VERSIONS, SHARED_ENV_PROVIDER)); - assertThat(kmm.metrics().isEnabled(), is(false)); - assertThat(kmm.metrics().getConfigMapName(), is(nullValue())); - assertThat(kmm.metrics().getConfigMapKey(), is(nullValue())); + assertThat(ex.getMessage(), is("The Strimzi Metrics Reporter is not supported for this component")); } @ParallelTest diff --git a/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModelTest.java b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModelTest.java new file mode 100644 index 00000000000..514e1c4156b --- /dev/null +++ b/cluster-operator/src/test/java/io/strimzi/operator/cluster/model/metrics/StrimziMetricsReporterModelTest.java @@ -0,0 +1,75 @@ +/* + * Copyright Strimzi authors. + * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). + */ +package io.strimzi.operator.cluster.model.metrics; + +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporter; +import io.strimzi.api.kafka.model.common.metrics.StrimziMetricsReporterBuilder; +import io.strimzi.api.kafka.model.kafka.KafkaClusterSpecBuilder; +import io.strimzi.operator.common.model.InvalidResourceException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class StrimziMetricsReporterModelTest { + + @Test + public void testDisabled() { + StrimziMetricsReporterModel metrics = new StrimziMetricsReporterModel(new KafkaClusterSpecBuilder().build()); + + assertThat(metrics.isEnabled(), is(false)); + assertThat(metrics.getAllowList(), is(Optional.empty())); + } + + @Test + public void testEnabled() { + StrimziMetricsReporter metricsConfig = new StrimziMetricsReporterBuilder() + .withNewValues() + .withAllowList(List.of("kafka_log.*", "kafka_network.*")) + .endValues() + .build(); + StrimziMetricsReporterModel metrics = new StrimziMetricsReporterModel(new KafkaClusterSpecBuilder() + .withMetricsConfig(metricsConfig).build()); + + assertThat(metrics.isEnabled(), is(true)); + assertThat(metrics.getAllowList().get(), is("kafka_log.*,kafka_network.*")); + } + + @Test + public void testValidation() { + assertDoesNotThrow(() -> StrimziMetricsReporterModel.validate(new StrimziMetricsReporterBuilder() + .withNewValues() + .withAllowList(List.of("kafka_log.*", "kafka_network.*")) + .endValues() + .build()) + ); + + InvalidResourceException ise0 = assertThrows(InvalidResourceException.class, () -> StrimziMetricsReporterModel.validate( + new StrimziMetricsReporterBuilder() + .withNewValues() + .withAllowList(List.of()) + .endValues() + .build()) + ); + assertThat(ise0.getMessage(), is("Metrics configuration is invalid: [Allowlist should contain at least one element]")); + + + InvalidResourceException ise1 = Assertions.assertThrows(InvalidResourceException.class, () -> StrimziMetricsReporterModel.validate( + new StrimziMetricsReporterBuilder() + .withNewValues() + .withAllowList(List.of("kafka_network.*", "kafka_log.***", "[a+")) + .endValues() + .build()) + ); + assertThat(ise1.getMessage(), is("Metrics configuration is invalid: [Invalid regex: kafka_log.***, Dangling meta character '*', Invalid regex: [a+, Unclosed character class]")); + } + +} diff --git a/docker-images/artifacts/kafka-thirdparty-libs/3.8.x/pom.xml b/docker-images/artifacts/kafka-thirdparty-libs/3.8.x/pom.xml index d71258c2fb3..a901ce5f8d7 100644 --- a/docker-images/artifacts/kafka-thirdparty-libs/3.8.x/pom.xml +++ b/docker-images/artifacts/kafka-thirdparty-libs/3.8.x/pom.xml @@ -17,6 +17,8 @@ 0.15.0 + 0.1.0 + 1.3.1 2.9.0 2.5.141 1.5.1 @@ -317,6 +319,27 @@ + + + io.strimzi + metrics-reporter + ${strimzi-metrics-reporter.version} + + + io.prometheus + prometheus-metrics-model + ${prometheus.version} + + + io.prometheus + prometheus-metrics-instrumentation-jvm + ${prometheus.version} + + + io.prometheus + prometheus-metrics-exporter-httpserver + ${prometheus.version} + org.openpolicyagent.kafka diff --git a/docker-images/artifacts/kafka-thirdparty-libs/3.9.x/pom.xml b/docker-images/artifacts/kafka-thirdparty-libs/3.9.x/pom.xml index d71258c2fb3..a901ce5f8d7 100644 --- a/docker-images/artifacts/kafka-thirdparty-libs/3.9.x/pom.xml +++ b/docker-images/artifacts/kafka-thirdparty-libs/3.9.x/pom.xml @@ -17,6 +17,8 @@ 0.15.0 + 0.1.0 + 1.3.1 2.9.0 2.5.141 1.5.1 @@ -317,6 +319,27 @@ + + + io.strimzi + metrics-reporter + ${strimzi-metrics-reporter.version} + + + io.prometheus + prometheus-metrics-model + ${prometheus.version} + + + io.prometheus + prometheus-metrics-instrumentation-jvm + ${prometheus.version} + + + io.prometheus + prometheus-metrics-exporter-httpserver + ${prometheus.version} + org.openpolicyagent.kafka diff --git a/docker-images/artifacts/kafka-thirdparty-libs/cc/pom.xml b/docker-images/artifacts/kafka-thirdparty-libs/cc/pom.xml index 9f60587f4a0..84b8c1b5705 100644 --- a/docker-images/artifacts/kafka-thirdparty-libs/cc/pom.xml +++ b/docker-images/artifacts/kafka-thirdparty-libs/cc/pom.xml @@ -17,6 +17,8 @@ 2.5.141 + 0.1.0 + 1.3.1 @@ -32,5 +34,25 @@ cruise-control ${cruise-control.version} + + io.strimzi + metrics-reporter + ${strimzi-metrics-reporter.version} + + + io.prometheus + prometheus-metrics-model + ${prometheus.version} + + + io.prometheus + prometheus-metrics-instrumentation-jvm + ${prometheus.version} + + + io.prometheus + prometheus-metrics-exporter-httpserver + ${prometheus.version} + diff --git a/docker-images/kafka-based/kafka/cruise-control-scripts/cruise_control_run.sh b/docker-images/kafka-based/kafka/cruise-control-scripts/cruise_control_run.sh index 7c33a729552..3a464566ae6 100755 --- a/docker-images/kafka-based/kafka/cruise-control-scripts/cruise_control_run.sh +++ b/docker-images/kafka-based/kafka/cruise-control-scripts/cruise_control_run.sh @@ -35,7 +35,7 @@ if [ "$FIPS_MODE" = "disabled" ]; then fi # enabling Prometheus JMX exporter as Java agent -if [ "$CRUISE_CONTROL_METRICS_ENABLED" = "true" ]; then +if [ "$CRUISE_CONTROL_JMX_EXPORTER_ENABLED" = "true" ]; then KAFKA_OPTS="${KAFKA_OPTS} -javaagent:$(ls "$JMX_EXPORTER_HOME"/jmx_prometheus_javaagent*.jar)=9404:$CRUISE_CONTROL_HOME/custom-config/metrics-config.json" export KAFKA_OPTS fi diff --git a/docker-images/kafka-based/kafka/scripts/kafka_connect_run.sh b/docker-images/kafka-based/kafka/scripts/kafka_connect_run.sh index 71b25a59951..cf84892b722 100755 --- a/docker-images/kafka-based/kafka/scripts/kafka_connect_run.sh +++ b/docker-images/kafka-based/kafka/scripts/kafka_connect_run.sh @@ -44,7 +44,7 @@ fi export LOG_DIR="$KAFKA_HOME" # enabling Prometheus JMX exporter as Java agent -if [ "$KAFKA_CONNECT_METRICS_ENABLED" = "true" ]; then +if [ "$KAFKA_CONNECT_JMX_EXPORTER_ENABLED" = "true" ]; then KAFKA_OPTS="${KAFKA_OPTS} -javaagent:$(ls "$JMX_EXPORTER_HOME"/jmx_prometheus_javaagent*.jar)=9404:$KAFKA_HOME/custom-config/metrics-config.json" export KAFKA_OPTS fi diff --git a/docker-images/kafka-based/kafka/scripts/kafka_run.sh b/docker-images/kafka-based/kafka/scripts/kafka_run.sh index b3a2f9ee0bc..b10837f3995 100755 --- a/docker-images/kafka-based/kafka/scripts/kafka_run.sh +++ b/docker-images/kafka-based/kafka/scripts/kafka_run.sh @@ -28,8 +28,8 @@ if [ "$FIPS_MODE" = "disabled" ]; then export KAFKA_OPTS="${KAFKA_OPTS} -Dcom.redhat.fips=false" fi -# enabling Prometheus JMX exporter as Java agent -if [ "$KAFKA_METRICS_ENABLED" = "true" ]; then +# Enable Prometheus JMX exporter as Java agent +if [ "$KAFKA_JMX_EXPORTER_ENABLED" = "true" ]; then KAFKA_OPTS="${KAFKA_OPTS} -javaagent:$(ls "$JMX_EXPORTER_HOME"/jmx_prometheus_javaagent*.jar)=9404:$KAFKA_HOME/custom-config/metrics-config.json" export KAFKA_OPTS fi diff --git a/documentation/modules/appendix_crds.adoc b/documentation/modules/appendix_crds.adoc index 6a054656287..b94bdb747a0 100644 --- a/documentation/modules/appendix_crds.adoc +++ b/documentation/modules/appendix_crds.adoc @@ -87,7 +87,7 @@ include::../api/io.strimzi.api.kafka.model.kafka.KafkaClusterSpec.adoc[leveloffs |Configures listeners to provide access to Kafka brokers. |config |map -|Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms). +|Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list, kafka.metric.reporters, prometheus.metrics.reporter. (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms). |storage |xref:type-EphemeralStorage-{context}[`EphemeralStorage`], xref:type-PersistentClaimStorage-{context}[`PersistentClaimStorage`], xref:type-JbodStorage-{context}[`JbodStorage`] |**The `storage` property has been deprecated.** For KRaft-based Apache Kafka clusters, storage is configured in the KafkaNodePool resources and this option is ignored. For KRaft-based Apache Kafka clusters, storage is configured in the KafkaNodePool resources and this option is ignored. @@ -116,7 +116,7 @@ include::../api/io.strimzi.api.kafka.model.kafka.KafkaClusterSpec.adoc[leveloffs |https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#resourcerequirements-v1-core[ResourceRequirements] |CPU and memory resources to reserve. |metricsConfig -|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`] +|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`], xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] |Metrics configuration. |logging |xref:type-InlineLogging-{context}[`InlineLogging`], xref:type-ExternalLogging-{context}[`ExternalLogging`] @@ -1020,7 +1020,7 @@ It must have the value `password` for the type `KafkaJmxAuthenticationPassword`. Used in: xref:type-CruiseControlSpec-{context}[`CruiseControlSpec`], xref:type-KafkaClusterSpec-{context}[`KafkaClusterSpec`], xref:type-KafkaConnectSpec-{context}[`KafkaConnectSpec`], xref:type-KafkaMirrorMaker2Spec-{context}[`KafkaMirrorMaker2Spec`], xref:type-ZookeeperClusterSpec-{context}[`ZookeeperClusterSpec`] -The `type` property is a discriminator that distinguishes use of the `JmxPrometheusExporterMetrics` type from other subtypes which may be added in the future. +The `type` property is a discriminator that distinguishes use of the `JmxPrometheusExporterMetrics` type from xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`]. It must have the value `jmxPrometheusExporter` for the type `JmxPrometheusExporterMetrics`. [cols="2,2,3a",options="header"] |==== @@ -1047,6 +1047,39 @@ Used in: xref:type-ExternalLogging-{context}[`ExternalLogging`], xref:type-JmxPr |Reference to the key in the ConfigMap containing the configuration. |==== +[id='type-StrimziMetricsReporter-{context}'] += `StrimziMetricsReporter` schema reference + +Used in: xref:type-CruiseControlSpec-{context}[`CruiseControlSpec`], xref:type-KafkaClusterSpec-{context}[`KafkaClusterSpec`], xref:type-KafkaConnectSpec-{context}[`KafkaConnectSpec`], xref:type-KafkaMirrorMaker2Spec-{context}[`KafkaMirrorMaker2Spec`], xref:type-ZookeeperClusterSpec-{context}[`ZookeeperClusterSpec`] + + +The `type` property is a discriminator that distinguishes use of the `StrimziMetricsReporter` type from xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`]. +It must have the value `strimziMetricsReporter` for the type `StrimziMetricsReporter`. +[cols="2,2,3a",options="header"] +|==== +|Property |Property type |Description +|type +|string +|Must be `strimziMetricsReporter`. +|values +|xref:type-StrimziMetricsReporterValues-{context}[`StrimziMetricsReporterValues`] +|Configuration values for the Strimzi Metrics Reporter. +|==== + +[id='type-StrimziMetricsReporterValues-{context}'] += `StrimziMetricsReporterValues` schema reference + +Used in: xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] + + +[cols="2,2,3a",options="header"] +|==== +|Property |Property type |Description +|allowList +|string array +|A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`. +|==== + [id='type-InlineLogging-{context}'] = `InlineLogging` schema reference @@ -1552,7 +1585,7 @@ Used in: xref:type-KafkaSpec-{context}[`KafkaSpec`] |https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#resourcerequirements-v1-core[ResourceRequirements] |CPU and memory resources to reserve. |metricsConfig -|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`] +|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`], xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] |Metrics configuration. |logging |xref:type-InlineLogging-{context}[`InlineLogging`], xref:type-ExternalLogging-{context}[`ExternalLogging`] @@ -1904,7 +1937,7 @@ include::../api/io.strimzi.api.kafka.model.kafka.cruisecontrol.CruiseControlSpec |map |The Cruise Control configuration. For a full list of configuration options refer to https://github.com/linkedin/cruise-control/wiki/Configurations. Note that properties with the following prefixes cannot be set: bootstrap.servers, client.id, zookeeper., network., security., failed.brokers.zk.path,webserver.http., webserver.api.urlprefix, webserver.session.path, webserver.accesslog., two.step., request.reason.required,metric.reporter.sampler.bootstrap.servers, capacity.config.file, self.healing., ssl., kafka.broker.failure.detection.enable, topic.config.provider.class (with the exception of: ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, webserver.http.cors.enabled, webserver.http.cors.origin, webserver.http.cors.exposeheaders, webserver.security.enable, webserver.ssl.enable). |metricsConfig -|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`] +|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`], xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] |Metrics configuration. |apiUsers |xref:type-HashLoginServiceApiUsers-{context}[`HashLoginServiceApiUsers`] @@ -2493,7 +2526,7 @@ include::../api/io.strimzi.api.kafka.model.connect.KafkaConnectSpec.adoc[levelof |xref:type-Rack-{context}[`Rack`] |Configuration of the node label which will be used as the `client.rack` consumer configuration. |metricsConfig -|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`] +|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`], xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] |Metrics configuration. |tracing |xref:type-JaegerTracing-{context}[`JaegerTracing`], xref:type-OpenTelemetryTracing-{context}[`OpenTelemetryTracing`] @@ -4088,7 +4121,7 @@ Used in: xref:type-KafkaMirrorMaker2-{context}[`KafkaMirrorMaker2`] |xref:type-Rack-{context}[`Rack`] |Configuration of the node label which will be used as the `client.rack` consumer configuration. |metricsConfig -|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`] +|xref:type-JmxPrometheusExporterMetrics-{context}[`JmxPrometheusExporterMetrics`], xref:type-StrimziMetricsReporter-{context}[`StrimziMetricsReporter`] |Metrics configuration. |tracing |xref:type-JaegerTracing-{context}[`JaegerTracing`], xref:type-OpenTelemetryTracing-{context}[`OpenTelemetryTracing`] diff --git a/documentation/modules/con-common-configuration-properties.adoc b/documentation/modules/con-common-configuration-properties.adoc index edf819c001f..e6b30bb83cc 100644 --- a/documentation/modules/con-common-configuration-properties.adoc +++ b/documentation/modules/con-common-configuration-properties.adoc @@ -433,7 +433,15 @@ For more information about the `livenessProbe` and `readinessProbe` options, see == `metricsConfig` Use the `metricsConfig` property to enable and configure Prometheus metrics. +Strimzi provides support for Prometheus JMX Exporter and Strimzi Metrics Reporter. Only one of these can be selected at any given time. +When metrics are enabled, they are exposed on port 9404. + +When the `metricsConfig` (or deprecated `metrics`) property is not defined in the resource, the Prometheus metrics are disabled. + +For more information about setting up and deploying Prometheus and Grafana, see link:{BookURLDeploying}#assembly-metrics-str[Introducing Metrics to Kafka^]. + +.Using Prometheus JMX Exporter The `metricsConfig` property contains a reference to a ConfigMap that has additional configurations for the {JMXExporter}. Strimzi supports Prometheus metrics using Prometheus JMX exporter to convert the JMX metrics supported by Apache Kafka to Prometheus metrics. @@ -481,11 +489,32 @@ spec: # ... ---- -When metrics are enabled, they are exposed on port 9404. +.Using Strimzi Metrics Reporter +The `metricsConfig` property contains configurations for the {StrimziMetricsReporter}. +Strimzi supports Prometheus metrics using Strimzi Metrics Reporter to directly expose the metrics provided by Apache Kafka (JMX is not required). -When the `metricsConfig` (or deprecated `metrics`) property is not defined in the resource, the Prometheus metrics are disabled. +To enable Strimzi Metrics Reporter, set the type to `strimziMetricsReporter`. +The `allowList` configuration is a comma separated list of regex patterns to filter the metrics that are collected. This defaults to `.*`, which allows all metrics. -For more information about setting up and deploying Prometheus and Grafana, see link:{BookURLDeploying}#assembly-metrics-str[Introducing Metrics to Kafka^]. +NOTE: Using `strimziMetricsReporter` is only supported in the Kafka component. + +.Example metrics configuration for Kafka +[source,yaml,subs="+attributes"] +---- +apiVersion: {KafkaApiVersion} +kind: Kafka +metadata: + name: my-cluster +spec: + kafka: + # ... + metricsConfig: + type: strimziMetricsReporter + values: + allowList: + key: ".*" + # ... +---- [id='con-common-configuration-jvm-{context}'] == `jvmOptions` diff --git a/documentation/shared/attributes.adoc b/documentation/shared/attributes.adoc index ec72fdce9d3..df70f31ebf4 100644 --- a/documentation/shared/attributes.adoc +++ b/documentation/shared/attributes.adoc @@ -46,6 +46,7 @@ //Monitoring links :GrafanaHome: link:https://grafana.com/[Grafana Labs^] :JMXExporter: link:https://github.com/prometheus/jmx_exporter[Prometheus JMX Exporter^] +:StrimziMetricsReporter: link:https://github.com/strimzi/metrics-reporter[Strimzi Metrics Reporter^] :PrometheusHome: link:https://github.com/prometheus[Prometheus^] :PrometheusConfig: link:https://prometheus.io/docs/prometheus/latest/configuration/configuration[Prometheus configuration^] :kafka-exporter-project: link:https://github.com/danielqsj/kafka_exporter[Kafka Exporter^] diff --git a/packaging/examples/metrics/grafana-dashboards/strimzi-kafka.json b/packaging/examples/metrics/grafana-dashboards/strimzi-kafka.json index 7e037281990..d9b88e097fa 100644 --- a/packaging/examples/metrics/grafana-dashboards/strimzi-kafka.json +++ b/packaging/examples/metrics/grafana-dashboards/strimzi-kafka.json @@ -268,7 +268,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_controller_controllerstats_uncleanleaderelections_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m]))", + "expr": "sum(irate(kafka_controller_controllerstats_uncleanleaderelections_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m])) or sum(irate(kafka_controller_controllerstats_uncleanleaderelectionspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1494,7 +1494,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1575,7 +1575,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesoutpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1656,7 +1656,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_messagesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1737,7 +1737,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1829,7 +1829,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "instant": false, @@ -1840,7 +1840,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesoutpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1931,7 +1931,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_messagesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Total Incoming Messages Rate", @@ -2022,7 +2022,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Total Produce Request Rate", @@ -2030,7 +2030,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_failedproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_failedproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_failedproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -2122,7 +2122,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalfetchrequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Fetch Request Rate", @@ -2130,7 +2130,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": " sum(irate(kafka_server_brokertopicmetrics_failedfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_failedfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_failedfetchrequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Failed Fetch Request Rate", @@ -2221,7 +2221,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_network_socketserver_networkprocessoravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", + "expr": "sum(kafka_network_socketserver_networkprocessoravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name) or sum(kafka_network_socketserver_networkprocessoravgidlepercent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{kubernetes_pod_name}}", @@ -2312,7 +2312,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name) or sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidlepercent_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "intervalFactor": 1, diff --git a/packaging/examples/metrics/grafana-dashboards/strimzi-kraft.json b/packaging/examples/metrics/grafana-dashboards/strimzi-kraft.json index 96055f96e4c..63582df613b 100644 --- a/packaging/examples/metrics/grafana-dashboards/strimzi-kraft.json +++ b/packaging/examples/metrics/grafana-dashboards/strimzi-kraft.json @@ -874,7 +874,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "instant": false, @@ -968,7 +968,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -1060,7 +1060,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "instant": false, @@ -1122,7 +1122,7 @@ "pluginVersion": "7.4.5", "targets": [ { - "expr": "max(kafka_server_raftmetrics_current_state) by (kubernetes_pod_name, current_state)", + "expr": "max(kafka_server_raftmetrics_current_state) by (kubernetes_pod_name, current_state) or max(kafka_server_raft_metrics_current_state_info) by (kubernetes_pod_name, current_state)", "format": "table", "instant": true, "interval": "", @@ -1238,7 +1238,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1332,7 +1332,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1426,7 +1426,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1519,7 +1519,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_incoming_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_incoming_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_incoming_byte{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1612,7 +1612,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_outgoing_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_outgoing_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_outgoing_byte{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1705,7 +1705,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_request_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_request_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_request{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1798,7 +1798,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_response_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_response_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_response{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1891,7 +1891,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1984,7 +1984,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -2031,7 +2031,7 @@ "multi": false, "name": "kubernetes_namespace", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader)", + "query": "query_result(kafka_server_raftmetrics_current_leader or kafka_server_raft_metrics_current_leader)", "refresh": 1, "regex": "/.*namespace=\"([^\"]*).*/", "skipUrlSync": false, @@ -2051,7 +2051,7 @@ "multi": false, "name": "strimzi_cluster_name", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\"})", + "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\"} or kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\"})", "refresh": 1, "regex": "/.*strimzi_io_cluster=\"([^\"]*).*/", "skipUrlSync": false, @@ -2072,7 +2072,7 @@ "multi": false, "name": "kraft_node", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"} or kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", "refresh": 1, "regex": "/.*pod_name=\"$strimzi_cluster_name-([^\"]*).*/", "skipUrlSync": false, diff --git a/packaging/examples/metrics/reporter/kafka-metrics.yaml b/packaging/examples/metrics/reporter/kafka-metrics.yaml new file mode 100644 index 00000000000..9194cf45cec --- /dev/null +++ b/packaging/examples/metrics/reporter/kafka-metrics.yaml @@ -0,0 +1,77 @@ +apiVersion: kafka.strimzi.io/v1beta2 +kind: KafkaNodePool +metadata: + name: controller + labels: + strimzi.io/cluster: my-cluster +spec: + replicas: 3 + roles: + - controller + storage: + type: jbod + volumes: + - id: 0 + type: persistent-claim + size: 100Gi + kraftMetadata: shared + deleteClaim: false +--- + +apiVersion: kafka.strimzi.io/v1beta2 +kind: KafkaNodePool +metadata: + name: broker + labels: + strimzi.io/cluster: my-cluster +spec: + replicas: 3 + roles: + - broker + storage: + type: jbod + volumes: + - id: 0 + type: persistent-claim + size: 100Gi + kraftMetadata: shared + deleteClaim: false +--- + +apiVersion: kafka.strimzi.io/v1beta2 +kind: Kafka +metadata: + name: my-cluster + annotations: + strimzi.io/node-pools: enabled + strimzi.io/kraft: enabled +spec: + kafka: + version: 3.9.0 + metadataVersion: 3.9-IV0 + listeners: + - name: plain + port: 9092 + type: internal + tls: false + - name: tls + port: 9093 + type: internal + tls: true + config: + offsets.topic.replication.factor: 3 + transaction.state.log.replication.factor: 3 + transaction.state.log.min.isr: 2 + default.replication.factor: 3 + min.insync.replicas: 2 + metricsConfig: + type: strimziMetricsReporter + values: + allowList: + - ".*" + entityOperator: + topicOperator: {} + userOperator: {} + kafkaExporter: + topicRegex: ".*" + groupRegex: ".*" diff --git a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/040-Crd-kafka.yaml b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/040-Crd-kafka.yaml index a7707980bf7..07e4b89464d 100644 --- a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/040-Crd-kafka.yaml +++ b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/040-Crd-kafka.yaml @@ -553,7 +553,7 @@ spec: config: x-kubernetes-preserve-unknown-fields: true type: object - description: "Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms)." + description: "Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list, kafka.metric.reporters, prometheus.metrics.reporter. (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms)." storage: type: object properties: @@ -917,7 +917,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -932,9 +933,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. logging: type: object @@ -2482,7 +2491,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -2497,9 +2507,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. logging: type: object @@ -6475,7 +6493,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -6490,9 +6509,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. apiUsers: type: object diff --git a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/041-Crd-kafkaconnect.yaml b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/041-Crd-kafkaconnect.yaml index 268c560e087..79f68696a97 100644 --- a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/041-Crd-kafkaconnect.yaml +++ b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/041-Crd-kafkaconnect.yaml @@ -452,7 +452,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -467,9 +468,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. tracing: type: object diff --git a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/048-Crd-kafkamirrormaker2.yaml b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/048-Crd-kafkamirrormaker2.yaml index a72814d313c..9869dd04275 100644 --- a/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/048-Crd-kafkamirrormaker2.yaml +++ b/packaging/helm-charts/helm3/strimzi-kafka-operator/crds/048-Crd-kafkamirrormaker2.yaml @@ -669,7 +669,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -684,9 +685,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. tracing: type: object diff --git a/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kafka.json b/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kafka.json index 7e037281990..d9b88e097fa 100644 --- a/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kafka.json +++ b/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kafka.json @@ -268,7 +268,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_controller_controllerstats_uncleanleaderelections_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m]))", + "expr": "sum(irate(kafka_controller_controllerstats_uncleanleaderelections_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m])) or sum(irate(kafka_controller_controllerstats_uncleanleaderelectionspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1494,7 +1494,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1575,7 +1575,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesoutpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1656,7 +1656,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_messagesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1737,7 +1737,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1829,7 +1829,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "instant": false, @@ -1840,7 +1840,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_bytesout_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_bytesoutpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -1931,7 +1931,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_messagesin_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_messagesinpersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Total Incoming Messages Rate", @@ -2022,7 +2022,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Total Produce Request Rate", @@ -2030,7 +2030,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_failedproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_failedproducerequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_failedproducerequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "hide": false, "intervalFactor": 1, @@ -2122,7 +2122,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_brokertopicmetrics_totalfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_totalfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_totalfetchrequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Fetch Request Rate", @@ -2130,7 +2130,7 @@ }, { "datasource": "${DS_PROMETHEUS}", - "expr": " sum(irate(kafka_server_brokertopicmetrics_failedfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", + "expr": "sum(irate(kafka_server_brokertopicmetrics_failedfetchrequests_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) or sum(irate(kafka_server_brokertopicmetrics_failedfetchrequestspersec_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",topic=~\"$kafka_topic\",topic!=\"\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "Failed Fetch Request Rate", @@ -2221,7 +2221,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_network_socketserver_networkprocessoravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", + "expr": "sum(kafka_network_socketserver_networkprocessoravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name) or sum(kafka_network_socketserver_networkprocessoravgidlepercent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{kubernetes_pod_name}}", @@ -2312,7 +2312,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidle_percent{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name) or sum(kafka_server_kafkarequesthandlerpool_requesthandleravgidlepercent_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}*100) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "intervalFactor": 1, diff --git a/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kraft.json b/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kraft.json index 96055f96e4c..63582df613b 100644 --- a/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kraft.json +++ b/packaging/helm-charts/helm3/strimzi-kafka-operator/files/grafana-dashboards/strimzi-kraft.json @@ -874,7 +874,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_append_records_rate{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "instant": false, @@ -968,7 +968,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_fetch_records_rate{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "interval": "", "intervalFactor": 1, @@ -1060,7 +1060,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_commit_latency_avg{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "instant": false, @@ -1122,7 +1122,7 @@ "pluginVersion": "7.4.5", "targets": [ { - "expr": "max(kafka_server_raftmetrics_current_state) by (kubernetes_pod_name, current_state)", + "expr": "max(kafka_server_raftmetrics_current_state) by (kubernetes_pod_name, current_state) or max(kafka_server_raft_metrics_current_state_info) by (kubernetes_pod_name, current_state)", "format": "table", "instant": true, "interval": "", @@ -1238,7 +1238,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1332,7 +1332,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_vote{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1426,7 +1426,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_current_epoch{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1519,7 +1519,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_incoming_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_incoming_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_incoming_byte{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1612,7 +1612,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_outgoing_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_outgoing_byte_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_outgoing_byte{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1705,7 +1705,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_request_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_request_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_request{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1798,7 +1798,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(irate(kafka_server_raftchannelmetrics_response_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", + "expr": "sum(irate(kafka_server_raftchannelmetrics_response_total{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name) or sum(irate(kafka_server_raft_channel_metrics_response{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\"}[5m])) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1891,7 +1891,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_high_watermark{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -1984,7 +1984,7 @@ "targets": [ { "datasource": "${DS_PROMETHEUS}", - "expr": "sum(kafka_server_raftmetrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "expr": "sum(kafka_server_raftmetrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name) or sum(kafka_server_raft_metrics_log_end_offset{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", "format": "time_series", "hide": false, "interval": "", @@ -2031,7 +2031,7 @@ "multi": false, "name": "kubernetes_namespace", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader)", + "query": "query_result(kafka_server_raftmetrics_current_leader or kafka_server_raft_metrics_current_leader)", "refresh": 1, "regex": "/.*namespace=\"([^\"]*).*/", "skipUrlSync": false, @@ -2051,7 +2051,7 @@ "multi": false, "name": "strimzi_cluster_name", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\"})", + "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\"} or kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\"})", "refresh": 1, "regex": "/.*strimzi_io_cluster=\"([^\"]*).*/", "skipUrlSync": false, @@ -2072,7 +2072,7 @@ "multi": false, "name": "kraft_node", "options": [], - "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "query": "query_result(kafka_server_raftmetrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"} or kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", "refresh": 1, "regex": "/.*pod_name=\"$strimzi_cluster_name-([^\"]*).*/", "skipUrlSync": false, diff --git a/packaging/install/cluster-operator/040-Crd-kafka.yaml b/packaging/install/cluster-operator/040-Crd-kafka.yaml index 9831144eb08..e3fe2565702 100644 --- a/packaging/install/cluster-operator/040-Crd-kafka.yaml +++ b/packaging/install/cluster-operator/040-Crd-kafka.yaml @@ -552,7 +552,7 @@ spec: config: x-kubernetes-preserve-unknown-fields: true type: object - description: "Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms)." + description: "Kafka broker config properties with the following prefixes cannot be set: listeners, advertised., broker., listener., host.name, port, inter.broker.listener.name, sasl., ssl., security., password., log.dir, zookeeper.connect, zookeeper.set.acl, zookeeper.ssl, zookeeper.clientCnxnSocket, authorizer., super.user, cruise.control.metrics.topic, cruise.control.metrics.reporter.bootstrap.servers, node.id, process.roles, controller., metadata.log.dir, zookeeper.metadata.migration.enable, client.quota.callback.static.kafka.admin., client.quota.callback.static.produce, client.quota.callback.static.fetch, client.quota.callback.static.storage.per.volume.limit.min.available., client.quota.callback.static.excluded.principal.name.list, kafka.metric.reporters, prometheus.metrics.reporter. (with the exception of: zookeeper.connection.timeout.ms, sasl.server.max.receive.size, ssl.cipher.suites, ssl.protocol, ssl.enabled.protocols, ssl.secure.random.implementation, cruise.control.metrics.topic.num.partitions, cruise.control.metrics.topic.replication.factor, cruise.control.metrics.topic.retention.ms, cruise.control.metrics.topic.auto.create.retries, cruise.control.metrics.topic.auto.create.timeout.ms, cruise.control.metrics.topic.min.insync.replicas, controller.quorum.election.backoff.max.ms, controller.quorum.election.timeout.ms, controller.quorum.fetch.timeout.ms)." storage: type: object properties: @@ -916,7 +916,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -931,9 +932,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. logging: type: object @@ -2481,7 +2490,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -2496,9 +2506,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. logging: type: object @@ -6474,7 +6492,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -6489,9 +6508,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. apiUsers: type: object diff --git a/packaging/install/cluster-operator/041-Crd-kafkaconnect.yaml b/packaging/install/cluster-operator/041-Crd-kafkaconnect.yaml index 4c2a995b00f..3ee447c4693 100644 --- a/packaging/install/cluster-operator/041-Crd-kafkaconnect.yaml +++ b/packaging/install/cluster-operator/041-Crd-kafkaconnect.yaml @@ -451,7 +451,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -466,9 +467,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. tracing: type: object diff --git a/packaging/install/cluster-operator/048-Crd-kafkamirrormaker2.yaml b/packaging/install/cluster-operator/048-Crd-kafkamirrormaker2.yaml index 67bcff310dd..666ca40d17b 100644 --- a/packaging/install/cluster-operator/048-Crd-kafkamirrormaker2.yaml +++ b/packaging/install/cluster-operator/048-Crd-kafkamirrormaker2.yaml @@ -668,7 +668,8 @@ spec: type: string enum: - jmxPrometheusExporter - description: Metrics type. Only 'jmxPrometheusExporter' supported currently. + - strimziMetricsReporter + description: Metrics type. The supported types are `jmxPrometheusExporter` and `strimziMetricsReporter`. Type `jmxPrometheusExporter` uses the Prometheus JMX Exporter to expose Kafka JMX metrics in Prometheus format through an HTTP endpoint. Type `strimziMetricsReporter` uses the Strimzi Metrics Reporter to directly expose Kafka metrics in Prometheus format through an HTTP endpoint. valueFrom: type: object properties: @@ -683,9 +684,17 @@ spec: type: boolean description: Reference to the key in the ConfigMap containing the configuration. description: 'ConfigMap entry where the Prometheus JMX Exporter configuration is stored. ' + values: + type: object + properties: + allowList: + type: array + items: + type: string + description: "A comma separated list of regex patterns to specify the metrics to collect. Default: `.*`." + description: Configuration values for the Strimzi Metrics Reporter. required: - type - - valueFrom description: Metrics configuration. tracing: type: object