From 3e865ed7ab53cf00827c79f81b87771b69e5b65e Mon Sep 17 00:00:00 2001 From: "huan.huynh" <1612858@student.hcmus.edu.vn> Date: Sat, 1 Nov 2025 16:25:04 +0700 Subject: [PATCH 1/3] feat: Add readTimeout and conenctionTimeout as configurable parameters Signed-off-by: huan.huynh <1612858@student.hcmus.edu.vn> --- .../pom.xml | 6 ++ .../exporter/pushgateway/PushGateway.java | 43 ++++++++++- .../pushgateway/PushGatewayTimeoutTest.java | 75 +++++++++++++++++++ 3 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java diff --git a/prometheus-metrics-exporter-pushgateway/pom.xml b/prometheus-metrics-exporter-pushgateway/pom.xml index 6d59b2b4d..350cb8ddc 100644 --- a/prometheus-metrics-exporter-pushgateway/pom.xml +++ b/prometheus-metrics-exporter-pushgateway/pom.xml @@ -39,5 +39,11 @@ ${project.version} test + + com.squareup.okhttp3 + mockwebserver + 5.3.0 + test + diff --git a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java index 643e0aeca..79e7686ce 100644 --- a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java +++ b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.Map; import java.util.TreeMap; +import java.util.Optional; import javax.annotation.Nullable; /** @@ -89,6 +90,8 @@ public class PushGateway { private final PrometheusRegistry registry; private final HttpConnectionFactory connectionFactory; private final EscapingScheme escapingScheme; + private final Integer connectionTimeout; + private final Integer readTimeout; private PushGateway( PrometheusRegistry registry, @@ -97,13 +100,17 @@ private PushGateway( HttpConnectionFactory connectionFactory, Map requestHeaders, boolean prometheusTimestampsInMs, - EscapingScheme escapingScheme) { + EscapingScheme escapingScheme, + @Nullable Integer connectionTimeout, + @Nullable Integer readTimeout) { this.registry = registry; this.url = url; this.requestHeaders = Collections.unmodifiableMap(new HashMap<>(requestHeaders)); this.connectionFactory = connectionFactory; this.prometheusTimestampsInMs = prometheusTimestampsInMs; this.escapingScheme = escapingScheme; + this.connectionTimeout = Optional.ofNullable(connectionTimeout).orElse(10 * MILLISECONDS_PER_SECOND); + this.readTimeout = Optional.ofNullable(readTimeout).orElse(10 * MILLISECONDS_PER_SECOND); writer = getWriter(format); if (!writer.isAvailable()) { throw new RuntimeException(writer.getClass() + " is not available"); @@ -206,8 +213,8 @@ private void doRequest(@Nullable PrometheusRegistry registry, String method) thr } connection.setRequestMethod(method); - connection.setConnectTimeout(10 * MILLISECONDS_PER_SECOND); - connection.setReadTimeout(10 * MILLISECONDS_PER_SECOND); + connection.setConnectTimeout(this.connectionTimeout); + connection.setReadTimeout(this.readTimeout); connection.connect(); try { @@ -277,6 +284,8 @@ public static class Builder { @Nullable private String address; @Nullable private Scheme scheme; @Nullable private String job; + @Nullable private Integer connectionTimeout; + @Nullable private Integer readTimeout; private boolean prometheusTimestampsInMs; private final Map requestHeaders = new HashMap<>(); private PrometheusRegistry registry = PrometheusRegistry.defaultRegistry; @@ -395,6 +404,30 @@ public Builder prometheusTimestampsInMs(boolean prometheusTimestampsInMs) { return this; } + /** + * Specify the connection timeout (in milliseconds) for HTTP connections to the PushGateway. + * Default is {@code 10000} (10 seconds). + * + * @param connectionTimeout timeout value in milliseconds + * @return this {@link Builder} instance + */ + public Builder connectionTimeout(Integer connectionTimeout) { + this.connectionTimeout = connectionTimeout; + return this; + } + + /** + * Specify the read timeout (in milliseconds) for reading the response from the PushGateway. + * Default is {@code 10000} (10 seconds). + * + * @param readTimeout timeout value in milliseconds + * @return this {@link Builder} instance + */ + public Builder readTimeout(Integer readTimeout) { + this.readTimeout = readTimeout; + return this; + } + private boolean getPrometheusTimestampsInMs() { // accept either to opt in to timestamps in milliseconds return config.getExporterProperties().getPrometheusTimestampsInMs() @@ -496,7 +529,9 @@ public PushGateway build() { connectionFactory, requestHeaders, getPrometheusTimestampsInMs(), - getEscapingScheme(properties)); + getEscapingScheme(properties), + connectionTimeout, + readTimeout); } catch (MalformedURLException e) { throw new PrometheusPropertiesException( address + ": Invalid address. Expecting :"); diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java new file mode 100644 index 000000000..ee7540ff1 --- /dev/null +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java @@ -0,0 +1,75 @@ +package io.prometheus.metrics.exporter.pushgateway; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.concurrent.TimeUnit; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PushGatewayTimeoutTest { + + private MockWebServer mockWebServer; + + @BeforeEach + void setUp() throws Exception { + mockWebServer = new MockWebServer(); + mockWebServer.start(); + } + + @AfterEach + void tearDown() throws Exception { + mockWebServer.shutdown(); + } + + @Test + void connectionTimeoutIsEnforced() { + // Simulate server that never accepts connection: by binding but delaying accept. + // Since MockWebServer always accepts connection immediately, we instead use a short connect timeout and a response delay. + int shortConnectTimeoutMillis = 10; + int readTimeoutMillis = 1000; + + PushGateway pushGateway = PushGateway.builder() + .connectionTimeout(shortConnectTimeoutMillis) + .readTimeout(readTimeoutMillis) + .build(); + + // Enqueue a response that delays sending headers to simulate slow connection + mockWebServer.enqueue(new MockResponse() + .setBody("ok") + .setBodyDelay(5, TimeUnit.SECONDS)); // very long delay + + String url = mockWebServer.url("/").toString(); + + Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); + + assertTrue(thrown.getMessage().contains("connect"), "Expected a connection‐timeout or connect error"); + } + + @Test + void readTimeoutIsEnforced() { + int connectTimeoutMillis = 1000; + int shortReadTimeoutMillis = 10; + + PushGateway pushGateway = PushGateway.builder() + .connectionTimeout(connectTimeoutMillis) + .readTimeout(shortReadTimeoutMillis) + .build(); + + // Enqueue a response that sends headers but delays body + mockWebServer.enqueue(new MockResponse() + .setHeadersDelay(0, TimeUnit.SECONDS) + .setBodyDelay(5, TimeUnit.SECONDS) + .setBody("ok")); + + String url = mockWebServer.url("/").toString(); + + Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); + + assertTrue(thrown.getMessage().contains("read") || thrown.getMessage().contains("timeout"), + "Expected a read‐timeout error"); + } +} From 72e46f71bcdb476c8473614388361f179ec08dfa Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 3 Nov 2025 17:04:37 +0100 Subject: [PATCH 2/3] read properties from file as well Signed-off-by: Gregor Zeitlinger Signed-off-by: huan.huynh <1612858@student.hcmus.edu.vn> --- .../config/ExporterPushgatewayProperties.java | 42 +++++++++++- .../io/prometheus/metrics/config/Util.java | 27 ++++++-- .../ExporterPushgatewayPropertiesTest.java | 5 ++ .../prometheus/metrics/config/UtilTest.java | 50 +++++++++++++++ .../exporter/pushgateway/PushGateway.java | 64 ++++++++++++------- .../pushgateway/PushGatewayTimeoutTest.java | 53 ++++++++------- 6 files changed, 185 insertions(+), 56 deletions(-) create mode 100644 prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java index 9d7b380d1..bd53f8b76 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterPushgatewayProperties.java @@ -1,5 +1,6 @@ package io.prometheus.metrics.config; +import java.time.Duration; import java.util.Map; import javax.annotation.Nullable; @@ -9,21 +10,29 @@ public class ExporterPushgatewayProperties { private static final String JOB = "job"; private static final String SCHEME = "scheme"; private static final String ESCAPING_SCHEME = "escapingScheme"; + private static final String READ_TIMEOUT = "readTimeoutSeconds"; + private static final String CONNECT_TIMEOUT = "connectTimeoutSeconds"; private static final String PREFIX = "io.prometheus.exporter.pushgateway"; @Nullable private final String scheme; @Nullable private final String address; @Nullable private final String job; @Nullable private final EscapingScheme escapingScheme; + @Nullable private final Duration connectTimeout; + @Nullable private final Duration readTimeout; private ExporterPushgatewayProperties( @Nullable String address, @Nullable String job, @Nullable String scheme, - @Nullable EscapingScheme escapingScheme) { + @Nullable EscapingScheme escapingScheme, + @Nullable Duration connectTimeout, + @Nullable Duration readTimeout) { this.address = address; this.job = job; this.scheme = scheme; this.escapingScheme = escapingScheme; + this.connectTimeout = connectTimeout; + this.readTimeout = readTimeout; } /** Address of the Pushgateway in the form {@code host:port}. Default is {@code localhost:9091} */ @@ -56,6 +65,18 @@ public EscapingScheme getEscapingScheme() { return escapingScheme; } + /** Connection timeout for connections to the Pushgateway. */ + @Nullable + public Duration getConnectTimeout() { + return connectTimeout; + } + + /** Read timeout for connections to the Pushgateway. */ + @Nullable + public Duration getReadTimeout() { + return readTimeout; + } + /** * Note that this will remove entries from {@code properties}. This is because we want to know if * there are unused properties remaining after all properties have been loaded. @@ -66,6 +87,8 @@ static ExporterPushgatewayProperties load(Map properties) String job = Util.loadString(PREFIX + "." + JOB, properties); String scheme = Util.loadString(PREFIX + "." + SCHEME, properties); String escapingScheme = Util.loadString(PREFIX + "." + ESCAPING_SCHEME, properties); + Duration connectTimeout = Util.loadOptionalDuration(PREFIX + "." + CONNECT_TIMEOUT, properties); + Duration readTimeout = Util.loadOptionalDuration(PREFIX + "." + READ_TIMEOUT, properties); if (scheme != null) { if (!scheme.equals("http") && !scheme.equals("https")) { @@ -77,7 +100,7 @@ static ExporterPushgatewayProperties load(Map properties) } return new ExporterPushgatewayProperties( - address, job, scheme, parseEscapingScheme(escapingScheme)); + address, job, scheme, parseEscapingScheme(escapingScheme), connectTimeout, readTimeout); } private static @Nullable EscapingScheme parseEscapingScheme(@Nullable String scheme) { @@ -111,6 +134,8 @@ public static class Builder { @Nullable private String job; @Nullable private String scheme; @Nullable private EscapingScheme escapingScheme; + @Nullable private Duration connectTimeout; + @Nullable private Duration readTimeout; private Builder() {} @@ -134,8 +159,19 @@ public Builder escapingScheme(EscapingScheme escapingScheme) { return this; } + public Builder connectTimeout(Duration connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + public Builder readTimeout(Duration readTimeout) { + this.readTimeout = readTimeout; + return this; + } + public ExporterPushgatewayProperties build() { - return new ExporterPushgatewayProperties(address, job, scheme, escapingScheme); + return new ExporterPushgatewayProperties( + address, job, scheme, escapingScheme, connectTimeout, readTimeout); } } } diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java index 75f0b721e..04eb78a19 100644 --- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java +++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/Util.java @@ -1,5 +1,6 @@ package io.prometheus.metrics.config; +import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -160,14 +161,30 @@ static Long loadLong(String name, Map properties) return null; } + @Nullable + static Duration loadOptionalDuration(String name, Map properties) + throws PrometheusPropertiesException { + + Long value = loadLong(name, properties); + + assertValue(value, t -> t >= 0, "Expecting value >= 0.", null, name); + + if (value == null || value == 0) { + return null; + } + return Duration.ofSeconds(value); + } + static void assertValue( - @Nullable T number, Predicate predicate, String message, String prefix, String name) + @Nullable T number, + Predicate predicate, + String message, + @Nullable String prefix, + String name) throws PrometheusPropertiesException { if (number != null && !predicate.test(number)) { - String fullMessage = - prefix == null - ? name + ": " + message - : String.format("%s.%s: %s Found: %s", prefix, name, message, number); + String fullKey = prefix == null ? name : prefix + "." + name; + String fullMessage = String.format("%s: %s Found: %s", fullKey, message, number); throw new PrometheusPropertiesException(fullMessage); } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java index 945fa83be..e1e06348a 100644 --- a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/ExporterPushgatewayPropertiesTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import java.time.Duration; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.Test; @@ -41,11 +42,15 @@ void builder() { .job("job") .scheme("http") .escapingScheme(EscapingScheme.DOTS_ESCAPING) + .connectTimeout(Duration.ofSeconds(1)) + .readTimeout(Duration.ofSeconds(2)) .build(); assertThat(properties.getAddress()).isEqualTo("http://localhost"); assertThat(properties.getJob()).isEqualTo("job"); assertThat(properties.getScheme()).isEqualTo("http"); assertThat(properties.getEscapingScheme()).isEqualTo(EscapingScheme.DOTS_ESCAPING); + assertThat(properties.getConnectTimeout()).isEqualTo(Duration.ofSeconds(1)); + assertThat(properties.getReadTimeout()).isEqualTo(Duration.ofSeconds(2)); } } diff --git a/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java new file mode 100644 index 000000000..23ffbd33b --- /dev/null +++ b/prometheus-metrics-config/src/test/java/io/prometheus/metrics/config/UtilTest.java @@ -0,0 +1,50 @@ +package io.prometheus.metrics.config; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class UtilTest { + @Test + void loadOptionalDuration_positive() { + Map properties = new HashMap<>(Map.of("foo", "5")); + + assertThat(Util.loadOptionalDuration("foo", properties)).isEqualTo(Duration.ofSeconds(5)); + } + + @Test + void loadOptionalDuration_zero() { + Map properties = new HashMap<>(Map.of("foo", "0")); + + assertThat(Util.loadOptionalDuration("foo", properties)).isNull(); + } + + @Test + void loadOptionalDuration_missing() { + Map properties = new HashMap<>(); + + assertThat(Util.loadOptionalDuration("foo", properties)).isNull(); + } + + @Test + void loadOptionalDuration_negative_throws() { + Map properties = new HashMap<>(Map.of("foo", "-1")); + + assertThatExceptionOfType(PrometheusPropertiesException.class) + .isThrownBy(() -> Util.loadOptionalDuration("foo", properties)) + .withMessage("foo: Expecting value >= 0. Found: -1"); + } + + @Test + void loadOptionalDuration_invalidNumber_throws() { + Map properties = new HashMap<>(Map.of("foo", "abc")); + + assertThatExceptionOfType(PrometheusPropertiesException.class) + .isThrownBy(() -> Util.loadOptionalDuration("foo", properties)) + .withMessage("foo=abc: Expecting long value"); + } +} diff --git a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java index 79e7686ce..72e0561c1 100644 --- a/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java +++ b/prometheus-metrics-exporter-pushgateway/src/main/java/io/prometheus/metrics/exporter/pushgateway/PushGateway.java @@ -27,12 +27,12 @@ import java.net.URLEncoder; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.Base64; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; -import java.util.Optional; import javax.annotation.Nullable; /** @@ -80,9 +80,6 @@ * href="https://github.com/prometheus/pushgateway">https://github.com/prometheus/pushgateway. */ public class PushGateway { - - private static final int MILLISECONDS_PER_SECOND = 1000; - private final URL url; private final ExpositionFormatWriter writer; private final boolean prometheusTimestampsInMs; @@ -90,8 +87,8 @@ public class PushGateway { private final PrometheusRegistry registry; private final HttpConnectionFactory connectionFactory; private final EscapingScheme escapingScheme; - private final Integer connectionTimeout; - private final Integer readTimeout; + private final Duration connectionTimeout; + private final Duration readTimeout; private PushGateway( PrometheusRegistry registry, @@ -101,16 +98,16 @@ private PushGateway( Map requestHeaders, boolean prometheusTimestampsInMs, EscapingScheme escapingScheme, - @Nullable Integer connectionTimeout, - @Nullable Integer readTimeout) { + Duration connectionTimeout, + Duration readTimeout) { this.registry = registry; this.url = url; this.requestHeaders = Collections.unmodifiableMap(new HashMap<>(requestHeaders)); this.connectionFactory = connectionFactory; this.prometheusTimestampsInMs = prometheusTimestampsInMs; this.escapingScheme = escapingScheme; - this.connectionTimeout = Optional.ofNullable(connectionTimeout).orElse(10 * MILLISECONDS_PER_SECOND); - this.readTimeout = Optional.ofNullable(readTimeout).orElse(10 * MILLISECONDS_PER_SECOND); + this.connectionTimeout = connectionTimeout; + this.readTimeout = readTimeout; writer = getWriter(format); if (!writer.isAvailable()) { throw new RuntimeException(writer.getClass() + " is not available"); @@ -213,8 +210,8 @@ private void doRequest(@Nullable PrometheusRegistry registry, String method) thr } connection.setRequestMethod(method); - connection.setConnectTimeout(this.connectionTimeout); - connection.setReadTimeout(this.readTimeout); + connection.setConnectTimeout((int) this.connectionTimeout.toMillis()); + connection.setReadTimeout((int) this.readTimeout.toMillis()); connection.connect(); try { @@ -284,8 +281,8 @@ public static class Builder { @Nullable private String address; @Nullable private Scheme scheme; @Nullable private String job; - @Nullable private Integer connectionTimeout; - @Nullable private Integer readTimeout; + @Nullable private Duration connectionTimeout; + @Nullable private Duration readTimeout; private boolean prometheusTimestampsInMs; private final Map requestHeaders = new HashMap<>(); private PrometheusRegistry registry = PrometheusRegistry.defaultRegistry; @@ -405,29 +402,48 @@ public Builder prometheusTimestampsInMs(boolean prometheusTimestampsInMs) { } /** - * Specify the connection timeout (in milliseconds) for HTTP connections to the PushGateway. - * Default is {@code 10000} (10 seconds). + * Specify the connection timeout for HTTP connections to the PushGateway. Default is 10 + * seconds. * - * @param connectionTimeout timeout value in milliseconds + * @param connectionTimeout timeout value * @return this {@link Builder} instance */ - public Builder connectionTimeout(Integer connectionTimeout) { + public Builder connectionTimeout(Duration connectionTimeout) { this.connectionTimeout = connectionTimeout; return this; } + private Duration getConnectionTimeout(@Nullable ExporterPushgatewayProperties properties) { + if (properties != null && properties.getConnectTimeout() != null) { + return properties.getConnectTimeout(); + } else if (this.connectionTimeout != null) { + return this.connectionTimeout; + } else { + return Duration.ofSeconds(10); + } + } + /** - * Specify the read timeout (in milliseconds) for reading the response from the PushGateway. - * Default is {@code 10000} (10 seconds). + * Specify the read timeout for HTTP connections to the PushGateway. Default is 10 seconds. * - * @param readTimeout timeout value in milliseconds + * @param readTimeout timeout value * @return this {@link Builder} instance */ - public Builder readTimeout(Integer readTimeout) { + public Builder readTimeout(Duration readTimeout) { this.readTimeout = readTimeout; return this; } + private Duration getReadTimeout(@Nullable ExporterPushgatewayProperties properties) { + if (properties != null && properties.getReadTimeout() != null) { + return properties.getReadTimeout(); + } else if (this.readTimeout != null) { + return this.readTimeout; + } else { + return Duration.ofSeconds(10); + } + } + private boolean getPrometheusTimestampsInMs() { // accept either to opt in to timestamps in milliseconds return config.getExporterProperties().getPrometheusTimestampsInMs() @@ -530,8 +546,8 @@ public PushGateway build() { requestHeaders, getPrometheusTimestampsInMs(), getEscapingScheme(properties), - connectionTimeout, - readTimeout); + getConnectionTimeout(properties), + getReadTimeout(properties)); } catch (MalformedURLException e) { throw new PrometheusPropertiesException( address + ": Invalid address. Expecting :"); diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java index ee7540ff1..ec1dc5b6c 100644 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java +++ b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java @@ -2,8 +2,8 @@ import static org.junit.jupiter.api.Assertions.*; +import java.time.Duration; import java.util.concurrent.TimeUnit; - import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.junit.jupiter.api.AfterEach; @@ -28,48 +28,53 @@ void tearDown() throws Exception { @Test void connectionTimeoutIsEnforced() { // Simulate server that never accepts connection: by binding but delaying accept. - // Since MockWebServer always accepts connection immediately, we instead use a short connect timeout and a response delay. - int shortConnectTimeoutMillis = 10; - int readTimeoutMillis = 1000; + // Since MockWebServer always accepts connection immediately, we instead use a short connect + // timeout and a response delay. + Duration shortConnectTimeout = Duration.ofMillis(10); + Duration readTimeout = Duration.ofSeconds(1); - PushGateway pushGateway = PushGateway.builder() - .connectionTimeout(shortConnectTimeoutMillis) - .readTimeout(readTimeoutMillis) - .build(); + PushGateway pushGateway = + PushGateway.builder() + .connectionTimeout(shortConnectTimeout) + .readTimeout(readTimeout) + .build(); // Enqueue a response that delays sending headers to simulate slow connection - mockWebServer.enqueue(new MockResponse() - .setBody("ok") - .setBodyDelay(5, TimeUnit.SECONDS)); // very long delay + mockWebServer.enqueue( + new MockResponse().setBody("ok").setBodyDelay(5, TimeUnit.SECONDS)); // very long delay String url = mockWebServer.url("/").toString(); Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); - assertTrue(thrown.getMessage().contains("connect"), "Expected a connection‐timeout or connect error"); + assertTrue( + thrown.getMessage().contains("connect"), "Expected a connection‐timeout or connect error"); } @Test void readTimeoutIsEnforced() { - int connectTimeoutMillis = 1000; - int shortReadTimeoutMillis = 10; + Duration connectTimeout = Duration.ofSeconds(1); + Duration shortReadTimeout = Duration.ofMillis(10); - PushGateway pushGateway = PushGateway.builder() - .connectionTimeout(connectTimeoutMillis) - .readTimeout(shortReadTimeoutMillis) - .build(); + PushGateway pushGateway = + PushGateway.builder() + .connectionTimeout(connectTimeout) + .readTimeout(shortReadTimeout) + .build(); // Enqueue a response that sends headers but delays body - mockWebServer.enqueue(new MockResponse() - .setHeadersDelay(0, TimeUnit.SECONDS) - .setBodyDelay(5, TimeUnit.SECONDS) - .setBody("ok")); + mockWebServer.enqueue( + new MockResponse() + .setHeadersDelay(0, TimeUnit.SECONDS) + .setBodyDelay(5, TimeUnit.SECONDS) + .setBody("ok")); String url = mockWebServer.url("/").toString(); Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); - assertTrue(thrown.getMessage().contains("read") || thrown.getMessage().contains("timeout"), - "Expected a read‐timeout error"); + assertTrue( + thrown.getMessage().contains("read") || thrown.getMessage().contains("timeout"), + "Expected a read‐timeout error"); } } From f2078a92efd010a7391e26583f1e5e2e63163954 Mon Sep 17 00:00:00 2001 From: "huan.huynh" <1612858@student.hcmus.edu.vn> Date: Thu, 6 Nov 2025 20:04:14 +0700 Subject: [PATCH 3/3] Remove test package in pushgateway and redundant test Signed-off-by: huan.huynh <1612858@student.hcmus.edu.vn> --- .../pom.xml | 6 -- .../pushgateway/PushGatewayTimeoutTest.java | 80 ------------------- 2 files changed, 86 deletions(-) delete mode 100644 prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java diff --git a/prometheus-metrics-exporter-pushgateway/pom.xml b/prometheus-metrics-exporter-pushgateway/pom.xml index 350cb8ddc..6d59b2b4d 100644 --- a/prometheus-metrics-exporter-pushgateway/pom.xml +++ b/prometheus-metrics-exporter-pushgateway/pom.xml @@ -39,11 +39,5 @@ ${project.version} test - - com.squareup.okhttp3 - mockwebserver - 5.3.0 - test - diff --git a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java b/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java deleted file mode 100644 index ec1dc5b6c..000000000 --- a/prometheus-metrics-exporter-pushgateway/src/test/java/io/prometheus/metrics/exporter/pushgateway/PushGatewayTimeoutTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.prometheus.metrics.exporter.pushgateway; - -import static org.junit.jupiter.api.Assertions.*; - -import java.time.Duration; -import java.util.concurrent.TimeUnit; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class PushGatewayTimeoutTest { - - private MockWebServer mockWebServer; - - @BeforeEach - void setUp() throws Exception { - mockWebServer = new MockWebServer(); - mockWebServer.start(); - } - - @AfterEach - void tearDown() throws Exception { - mockWebServer.shutdown(); - } - - @Test - void connectionTimeoutIsEnforced() { - // Simulate server that never accepts connection: by binding but delaying accept. - // Since MockWebServer always accepts connection immediately, we instead use a short connect - // timeout and a response delay. - Duration shortConnectTimeout = Duration.ofMillis(10); - Duration readTimeout = Duration.ofSeconds(1); - - PushGateway pushGateway = - PushGateway.builder() - .connectionTimeout(shortConnectTimeout) - .readTimeout(readTimeout) - .build(); - - // Enqueue a response that delays sending headers to simulate slow connection - mockWebServer.enqueue( - new MockResponse().setBody("ok").setBodyDelay(5, TimeUnit.SECONDS)); // very long delay - - String url = mockWebServer.url("/").toString(); - - Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); - - assertTrue( - thrown.getMessage().contains("connect"), "Expected a connection‐timeout or connect error"); - } - - @Test - void readTimeoutIsEnforced() { - Duration connectTimeout = Duration.ofSeconds(1); - Duration shortReadTimeout = Duration.ofMillis(10); - - PushGateway pushGateway = - PushGateway.builder() - .connectionTimeout(connectTimeout) - .readTimeout(shortReadTimeout) - .build(); - - // Enqueue a response that sends headers but delays body - mockWebServer.enqueue( - new MockResponse() - .setHeadersDelay(0, TimeUnit.SECONDS) - .setBodyDelay(5, TimeUnit.SECONDS) - .setBody("ok")); - - String url = mockWebServer.url("/").toString(); - - Exception thrown = assertThrows(Exception.class, pushGateway::pushAdd); - - assertTrue( - thrown.getMessage().contains("read") || thrown.getMessage().contains("timeout"), - "Expected a read‐timeout error"); - } -}