This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new 7d14ed80ba [fix] expose prestodb auth parameters and wire
authorization into all metrics (#4188)
7d14ed80ba is described below
commit 7d14ed80ba8cf1be61ec660e88571a11de0ccf2f
Author: NekoPunch <[email protected]>
AuthorDate: Sun Jul 12 23:46:00 2026 -0700
[fix] expose prestodb auth parameters and wire authorization into all
metrics (#4188)
Co-authored-by: Duansg <[email protected]>
---
.../collect/basic/http/PrestodbMonitorE2eTest.java | 183 +++++++++++++++++++++
.../src/main/resources/define/app-prestodb.yml | 42 +++++
home/docs/help/prestodb.md | 4 +
.../current/help/prestodb.md | 4 +
4 files changed, 233 insertions(+)
diff --git
a/hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/http/PrestodbMonitorE2eTest.java
b/hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/http/PrestodbMonitorE2eTest.java
new file mode 100644
index 0000000000..04a821c0cc
--- /dev/null
+++
b/hertzbeat-e2e/hertzbeat-collector-basic-e2e/src/test/java/org/apache/hertzbeat/collector/collect/basic/http/PrestodbMonitorE2eTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.hertzbeat.collector.collect.basic.http;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.collector.collect.AbstractCollectE2eTest;
+import org.apache.hertzbeat.collector.collect.http.HttpCollectImpl;
+import org.apache.hertzbeat.collector.util.CollectUtil;
+import org.apache.hertzbeat.common.entity.job.Configmap;
+import org.apache.hertzbeat.common.entity.job.Job;
+import org.apache.hertzbeat.common.entity.job.Metrics;
+import org.apache.hertzbeat.common.entity.job.protocol.Protocol;
+import org.apache.hertzbeat.common.entity.message.CollectRep;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * E2E test for PrestoDB monitor with HTTP Basic Auth enabled (issue #2838).
+ * Unlike other http monitor tests, the protocol is taken from the template
definition
+ * after placeholder replacement (mirroring WheelTimerTask#initJobMetrics), so
a metric
+ * whose http section lacks the authorization wiring fails this test with a
401.
+ */
+@Slf4j
+@ExtendWith(MockitoExtension.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class PrestodbMonitorE2eTest extends AbstractCollectE2eTest {
+
+ private static final int MOCK_SERVER_PORT = 52390;
+ private static final String LOCALHOST = "127.0.0.1";
+ private static final String USERNAME = "presto-admin";
+ private static final String PASSWORD = "presto-secret";
+ private static final Gson GSON = new Gson();
+ private static HttpServer mockServer;
+
+ private static final String CLUSTER_JSON = """
+ {"activeWorkers": 3, "runningQueries": 2, "queuedQueries": 1,
+ "blockedQueries": 0, "runningDrivers": 12, "runningTasks": 5}""";
+
+ private static final String NODE_JSON = """
+ [{"uri": "http://127.0.0.1:8080", "recentRequests": 25.3,
"recentFailures": 0.0,
+ "recentSuccesses": 25.3, "lastRequestTime":
"2026-07-08T10:00:00.000Z",
+ "lastResponseTime": "2026-07-08T10:00:00.100Z", "age": "5.20d",
"recentFailureRatio": 0.0}]""";
+
+ private static final String STATUS_JSON = """
+ {"nodeId": "coordinator-1", "nodeVersion": {"version": "0.289"},
"environment": "production",
+ "coordinator": true, "uptime": "5.20d", "externalAddress":
"127.0.0.1",
+ "internalAddress": "127.0.0.1", "processors": 8,
"processCpuLoad": 0.35,
+ "systemCpuLoad": 0.42, "heapUsed": 1073741824, "heapAvailable":
4294967296, "nonHeapUsed": 268435456}""";
+
+ private static final String TASK_JSON = """
+ [{"taskId": "20260708_100000_00001_abcde.1.0.0", "version": 42,
"state": "RUNNING",
+ "self":
"http://127.0.0.1:8080/v1/task/20260708_100000_00001_abcde.1.0.0",
+ "lastHeartbeat": "2026-07-08T10:00:00.000Z"}]""";
+
+ @AfterEach
+ public void tearDown() {
+ if (mockServer != null) {
+ mockServer.stop(0);
+ }
+ }
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ super.setUp();
+ collect = new HttpCollectImpl();
+
+ mockServer = HttpServer.create(new
InetSocketAddress(MOCK_SERVER_PORT), 0);
+ mockServer.setExecutor(null);
+ mockServer.start();
+ mockServer.createContext("/v1/cluster", exchange ->
sendAuthenticatedJson(exchange, CLUSTER_JSON));
+ mockServer.createContext("/v1/node", exchange ->
sendAuthenticatedJson(exchange, NODE_JSON));
+ mockServer.createContext("/v1/status", exchange ->
sendAuthenticatedJson(exchange, STATUS_JSON));
+ mockServer.createContext("/v1/task", exchange ->
sendAuthenticatedJson(exchange, TASK_JSON));
+ }
+
+ private void sendAuthenticatedJson(HttpExchange exchange, String response)
throws IOException {
+ String expected = "Basic " + Base64.getEncoder()
+ .encodeToString((USERNAME + ":" +
PASSWORD).getBytes(StandardCharsets.UTF_8));
+ if
(!expected.equals(exchange.getRequestHeaders().getFirst("Authorization"))) {
+ exchange.getResponseHeaders().set("WWW-Authenticate", "Basic
realm=\"presto\"");
+ exchange.sendResponseHeaders(401, -1);
+ exchange.close();
+ return;
+ }
+ exchange.getResponseHeaders().set("Content-Type", "application/json");
+ final byte[] array = response.getBytes(StandardCharsets.UTF_8);
+ exchange.sendResponseHeaders(200, array.length);
+ try (OutputStream os = exchange.getResponseBody()) {
+ os.write(array);
+ }
+ }
+
+ @Test
+ public void testPrestodbMonitorWithBasicAuth() {
+ Job prestodbJob = appService.getAppDefine("prestodb");
+ Map<String, Configmap> configmap = buildParamConfigmap(true);
+ for (Metrics metricsDef : prestodbJob.getMetrics()) {
+ metricsDef = replaceJobPlaceholder(metricsDef, configmap);
+ validateMetricsCollection(metricsDef, metricsDef.getName());
+ }
+ }
+
+ @Test
+ public void testPrestodbMonitorWithoutAuthIsRejected() {
+ Job prestodbJob = appService.getAppDefine("prestodb");
+ Map<String, Configmap> configmap = buildParamConfigmap(false);
+ Metrics availabilityMetric = prestodbJob.getMetrics().stream()
+ .filter(m -> "cluster".equals(m.getName()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalStateException("prestodb
template has no cluster metric"));
+ availabilityMetric = replaceJobPlaceholder(availabilityMetric,
configmap);
+ CollectRep.MetricsData.Builder metricsData =
collectMetrics(availabilityMetric);
+ Assertions.assertNotEquals(CollectRep.Code.SUCCESS,
metricsData.getCode(),
+ "collection against an auth-protected endpoint must fail when
no credentials are configured");
+ }
+
+ private Map<String, Configmap> buildParamConfigmap(boolean withAuth) {
+ Map<String, Configmap> configmap = new HashMap<>();
+ configmap.put("host", new Configmap("host", LOCALHOST, (byte) 1));
+ configmap.put("port", new Configmap("port",
String.valueOf(MOCK_SERVER_PORT), (byte) 1));
+ configmap.put("ssl", new Configmap("ssl", "false", (byte) 1));
+ configmap.put("timeout", new Configmap("timeout", "6000", (byte) 1));
+ if (withAuth) {
+ configmap.put("authType", new Configmap("authType", "Basic Auth",
(byte) 1));
+ configmap.put("username", new Configmap("username", USERNAME,
(byte) 1));
+ configmap.put("password", new Configmap("password", PASSWORD,
(byte) 1));
+ }
+ return configmap;
+ }
+
+ /**
+ * Mirrors WheelTimerTask#initJobMetrics: replace ^_^param^_^ placeholders
+ * in the whole metric definition, keeping the template's http
authorization wiring.
+ */
+ private Metrics replaceJobPlaceholder(Metrics metricsDef, Map<String,
Configmap> configmap) {
+ JsonElement jsonElement = GSON.toJsonTree(metricsDef);
+ CollectUtil.replaceSmilingPlaceholder(jsonElement, configmap);
+ return GSON.fromJson(jsonElement, Metrics.class);
+ }
+
+ @Override
+ protected Protocol buildProtocol(Metrics metricsDef) {
+ return metricsDef.getHttp();
+ }
+
+ @Override
+ protected CollectRep.MetricsData.Builder collectMetrics(Metrics
metricsDef) {
+ metrics.setHttp(metricsDef.getHttp());
+ return collectMetricsData(metrics, metricsDef);
+ }
+}
diff --git a/hertzbeat-manager/src/main/resources/define/app-prestodb.yml
b/hertzbeat-manager/src/main/resources/define/app-prestodb.yml
index 120e92afb0..813681e009 100644
--- a/hertzbeat-manager/src/main/resources/define/app-prestodb.yml
+++ b/hertzbeat-manager/src/main/resources/define/app-prestodb.yml
@@ -53,6 +53,36 @@ params:
ja-JP: HTTPS
type: boolean
required: true
+ - field: authType
+ name:
+ zh-CN: 认证方式
+ en-US: Auth Type
+ ja-JP: 認証方法
+ type: radio
+ required: false
+ hide: true
+ options:
+ - label: Basic Auth
+ value: Basic Auth
+ - label: Digest Auth
+ value: Digest Auth
+ - field: username
+ name:
+ zh-CN: 用户名
+ en-US: Username
+ ja-JP: ユーザー名
+ type: text
+ limit: 50
+ required: false
+ hide: true
+ - field: password
+ name:
+ zh-CN: 密码
+ en-US: Password
+ ja-JP: パスワード
+ type: password
+ required: false
+ hide: true
- field: timeout
name:
zh-CN: 超时时间(ms)
@@ -115,6 +145,12 @@ metrics:
timeout: ^_^timeout^_^
method: GET
ssl: ^_^ssl^_^
+ authorization:
+ type: ^_^authType^_^
+ basicAuthUsername: ^_^username^_^
+ basicAuthPassword: ^_^password^_^
+ digestAuthUsername: ^_^username^_^
+ digestAuthPassword: ^_^password^_^
parseType: jsonPath
parseScript: '$'
@@ -182,6 +218,12 @@ metrics:
timeout: ^_^timeout^_^
method: GET
ssl: ^_^ssl^_^
+ authorization:
+ type: ^_^authType^_^
+ basicAuthUsername: ^_^username^_^
+ basicAuthPassword: ^_^password^_^
+ digestAuthUsername: ^_^username^_^
+ digestAuthPassword: ^_^password^_^
parseType: jsonPath
parseScript: '$[*]'
diff --git a/home/docs/help/prestodb.md b/home/docs/help/prestodb.md
index 2ebe19fcf8..58081d1ded 100644
--- a/home/docs/help/prestodb.md
+++ b/home/docs/help/prestodb.md
@@ -13,6 +13,10 @@ keywords: [ open source monitoring system, open source
database monitoring, pres
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
| Target Host | The IP address, IPv4, IPv6, or domain name of the
target to be monitored. Note: ⚠️ Do not include protocol headers (e.g.,
https://, http://). |
| port | Port
|
+| HTTPS | Whether to enable HTTPS for the PrestoDB API endpoint.
|
+| Auth Type | Optional HTTP authentication mode. Supported values
are `Basic Auth` and `Digest Auth`.
|
+| Username | Username used when `Basic Auth` or `Digest Auth` is
enabled.
|
+| Password | Password used when `Basic Auth` or `Digest Auth` is
enabled.
|
| Task Name | The name identifying this monitor, which must be
unique.
|
| Connection Timeout | Timeout for PrestoDB connection when no response is
received, in milliseconds (ms). Default is 6000 ms.
|
| Collection Interval | Interval for periodic data collection, in seconds. The
minimum interval is 30 seconds.
|
diff --git
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/prestodb.md
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/prestodb.md
index 423f35f49f..a2216cdcbd 100644
--- a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/prestodb.md
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/prestodb.md
@@ -14,6 +14,10 @@ keywords: [ 开源监控系统, 开源数据库监控, Presto数据库监控 ]
| 目标Host | 被监控的对端IPV4,IPV6或域名。注意⚠️不带协议头(eg: https://, http://)。 |
| 任务名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 被监控的平台端口。 |
+| 启用HTTPS | 是否启用 PrestoDB API 的 HTTPS 访问。 |
+| 认证方式 | 可选的 HTTP 认证方式,支持 `Basic Auth` 和 `Digest Auth`。 |
+| 用户名 | 启用 `Basic Auth` 或 `Digest Auth` 后使用的用户名。 |
+| 密码 | 启用 `Basic Auth` 或 `Digest Auth` 后使用的密码。 |
| 连接超时时间 | 设置连接PrestoDB未响应数据时的超时时间,单位ms毫秒,默认6000毫秒。 |
| 采集间隔 | 监控周期性采集数据间隔时间,单位秒,可设置的最小间隔为30秒。 |
| 绑定标签 | 用于对监控资源进行分类管理。 |
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]