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

zhaoqingran 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 e1affb169f [feature]Make GreptimeDB as a grafana data source  (#3403)
e1affb169f is described below

commit e1affb169f73f882224fd161ac6c83022fc45b5c
Author: Logic <zqr10...@dromara.org>
AuthorDate: Tue Jun 3 23:37:31 2025 +0800

    [feature]Make GreptimeDB as a grafana data source  (#3403)
    
    Signed-off-by: Logic <zqr10...@126.com>
    Co-authored-by: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
    Co-authored-by: Calvin <zhengqi...@apache.org>
    Co-authored-by: tomsun28 <tomsu...@outlook.com>
---
 .../prometheus/PrometheusAutoCollectImpl.java      |   4 +-
 .../collect/prometheus/PrometheusCollect.java      |  45 +++++
 ...ctImpl.java => PrometheusProxyCollectImpl.java} | 210 ++++++++++-----------
 .../collector/dispatch/MetricsCollect.java         |  33 +++-
 .../apache/hertzbeat/common/entity/job/Job.java    |   5 +
 .../hertzbeat/grafana/common/GrafanaConstants.java |  65 +++++--
 .../hertzbeat/grafana/config/GrafanaInit.java      |   5 +-
 .../grafana/service/DashboardService.java          | 139 ++++++++++----
 .../grafana/service/DatasourceService.java         | 163 +++++++++++++---
 .../manager/config/PrometheusProxyConfig.java      |  81 ++++++++
 .../hertzbeat/manager/scheduler/SchedulerInit.java |   6 +
 .../org/apache/hertzbeat/manager/ManagerTest.java  |   4 +-
 .../otel/config/LogAutoConfiguration.java          |   2 +-
 .../hertzbeat/otel/config/OpenTelemetryConfig.java |   2 +-
 .../warehouse/db/GreptimePromqlQueryExecutor.java  |   2 +-
 .../warehouse/db/PromqlQueryExecutor.java          |   2 +-
 .../warehouse/db/VictoriaMetricsQueryExecutor.java |   2 +-
 .../WareHouseApplicationReadyListener.java         |   2 +-
 .../service/impl/MetricsDataServiceImpl.java       |   2 +-
 .../warehouse/store/DataStorageDispatch.java       |   2 +-
 .../{ => tsdb}/AbstractHistoryDataStorage.java     |   2 +-
 .../history/{ => tsdb}/HistoryDataReader.java      |   2 +-
 .../history/{ => tsdb}/HistoryDataWriter.java      |   2 +-
 .../{ => tsdb}/greptime/GreptimeDbDataStorage.java |  18 +-
 .../{ => tsdb}/greptime/GreptimeProperties.java    |   2 +-
 .../{ => tsdb}/influxdb/InfluxdbDataStorage.java   |   4 +-
 .../{ => tsdb}/influxdb/InfluxdbProperties.java    |   2 +-
 .../history/{ => tsdb}/iotdb/IotDbDataStorage.java |   4 +-
 .../history/{ => tsdb}/iotdb/IotDbProperties.java  |   2 +-
 .../{ => tsdb}/jpa/JpaDatabaseDataStorage.java     |   4 +-
 .../history/{ => tsdb}/jpa/JpaProperties.java      |   2 +-
 .../{ => tsdb}/tdengine/TdEngineDataStorage.java   |   4 +-
 .../{ => tsdb}/tdengine/TdEngineProperties.java    |   2 +-
 .../history/{ => tsdb}/vm/PromQlQueryContent.java  |   2 +-
 .../vm/VictoriaMetricsClusterDataStorage.java      |   4 +-
 .../vm/VictoriaMetricsClusterProperties.java       |   2 +-
 .../{ => tsdb}/vm/VictoriaMetricsDataStorage.java  |   4 +-
 .../vm/VictoriaMetricsInsertProperties.java        |   2 +-
 .../{ => tsdb}/vm/VictoriaMetricsProperties.java   |   2 +-
 .../vm/VictoriaMetricsSelectProperties.java        |   2 +-
 .../warehouse/service/MetricsDataServiceTest.java  |   2 +-
 .../warehouse/store/TdEngineDataStorageTest.java   |   2 +-
 42 files changed, 604 insertions(+), 244 deletions(-)

diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
index 0dd8ccfde4..5ab95579d5 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
@@ -72,12 +72,13 @@ import org.springframework.util.StringUtils;
  * prometheus auto collect
  */
 @Slf4j
-public class PrometheusAutoCollectImpl {
+public class PrometheusAutoCollectImpl implements PrometheusCollect {
     
     private final Set<Integer> defaultSuccessStatusCodes = 
Stream.of(HttpStatus.SC_OK, HttpStatus.SC_CREATED,
             HttpStatus.SC_ACCEPTED, HttpStatus.SC_MULTIPLE_CHOICES, 
HttpStatus.SC_MOVED_PERMANENTLY,
             HttpStatus.SC_MOVED_TEMPORARILY).collect(Collectors.toSet());
     
+    @Override
     public List<CollectRep.MetricsData> collect(CollectRep.MetricsData.Builder 
builder,
                                                 Metrics metrics) {
         try {
@@ -139,6 +140,7 @@ public class PrometheusAutoCollectImpl {
         return Collections.singletonList(builder.build());
     }
     
+    @Override
     public String supportProtocol() {
         return DispatchConstants.PROTOCOL_PROMETHEUS;
     }
diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusCollect.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusCollect.java
new file mode 100644
index 0000000000..7935b4bacd
--- /dev/null
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusCollect.java
@@ -0,0 +1,45 @@
+/*
+ * 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.prometheus;
+
+import org.apache.hertzbeat.common.entity.job.Metrics;
+import org.apache.hertzbeat.common.entity.message.CollectRep;
+
+import java.util.List;
+
+/**
+ * Prometheus metrics collector interface
+ */
+public interface PrometheusCollect {
+
+    /**
+     * Collect prometheus metrics data
+     * @param builder metrics data builder
+     * @param metrics metrics config
+     * @return list of metrics data
+     */
+    List<CollectRep.MetricsData> collect(CollectRep.MetricsData.Builder 
builder, Metrics metrics);
+
+    /**
+     * Get the protocol name this collector supported
+     * @return protocol name
+     */
+    String supportProtocol();
+}
diff --git 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusProxyCollectImpl.java
similarity index 67%
copy from 
hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
copy to 
hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusProxyCollectImpl.java
index 0dd8ccfde4..2177710d0a 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusAutoCollectImpl.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-basic/src/main/java/org/apache/hertzbeat/collector/collect/prometheus/PrometheusProxyCollectImpl.java
@@ -17,24 +17,8 @@
 
 package org.apache.hertzbeat.collector.collect.prometheus;
 
-import static org.apache.hertzbeat.common.constants.SignConstants.RIGHT_DASH;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.net.ConnectException;
-import java.net.UnknownHostException;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.net.ssl.SSLException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.collector.collect.common.http.CommonHttpClient;
-import org.apache.hertzbeat.collector.collect.prometheus.parser.MetricFamily;
 import org.apache.hertzbeat.collector.dispatch.DispatchConstants;
 import org.apache.hertzbeat.collector.util.CollectUtil;
 import org.apache.hertzbeat.common.constants.CommonConstants;
@@ -46,7 +30,6 @@ import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.util.Base64Util;
 import org.apache.hertzbeat.common.util.CommonUtil;
 import org.apache.hertzbeat.common.util.IpDomainUtil;
-import org.apache.hertzbeat.collector.collect.prometheus.parser.OnlineParser;
 import org.apache.http.HttpHeaders;
 import org.apache.http.HttpHost;
 import org.apache.http.HttpStatus;
@@ -65,70 +48,99 @@ import org.apache.http.impl.auth.DigestScheme;
 import org.apache.http.impl.client.BasicAuthCache;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
 import org.springframework.http.MediaType;
 import org.springframework.util.StringUtils;
 
-/**
- * prometheus auto collect
- */
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ConnectException;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.net.ssl.SSLException;
+
+import static org.apache.hertzbeat.common.constants.SignConstants.RIGHT_DASH;
+
+
 @Slf4j
-public class PrometheusAutoCollectImpl {
-    
+public class PrometheusProxyCollectImpl implements PrometheusCollect {
+
     private final Set<Integer> defaultSuccessStatusCodes = 
Stream.of(HttpStatus.SC_OK, HttpStatus.SC_CREATED,
             HttpStatus.SC_ACCEPTED, HttpStatus.SC_MULTIPLE_CHOICES, 
HttpStatus.SC_MOVED_PERMANENTLY,
             HttpStatus.SC_MOVED_TEMPORARILY).collect(Collectors.toSet());
-    
-    public List<CollectRep.MetricsData> collect(CollectRep.MetricsData.Builder 
builder,
-                                                Metrics metrics) {
+
+    public static final String RAW_TEXT_CONTENT_FIELD_NAME = 
"raw_text_content";
+
+    @Override
+    public List<CollectRep.MetricsData> collect(CollectRep.MetricsData.Builder 
builder, Metrics metrics) {
+        PrometheusProtocol prometheusProtocol = metrics.getPrometheus();
+        HttpUriRequest request;
         try {
             validateParams(metrics);
         } catch (Exception e) {
             builder.setCode(CollectRep.Code.FAIL);
             builder.setMsg(e.getMessage());
-            return null;
+            return Collections.singletonList(builder.build());
         }
-        HttpContext httpContext = createHttpContext(metrics.getPrometheus());
-        HttpUriRequest request = createHttpRequest(metrics.getPrometheus());
-        try (CloseableHttpResponse response =
-             CommonHttpClient.getHttpClient().execute(request, httpContext)) {
+
+        HttpContext httpContext = createHttpContext(prometheusProtocol);
+        request = createHttpRequest(prometheusProtocol);
+
+        try (CloseableHttpResponse response = 
CommonHttpClient.getHttpClient().execute(request, httpContext)) {
             int statusCode = response.getStatusLine().getStatusCode();
-            boolean isSuccessInvoke = 
defaultSuccessStatusCodes.contains(statusCode);
-            log.debug("http response status: {}", statusCode);
-            if (!isSuccessInvoke) {
+            log.debug("Prometheus proxy collect, response status: {}", 
statusCode);
+
+            if (!defaultSuccessStatusCodes.contains(statusCode)) {
                 builder.setCode(CollectRep.Code.FAIL);
                 builder.setMsg(NetworkConstants.STATUS_CODE + 
SignConstants.BLANK + statusCode);
-                return null;
-            }
-            try {
-                return 
parseResponseByPrometheusExporter(response.getEntity().getContent(), builder);
-            } catch (Exception e) {
-                log.info("parse error: {}.", e.getMessage(), e);
-                builder.setCode(CollectRep.Code.FAIL);
-                builder.setMsg("parse response data error:" + e.getMessage());
+                return Collections.singletonList(builder.build());
             }
+
+            String rawTextContent = EntityUtils.toString(response.getEntity(), 
StandardCharsets.UTF_8);
+
+            builder.clearFields();
+            builder.clearValues();
+
+            CollectRep.Field rawDataField = CollectRep.Field.newBuilder()
+                    .setName(RAW_TEXT_CONTENT_FIELD_NAME)
+                    .setType(CommonConstants.TYPE_STRING)
+                    .build();
+            builder.addField(rawDataField);
+
+            CollectRep.ValueRow.Builder valueRowBuilder = 
CollectRep.ValueRow.newBuilder();
+            valueRowBuilder.addColumn(rawTextContent);
+            builder.addValueRow(valueRowBuilder.build());
+
+            builder.setCode(CollectRep.Code.SUCCESS);
         } catch (ClientProtocolException e1) {
             String errorMsg = CommonUtil.getMessageFromThrowable(e1);
-            log.error(errorMsg);
+            log.error("Prometheus proxy collect error: {}. Host: {}, Port: 
{}", errorMsg, prometheusProtocol.getHost(), prometheusProtocol.getPort(), e1);
             builder.setCode(CollectRep.Code.UN_CONNECTABLE);
             builder.setMsg(errorMsg);
         } catch (UnknownHostException e2) {
             String errorMsg = CommonUtil.getMessageFromThrowable(e2);
-            log.info(errorMsg);
+            log.info("Prometheus proxy collect unknown host: {}. Host: {}", 
errorMsg, prometheusProtocol.getHost(), e2);
             builder.setCode(CollectRep.Code.UN_REACHABLE);
             builder.setMsg("unknown host:" + errorMsg);
         } catch (InterruptedIOException | ConnectException | SSLException e3) {
             String errorMsg = CommonUtil.getMessageFromThrowable(e3);
-            log.info(errorMsg);
+            log.info("Prometheus proxy collect connect error: {}. Host: {}, 
Port: {}", errorMsg, prometheusProtocol.getHost(), 
prometheusProtocol.getPort(), e3);
             builder.setCode(CollectRep.Code.UN_CONNECTABLE);
             builder.setMsg(errorMsg);
         } catch (IOException e4) {
             String errorMsg = CommonUtil.getMessageFromThrowable(e4);
-            log.info(errorMsg);
+            log.info("Prometheus proxy collect IO error: {}. Host: {}, Port: 
{}", errorMsg, prometheusProtocol.getHost(), prometheusProtocol.getPort(), e4);
             builder.setCode(CollectRep.Code.FAIL);
             builder.setMsg(errorMsg);
         } catch (Exception e) {
             String errorMsg = CommonUtil.getMessageFromThrowable(e);
-            log.error(errorMsg, e);
+            log.error("Prometheus proxy collect unknown error: {}. Host: {}, 
Port: {}", errorMsg, prometheusProtocol.getHost(), 
prometheusProtocol.getPort(), e);
             builder.setCode(CollectRep.Code.FAIL);
             builder.setMsg(errorMsg);
         } finally {
@@ -138,70 +150,31 @@ public class PrometheusAutoCollectImpl {
         }
         return Collections.singletonList(builder.build());
     }
-    
+
+    @Override
     public String supportProtocol() {
         return DispatchConstants.PROTOCOL_PROMETHEUS;
     }
-    
+
     private void validateParams(Metrics metrics) throws Exception {
         if (metrics == null || metrics.getPrometheus() == null) {
             throw new Exception("Prometheus collect must has prometheus 
params");
         }
         PrometheusProtocol protocol = metrics.getPrometheus();
+        if (!StringUtils.hasText(protocol.getHost())
+            || !StringUtils.hasText(protocol.getPort())) {
+            throw new Exception("Prometheus collect must has host and port 
params");
+        }
         if (protocol.getPath() == null
-                    || !StringUtils.hasText(protocol.getPath())
-                    || !protocol.getPath().startsWith(RIGHT_DASH)) {
+                || !StringUtils.hasText(protocol.getPath())
+                || !protocol.getPath().startsWith(RIGHT_DASH)) {
             protocol.setPath(protocol.getPath() == null ? RIGHT_DASH : 
RIGHT_DASH + protocol.getPath().trim());
         }
     }
     
-    private List<CollectRep.MetricsData> 
parseResponseByPrometheusExporter(InputStream inputStream, 
CollectRep.MetricsData.Builder builder) throws IOException {
-        long endTime = System.currentTimeMillis();
-        builder.setTime(endTime);
-        Map<String, MetricFamily> metricFamilyMap = 
OnlineParser.parseMetrics(inputStream);
-        List<CollectRep.MetricsData> metricsDataList = new LinkedList<>();
-        if (metricFamilyMap == null) {
-            return metricsDataList;
-        }
-        for (Map.Entry<String, MetricFamily> entry : 
metricFamilyMap.entrySet()) {
-            builder.clearFields();
-            builder.clearValues();
-            String metricsName = entry.getKey();
-            builder.setMetrics(metricsName);
-            MetricFamily metricFamily = entry.getValue();
-            if (!metricFamily.getMetricList().isEmpty()) {
-                List<String> metricsFields = new LinkedList<>();
-                for (int index = 0; index < 
metricFamily.getMetricList().size(); index++) {
-                    MetricFamily.Metric metric = 
metricFamily.getMetricList().get(index);
-                    if (index == 0) {
-                        metric.getLabels().forEach(label -> {
-                            metricsFields.add(label.getName());
-                            
builder.addField(CollectRep.Field.newBuilder().setName(label.getName())
-                                    
.setType(CommonConstants.TYPE_STRING).setLabel(true).build());
-                        });
-                        
builder.addField(CollectRep.Field.newBuilder().setName("metric_value")
-                                
.setType(CommonConstants.TYPE_NUMBER).setLabel(false).build());
-                    }
-                    Map<String, String> labelMap = metric.getLabels()
-                            .stream()
-                            
.collect(Collectors.toMap(MetricFamily.Label::getName, 
MetricFamily.Label::getValue));
-                    CollectRep.ValueRow.Builder valueRowBuilder = 
CollectRep.ValueRow.newBuilder();
-                    for (String field : metricsFields) {
-                        String fieldValue = labelMap.get(field);
-                        valueRowBuilder.addColumn(fieldValue == null ? 
CommonConstants.NULL_VALUE : fieldValue);
-                    }
-                    
valueRowBuilder.addColumn(String.valueOf(metric.getValue()));
-                    builder.addValueRow(valueRowBuilder.build());
-                }
-                metricsDataList.add(builder.build());
-            }
-        }
-        return metricsDataList;
-    }
-    
     /**
      * create httpContext
-     *
+     * This method is adapted from PrometheusAutoCollectImpl
      * @param protocol prometheus protocol
      * @return context
      */
@@ -216,7 +189,8 @@ public class PrometheusAutoCollectImpl {
                         new 
UsernamePasswordCredentials(auth.getDigestAuthUsername(), 
auth.getDigestAuthPassword());
                 provider.setCredentials(AuthScope.ANY, credentials);
                 AuthCache authCache = new BasicAuthCache();
-                authCache.put(new HttpHost(protocol.getHost(), 
Integer.parseInt(protocol.getPort())), new DigestScheme());
+                HttpHost targetHost = new HttpHost(protocol.getHost(), 
Integer.parseInt(protocol.getPort()));
+                authCache.put(targetHost, new DigestScheme());
                 clientContext.setCredentialsProvider(provider);
                 clientContext.setAuthCache(authCache);
                 return clientContext;
@@ -227,6 +201,7 @@ public class PrometheusAutoCollectImpl {
 
     /**
      * create http request
+     * This method is adapted from PrometheusAutoCollectImpl
      * @param protocol http params
      * @return http uri request
      */
@@ -241,8 +216,6 @@ public class PrometheusAutoCollectImpl {
                 }
             }
         }
-        // The default request header can be overridden if customized
-        // keep-alive
         requestBuilder.addHeader(HttpHeaders.CONNECTION, 
NetworkConstants.KEEP_ALIVE);
         requestBuilder.addHeader(HttpHeaders.USER_AGENT, 
NetworkConstants.USER_AGENT);
         // headers  The custom request header is overwritten here
@@ -255,14 +228,17 @@ public class PrometheusAutoCollectImpl {
                 }
             }
         }
-        // add accept
-        requestBuilder.addHeader(HttpHeaders.ACCEPT, 
MediaType.TEXT_PLAIN_VALUE);
+        if (headers == null || 
headers.keySet().stream().noneMatch(HttpHeaders.ACCEPT::equalsIgnoreCase)) {
+            requestBuilder.addHeader(HttpHeaders.ACCEPT, 
MediaType.TEXT_PLAIN_VALUE + ";version=0.0.4,*/*;q=0.1");
+        }
         
         if (protocol.getAuthorization() != null) {
             PrometheusProtocol.Authorization authorization = 
protocol.getAuthorization();
             if 
(DispatchConstants.BEARER_TOKEN.equalsIgnoreCase(authorization.getType())) {
-                String value = DispatchConstants.BEARER + " " + 
authorization.getBearerTokenToken();
-                requestBuilder.addHeader(HttpHeaders.AUTHORIZATION, value);
+                if (StringUtils.hasText(authorization.getBearerTokenToken())) {
+                    String value = DispatchConstants.BEARER + " " + 
authorization.getBearerTokenToken();
+                    requestBuilder.addHeader(HttpHeaders.AUTHORIZATION, value);
+                }
             } else if 
(DispatchConstants.BASIC_AUTH.equals(authorization.getType())) {
                 if (StringUtils.hasText(authorization.getBasicAuthUsername())
                             && 
StringUtils.hasText(authorization.getBasicAuthPassword())) {
@@ -273,21 +249,21 @@ public class PrometheusAutoCollectImpl {
             }
         }
 
-        // if it has payload, would override post params
         if (StringUtils.hasLength(protocol.getPayload())) {
             requestBuilder.setEntity(new StringEntity(protocol.getPayload(), 
StandardCharsets.UTF_8));
+            if (headers == null || 
headers.keySet().stream().noneMatch(HttpHeaders.CONTENT_TYPE::equalsIgnoreCase))
 {
+                requestBuilder.setHeader(HttpHeaders.CONTENT_TYPE, 
MediaType.TEXT_PLAIN_VALUE);
+            }
         }
         
-        // uri
-        String uri = CollectUtil.replaceUriSpecialChar(protocol.getPath());
+        String uriPath = CollectUtil.replaceUriSpecialChar(protocol.getPath());
         if (IpDomainUtil.isHasSchema(protocol.getHost())) {
-            
-            requestBuilder.setUri(protocol.getHost() + 
SignConstants.DOUBLE_MARK + protocol.getPort() + uri);
+            requestBuilder.setUri(protocol.getHost() + 
SignConstants.DOUBLE_MARK + protocol.getPort() + uriPath);
         } else {
             String ipAddressType = 
IpDomainUtil.checkIpAddressType(protocol.getHost());
             String baseUri = NetworkConstants.IPV6.equals(ipAddressType)
-                                     ? String.format("[%s]:%s%s", 
protocol.getHost(), protocol.getPort(), uri)
-                                     : String.format("%s:%s%s", 
protocol.getHost(), protocol.getPort(), uri);
+                                     ? String.format("[%s]:%s%s", 
protocol.getHost(), protocol.getPort(), uriPath)
+                                     : String.format("%s:%s%s", 
protocol.getHost(), protocol.getPort(), uriPath);
             boolean ssl = Boolean.parseBoolean(protocol.getSsl());
             if (ssl) {
                 requestBuilder.setUri(NetworkConstants.HTTPS_HEADER + baseUri);
@@ -297,11 +273,17 @@ public class PrometheusAutoCollectImpl {
         }
         
         // custom timeout
-        int timeout = CollectUtil.getTimeout(protocol.getTimeout(), 0);
+        int timeout = CollectUtil.getTimeout(protocol.getTimeout());
         if (timeout > 0) {
             RequestConfig requestConfig = RequestConfig.custom()
                                                   .setConnectTimeout(timeout)
                                                   .setSocketTimeout(timeout)
+                                                  
.setConnectionRequestTimeout(timeout)
+                                                  .setRedirectsEnabled(true)
+                                                  .build();
+            requestBuilder.setConfig(requestConfig);
+        } else {
+            RequestConfig requestConfig = RequestConfig.custom()
                                                   .setRedirectsEnabled(true)
                                                   .build();
             requestBuilder.setConfig(requestConfig);
@@ -313,14 +295,14 @@ public class PrometheusAutoCollectImpl {
      * get collect instance
      * @return instance
      */
-    public static PrometheusAutoCollectImpl getInstance() {
-        return PrometheusAutoCollectImpl.SingleInstance.INSTANCE;
+    public static PrometheusProxyCollectImpl getInstance() {
+        return PrometheusProxyCollectImpl.SingleInstance.INSTANCE;
     }
-    
+
     /**
      * static instance
      */
     private static class SingleInstance {
-        private static final PrometheusAutoCollectImpl INSTANCE = new 
PrometheusAutoCollectImpl();
+        private static final PrometheusProxyCollectImpl INSTANCE = new 
PrometheusProxyCollectImpl();
     }
 }
diff --git 
a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
 
b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
index fe01388d54..e60f1a4d6f 100644
--- 
a/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
+++ 
b/hertzbeat-collector/hertzbeat-collector-collector/src/main/java/org/apache/hertzbeat/collector/dispatch/MetricsCollect.java
@@ -115,6 +115,10 @@ public class MetricsCollect implements Runnable, 
Comparable<MetricsCollect> {
      * Whether it is a service discovery job, true is yes, false is no
      */
     protected boolean isSd;
+    /**
+     * Whether to use the Prometheus proxy
+     */
+    protected boolean prometheusProxyMode;
 
     protected List<UnitConvert> unitConvertList;
 
@@ -137,6 +141,7 @@ public class MetricsCollect implements Runnable, 
Comparable<MetricsCollect> {
         this.collectDataDispatch = collectDataDispatch;
         this.isCyclic = job.isCyclic();
         this.isSd = job.isSd();
+        this.prometheusProxyMode = job.isPrometheusProxyMode();
         this.unitConvertList = unitConvertList;
         // Temporary one-time tasks are executed with high priority
         if (isCyclic) {
@@ -153,11 +158,31 @@ public class MetricsCollect implements Runnable, 
Comparable<MetricsCollect> {
         CollectRep.MetricsData.Builder response = 
CollectRep.MetricsData.newBuilder();
         response.setApp(app).setId(id).setTenantId(tenantId)
                 
.setLabels(labels).setAnnotations(annotations).addMetadataAll(metadata);
-        // for prometheus auto
+        // for prometheus auto or proxy mode
         if 
(DispatchConstants.PROTOCOL_PROMETHEUS.equalsIgnoreCase(metrics.getProtocol())) 
{
-            List<CollectRep.MetricsData> metricsData = 
PrometheusAutoCollectImpl
-                    .getInstance().collect(response, metrics);
-            validateResponse(metricsData.stream().findFirst().orElse(null));
+            List<CollectRep.MetricsData> metricsData;
+
+            // TODO: Refactor Prometheus metrics collection logic.
+            // The current implementation for proxy mode and auto mode needs 
review and potential simplification.
+            // Consider a more unified approach or clarify the conditions for 
each mode.
+            /*
+            // TODO USE PROXY MODE
+            if (prometheusProxyMode) {
+                List<CollectRep.MetricsData> proxyData = 
PrometheusProxyCollectImpl.getInstance().collect(response, metrics);
+                List<CollectRep.MetricsData> autoData = 
PrometheusAutoCollectImpl.getInstance().collect(response, metrics);
+                metricsData = new LinkedList<>();
+                if (proxyData != null) {
+                    metricsData.addAll(proxyData);
+                }
+                if (autoData != null) {
+                    metricsData.addAll(autoData);
+                }
+            } else {
+                metricsData = 
PrometheusAutoCollectImpl.getInstance().collect(response, metrics);
+            }
+            */
+            metricsData = 
PrometheusAutoCollectImpl.getInstance().collect(response, metrics);
+            validateResponse(metricsData == null ? null : 
metricsData.stream().findFirst().orElse(null));
             collectDataDispatch.dispatchCollectData(timeout, metrics, 
metricsData);
             return;
         }
diff --git 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Job.java
 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Job.java
index 67bc2978de..6ab4e10b0d 100644
--- 
a/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Job.java
+++ 
b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/job/Job.java
@@ -138,6 +138,11 @@ public class Job {
      */
     private boolean isSd = false;
 
+    /**
+     * Whether to use the Prometheus proxy
+     */
+    private boolean prometheusProxyMode = false;
+
     /**
      * the collect data response metrics as env configmap for other collect 
use. ^o^xxx^o^
      */
diff --git 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/common/GrafanaConstants.java
 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/common/GrafanaConstants.java
index 9c26924a13..b30f699e47 100644
--- 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/common/GrafanaConstants.java
+++ 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/common/GrafanaConstants.java
@@ -18,6 +18,7 @@
 package org.apache.hertzbeat.grafana.common;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
+import java.net.URL;
 
 /**
  * Grafana Common Constants
@@ -31,32 +32,64 @@ public interface GrafanaConstants {
     String REFRESH = "&refresh=15s";
 
     String INSTANCE = "&var-instance=";
-    
+
     String CREATE_DASHBOARD_API = "/api/dashboards/db";
-    
+
     String DELETE_DASHBOARD_API = "/api/dashboards/uid/%s";
-    
-    String DATASOURCE_NAME = "hertzbeat-victoria-metrics";
-    
-    String USE_DATASOURCE = "&var-ds=" + DATASOURCE_NAME;
-    
+
+    String DATASOURCE_BASE_NAME = "hertzbeat";
+
     String DATASOURCE_TYPE = "prometheus";
-    
+
     String DATASOURCE_ACCESS = "proxy";
-    
+
     String CREATE_DATASOURCE_API = "/api/datasources";
-    
-    String QUERY_DATASOURCE_API = "/api/datasources/name/" + DATASOURCE_NAME;
-    
+
+    String QUERY_DATASOURCE_API = "/api/datasources/name/";
+
     String GET_SERVICE_ACCOUNTS_API = "%s/api/serviceaccounts/search";
 
     String ACCOUNT_NAME = ConfigConstants.SystemConstant.PROJECT_NAME;
-    
+
     String ACCOUNT_ROLE = "Admin";
-    
+
     String CREATE_SERVICE_ACCOUNT_API = "%s/api/serviceaccounts";
-    
+
     String CREATE_SERVICE_TOKEN_API = "%s/api/serviceaccounts/%d/tokens";
 
     String GRAFANA_CONFIG = "grafanaConfig";
-}
+
+    /**
+     * Generate data source name based on type and URL
+     * @param type Data source type (vm or greptime)
+     * @param url Data source URL
+     * @return Generated unique data source name
+     */
+    static String generateDatasourceName(String type, String url) {
+        try {
+            URL parsedUrl = new URL(url);
+            String host = parsedUrl.getHost();
+            int port = parsedUrl.getPort();
+
+            // Extract host without subdomain for cleaner names
+            String hostPart = host != null ? host.replaceAll("^www\\.", "") : 
"localhost";
+
+            // Include port if it's not default
+            String portPart = (port > 0 && port != 80 && port != 443) ? "-" + 
port : "";
+
+            return String.format("%s-%s-%s%s", DATASOURCE_BASE_NAME, type, 
hostPart, portPart);
+        } catch (Exception e) {
+            // Fallback to simple naming if URL parsing fails
+            return String.format("%s-%s-%s", DATASOURCE_BASE_NAME, type, 
url.hashCode());
+        }
+    }
+
+    /**
+     * Generate USE_DATASOURCE parameter with dynamic datasource name
+     * @param datasourceName The datasource name
+     * @return USE_DATASOURCE parameter string
+     */
+    static String generateUseDatasource(String datasourceName) {
+        return "&var-ds=" + datasourceName;
+    }
+}
\ No newline at end of file
diff --git 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/config/GrafanaInit.java
 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/config/GrafanaInit.java
index 7b8537c520..8e85a6725e 100644
--- 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/config/GrafanaInit.java
+++ 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/config/GrafanaInit.java
@@ -45,10 +45,7 @@ public class GrafanaInit implements CommandLineRunner {
         if (grafanaProperties.enabled()) {
             log.info("grafana init start");
             try {
-                String token = serviceAccountService.getToken();
-                if (token == null) {
-                    token = serviceAccountService.applyForToken();
-                }
+                String token = serviceAccountService.applyForToken();
                 datasourceService.existOrCreateDatasource(token);   
             } catch (Exception e) {
                 log.error("grafana init error", e);
diff --git 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DashboardService.java
 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DashboardService.java
index 288b411eb9..9e4bc44206 100644
--- 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DashboardService.java
+++ 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DashboardService.java
@@ -22,7 +22,6 @@ import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.DELETE_DASHBO
 import static org.apache.hertzbeat.grafana.common.GrafanaConstants.INSTANCE;
 import static org.apache.hertzbeat.grafana.common.GrafanaConstants.KIOSK;
 import static org.apache.hertzbeat.grafana.common.GrafanaConstants.REFRESH;
-import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.USE_DATASOURCE;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +29,7 @@ import java.util.Objects;
 
 import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard;
 import org.apache.hertzbeat.common.util.JsonUtil;
+import org.apache.hertzbeat.grafana.common.GrafanaConstants;
 import org.apache.hertzbeat.grafana.config.GrafanaProperties;
 import org.apache.hertzbeat.grafana.dao.DashboardDao;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -63,10 +63,15 @@ public class DashboardService {
     @Autowired
     private RestTemplate restTemplate;
 
+    @Autowired
+    private DatasourceService datasourceService;
+
     /**
-     * Creates a new dashboard in Grafana.
+     * Creates or updates a dashboard in Grafana.
+     * The "id" field will be removed from the dashboard JSON before sending
+     * to Grafana to ensure new dashboards are created correctly.
      *
-     * @param dashboardJson the JSON representation of the dashboard
+     * @param dashboardJson the JSON representation of the dashboard definition
      * @param monitorId the ID of the monitor associated with the dashboard
      * @return ResponseEntity containing the response from Grafana
      */
@@ -84,11 +89,31 @@ public class DashboardService {
         headers.setContentType(MediaType.APPLICATION_JSON);
         headers.setBearerAuth(token);
 
-        Map<String, Object> body = new HashMap<>();
-        body.put("dashboard", JsonUtil.fromJson(dashboardJson, Object.class));
-        body.put("overwrite", true);
+        Map<String, Object> dashboardObjectMap;
+        try {
+            dashboardObjectMap = JsonUtil.fromJson(dashboardJson, Map.class);
+        } catch (Exception e) {
+            log.error("Failed to parse dashboardJson. Monitor ID: {}. JSON: 
{}", monitorId, dashboardJson, e);
+            throw new RuntimeException("Invalid dashboard JSON structure", e);
+        }
 
-        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(body, 
headers);
+        if (dashboardObjectMap == null) {
+            log.error("Parsed dashboardJson is null. Monitor ID: {}. Original 
JSON: {}", monitorId, dashboardJson);
+            throw new RuntimeException("Parsed dashboard JSON is null");
+        }
+
+        if (dashboardObjectMap.containsKey("id")) {
+            dashboardObjectMap.remove("id");
+            log.debug("Removed 'id' field from dashboard JSON for monitorId: 
{}", monitorId);
+        }
+
+        // Construct the full request payload for Grafana API
+        Map<String, Object> requestPayload = new HashMap<>();
+        requestPayload.put("dashboard", dashboardObjectMap);
+        requestPayload.put("overwrite", true); // Overwrite if a dashboard 
with the same UID exists
+
+        String finalJsonPayload = JsonUtil.toJson(requestPayload);
+        HttpEntity<String> requestEntity = new HttpEntity<>(finalJsonPayload, 
headers);
 
         try {
             ResponseEntity<String> response = restTemplate.postForEntity(url, 
requestEntity, String.class);
@@ -97,30 +122,49 @@ public class DashboardService {
                 GrafanaDashboard grafanaDashboard = 
JsonUtil.fromJson(response.getBody(), GrafanaDashboard.class);
                 if (grafanaDashboard != null) {
                     grafanaDashboard.setEnabled(true);
-                    grafanaDashboard.setUrl(grafanaProperties.exposeUrl()
-                            + 
grafanaDashboard.getUrl().replace(grafanaProperties.getUrl(), "")
-                            + KIOSK + REFRESH + INSTANCE + monitorId + 
USE_DATASOURCE);
+
+                    String currentDatasourceName = 
datasourceService.getCurrentDatasourceName();
+                    String useDatasource = currentDatasourceName != null
+                            ? 
GrafanaConstants.generateUseDatasource(currentDatasourceName) : "";
+
+                    String relativeDashboardUrl = grafanaDashboard.getUrl();
+                    if (relativeDashboardUrl != null && 
grafanaProperties.getUrl() != null && 
relativeDashboardUrl.startsWith(grafanaProperties.getUrl())) {
+                        relativeDashboardUrl = 
relativeDashboardUrl.substring(grafanaProperties.getUrl().length());
+                    }
+                    String fullDashboardUrl = 
grafanaProperties.exposeUrl().replaceAll("/$", "")
+                            + (relativeDashboardUrl != null ? 
relativeDashboardUrl.replaceAll("^/", "") : "");
+
+                    grafanaDashboard.setUrl(fullDashboardUrl + KIOSK + REFRESH 
+ INSTANCE + monitorId + useDatasource);
+
                     grafanaDashboard.setMonitorId(monitorId);
                     dashboardDao.save(grafanaDashboard);
-                    log.info("create dashboard success, token: {}", 
response.getBody());
+                    log.info("Successfully created/updated Grafana dashboard 
for monitorId: {}. Response: {}", monitorId, response.getBody());
+                } else {
+                    log.error("Failed to parse Grafana response into 
GrafanaDashboard object. MonitorId: {}. Response body: {}", monitorId, 
response.getBody());
                 }
                 return response;
             } else {
-                log.error("create dashboard error: {}", 
response.getStatusCode());
-                throw new RuntimeException("create dashboard error");
+                log.error("Failed to create/update Grafana dashboard for 
monitorId: {}. Status: {}, Response: {}",
+                        monitorId, response.getStatusCode(), 
response.getBody());
+                throw new RuntimeException("Failed to create/update Grafana 
dashboard: " + response.getStatusCode() + " - " + response.getBody());
             }
-        } catch (HttpClientErrorException.Forbidden ex) {
-            log.error("Grafana Access denied to save dashboard", ex);
-            throw new RuntimeException("Grafana Access denied to save 
dashboard", ex);
-        } catch (HttpClientErrorException.NotFound ex){
-            log.error("Grafana Dashboard not found", ex);
-            throw new RuntimeException("Grafana Dashboard not found", ex);
+        } catch (HttpClientErrorException ex) {
+            String responseBody = ex.getResponseBodyAsString();
+            log.error("Grafana API request failed for monitorId: {}. Status: 
{}. URL: {}. Request: {}. Response: {}",
+                    monitorId, ex.getStatusCode(), url, finalJsonPayload, 
responseBody, ex);
+            if (ex instanceof HttpClientErrorException.Forbidden) {
+                throw new RuntimeException("Grafana Access Denied: " + 
responseBody, ex);
+            } else if (ex instanceof HttpClientErrorException.NotFound) {
+                throw new RuntimeException("Grafana API endpoint or resource 
not found: " + responseBody, ex);
+            }
+            throw new RuntimeException("Grafana API client error (" + 
ex.getStatusCode() + "): " + responseBody, ex);
         } catch (Exception ex) {
-            log.error("create dashboard error", ex);
-            throw new RuntimeException("create dashboard error", ex);
+            log.error("An unexpected error occurred while creating/updating 
Grafana dashboard for monitorId: {}. URL: {}. Request: {}",
+                    monitorId, url, finalJsonPayload, ex);
+            throw new RuntimeException("Error during Grafana dashboard 
operation: " + ex.getMessage(), ex);
         }
     }
-    
+
     /**
      * Deletes a dashboard in Grafana by monitor ID.
      *
@@ -130,6 +174,7 @@ public class DashboardService {
     public void deleteDashboard(Long monitorId) {
         GrafanaDashboard grafanaDashboard = 
dashboardDao.findByMonitorId(monitorId);
         if (Objects.isNull(grafanaDashboard)) {
+            log.info("No Grafana dashboard found for monitorId {} to delete.", 
monitorId);
             return;
         }
         String uid = grafanaDashboard.getUid();
@@ -137,6 +182,7 @@ public class DashboardService {
 
         if (grafanaDashboards.size() > 1) {
             dashboardDao.deleteByMonitorId(monitorId);
+            log.info("Deleted hertzbeat dashboard record for monitorId: {}, 
Grafana dashboard with UID: {} still used by other monitors.", monitorId, uid);
         } else {
             String token = serviceAccountService.getToken();
             String url = grafanaProperties.getPrefix() + 
grafanaProperties.getUrl() + String.format(DELETE_DASHBOARD_API, uid);
@@ -146,19 +192,36 @@ public class DashboardService {
             headers.setBearerAuth(token);
 
             HttpEntity<Void> requestEntity = new HttpEntity<>(headers);
-            dashboardDao.deleteByMonitorId(monitorId);
 
-            ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.DELETE, requestEntity, String.class);
-
-            if (response.getStatusCode().is2xxSuccessful()) {
-                log.info("delete dashboard success");
-            } else {
-                log.error("delete dashboard error: {}", 
response.getStatusCode());
-                throw new RuntimeException("delete dashboard error");
+            try {
+                ResponseEntity<String> response = restTemplate.exchange(url, 
HttpMethod.DELETE, requestEntity, String.class);
+
+                if (response.getStatusCode().is2xxSuccessful()) {
+                    // Delete from local DB only after successful Grafana 
deletion
+                    dashboardDao.deleteByMonitorId(monitorId);
+                    log.info("Successfully deleted Grafana dashboard with UID: 
{} and corresponding hertzbeat record for monitorId: {}", uid, monitorId);
+                } else {
+                    log.error("Failed to delete Grafana dashboard with UID: 
{}. Status: {}, Response: {}",
+                            uid, response.getStatusCode(), response.getBody());
+                    throw new RuntimeException("Failed to delete Grafana 
dashboard: " + response.getStatusCode() + " - " + response.getBody());
+                }
+            } catch (HttpClientErrorException ex) {
+                String responseBody = ex.getResponseBodyAsString();
+                log.error("Grafana API request failed during dashboard 
deletion for UID: {}. Status: {}. URL: {}. Response: {}",
+                        uid, ex.getStatusCode(), url, responseBody, ex);
+                if (ex.getStatusCode() == 
org.springframework.http.HttpStatus.NOT_FOUND) {
+                    log.warn("Grafana dashboard with UID: {} not found during 
deletion attempt. Assuming already deleted. Deleting local record for 
monitorId: {}", uid, monitorId);
+                    dashboardDao.deleteByMonitorId(monitorId);
+                } else {
+                    throw new RuntimeException("Grafana API client error 
during deletion (" + ex.getStatusCode() + "): " + responseBody, ex);
+                }
+            } catch (Exception ex) {
+                log.error("An unexpected error occurred while deleting Grafana 
dashboard with UID: {}. URL: {}", uid, url, ex);
+                throw new RuntimeException("Error during Grafana dashboard 
deletion: " + ex.getMessage(), ex);
             }
         }
     }
-    
+
     /**
      * Retrieves a dashboard by monitor ID.
      *
@@ -171,14 +234,22 @@ public class DashboardService {
 
     /**
      * Disables a Grafana dashboard by monitor ID.
+     * (This only updates the local HertzBeat database flag, does not interact 
with Grafana API)
      *
      * @param monitorId the ID of the monitor associated with the dashboard
      */
     public void closeGrafanaDashboard(Long monitorId) {
         GrafanaDashboard grafanaDashboard = 
dashboardDao.findByMonitorId(monitorId);
         if (grafanaDashboard != null) {
-            grafanaDashboard.setEnabled(false);
-            dashboardDao.save(grafanaDashboard);
+            if (grafanaDashboard.isEnabled()) { // Only save if there's a 
change
+                grafanaDashboard.setEnabled(false);
+                dashboardDao.save(grafanaDashboard);
+                log.info("Disabled Grafana dashboard link in HertzBeat for 
monitorId: {}", monitorId);
+            } else {
+                log.info("Grafana dashboard link for monitorId: {} was already 
disabled.", monitorId);
+            }
+        } else {
+            log.warn("No Grafana dashboard record found for monitorId {} to 
disable.", monitorId);
         }
     }
-}
+}
\ No newline at end of file
diff --git 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DatasourceService.java
 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DatasourceService.java
index 06773665ae..9828422758 100644
--- 
a/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DatasourceService.java
+++ 
b/hertzbeat-grafana/src/main/java/org/apache/hertzbeat/grafana/service/DatasourceService.java
@@ -19,12 +19,18 @@ package org.apache.hertzbeat.grafana.service;
 
 import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.CREATE_DATASOURCE_API;
 import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.DATASOURCE_ACCESS;
-import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.DATASOURCE_NAME;
 import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.DATASOURCE_TYPE;
 import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.QUERY_DATASOURCE_API;
+import static 
org.apache.hertzbeat.grafana.common.GrafanaConstants.generateDatasourceName;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.HashMap;
+import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.grafana.config.GrafanaProperties;
-import 
org.apache.hertzbeat.warehouse.store.history.vm.VictoriaMetricsProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.vm.VictoriaMetricsProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
@@ -36,7 +42,8 @@ import 
org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.RestTemplate;
 
 /**
- * Service for managing Grafana datasource.
+ * Service for managing Grafana datasources.
+ * This service checks if a datasource exists and creates it if not.
  */
 @Service
 @Slf4j
@@ -44,57 +51,163 @@ public class DatasourceService {
 
     private final GrafanaProperties grafanaProperties;
     private final VictoriaMetricsProperties warehouseProperties;
+    private final GreptimeProperties greptimeProperties;
     private final RestTemplate restTemplate;
 
     @Autowired
     public DatasourceService(
             GrafanaProperties grafanaProperties,
             VictoriaMetricsProperties warehouseProperties,
+            GreptimeProperties greptimeProperties,
             RestTemplate restTemplate
     ) {
         this.grafanaProperties = grafanaProperties;
         this.warehouseProperties = warehouseProperties;
+        this.greptimeProperties = greptimeProperties;
         this.restTemplate = restTemplate;
     }
 
-    /**
-     * Create a new datasource in Grafana.
-     */
     public void existOrCreateDatasource(String token) {
-        if (!warehouseProperties.enabled()) {
-            log.info("HertzBeat VictoriaMetrics config not enabled");
+        boolean vmEnabled = warehouseProperties.enabled();
+        boolean greptimeEnabled = greptimeProperties.enabled();
+
+        if (vmEnabled && greptimeEnabled) {
+            throw new IllegalStateException("Conflict: Both VictoriaMetrics 
and Greptime are enabled, only one can be used for Grafana datasource");
+        }
+
+        if (!vmEnabled && !greptimeEnabled) {
+            log.info("HertzBeat warehouse config not enabled");
             return;
         }
 
+        // Determine datasource type and URL
+        String datasourceType;
+        String datasourceUrl;
+
+        if (vmEnabled) {
+            datasourceType = "vm";
+            datasourceUrl = warehouseProperties.url();
+        } else {
+            datasourceType = "greptime";
+            datasourceUrl = greptimeProperties.httpEndpoint();
+        }
+
+        // Generate unique datasource name
+        String datasourceName = generateDatasourceName(datasourceType, 
datasourceUrl);
+
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.APPLICATION_JSON);
         headers.setBearerAuth(token);
-        // query if exist this datasource
-        String queryUrl = grafanaProperties.getPrefix() + 
grafanaProperties.getUrl() + QUERY_DATASOURCE_API;
+
+        String queryUrl = grafanaProperties.getPrefix() + 
grafanaProperties.getUrl() + QUERY_DATASOURCE_API + datasourceName;
         HttpEntity<Void> entity = new HttpEntity<>(headers);
+
         try {
             ResponseEntity<String> response = restTemplate.exchange(queryUrl, 
HttpMethod.GET, entity, String.class);
             if (response.getStatusCode().is2xxSuccessful()) {
-                log.info("{} datasource exist", DATASOURCE_NAME);
+                log.info("{} datasource already exists", datasourceName);
+                return;
             }
         } catch (HttpClientErrorException.NotFound notFound) {
-            String createUrl = grafanaProperties.getPrefix() + 
grafanaProperties.getUrl() + CREATE_DATASOURCE_API;
-            String body = String.format(
-                    
"{\"name\":\"%s\",\"type\":\"%s\",\"access\":\"%s\",\"url\":\"%s\",\"basicAuth\":%s}",
-                    DATASOURCE_NAME, DATASOURCE_TYPE, DATASOURCE_ACCESS, 
warehouseProperties.url(), false
+            log.info("Datasource {} not found, creating new one", 
datasourceName);
+        } catch (Exception e) {
+            log.error("Query datasource error", e);
+            return;
+        }
+
+        // Create new datasource
+        createDatasource(token, datasourceName, datasourceUrl, datasourceType);
+    }
+
+    public void createDatasource(String token, String datasourceName, String 
datasourceUrl, String datasourceType) {
+        String createUrl = grafanaProperties.getPrefix() + 
grafanaProperties.getUrl() + CREATE_DATASOURCE_API;
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.setBearerAuth(token);
+
+        DatasourceRequest datasourceRequest;
+        if ("greptime".equals(datasourceType)) {
+            datasourceUrl += "/v1/prometheus";
+            Map<String, Object> jsonData = new HashMap<>();
+            Map<String, Object> secureJsonData = new HashMap<>();
+            jsonData.put("httpHeaderName1", "x-greptime-db-name");
+            secureJsonData.put("httpHeaderValue1", 
greptimeProperties.database());
+            datasourceRequest = new DatasourceRequest(
+                    datasourceName,
+                    DATASOURCE_TYPE,
+                    DATASOURCE_ACCESS,
+                    datasourceUrl,
+                    false,
+                    jsonData,
+                    secureJsonData
+            );
+        } else {
+            datasourceRequest = new DatasourceRequest(
+                    datasourceName,
+                    DATASOURCE_TYPE,
+                    DATASOURCE_ACCESS,
+                    datasourceUrl,
+                    false,
+                    null,
+                    null
             );
+        }
+
+        try {
+            String body = JsonUtil.toJson(datasourceRequest);
             HttpEntity<String> createEntity = new HttpEntity<>(body, headers);
-            try {
-                ResponseEntity<String> createResponse = 
restTemplate.postForEntity(createUrl, createEntity, String.class);
-                if (createResponse.getStatusCode().is2xxSuccessful()) {
-                    log.info("Create datasource success");
-                }
-            } catch (Exception e) {
-                log.error("Create datasource error", e);
+
+            ResponseEntity<String> createResponse = 
restTemplate.postForEntity(createUrl, createEntity, String.class);
+            if (createResponse.getStatusCode().is2xxSuccessful()) {
+                log.info("Create datasource success");
             }
+        } catch (HttpClientErrorException.Conflict conflict) {
+            log.info("Datasource already exists");
         } catch (Exception e) {
-            log.error("Query datasource error", e);
+            log.error("Create datasource error", e);
         }
-        
     }
-}
+
+    /**
+     * Request object for creating a Grafana datasource.
+     * Fields are annotated with @JsonInclude to exclude null values from 
serialization.
+     */
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    public static class DatasourceRequest {
+        public String name;
+        public String type;
+        public String access;
+        public String url;
+        public boolean basicAuth;
+        public Map<String, Object> jsonData;
+        public Map<String, Object> secureJsonData;
+
+        public DatasourceRequest(String name, String type, String access, 
String url, boolean basicAuth, Map<String, Object> jsonData, Map<String, 
Object> secureJsonData) {
+            this.name = name;
+            this.type = type;
+            this.access = access;
+            this.url = url;
+            this.basicAuth = basicAuth;
+            this.jsonData = jsonData;
+            this.secureJsonData = secureJsonData;
+        }
+    }
+
+    /**
+     * Get the current active datasource name
+     * @return Current datasource name or null if none active
+     */
+    public String getCurrentDatasourceName() {
+        boolean vmEnabled = warehouseProperties.enabled();
+        boolean greptimeEnabled = greptimeProperties.enabled();
+
+        if (vmEnabled) {
+            return generateDatasourceName("vm", warehouseProperties.url());
+        } else if (greptimeEnabled) {
+            return generateDatasourceName("greptime", 
greptimeProperties.httpEndpoint());
+        }
+
+        return null;
+    }
+}
\ No newline at end of file
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/PrometheusProxyConfig.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/PrometheusProxyConfig.java
new file mode 100644
index 0000000000..9947034215
--- /dev/null
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/PrometheusProxyConfig.java
@@ -0,0 +1,81 @@
+/*
+ * 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.manager.config;
+
+import jakarta.annotation.PostConstruct;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.vm.VictoriaMetricsProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * Configuration class for Prometheus Proxy.
+ * This class determines whether to use PrometheusProxyCollectImpl or 
PrometheusAutoCollectImpl
+ * based on the presence of GreptimeDB or VictoriaMetrics properties.
+ */
+@Component
+public class PrometheusProxyConfig {
+    private static GreptimeProperties staticGreptimeProperties;
+    private static VictoriaMetricsProperties staticVictoriaMetricsProperties;
+
+    private final GreptimeProperties greptimeProperties;
+    private final VictoriaMetricsProperties victoriaMetricsProperties;
+
+    /**
+     * Constructs the factory and injects warehouse properties.
+     * Uses @Autowired(required = false) to allow these properties to be 
optional,
+     * in case they are not configured or enabled in the warehouse module.
+     *
+     * @param greptimeProperties GreptimeDB configuration properties.
+     * @param victoriaMetricsProperties VictoriaMetrics configuration 
properties.
+     */
+    @Autowired
+    public PrometheusProxyConfig(
+            @Autowired(required = false) GreptimeProperties greptimeProperties,
+            @Autowired(required = false) VictoriaMetricsProperties 
victoriaMetricsProperties) {
+        this.greptimeProperties = greptimeProperties;
+        this.victoriaMetricsProperties = victoriaMetricsProperties;
+    }
+
+    /**
+     * Initializes static fields with the injected properties after 
construction.
+     * This allows the static getCollector method to access these 
configurations.
+     */
+    @PostConstruct
+    private void initStatic() {
+        staticGreptimeProperties = this.greptimeProperties;
+        staticVictoriaMetricsProperties = this.victoriaMetricsProperties;
+    }
+
+    /**
+     * Judges whether to use PrometheusProxyCollectImpl or 
PrometheusAutoCollectImpl
+     */
+    public boolean isPrometheusProxy() {
+        if (staticGreptimeProperties != null && 
staticGreptimeProperties.enabled()) {
+            return true;
+        }
+        if (staticVictoriaMetricsProperties != null && 
staticVictoriaMetricsProperties.enabled()) {
+            return true;
+        }
+        return false;
+    }
+
+
+}
diff --git 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java
 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java
index 592d913f58..868ac259b6 100644
--- 
a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java
+++ 
b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/scheduler/SchedulerInit.java
@@ -30,6 +30,7 @@ import 
org.apache.hertzbeat.common.entity.manager.CollectorMonitorBind;
 import org.apache.hertzbeat.common.entity.manager.Monitor;
 import org.apache.hertzbeat.common.entity.manager.Param;
 import org.apache.hertzbeat.common.entity.manager.ParamDefine;
+import org.apache.hertzbeat.manager.config.PrometheusProxyConfig;
 import org.apache.hertzbeat.manager.dao.CollectorDao;
 import org.apache.hertzbeat.manager.dao.CollectorMonitorBindDao;
 import org.apache.hertzbeat.manager.dao.MonitorDao;
@@ -73,6 +74,9 @@ public class SchedulerInit implements CommandLineRunner {
     
     @Autowired
     private CollectorMonitorBindDao collectorMonitorBindDao;
+
+    @Autowired
+    private PrometheusProxyConfig prometheusProxyConfig;
     
     @Override
     public void run(String... args) throws Exception {
@@ -99,6 +103,8 @@ public class SchedulerInit implements CommandLineRunner {
                 boolean isStatic = 
CommonConstants.SCRAPE_STATIC.equals(monitor.getScrape()) || 
!StringUtils.hasText(monitor.getScrape());
                 String app = isStatic ? monitor.getApp() : monitor.getScrape();
                 Job appDefine = appService.getAppDefine(app);
+                // set Prometheus proxy mode
+                
appDefine.setPrometheusProxyMode(prometheusProxyConfig.isPrometheusProxy());
                 if (!isStatic) {
                     appDefine.setSd(true);
                 }
diff --git 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/ManagerTest.java 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/ManagerTest.java
index e875fe93e8..de3cfdf750 100644
--- 
a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/ManagerTest.java
+++ 
b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/ManagerTest.java
@@ -46,8 +46,8 @@ import 
org.apache.hertzbeat.common.support.SpringContextHolder;
 import org.apache.hertzbeat.alert.service.impl.TencentSmsClientImpl;
 import org.apache.hertzbeat.warehouse.WarehouseWorkerPool;
 import org.apache.hertzbeat.warehouse.controller.MetricsDataController;
-import org.apache.hertzbeat.warehouse.store.history.iotdb.IotDbDataStorage;
-import 
org.apache.hertzbeat.warehouse.store.history.tdengine.TdEngineDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.iotdb.IotDbDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine.TdEngineDataStorage;
 import org.apache.hertzbeat.warehouse.store.realtime.memory.MemoryDataStorage;
 import org.apache.hertzbeat.warehouse.store.realtime.redis.RedisDataStorage;
 import org.junit.jupiter.api.Test;
diff --git 
a/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/LogAutoConfiguration.java
 
b/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/LogAutoConfiguration.java
index fbf517d427..f58973b12d 100644
--- 
a/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/LogAutoConfiguration.java
+++ 
b/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/LogAutoConfiguration.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.otel.config;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
-import 
org.apache.hertzbeat.warehouse.store.history.greptime.GreptimeProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
 import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.ComponentScan;
 
diff --git 
a/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/OpenTelemetryConfig.java
 
b/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/OpenTelemetryConfig.java
index 4dba2b62ba..167458f472 100644
--- 
a/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/OpenTelemetryConfig.java
+++ 
b/hertzbeat-otel/src/main/java/org/apache/hertzbeat/otel/config/OpenTelemetryConfig.java
@@ -36,7 +36,7 @@ import java.util.concurrent.TimeUnit;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import 
org.apache.hertzbeat.warehouse.store.history.greptime.GreptimeProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimePromqlQueryExecutor.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimePromqlQueryExecutor.java
index 9a3a81f956..5be5ae4e2a 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimePromqlQueryExecutor.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimePromqlQueryExecutor.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.warehouse.db;
 
 
 import lombok.extern.slf4j.Slf4j;
-import 
org.apache.hertzbeat.warehouse.store.history.greptime.GreptimeProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeProperties;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/PromqlQueryExecutor.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/PromqlQueryExecutor.java
index ee51990879..a67a679f02 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/PromqlQueryExecutor.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/PromqlQueryExecutor.java
@@ -30,7 +30,7 @@ import org.apache.hertzbeat.common.util.TimePeriodUtil;
 import static 
org.apache.hertzbeat.warehouse.constants.WarehouseConstants.INSTANT;
 import static 
org.apache.hertzbeat.warehouse.constants.WarehouseConstants.PROMQL;
 import static 
org.apache.hertzbeat.warehouse.constants.WarehouseConstants.RANGE;
-import org.apache.hertzbeat.warehouse.store.history.vm.PromQlQueryContent;
+import org.apache.hertzbeat.warehouse.store.history.tsdb.vm.PromQlQueryContent;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.MediaType;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/VictoriaMetricsQueryExecutor.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/VictoriaMetricsQueryExecutor.java
index cf4297b2d0..d139550702 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/VictoriaMetricsQueryExecutor.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/VictoriaMetricsQueryExecutor.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.warehouse.db;
 
 
 import lombok.extern.slf4j.Slf4j;
-import 
org.apache.hertzbeat.warehouse.store.history.vm.VictoriaMetricsProperties;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.vm.VictoriaMetricsProperties;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/listener/WareHouseApplicationReadyListener.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/listener/WareHouseApplicationReadyListener.java
index 4ce7887f88..aa1969d67d 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/listener/WareHouseApplicationReadyListener.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/listener/WareHouseApplicationReadyListener.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.warehouse.listener;
 
 import java.util.Optional;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Component;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/service/impl/MetricsDataServiceImpl.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/service/impl/MetricsDataServiceImpl.java
index d42f35a627..7d2935af16 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/service/impl/MetricsDataServiceImpl.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/service/impl/MetricsDataServiceImpl.java
@@ -34,7 +34,7 @@ import org.apache.hertzbeat.common.entity.dto.ValueRow;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.support.exception.CommonException;
 import org.apache.hertzbeat.warehouse.service.MetricsDataService;
-import org.apache.hertzbeat.warehouse.store.history.HistoryDataReader;
+import org.apache.hertzbeat.warehouse.store.history.tsdb.HistoryDataReader;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
 import org.springframework.stereotype.Service;
 
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/DataStorageDispatch.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/DataStorageDispatch.java
index 9b29aa6eef..222b644f07 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/DataStorageDispatch.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/DataStorageDispatch.java
@@ -28,7 +28,7 @@ import org.apache.hertzbeat.common.queue.CommonDataQueue;
 import org.apache.hertzbeat.plugin.PostCollectPlugin;
 import org.apache.hertzbeat.plugin.runner.PluginRunner;
 import org.apache.hertzbeat.warehouse.WarehouseWorkerPool;
-import org.apache.hertzbeat.warehouse.store.history.HistoryDataWriter;
+import org.apache.hertzbeat.warehouse.store.history.tsdb.HistoryDataWriter;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataWriter;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/AbstractHistoryDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/AbstractHistoryDataStorage.java
similarity index 95%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/AbstractHistoryDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/AbstractHistoryDataStorage.java
index f11e4e0f1f..47c5da1105 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/AbstractHistoryDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/AbstractHistoryDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history;
+package org.apache.hertzbeat.warehouse.store.history.tsdb;
 
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.DisposableBean;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataReader.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataReader.java
similarity index 97%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataReader.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataReader.java
index b98a6e0f8b..93b4afa036 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataReader.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataReader.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history;
+package org.apache.hertzbeat.warehouse.store.history.tsdb;
 
 import java.util.List;
 import java.util.Map;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataWriter.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataWriter.java
similarity index 95%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataWriter.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataWriter.java
index 6ea065bb17..b9c12ba95d 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/HistoryDataWriter.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/HistoryDataWriter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history;
+package org.apache.hertzbeat.warehouse.store.history.tsdb;
 
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java
similarity index 95%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java
index 500599b715..0da9605686 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.greptime;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.greptime;
 
 import io.greptime.GreptimeDB;
 import io.greptime.models.AuthInfo;
@@ -55,8 +55,8 @@ import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.util.Base64Util;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.TimePeriodUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
-import org.apache.hertzbeat.warehouse.store.history.vm.PromQlQueryContent;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
+import org.apache.hertzbeat.warehouse.store.history.tsdb.vm.PromQlQueryContent;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
@@ -81,7 +81,6 @@ public class GreptimeDbDataStorage extends 
AbstractHistoryDataStorage {
     private static final String LABEL_KEY_NAME = "__name__";
     private static final String LABEL_KEY_FIELD = "__field__";
     private static final String LABEL_KEY_INSTANCE = "instance";
-    private static final String SPILT = "_";
 
     private GreptimeDB greptimeDb;
 
@@ -126,7 +125,7 @@ public class GreptimeDbDataStorage extends 
AbstractHistoryDataStorage {
             return;
         }
         String monitorId = String.valueOf(metricsData.getId());
-        String tableName = getTableName(metricsData.getId(), 
metricsData.getMetrics());
+        String tableName = getTableName(metricsData.getMetrics());
         TableSchema.Builder tableSchemaBuilder = 
TableSchema.newBuilder(tableName);
 
         tableSchemaBuilder.addTag("instance", DataType.String)
@@ -194,7 +193,7 @@ public class GreptimeDbDataStorage extends 
AbstractHistoryDataStorage {
     @Override
     public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
                                                          String label, String 
history) {
-        String name = getTableName(monitorId, metrics);
+        String name = getTableName(metrics);
         String timeSeriesSelector = LABEL_KEY_NAME + "=\"" + name + "\""
                 + "," + LABEL_KEY_INSTANCE + "=\"" + monitorId + "\"";
         if (!CommonConstants.PROMETHEUS.equals(app)) {
@@ -242,12 +241,13 @@ public class GreptimeDbDataStorage extends 
AbstractHistoryDataStorage {
                     .queryParam("start", start)
                     .queryParam("end", end)
                     .queryParam("step", step)
+                    .queryParam("db", greptimeProperties.database())
                     .build(true).toUri();
 
             ResponseEntity<PromQlQueryContent> responseEntity = 
restTemplate.exchange(uri,
                     HttpMethod.GET, httpEntity, PromQlQueryContent.class);
             if (responseEntity.getStatusCode().is2xxSuccessful()) {
-                log.debug("query metrics data from victoria-metrics success. 
{}", uri);
+                log.debug("query metrics data from greptime success. {}", uri);
                 if (responseEntity.getBody() != null && 
responseEntity.getBody().getData() != null
                         && responseEntity.getBody().getData().getResult() != 
null) {
                     List<PromQlQueryContent.ContentData.Content> contents = 
responseEntity.getBody().getData().getResult();
@@ -275,8 +275,8 @@ public class GreptimeDbDataStorage extends 
AbstractHistoryDataStorage {
         return instanceValuesMap;
     }
 
-    private String getTableName(Long monitorId, String metrics) {
-        return "hzb" + SPILT + monitorId + SPILT + metrics;
+    private String getTableName(String metrics) {
+        return metrics;
     }
 
     @Override
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeProperties.java
index c48d4af0d2..7913eec5fd 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.greptime;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.greptime;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbDataStorage.java
similarity index 99%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbDataStorage.java
index b5b4fb9425..4805d71e81 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.influxdb;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.influxdb;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -46,7 +46,7 @@ import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
 import org.apache.hertzbeat.common.entity.dto.Value;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.util.JsonUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.apache.http.ssl.SSLContexts;
 import org.influxdb.InfluxDB;
 import org.influxdb.InfluxDBFactory;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbProperties.java
index de9d749b1c..943a414c4d 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/influxdb/InfluxdbProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/influxdb/InfluxdbProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.influxdb;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.influxdb;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbDataStorage.java
similarity index 99%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbDataStorage.java
index 0e553f4964..4d85fba3b1 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.iotdb;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.iotdb;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -33,7 +33,7 @@ import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
 import org.apache.hertzbeat.common.entity.dto.Value;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.util.JsonUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 import org.apache.iotdb.session.pool.SessionDataSetWrapper;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbProperties.java
similarity index 97%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbProperties.java
index 9e7293e39c..b2deeff658 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/iotdb/IotDbProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/iotdb/IotDbProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.iotdb;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.iotdb;
 
 import java.time.ZoneId;
 import java.util.List;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaDatabaseDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaDatabaseDataStorage.java
similarity index 98%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaDatabaseDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaDatabaseDataStorage.java
index f226e352ce..f1800c2389 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaDatabaseDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaDatabaseDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.jpa;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.jpa;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -49,7 +49,7 @@ import org.apache.hertzbeat.common.entity.warehouse.History;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.TimePeriodUtil;
 import org.apache.hertzbeat.warehouse.dao.HistoryDao;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.jpa.domain.Specification;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaProperties.java
index ab04a7ea50..0f8c586815 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/jpa/JpaProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/jpa/JpaProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.jpa;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.jpa;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineDataStorage.java
similarity index 99%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineDataStorage.java
index bc3e590e21..22a1acb37e 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.tdengine;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine;
 
 import com.google.common.collect.Maps;
 import com.taosdata.jdbc.TSDBDriver;
@@ -47,7 +47,7 @@ import org.apache.hertzbeat.common.entity.arrow.RowWrapper;
 import org.apache.hertzbeat.common.entity.dto.Value;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.util.JsonUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Component;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineProperties.java
index 631b8271a2..270c8b91eb 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tdengine/TdEngineProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/tdengine/TdEngineProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.tdengine;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/PromQlQueryContent.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/PromQlQueryContent.java
similarity index 97%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/PromQlQueryContent.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/PromQlQueryContent.java
index b16b0030b2..59f7955df6 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/PromQlQueryContent.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/PromQlQueryContent.java
@@ -34,7 +34,7 @@
  * under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import java.util.List;
 import java.util.Map;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterDataStorage.java
similarity index 99%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterDataStorage.java
index 78187fc186..8ac1963088 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import com.fasterxml.jackson.databind.JsonNode;
 
@@ -63,7 +63,7 @@ import org.apache.hertzbeat.common.util.Base64Util;
 import org.apache.hertzbeat.common.util.CommonUtil;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.TimePeriodUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Primary;
 import org.springframework.http.HttpEntity;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterProperties.java
index 6eb5e4321c..7a3635b8ee 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsClusterProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsClusterProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsDataStorage.java
similarity index 99%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsDataStorage.java
index 76b943eca5..e72320f792 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsDataStorage.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsDataStorage.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -57,7 +57,7 @@ import org.apache.hertzbeat.common.util.Base64Util;
 import org.apache.hertzbeat.common.util.CommonUtil;
 import org.apache.hertzbeat.common.util.JsonUtil;
 import org.apache.hertzbeat.common.util.TimePeriodUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.AbstractHistoryDataStorage;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Primary;
 import org.springframework.http.HttpEntity;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsInsertProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsInsertProperties.java
similarity index 94%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsInsertProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsInsertProperties.java
index 91e807bea3..0b2b230925 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsInsertProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsInsertProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import org.springframework.boot.context.properties.bind.DefaultValue;
 
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsProperties.java
similarity index 96%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsProperties.java
index 16fbc2df7c..3ce6f07077 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 import org.apache.hertzbeat.common.constants.ConfigConstants;
 import org.apache.hertzbeat.common.constants.SignConstants;
diff --git 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsSelectProperties.java
 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsSelectProperties.java
similarity index 94%
rename from 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsSelectProperties.java
rename to 
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsSelectProperties.java
index dad163617b..421756d07f 100644
--- 
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/vm/VictoriaMetricsSelectProperties.java
+++ 
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/vm/VictoriaMetricsSelectProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.warehouse.store.history.vm;
+package org.apache.hertzbeat.warehouse.store.history.tsdb.vm;
 
 /**
  * vmselect configuration information
diff --git 
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/service/MetricsDataServiceTest.java
 
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/service/MetricsDataServiceTest.java
index fd04d0af32..07c7072bd3 100644
--- 
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/service/MetricsDataServiceTest.java
+++ 
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/service/MetricsDataServiceTest.java
@@ -31,7 +31,7 @@ import java.util.Optional;
 import org.apache.hertzbeat.common.entity.message.CollectRep;
 import org.apache.hertzbeat.common.support.exception.CommonException;
 import org.apache.hertzbeat.warehouse.service.impl.MetricsDataServiceImpl;
-import org.apache.hertzbeat.warehouse.store.history.HistoryDataReader;
+import org.apache.hertzbeat.warehouse.store.history.tsdb.HistoryDataReader;
 import org.apache.hertzbeat.warehouse.store.realtime.RealTimeDataReader;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git 
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/store/TdEngineDataStorageTest.java
 
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/store/TdEngineDataStorageTest.java
index 15ac315515..2326191b63 100644
--- 
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/store/TdEngineDataStorageTest.java
+++ 
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/store/TdEngineDataStorageTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.hertzbeat.warehouse.store;
 
-import 
org.apache.hertzbeat.warehouse.store.history.tdengine.TdEngineDataStorage;
+import 
org.apache.hertzbeat.warehouse.store.history.tsdb.tdengine.TdEngineDataStorage;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@hertzbeat.apache.org
For additional commands, e-mail: notifications-h...@hertzbeat.apache.org

Reply via email to