@Override public double measure(MetricConfig config, long now) { double recordsConsumedRate = metrics.metrics().get(metrics.metricName("records-consumed-rate", METRIC_GROUP_NAME, tags)).value(); double recordsLostRate = metrics.metrics().get(metrics.metricName("records-lost-rate", METRIC_GROUP_NAME, tags)).value(); double recordsDelayedRate = metrics.metrics().get(metrics.metricName("records-delayed-rate", METRIC_GROUP_NAME, tags)).value(); if (new Double(recordsLostRate).isNaN()) recordsLostRate = 0; if (new Double(recordsDelayedRate).isNaN()) recordsDelayedRate = 0; double consumeAvailability = recordsConsumedRate + recordsLostRate > 0 ? (recordsConsumedRate - recordsDelayedRate) / (recordsConsumedRate + recordsLostRate) : 0; return consumeAvailability; } }
@Override public double measure(MetricConfig config, long now) { double availabilitySum = 0.0; int partitionNum = _partitionNum.get(); for (int partition = 0; partition < partitionNum; partition++) { double recordsProduced = metrics.metrics().get(metrics.metricName("records-produced-rate-partition-" + partition, METRIC_GROUP_NAME, tags)).value(); double produceError = metrics.metrics().get(metrics.metricName("produce-error-rate-partition-" + partition, METRIC_GROUP_NAME, tags)).value(); // If there is no error, error rate sensor may expire and the value may be NaN. Treat NaN as 0 for error rate. if (Double.isNaN(produceError) || Double.isInfinite(produceError)) { produceError = 0; } // If there is either succeeded or failed produce to a partition, consider its availability as 0. if (recordsProduced + produceError > 0) { availabilitySum += recordsProduced / (recordsProduced + produceError); } else if (!_treatZeroThroughputAsUnavailable) { // If user configures treatZeroThroughputAsUnavailable to be false, a partition's availability // is 1.0 as long as there is no exception thrown from producer. // This allows kafka admin to exactly monitor the availability experienced by Kafka users which // will block and retry for a certain amount of time based on its configuration (e.g. retries, retry.backoff.ms). // Note that if it takes a long time for messages to be retries and sent, the latency in the ConsumeService // will increase and it will reduce ConsumeAvailability if the latency exceeds consume.latency.sla.ms availabilitySum += 1.0; } } // Assign equal weight to per-partition availability when calculating overall availability return availabilitySum / partitionNum; } }
/** * Convert a KafkaMetric to a CruiseControlMetric */ public static CruiseControlMetric toCruiseControlMetric(KafkaMetric kafkaMetric, long now, int brokerId) { org.apache.kafka.common.MetricName metricName = kafkaMetric.metricName(); CruiseControlMetric ccm = toCruiseControlMetric(now, brokerId, metricName.name(), metricName.tags(), kafkaMetric.value()); if (ccm == null) { throw new IllegalArgumentException(String.format("Cannot convert KafkaMetric %s to a Cruise Control metric for " + "broker %d at time %d", kafkaMetric.metricName(), brokerId, now)); } return ccm; }
@Override public Double getValue() { return kafkaMetric.value(); } };
@Override public Object getAttribute(String name) throws AttributeNotFoundException, MBeanException, ReflectionException { if (this.metrics.containsKey(name)) return this.metrics.get(name).value(); else throw new AttributeNotFoundException("Could not find attribute " + name); }
@Override public void run() { for (Map.Entry<DoubleGauge, KafkaMetric> e : gauges.entrySet()) { e.getKey().set(e.getValue().value()); } } }, millis, millis, TimeUnit.MILLISECONDS);
@Override public double value() { synchronized (this.lock) { return value(time.milliseconds()); } }
metricMsg.put("group", metricName.group()); metricMsg.put("attribute", metricName.name()); metricMsg.put("value", String.valueOf(metric.value())); if (metricType == MetricsType.CONSUMER && !"".equals(groupId)) { metricMsg.put("group.id", groupId);
public void mirrorFrom(final ConcurrentMap<MetricName, KafkaMetric> kafkaMetrics, final Predicate<String> metricFilter, final Function<MetricName, String> metricNameAdjuster) { for (final Map.Entry<MetricName, KafkaMetric> entry : filter(kafkaMetrics, metricFilter)) { try { final MetricName metricName = entry.getKey(); final String realMetricName = metricNameAdjuster.apply(metricName); metricsFactory.createGauge( (metricName.group() + "_" + realMetricName).replaceAll("(-|\\.)", "_"), Strings.isNullOrEmpty(metricName.description()) ? "No description" : metricName.description(), () -> entry.getValue().value() ); } catch (final Exception e) { log.error("Could not process metrics", e); } } } }
/** * Convert a KafkaMetric to a CruiseControlMetric */ public static CruiseControlMetric toCruiseControlMetric(KafkaMetric kafkaMetric, long now, int brokerId) { org.apache.kafka.common.MetricName metricName = kafkaMetric.metricName(); CruiseControlMetric ccm = toCruiseControlMetric(now, brokerId, metricName.name(), metricName.tags(), kafkaMetric.value()); if (ccm == null) { throw new IllegalArgumentException(String.format("Cannot convert KafkaMetric %s to a Cruise Control metric for " + "broker %d at time %d", kafkaMetric.metricName(), brokerId, now)); } return ccm; }
for (Map.Entry<org.apache.kafka.common.MetricName, org.apache.kafka.common.metrics.KafkaMetric> m : kafkaMetrics.entrySet()) { Double value = m.getValue().value(); if (!value.isNaN() && !value.isInfinite()) { MeasurementV1 measurement = new MeasurementV1();
/** * Check if we have violated our quota for any metric that has a configured quota * @param timeMs */ private void checkQuotas(long timeMs) { for (int i = 0; i < this.metrics.size(); i++) { KafkaMetric metric = this.metrics.get(i); MetricConfig config = metric.config(); if (config != null) { Quota quota = config.quota(); if (quota != null) { if (!quota.acceptable(metric.value(timeMs))) throw new QuotaViolationException(metric.metricName() + " is in violation of its quota of " + quota.bound()); } } } }