diff --git a/CHANGELOG.md b/CHANGELOG.md index 1039c8ccccd..d7aba6f147d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * 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 brokers/controllers components. + Support for Kafka Connect, MirrorMaker2 and Http Bridge will be added subsequently. ### 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..63be3f29c9f 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,7 @@ 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()))); + varList.add(ContainerUtils.createEnvVar(ENV_VAR_CRUISE_CONTROL_JMX_EXPORTER_ENABLED, jmxExporterMetrics != null && jmxExporterMetrics.isEnabled() ? Boolean.TRUE.toString() : Boolean.FALSE.toString())); 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 +486,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 +511,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..859f001bd5b 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; @@ -55,11 +56,11 @@ */ public class KafkaBrokerConfigurationBuilder { private final static String CONTROL_PLANE_LISTENER_NAME = "CONTROLPLANE-9090"; + private final static String KAFKA_METRIC_REPORTERS_CONFIG_FIELD = "metric.reporters"; private final static String REPLICATION_LISTENER_NAME = "REPLICATION-9091"; // 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 +135,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. @@ -787,28 +808,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(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(KAFKA_METRIC_REPORTERS_CONFIG_FIELD, metricReporters); } printSectionHeader("User provided configuration"); @@ -818,10 +844,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(KAFKA_METRIC_REPORTERS_CONFIG_FIELD + "=" + metricReporters); writer.println(); } } @@ -829,6 +862,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..0b19bd29782 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,7 @@ 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"; + /** * Port number used for control plane */ @@ -228,7 +232,9 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp private String clusterId; private JmxModel jmx; private CruiseControlMetricsReporter ccMetricsReporter; - private MetricsModel metrics; + // new MetricsModel metrics + private MetricsModel jmxExporterMetrics; + private StrimziMetricsReporterModel strimziMetricsReporter; private LoggingModel logging; private QuotasPlugin quotas; /* test */ KafkaConfiguration configuration; @@ -289,6 +295,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 +305,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 +338,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 +1322,11 @@ private List getContainerPortList(KafkaPool pool) { } // Metrics port is enabled on all node types regardless their role - if (metrics.isEnabled()) { + // if metrics instance of + 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 +1520,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 +1640,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 +1753,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 +1855,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 +1873,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 +1951,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..e1e0e3b5d26 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", @@ -609,14 +669,14 @@ public void testUserConfigurationWithCCMetricsReporter() { } @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/reporter/grafana-dashboards/strimzi-kafka.json b/packaging/examples/metrics/reporter/grafana-dashboards/strimzi-kafka.json new file mode 100644 index 00000000000..ca61248a9d3 --- /dev/null +++ b/packaging/examples/metrics/reporter/grafana-dashboards/strimzi-kafka.json @@ -0,0 +1,2888 @@ +{ + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Timeseries" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 22, + "links": [], + "panels": [ + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of brokers online", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 46, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "repeatDirection": "h", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "count(kafka_server_replicamanager_leadercount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Brokers Online", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of active controllers in the cluster", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + }, + { + "color": "#e5ac0e", + "value": 2 + }, + { + "color": "#bf1b00" + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 0 + }, + "id": 36, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_controller_kafkacontroller_activecontrollercount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Active Controllers", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Unclean leader election rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 2 + }, + { + "color": "#d44a3a" + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 0 + }, + "id": 38, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "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, + "refId": "A" + } + ], + "title": "Unclean Leader Election Rate", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Replicas that are online", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 0 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 0 + }, + "id": 40, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_server_replicamanager_partitioncount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Online Replicas", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of under-replicated partitions (| ISR | < | all replicas |).", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#508642", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 1 + }, + { + "color": "#bf1b00", + "value": 5 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 0 + }, + "id": 30, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_server_replicamanager_underreplicatedpartitions{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "A" + } + ], + "title": "Under Replicated Partitions", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of partitions which are at their minimum in sync replica count (| ISR | == | min.insync.replicas |)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "#508642", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#508642", + "value": null + }, + { + "color": "#ef843c", + "value": 1 + }, + { + "color": "#bf1b00", + "value": 5 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 0 + }, + "id": 102, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_cluster_partition_atminisr{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "A" + } + ], + "title": "Partitions at minimum ISR", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of partitions which are under their minimum in sync replica count (| ISR | < | min.insync.replicas |)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "#508642", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#508642", + "value": null + }, + { + "color": "#ef843c", + "value": 1 + }, + { + "color": "#bf1b00", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 0 + }, + "id": 103, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_cluster_partition_underminisr{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "refId": "A" + } + ], + "title": "Partitions under minimum ISR", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Number of partitions that don’t have an active leader and are hence not writable or readable", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#508642", + "value": null + }, + { + "color": "#ef843c", + "value": 1 + }, + { + "color": "#bf1b00", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 0 + }, + "id": 32, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_controller_kafkacontroller_offlinepartitionscount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "refId": "A" + } + ], + "title": "Offline Partitions Count", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 28, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Kafka", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Kafka broker pods memory usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 5 + }, + "id": 82, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(container_memory_usage_bytes{namespace=\"$kubernetes_namespace\",pod=~\"$strimzi_cluster_name-$kafka_broker\",container=\"kafka\"}) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Aggregated Kafka broker pods CPU usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 5 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$kubernetes_namespace\",pod=~\"$strimzi_cluster_name-$kafka_broker\",container=\"kafka\"}[5m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Kafka broker pods disk usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 5 + }, + "id": 83, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kubelet_volume_stats_available_bytes{namespace=\"$kubernetes_namespace\",persistentvolumeclaim=~\"data(-[0-9]+)?-$strimzi_cluster_name-$kafka_broker\", persistentvolumeclaim!~\".*zookeeper(-[0-9]+)?$\"}) by (persistentvolumeclaim)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{persistentvolumeclaim}}", + "refId": "A" + } + ], + "title": "Available Disk Space", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Open File Descriptors", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 5 + }, + "id": 107, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(process_open_fds{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",container=\"kafka\"}) by (kubernetes_pod_name)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Open File Descriptors", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 12 + }, + "id": 93, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(jvm_memory_used_bytes{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM Memory Used", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 12 + }, + "id": 95, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(jvm_gc_collection_seconds_sum{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM GC Time", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 12 + }, + "id": 97, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(jvm_gc_collection_seconds_count{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM GC Count", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "JVM thread count", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 12 + }, + "id": 108, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(jvm_threads_current{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM Thread Count", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Total incoming byte rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgba(237, 129, 40, 0.89)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 0, + "y": 19 + }, + "id": 98, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "repeatDirection": "h", + "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])) 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, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Incoming Byte Rate", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Total outgoing byte rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgba(237, 129, 40, 0.89)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 6, + "y": 19 + }, + "id": 99, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "repeatDirection": "h", + "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])) 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, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Outgoing Byte Rate", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Incoming messages rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgba(237, 129, 40, 0.89)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "wps" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 12, + "y": 19 + }, + "id": 100, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "repeatDirection": "h", + "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])) 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, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Incoming Messages Rate", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Total produce request rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "color": "rgba(237, 129, 40, 0.89)", + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 0 + }, + { + "color": "#299c46", + "value": 2 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 6, + "x": 18, + "y": 19 + }, + "id": 101, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "7.4.5", + "repeatDirection": "h", + "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])) 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, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Produce Request Rate", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Byte rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Total Incoming Byte Rate", + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "legendFormat": "Total Outgoing Byte Rate", + "refId": "B" + } + ], + "title": "Byte Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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", + "refId": "D" + } + ], + "title": "Messages In Per Second", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Produce request rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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", + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "legendFormat": "Failed Produce Request Rate", + "refId": "B" + } + ], + "title": "Produce Request Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Fetch request rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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", + "refId": "A" + }, + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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", + "refId": "B" + } + ], + "title": "Fetch Request Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Average percentage of time network processor is idle", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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}}", + "refId": "A" + } + ], + "title": "Network Processor Avg Idle Percent", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Average percentage of time request handler threads are idle", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 62, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Request Handler Avg Idle Percent", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Disk writes", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 104, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(kafka_server_kafkaserver_linux_disk_write_bytes{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Disk Writes", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Disk reads", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 105, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(irate(kafka_server_kafkaserver_linux_disk_read_bytes{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Disk Reads", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Disk reads", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 55 + }, + "id": 106, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kafka_server_socket_server_metrics_connection_count{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"}) by (kubernetes_pod_name, listener)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{listener}}-{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Connection Count per Listener", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "filterable": true + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Log Size" + }, + "properties": [ + { + "id": "unit", + "value": "decbytes" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 55 + }, + "id": 91, + "links": [], + "options": { + "showHeader": true + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "kafka_log_log_size{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",topic=~\"$kafka_topic\",partition=~\"$kafka_partition\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{topic}}:{{partition}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Log Size", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "container": true, + "endpoint": true, + "instance": true, + "job": true, + "kubernetes_pod_name": true, + "namespace": true, + "node_ip": true, + "node_name": true, + "pod": true, + "strimzi_io_broker_role": true, + "strimzi_io_cluster": true, + "strimzi_io_component_type": true, + "strimzi_io_controller": true, + "strimzi_io_controller_name": true, + "strimzi_io_controller_role": true, + "strimzi_io_kind": true, + "strimzi_io_name": true, + "strimzi_io_pod_name": true, + "strimzi_io_pool_name": true + }, + "indexByName": { + "Time": 0, + "Value": 23, + "__name__": 1, + "container": 3, + "endpoint": 4, + "instance": 5, + "job": 6, + "kubernetes_pod_name": 7, + "namespace": 8, + "node_ip": 9, + "node_name": 10, + "partition": 11, + "pod": 12, + "strimzi_io_broker_role": 13, + "strimzi_io_cluster": 14, + "strimzi_io_component_type": 15, + "strimzi_io_controller": 16, + "strimzi_io_controller_name": 17, + "strimzi_io_controller_role": 18, + "strimzi_io_kind": 19, + "strimzi_io_name": 20, + "strimzi_io_pod_name": 21, + "strimzi_io_pool_name": 22, + "topic": 2 + }, + "renameByName": { + "Value": "Log Size", + "partition": "Partition", + "strimzi_io_name": "", + "topic": "Topic" + } + } + } + ], + "type": "table" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [ + "Strimzi", + "Kafka" + ], + "templating": { + "list": [ + { + "current": {}, + "error": null, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "kubernetes_namespace", + "options": [], + "query": "query_result(kafka_server_replicamanager_leadercount)", + "refresh": 1, + "regex": "/.*namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Cluster Name", + "multi": false, + "name": "strimzi_cluster_name", + "options": [], + "query": "query_result(kafka_server_replicamanager_leadercount{namespace=\"$kubernetes_namespace\"})", + "refresh": 1, + "regex": "/.*strimzi_io_cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": true, + "label": "Broker", + "multi": false, + "name": "kafka_broker", + "options": [], + "query": "query_result(kafka_server_replicamanager_leadercount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\"})", + "refresh": 1, + "regex": "/.*pod_name=\"$strimzi_cluster_name-([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".+", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": true, + "label": "Topic", + "multi": false, + "name": "kafka_topic", + "options": [], + "query": "query_result(kafka_cluster_partition_replicascount{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\"})", + "refresh": 1, + "regex": "/.*topic=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": true, + "label": "Partition", + "multi": true, + "name": "kafka_partition", + "options": [], + "query": "query_result(kafka_log_log_size{namespace=\"$kubernetes_namespace\",strimzi_io_cluster=\"$strimzi_cluster_name\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kafka_broker\",topic=~\"$kafka_topic\"})", + "refresh": 1, + "regex": "/.*partition=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 3, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Strimzi Kafka", + "version": 4, + "weekStart": "" +} diff --git a/packaging/examples/metrics/reporter/grafana-dashboards/strimzi-kraft.json b/packaging/examples/metrics/reporter/grafana-dashboards/strimzi-kraft.json new file mode 100644 index 00000000000..da63e7ee8be --- /dev/null +++ b/packaging/examples/metrics/reporter/grafana-dashboards/strimzi-kraft.json @@ -0,0 +1,2120 @@ +{ + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Timeseries" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 14, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 28, + "panels": [], + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "refId": "A" + } + ], + "title": "KRaft", + "type": "row" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Kafka broker pods memory usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 82, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(container_memory_usage_bytes{namespace=\"$kubernetes_namespace\",pod=~\"$strimzi_cluster_name-$kraft_node\",container=\"kafka\"}) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "Memory Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Aggregated Kafka broker pods CPU usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 81, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$kubernetes_namespace\",pod=~\"$strimzi_cluster_name-$kraft_node\",container=\"kafka\"}[5m])) by (pod)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{pod}}", + "refId": "A" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Kafka broker pods disk usage", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 83, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(kubelet_volume_stats_available_bytes{namespace=\"$kubernetes_namespace\",persistentvolumeclaim=~\"data(-[0-9]+)?-$strimzi_cluster_name-$kraft_node\", persistentvolumeclaim!~\".*zookeeper(-[0-9]+)?$\"}) by (persistentvolumeclaim)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{persistentvolumeclaim}}", + "refId": "A" + } + ], + "title": "Available Disk Space", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "Open File Descriptors", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 107, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(process_open_fds{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",container=\"kafka\"}) by (kubernetes_pod_name)", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Open File Descriptors", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 8 + }, + "id": 93, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(jvm_memory_used_bytes{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", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM Memory Used", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 8 + }, + "id": 95, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(jvm_gc_collection_seconds_sum{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM GC Time", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 8 + }, + "id": 97, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(rate(jvm_gc_collection_seconds_count{namespace=\"$kubernetes_namespace\",kubernetes_pod_name=~\"$strimzi_cluster_name-$kraft_node\",strimzi_io_name=\"$strimzi_cluster_name-kafka\"}[5m])) by (kubernetes_pod_name)", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM GC Count", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "JVM thread count", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 8 + }, + "id": 108, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "sum(jvm_threads_current{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", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "JVM Thread Count", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The average number of records appended per sec as the leader of the raft quorum.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 15 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Append Metadata Records Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The average number of records fetched from the leader of the raft quorum.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 15 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "D" + } + ], + "title": "Fetch Metadata Records Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The average time in milliseconds to commit an entry in the raft log.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 15 + }, + "id": 112, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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, + "interval": "", + "intervalFactor": 1, + "legendFormat": " {{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Metadata Records Commit Latency", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The role of the node in KRaft", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 23 + }, + "id": 122, + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "Pod Name" + } + ] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "max(kafka_server_raft_metrics_current_state_info) by (kubernetes_pod_name, current_state)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Current Raft State", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true + }, + "indexByName": { + "Time": 0, + "Value": 3, + "current_state": 2, + "kubernetes_pod_name": 1 + }, + "renameByName": { + "current_state": "Current State", + "kubernetes_pod_name": "Pod Name" + } + } + } + ], + "type": "table" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The current quorum leader's id; -1 indicates unknown", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 23 + }, + "id": 104, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Current Quorum Leader", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The current voted leader's id; -1 indicates not voted for anyone", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 23 + }, + "id": 105, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Current Voted Leader", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The current quorum epoch", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 23 + }, + "id": 113, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Current Quorum Epoch", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The number of bytes read off all sockets per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 114, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Metadata Topic Incoming Bytes Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The number of outgoing bytes sent to all servers per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 115, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Metadata Topic Outgoing Bytes Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The number of requests sent per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 116, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Metadata Topic Requests Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The number of responses received per second", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 117, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Metadata Topic Responses Rate", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The high watermark maintained on this member; -1 if it is unknown.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 118, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "High Watermark", + "type": "timeseries" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "The current raft log end offset.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 119, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "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": "", + "intervalFactor": 1, + "legendFormat": "{{kubernetes_pod_name}}", + "refId": "A" + } + ], + "title": "Log End Offset", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [ + "Strimzi", + "Kafka", + "KRaft" + ], + "templating": { + "list": [ + { + "current": {}, + "error": null, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "kubernetes_namespace", + "options": [], + "query": "query_result(kafka_server_raft_metrics_current_leader)", + "refresh": 1, + "regex": "/.*namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": false, + "label": "Cluster Name", + "multi": false, + "name": "strimzi_cluster_name", + "options": [], + "query": "query_result(kafka_server_raft_metrics_current_leader{namespace=\"$kubernetes_namespace\"})", + "refresh": 1, + "regex": "/.*strimzi_io_cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "", + "hide": 0, + "includeAll": true, + "label": "Broker", + "multi": false, + "name": "kraft_node", + "options": [], + "query": "query_result(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, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Strimzi KRaft", + "version": 6, + "weekStart": "" +} 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/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