Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions dubbo-dependencies-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
<micrometer-tracing.version>1.6.3</micrometer-tracing.version>
<t_digest.version>3.3</t_digest.version>
<prometheus_client.version>0.16.0</prometheus_client.version>
<prometheus_metrics.version>1.5.0</prometheus_metrics.version>
<reactive.version>1.0.4</reactive.version>
<reactor.version>3.8.3</reactor.version>
<mutiny.version>2.9.5</mutiny.version>
Expand Down Expand Up @@ -260,6 +261,13 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-bom</artifactId>
<version>${prometheus_metrics.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -945,6 +953,11 @@
<artifactId>simpleclient_pushgateway</artifactId>
<version>${prometheus_client.version}</version>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-exporter-pushgateway</artifactId>
<version>${prometheus_metrics.version}</version>
</dependency>
<!-- reactive related dependencies -->
<dependency>
<groupId>org.reactivestreams</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,45 @@

public class MetricsSupportUtil {

private static final String[] LEGACY_PROMETHEUS_STACK = {
"io.micrometer.prometheus.PrometheusConfig",
"io.micrometer.prometheus.PrometheusMeterRegistry",
"io.prometheus.client.exporter.PushGateway",
"io.prometheus.client.exporter.BasicAuthHttpConnectionFactory"
};

private static final String[] NEW_PROMETHEUS_STACK = {
"io.micrometer.prometheusmetrics.PrometheusConfig",
"io.micrometer.prometheusmetrics.PrometheusMeterRegistry",
"io.prometheus.metrics.exporter.pushgateway.PushGateway"
};

public static boolean isSupportMetrics() {
return isClassPresent("io.micrometer.core.instrument.MeterRegistry");
}

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");
return isAllClassPresent(LEGACY_PROMETHEUS_STACK) || isAllClassPresent(NEW_PROMETHEUS_STACK);
}

public static boolean isSupportLegacyPrometheus() {
return isAllClassPresent(LEGACY_PROMETHEUS_STACK);
}

public static boolean isSupportNewPrometheus() {
return isAllClassPresent(NEW_PROMETHEUS_STACK);
}

private static boolean isClassPresent(String className) {
return ClassUtils.isPresent(className, MetricsSupportUtil.class.getClassLoader());
}

private static boolean isAllClassPresent(String... classNames) {
for (String className : classNames) {
if (!isClassPresent(className)) {
return false;
}
}
return true;
}
}
5 changes: 0 additions & 5 deletions dubbo-metrics/dubbo-metrics-otlp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-otlp</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
Expand Down
8 changes: 8 additions & 0 deletions dubbo-metrics/dubbo-metrics-prometheus/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,18 @@
<artifactId>dubbo-metrics-default</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus-simpleclient</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>prometheus-metrics-exporter-pushgateway</artifactId>
</dependency>
<dependency>
<groupId>io.prometheus</groupId>
<artifactId>simpleclient_pushgateway</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metrics.report.AbstractMetricsReporter;
import org.apache.dubbo.metrics.utils.MetricsSupportUtil;
import org.apache.dubbo.rpc.model.ApplicationModel;

import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
import io.prometheus.client.exporter.PushGateway;
import io.micrometer.core.instrument.MeterRegistry;

import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_METRICS_COLLECTOR_EXCEPTION;
import static org.apache.dubbo.common.constants.MetricsConstants.PROMETHEUS_DEFAULT_JOB_NAME;
Expand All @@ -51,21 +49,23 @@ public class PrometheusMetricsReporter extends AbstractMetricsReporter {

private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(PrometheusMetricsReporter.class);

private final PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
private final PrometheusClientAdapter adapter;
private ScheduledExecutorService pushJobExecutor = null;

public PrometheusMetricsReporter(URL url, ApplicationModel applicationModel) {
super(url, applicationModel);
this.adapter = createAdapter();
}

@Override
public void doInit() {
addMeterRegistry(prometheusRegistry);
addMeterRegistry(adapter.getMeterRegistry());
schedulePushJob();
}

@Override
public String getResponse() {
return prometheusRegistry.scrape();
return adapter.scrape();
}

private void schedulePushJob() {
Expand All @@ -80,30 +80,17 @@ private void schedulePushJob() {

NamedThreadFactory threadFactory = new NamedThreadFactory("prometheus-push-job", true);
pushJobExecutor = Executors.newScheduledThreadPool(1, threadFactory);
PushGateway pushGateway = new PushGateway(baseUrl);

Object pushGateway = adapter.createPushGateway(baseUrl);
if (!StringUtils.isBlank(username)) {
pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password));
adapter.setBasicAuth(pushGateway, username, password);
}

pushJobExecutor.scheduleWithFixedDelay(
() -> push(pushGateway, job), pushInterval, pushInterval, TimeUnit.SECONDS);
}
}

protected void push(PushGateway pushGateway, String job) {
try {
resetIfSamplesChanged();
pushGateway.pushAdd(prometheusRegistry.getPrometheusRegistry(), job);
} catch (IOException e) {
logger.error(
COMMON_METRICS_COLLECTOR_EXCEPTION,
"",
"",
"Error occurred when pushing metrics to prometheus: ",
e);
}
}

