diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/utils/MetricsSupportUtil.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/utils/MetricsSupportUtil.java index b304197bb8b..4d4744a136a 100644 --- a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/utils/MetricsSupportUtil.java +++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/utils/MetricsSupportUtil.java @@ -25,10 +25,16 @@ public static boolean isSupportMetrics() { } public static boolean isSupportPrometheus() { - return isClassPresent("io.micrometer.prometheus.PrometheusConfig") - && isClassPresent("io.prometheus.client.exporter.BasicAuthHttpConnectionFactory") - && isClassPresent("io.prometheus.client.exporter.HttpConnectionFactory") - && isClassPresent("io.prometheus.client.exporter.PushGateway"); + // Micrometer 1.13+ renamed the prometheus package: + // io.micrometer.prometheus.* -> io.micrometer.prometheusmetrics.* + // Accept either package to support both old and new versions. + boolean hasPrometheusConfig = isClassPresent("io.micrometer.prometheus.PrometheusConfig") + || isClassPresent("io.micrometer.prometheusmetrics.PrometheusConfig"); + + // PushGateway classes (io.prometheus.client.exporter.*) are only needed + // when pushgateway mode is enabled, not for the default scrape endpoint. + // Do not require them here to avoid blocking reporter initialization. + return hasPrometheusConfig; } private static boolean isClassPresent(String className) { diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/utils/MetricsSupportUtilTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/utils/MetricsSupportUtilTest.java new file mode 100644 index 00000000000..eff4f14d2d3 --- /dev/null +++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/utils/MetricsSupportUtilTest.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.metrics.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class MetricsSupportUtilTest { + + @Test + void isSupportMetricsShouldReturnTrue() { + // micrometer-core is on the test classpath + Assertions.assertTrue(MetricsSupportUtil.isSupportMetrics()); + } + + @Test + void isSupportPrometheusShouldNotThrow() { + // Prometheus support depends on classpath; verify no exception is thrown + // regardless of which micrometer-prometheus variant is available. + boolean result = MetricsSupportUtil.isSupportPrometheus(); + // In the dubbo-metrics-api test context, prometheus classes are not present + Assertions.assertFalse(result); + } +} diff --git a/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporter.java b/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporter.java index 96948e15317..91676ce2201 100644 --- a/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporter.java +++ b/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporter.java @@ -71,22 +71,33 @@ public String getResponse() { private void schedulePushJob() { boolean pushEnabled = url.getParameter(PROMETHEUS_PUSHGATEWAY_ENABLED_KEY, false); if (pushEnabled) { - String baseUrl = url.getParameter(PROMETHEUS_PUSHGATEWAY_BASE_URL_KEY); - String job = url.getParameter(PROMETHEUS_PUSHGATEWAY_JOB_KEY, PROMETHEUS_DEFAULT_JOB_NAME); - int pushInterval = - url.getParameter(PROMETHEUS_PUSHGATEWAY_PUSH_INTERVAL_KEY, PROMETHEUS_DEFAULT_PUSH_INTERVAL); - String username = url.getParameter(PROMETHEUS_PUSHGATEWAY_USERNAME_KEY); - String password = url.getParameter(PROMETHEUS_PUSHGATEWAY_PASSWORD_KEY); - - NamedThreadFactory threadFactory = new NamedThreadFactory("prometheus-push-job", true); - pushJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); - PushGateway pushGateway = new PushGateway(baseUrl); - if (!StringUtils.isBlank(username)) { - pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password)); + try { + String baseUrl = url.getParameter(PROMETHEUS_PUSHGATEWAY_BASE_URL_KEY); + String job = url.getParameter(PROMETHEUS_PUSHGATEWAY_JOB_KEY, PROMETHEUS_DEFAULT_JOB_NAME); + int pushInterval = + url.getParameter(PROMETHEUS_PUSHGATEWAY_PUSH_INTERVAL_KEY, PROMETHEUS_DEFAULT_PUSH_INTERVAL); + String username = url.getParameter(PROMETHEUS_PUSHGATEWAY_USERNAME_KEY); + String password = url.getParameter(PROMETHEUS_PUSHGATEWAY_PASSWORD_KEY); + + NamedThreadFactory threadFactory = new NamedThreadFactory("prometheus-push-job", true); + pushJobExecutor = Executors.newScheduledThreadPool(1, threadFactory); + PushGateway pushGateway = new PushGateway(baseUrl); + if (!StringUtils.isBlank(username)) { + pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password)); + } + + pushJobExecutor.scheduleWithFixedDelay( + () -> push(pushGateway, job), pushInterval, pushInterval, TimeUnit.SECONDS); + } catch (NoClassDefFoundError e) { + logger.warn( + COMMON_METRICS_COLLECTOR_EXCEPTION, + "", + "", + "PushGateway classes not found on classpath. " + + "Add simpleclient_pushgateway dependency to use pushgateway mode. " + + "Scrape endpoint will still work.", + e); } - - pushJobExecutor.scheduleWithFixedDelay( - () -> push(pushGateway, job), pushInterval, pushInterval, TimeUnit.SECONDS); } } diff --git a/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporterFactory.java b/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporterFactory.java index fcad830e1e8..7b0bc55684d 100644 --- a/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporterFactory.java +++ b/dubbo-metrics/dubbo-metrics-prometheus/src/main/java/org/apache/dubbo/metrics/prometheus/PrometheusMetricsReporterFactory.java @@ -74,9 +74,14 @@ private static boolean dependenciesNotFound(String msg) { if (msg == null) { return false; } - if (msg.contains("io/micrometer/core/instrument/composite/CompositeMeterRegistry")) { + // Micrometer core classes + if (msg.contains("io/micrometer/") || msg.contains("io.micrometer.")) { return true; } - return msg.contains("io.micrometer.core.instrument.composite.CompositeMeterRegistry"); + // Prometheus client classes (old simpleclient or new client) + if (msg.contains("io/prometheus/") || msg.contains("io.prometheus.")) { + return true; + } + return false; } }