This is an automated email from the ASF dual-hosted git repository.

junrui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/master by this push:
     new 4cbe3644ac7 [FLINK-27661][Runtime / Metrics] 
PrometheusPushGatewayReporter support pushgateway http authentication (#27576)
4cbe3644ac7 is described below

commit 4cbe3644ac70e773c042ef5e42eda1e7baaab200
Author: Liu Jiangang <[email protected]>
AuthorDate: Tue Mar 3 12:14:51 2026 +0800

    [FLINK-27661][Runtime / Metrics] PrometheusPushGatewayReporter support 
pushgateway http authentication (#27576)
    
    * [FLINK-27661][Runtime / Metrics] PrometheusPushGatewayReporter support 
pushgateway http authentication
    
    * hotfix
    
    * [hotfix] Reuse basicAuthEnabled
    
    * [hotfix] Generate docs
---
 .../content.zh/docs/deployment/metric_reporters.md | 15 +++++
 docs/content/docs/deployment/metric_reporters.md   | 15 +++++
 ...etheus_push_gateway_reporter_configuration.html | 12 ++++
 ...eus_push_gateway_reporter_configuration_zh.html | 12 ++++
 .../prometheus/PrometheusPushGatewayReporter.java  | 15 ++++-
 .../PrometheusPushGatewayReporterFactory.java      | 39 +++++++++---
 .../PrometheusPushGatewayReporterOptions.java      | 14 +++++
 .../PrometheusPushGatewayReporterTest.java         | 71 ++++++++++++++++++++++
 8 files changed, 183 insertions(+), 10 deletions(-)

diff --git a/docs/content.zh/docs/deployment/metric_reporters.md 
b/docs/content.zh/docs/deployment/metric_reporters.md
index 23f1d4b674e..9c02675b872 100644
--- a/docs/content.zh/docs/deployment/metric_reporters.md
+++ b/docs/content.zh/docs/deployment/metric_reporters.md
@@ -231,6 +231,21 @@ PrometheusPushGatewayReporter 发送器将运行指标发送给 [Pushgateway](ht
 
 更多使用方法可查看 [Prometheus 的文档](https://prometheus.io/docs/practices/pushing/)
 
+#### HTTP Basic 认证
+
+该发送器支持通过 HTTP Basic 认证连接到需要安全验证的 PushGateway 实例。要启用认证功能,需要同时配置 `username` 和 
`password`:
+
+```yaml
+metrics.reporter.promgateway.factory.class: 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterFactory
+metrics.reporter.promgateway.hostUrl: https://pushgateway.example.com:9091
+metrics.reporter.promgateway.jobName: myJob
+metrics.reporter.promgateway.username: flink-reporter
+metrics.reporter.promgateway.password: ${PUSHGATEWAY_PASSWORD}
+metrics.reporter.promgateway.interval: 60 SECONDS
+```
+
+<span class="label label-info">注意</span> 只有同时配置了 `username` 和 `password` 
时,Basic 认证才会启用。建议在启用认证时使用 HTTPS 以保护传输中的凭据安全。
+
 <a name="statsd"></a>
 
 ### StatsD
diff --git a/docs/content/docs/deployment/metric_reporters.md 
b/docs/content/docs/deployment/metric_reporters.md
index 70d3aee87fb..d0b7246f274 100644
--- a/docs/content/docs/deployment/metric_reporters.md
+++ b/docs/content/docs/deployment/metric_reporters.md
@@ -219,6 +219,21 @@ The PrometheusPushGatewayReporter pushes metrics to a 
[Pushgateway](https://gith
 
 Please see the [Prometheus 
documentation](https://prometheus.io/docs/practices/pushing/) for use-cases.
 
+#### HTTP Basic Authentication
+
+The reporter supports HTTP Basic Authentication for connecting to secured 
PushGateway instances. To enable authentication, configure both `username` and 
`password`:
+
+```yaml
+metrics.reporter.promgateway.factory.class: 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterFactory
+metrics.reporter.promgateway.hostUrl: https://pushgateway.example.com:9091
+metrics.reporter.promgateway.jobName: myJob
+metrics.reporter.promgateway.username: flink-reporter
+metrics.reporter.promgateway.password: ${PUSHGATEWAY_PASSWORD}
+metrics.reporter.promgateway.interval: 60 SECONDS
+```
+
+<span class="label label-info">Note</span> Basic authentication is enabled 
only when both `username` and `password` are configured. It is recommended to 
use HTTPS when authentication is enabled to protect credentials in transit.
+
 ### StatsD
 #### (org.apache.flink.metrics.statsd.StatsDReporter)
 
diff --git 
a/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration.html
 
b/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration.html
index 9d03e1d02dc..8d3fd370f37 100644
--- 
a/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration.html
+++ 
b/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration.html
@@ -38,11 +38,23 @@
             <td>String</td>
             <td>The job name under which metrics will be pushed</td>
         </tr>
+        <tr>
+            <td><h5>metrics.reporter.prometheus.password</h5></td>
+            <td style="word-wrap: break-word;">(none)</td>
+            <td>String</td>
+            <td>(Optional) The password for HTTP Basic Authentication with the 
PushGateway.</td>
+        </tr>
         <tr>
             <td><h5>metrics.reporter.prometheus.randomJobNameSuffix</h5></td>
             <td style="word-wrap: break-word;">true</td>
             <td>Boolean</td>
             <td>Specifies whether a random suffix should be appended to the 
job name.</td>
         </tr>
+        <tr>
+            <td><h5>metrics.reporter.prometheus.username</h5></td>
+            <td style="word-wrap: break-word;">(none)</td>
+            <td>String</td>
+            <td>(Optional) The username for HTTP Basic Authentication with the 
PushGateway.</td>
+        </tr>
     </tbody>
 </table>
diff --git 
a/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration_zh.html
 
b/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration_zh.html
index d79a5ba0e97..8623bba55df 100644
--- 
a/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration_zh.html
+++ 
b/docs/layouts/shortcodes/generated/prometheus_push_gateway_reporter_configuration_zh.html
@@ -38,11 +38,23 @@
             <td>String</td>
             <td>推送运行指标数据时的作业名。</td>
         </tr>
+        <tr>
+            <td><h5>metrics.reporter.prometheus.password</h5></td>
+            <td style="word-wrap: break-word;">(none)</td>
+            <td>String</td>
+            <td>(可选)用于 PushGateway HTTP Basic 认证的密码。</td>
+        </tr>
         <tr>
             <td><h5>metrics.reporter.prometheus.randomJobNameSuffix</h5></td>
             <td style="word-wrap: break-word;">true</td>
             <td>Boolean</td>
             <td>是否在作业名后添加一个随机后缀。</td>
         </tr>
+        <tr>
+            <td><h5>metrics.reporter.prometheus.username</h5></td>
+            <td style="word-wrap: break-word;">(none)</td>
+            <td>String</td>
+            <td>(可选)用于 PushGateway HTTP Basic 认证的用户名。</td>
+        </tr>
     </tbody>
 </table>
diff --git 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporter.java
 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporter.java
index 226858a3182..2ee6d6df431 100644
--- 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporter.java
+++ 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporter.java
@@ -25,8 +25,11 @@ import org.apache.flink.metrics.reporter.MetricReporter;
 import org.apache.flink.metrics.reporter.Scheduled;
 import org.apache.flink.util.Preconditions;
 
+import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;
 import io.prometheus.client.exporter.PushGateway;
 
+import javax.annotation.Nullable;
+
 import java.io.IOException;
 import java.net.URL;
 import java.util.Map;
@@ -42,14 +45,24 @@ public class PrometheusPushGatewayReporter extends 
AbstractPrometheusReporter im
     private final Map<String, String> groupingKey;
     private final boolean deleteOnShutdown;
     @VisibleForTesting final URL hostUrl;
+    @VisibleForTesting final boolean basicAuthEnabled;
 
     PrometheusPushGatewayReporter(
             URL hostUrl,
             String jobName,
             Map<String, String> groupingKey,
-            final boolean deleteOnShutdown) {
+            final boolean deleteOnShutdown,
+            @Nullable String username,
+            @Nullable String password) {
         this.hostUrl = hostUrl;
         this.pushGateway = new PushGateway(hostUrl);
+        if (username != null && password != null) {
+            this.pushGateway.setConnectionFactory(
+                    new BasicAuthHttpConnectionFactory(username, password));
+            this.basicAuthEnabled = true;
+        } else {
+            this.basicAuthEnabled = false;
+        }
         this.jobName = Preconditions.checkNotNull(jobName);
         this.groupingKey = Preconditions.checkNotNull(groupingKey);
         this.deleteOnShutdown = deleteOnShutdown;
diff --git 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterFactory.java
 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterFactory.java
index 35a23d9e957..b08f5c0fd5d 100644
--- 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterFactory.java
+++ 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterFactory.java
@@ -37,7 +37,9 @@ import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterO
 import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.GROUPING_KEY;
 import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.HOST_URL;
 import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.JOB_NAME;
+import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.PASSWORD;
 import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.RANDOM_JOB_NAME_SUFFIX;
+import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.USERNAME;
 
 /** {@link MetricReporterFactory} for {@link PrometheusPushGatewayReporter}. */
 public class PrometheusPushGatewayReporterFactory implements 
MetricReporterFactory {
@@ -70,17 +72,36 @@ public class PrometheusPushGatewayReporterFactory 
implements MetricReporterFacto
             jobName = configuredJobName + new AbstractID();
         }
 
-        LOG.info(
-                "Configured PrometheusPushGatewayReporter with {hostUrl:{}, 
jobName:{}, randomJobNameSuffix:{}, deleteOnShutdown:{}, groupingKey:{}}",
-                hostUrl,
-                jobName,
-                randomSuffix,
-                deleteOnShutdown,
-                groupingKey);
+        String username = metricConfig.getString(USERNAME.key(), 
USERNAME.defaultValue());
+        String password = metricConfig.getString(PASSWORD.key(), 
PASSWORD.defaultValue());
+
+        if ((username != null && password == null) || (username == null && 
password != null)) {
+            LOG.warn(
+                    "Both username and password must be configured to enable 
HTTP Basic Authentication. "
+                            + "Currently only {} is configured, Basic Auth 
will be disabled.",
+                    username != null ? "username" : "password");
+        }
 
         try {
-            return new PrometheusPushGatewayReporter(
-                    new URL(hostUrl), jobName, groupingKey, deleteOnShutdown);
+            PrometheusPushGatewayReporter reporter =
+                    new PrometheusPushGatewayReporter(
+                            new URL(hostUrl),
+                            jobName,
+                            groupingKey,
+                            deleteOnShutdown,
+                            username,
+                            password);
+
+            LOG.info(
+                    "Configured PrometheusPushGatewayReporter with 
{hostUrl:{}, jobName:{}, randomJobNameSuffix:{}, deleteOnShutdown:{}, 
groupingKey:{}, basicAuth:{}}",
+                    hostUrl,
+                    jobName,
+                    randomSuffix,
+                    deleteOnShutdown,
+                    groupingKey,
+                    reporter.basicAuthEnabled);
+
+            return reporter;
         } catch (MalformedURLException e) {
             throw new RuntimeException(e);
         }
diff --git 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterOptions.java
 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterOptions.java
index 84404b5ef7b..bdb48e9c611 100644
--- 
a/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterOptions.java
+++ 
b/flink-metrics/flink-metrics-prometheus/src/main/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterOptions.java
@@ -98,4 +98,18 @@ public class PrometheusPushGatewayReporterOptions {
                                                     
"https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels";,
                                                     "Prometheus requirements"))
                                     .build());
+
+    public static final ConfigOption<String> USERNAME =
+            ConfigOptions.key("username")
+                    .stringType()
+                    .noDefaultValue()
+                    .withDescription(
+                            "(Optional) The username for HTTP Basic 
Authentication with the PushGateway.");
+
+    public static final ConfigOption<String> PASSWORD =
+            ConfigOptions.key("password")
+                    .stringType()
+                    .noDefaultValue()
+                    .withDescription(
+                            "(Optional) The password for HTTP Basic 
Authentication with the PushGateway.");
 }
diff --git 
a/flink-metrics/flink-metrics-prometheus/src/test/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterTest.java
 
b/flink-metrics/flink-metrics-prometheus/src/test/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterTest.java
index 6f70f45a075..81be12eaf84 100644
--- 
a/flink-metrics/flink-metrics-prometheus/src/test/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterTest.java
+++ 
b/flink-metrics/flink-metrics-prometheus/src/test/java/org/apache/flink/metrics/prometheus/PrometheusPushGatewayReporterTest.java
@@ -19,18 +19,27 @@
 package org.apache.flink.metrics.prometheus;
 
 import org.apache.flink.metrics.MetricConfig;
+import org.apache.flink.testutils.logging.LoggerAuditingExtension;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.slf4j.event.Level;
 
 import java.util.Map;
 
 import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.HOST_URL;
+import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.PASSWORD;
+import static 
org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporterOptions.USERNAME;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 /** Test for {@link PrometheusPushGatewayReporter}. */
 class PrometheusPushGatewayReporterTest {
 
+    @RegisterExtension
+    private final LoggerAuditingExtension loggerExtension =
+            new 
LoggerAuditingExtension(PrometheusPushGatewayReporterFactory.class, Level.WARN);
+
     @Test
     void testParseGroupingKey() {
         Map<String, String> groupingKey =
@@ -68,4 +77,66 @@ class PrometheusPushGatewayReporterTest {
         assertThatThrownBy(() -> factory.createMetricReporter(metricConfig))
                 .isInstanceOf(IllegalArgumentException.class);
     }
+
+    @Test
+    void testBasicAuthNotEnabledWithoutCredentials() {
+        PrometheusPushGatewayReporterFactory factory = new 
PrometheusPushGatewayReporterFactory();
+        MetricConfig metricConfig = new MetricConfig();
+        metricConfig.setProperty(HOST_URL.key(), "http://localhost:9091";);
+        // No authentication configured - should create reporter successfully 
without Basic Auth
+        PrometheusPushGatewayReporter reporter = 
factory.createMetricReporter(metricConfig);
+        assertThat(reporter).isNotNull();
+        
assertThat(reporter.hostUrl.toString()).isEqualTo("http://localhost:9091";);
+        assertThat(reporter.basicAuthEnabled).isFalse();
+    }
+
+    @Test
+    void testBasicAuthNotEnabledWithOnlyUsername() {
+        PrometheusPushGatewayReporterFactory factory = new 
PrometheusPushGatewayReporterFactory();
+        MetricConfig metricConfig = new MetricConfig();
+        metricConfig.setProperty(HOST_URL.key(), "http://localhost:9091";);
+        metricConfig.setProperty(USERNAME.key(), "flink-user");
+        // Only username configured - should create reporter successfully 
without Basic Auth
+        PrometheusPushGatewayReporter reporter = 
factory.createMetricReporter(metricConfig);
+        assertThat(reporter).isNotNull();
+        assertThat(reporter.basicAuthEnabled).isFalse();
+        // Verify warning log is emitted
+        assertThat(loggerExtension.getMessages())
+                .anyMatch(
+                        msg ->
+                                msg.contains("Both username and password must 
be configured")
+                                        && msg.contains("Currently only 
username is configured"));
+    }
+
+    @Test
+    void testBasicAuthNotEnabledWithOnlyPassword() {
+        PrometheusPushGatewayReporterFactory factory = new 
PrometheusPushGatewayReporterFactory();
+        MetricConfig metricConfig = new MetricConfig();
+        metricConfig.setProperty(HOST_URL.key(), "http://localhost:9091";);
+        metricConfig.setProperty(PASSWORD.key(), "flink-password");
+        // Only password configured - should create reporter successfully 
without Basic Auth
+        PrometheusPushGatewayReporter reporter = 
factory.createMetricReporter(metricConfig);
+        assertThat(reporter).isNotNull();
+        assertThat(reporter.basicAuthEnabled).isFalse();
+        // Verify warning log is emitted
+        assertThat(loggerExtension.getMessages())
+                .anyMatch(
+                        msg ->
+                                msg.contains("Both username and password must 
be configured")
+                                        && msg.contains("Currently only 
password is configured"));
+    }
+
+    @Test
+    void testBasicAuthEnabledWithBothCredentials() {
+        PrometheusPushGatewayReporterFactory factory = new 
PrometheusPushGatewayReporterFactory();
+        MetricConfig metricConfig = new MetricConfig();
+        metricConfig.setProperty(HOST_URL.key(), "http://localhost:9091";);
+        metricConfig.setProperty(USERNAME.key(), "flink-user");
+        metricConfig.setProperty(PASSWORD.key(), "flink-password");
+        // Both username and password configured - Basic Auth should be enabled
+        PrometheusPushGatewayReporter reporter = 
factory.createMetricReporter(metricConfig);
+        assertThat(reporter).isNotNull();
+        
assertThat(reporter.hostUrl.toString()).isEqualTo("http://localhost:9091";);
+        assertThat(reporter.basicAuthEnabled).isTrue();
+    }
 }

Reply via email to