@Override
public void doDestroy() {

Expand All @@ -120,11 +107,155 @@ public ScheduledExecutorService getPushJobExecutor() {
return pushJobExecutor;
}

protected void push(Object pushGateway, String job) {
try {
resetIfSamplesChanged();
adapter.pushAdd(pushGateway, job);
} catch (IOException e) {
logger.error(
COMMON_METRICS_COLLECTOR_EXCEPTION,
"",
"",
"Error occurred when pushing metrics to prometheus: ",
e);
}
}

/**
* ut only
*/
@Deprecated
public PrometheusMeterRegistry getPrometheusRegistry() {
return prometheusRegistry;
public MeterRegistry getPrometheusRegistry() {
return adapter.getMeterRegistry();
}

private PrometheusClientAdapter createAdapter() {
PrometheusClientAdapter adapter = tryCreateNewPrometheusClientAdapter();
if (adapter != null) {
logger.info("Using new Prometheus client implementation.");
return adapter;
}
adapter = tryCreateLegacyPrometheusClientAdapter();
if (adapter != null) {
logger.info("Using legacy Prometheus client implementation.");
return adapter;
}
throw new IllegalStateException("No supported Prometheus client implementation found.");
}

private PrometheusClientAdapter tryCreateNewPrometheusClientAdapter() {
try {
if (NewPrometheusClientAdapter.isAvailable()) {
return new NewPrometheusClientAdapter();
}
} catch (NoClassDefFoundError ignored) {
// The new Prometheus stack is only partially present. Treat it as unavailable
// so that we can fall back to the legacy implementation or to NOP reporting.
}
return null;
}

private PrometheusClientAdapter tryCreateLegacyPrometheusClientAdapter() {
try {
if (LegacyPrometheusClientAdapter.isAvailable()) {
return new LegacyPrometheusClientAdapter();
}
} catch (NoClassDefFoundError ignored) {
// The legacy Prometheus stack is only partially present. Treat it as unavailable
// so that factory-level fallback can downgrade to a NOP reporter.
}
return null;
}

private interface PrometheusClientAdapter {

MeterRegistry getMeterRegistry();

String scrape();

Object createPushGateway(String baseUrl);

void setBasicAuth(Object pushGateway, String username, String password);

void pushAdd(Object pushGateway, String job) throws IOException;
}

private static class LegacyPrometheusClientAdapter implements PrometheusClientAdapter {

private final io.micrometer.prometheus.PrometheusMeterRegistry registry =
new io.micrometer.prometheus.PrometheusMeterRegistry(io.micrometer.prometheus.PrometheusConfig.DEFAULT);

static boolean isAvailable() {
return MetricsSupportUtil.isSupportLegacyPrometheus();
}

@Override
public MeterRegistry getMeterRegistry() {
return registry;
}

@Override
public String scrape() {
return registry.scrape();
}

@Override
public Object createPushGateway(String baseUrl) {
return new io.prometheus.client.exporter.PushGateway(baseUrl);
}

@Override
public void setBasicAuth(Object pushGateway, String username, String password) {
((io.prometheus.client.exporter.PushGateway) pushGateway)
.setConnectionFactory(
new io.prometheus.client.exporter.BasicAuthHttpConnectionFactory(username, password));
}

@Override
public void pushAdd(Object pushGateway, String job) throws IOException {
((io.prometheus.client.exporter.PushGateway) pushGateway).pushAdd(registry.getPrometheusRegistry(), job);
}
}

private static class NewPrometheusClientAdapter implements PrometheusClientAdapter {

private final io.micrometer.prometheusmetrics.PrometheusMeterRegistry registry =
new io.micrometer.prometheusmetrics.PrometheusMeterRegistry(
io.micrometer.prometheusmetrics.PrometheusConfig.DEFAULT);

static boolean isAvailable() {
return MetricsSupportUtil.isSupportNewPrometheus();
}

@Override
public MeterRegistry getMeterRegistry() {
return registry;
}

@Override
public String scrape() {
return registry.scrape();
}

@Override
public Object createPushGateway(String baseUrl) {
return io.prometheus.metrics.exporter.pushgateway.PushGateway.builder()
.registry(registry.getPrometheusRegistry())
.address(baseUrl);
}

@Override
public void setBasicAuth(Object pushGateway, String username, String password) {
((io.prometheus.metrics.exporter.pushgateway.PushGateway.Builder) pushGateway)
.basicAuth(username, password);
}

@Override
public void pushAdd(Object pushGateway, String job) throws IOException {
((io.prometheus.metrics.exporter.pushgateway.PushGateway.Builder) pushGateway)
.job(job)
.build()
.pushAdd();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public MetricsReporter createMetricsReporter(URL url) {
logger.error(INTERNAL_ERROR, "", "", "Failed to instantiate PrometheusMetricsReporter", ncde);
throw ncde;
}
} catch (IllegalStateException ise) {
logger.error(INTERNAL_ERROR, "", "", "Failed to initialize PrometheusMetricsReporter", ise);
return new NopPrometheusMetricsReporter();
}
}

Expand All @@ -77,6 +80,16 @@ private static boolean dependenciesNotFound(String msg) {
if (msg.contains("io/micrometer/core/instrument/composite/CompositeMeterRegistry")) {
return true;
}
return msg.contains("io.micrometer.core.instrument.composite.CompositeMeterRegistry");
if (msg.contains("io.micrometer.core.instrument.composite.CompositeMeterRegistry")) {
return true;
}
return msg.contains("io/micrometer/prometheus/")
|| msg.contains("io.micrometer.prometheus.")
|| msg.contains("io/micrometer/prometheusmetrics/")
|| msg.contains("io.micrometer.prometheusmetrics.")
|| msg.contains("io/prometheus/client/exporter/")
|| msg.contains("io.prometheus.client.exporter.")
|| msg.contains("io/prometheus/metrics/exporter/pushgateway/")
|| msg.contains("io.prometheus.metrics.exporter.pushgateway.");
}
}
Loading
Loading