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 1bac42b09 fix: greptimedb can't work with version >= 0.5 (#2095)
1bac42b09 is described below

commit 1bac42b094a7d7a34be9852096a2aa8e64333fda
Author: dennis zhuang <[email protected]>
AuthorDate: Wed Jun 19 03:54:04 2024 -0700

    fix: greptimedb can't work with version >= 0.5 (#2095)
---
 home/docs/start/greptime-init.md                   |  31 +-
 .../current/start/greptime-init.md                 |  33 +-
 manager/src/main/resources/application.yml         |   6 +-
 warehouse/pom.xml                                  |  32 +-
 .../history/greptime/GrepTimeDbDataStorage.java    | 427 ---------------------
 .../history/greptime/GreptimeDbDataStorage.java    | 423 ++++++++++++++++++++
 .../store/history/greptime/GreptimeProperties.java |   6 +-
 7 files changed, 480 insertions(+), 478 deletions(-)

diff --git a/home/docs/start/greptime-init.md b/home/docs/start/greptime-init.md
index d2b73d390..f4a0ccbdd 100644
--- a/home/docs/start/greptime-init.md
+++ b/home/docs/start/greptime-init.md
@@ -8,7 +8,7 @@ Apache HertzBeat (incubating)'s historical data storage relies 
on the time serie
 
 > It is recommended to use VictoriaMetrics as metrics storage.
 
-GreptimeDB is an open-source time-series database with a special focus on 
scalability, analytical capabilities and efficiency.   
+[GreptimeDB](https://github.com/GreptimeTeam/greptimedb) is an open-source 
time-series database with a special focus on scalability, analytical 
capabilities and efficiency.
 
 It's designed to work on infrastructure of the cloud era, and users benefit 
from its elasticity and commodity storage.
 
@@ -26,21 +26,24 @@ It's designed to work on infrastructure of the cloud era, 
and users benefit from
 2. Install GreptimeDB with Docker   
 
 ```shell
-$ docker run -p 4000-4004:4000-4004 \
-    -p 4242:4242 -v /opt/greptimedb:/tmp/greptimedb \
-    --name greptime \
-    greptime/greptimedb standalone start \
-    --http-addr 0.0.0.0:4000 \
-    --rpc-addr 0.0.0.0:4001 \
+$ docker run -p 127.0.0.1:4000-4003:4000-4003 \
+  -v "$(pwd)/greptimedb:/tmp/greptimedb" \
+  --name greptime --rm \
+  greptime/greptimedb:latest standalone start \
+  --http-addr 0.0.0.0:4000 \
+  --rpc-addr 0.0.0.0:4001 \
+  --mysql-addr 0.0.0.0:4002 \
+  --postgres-addr 0.0.0.0:4003
 ```
-   `-v /opt/greptimedb:/tmp/greptimedb` is local persistent mount of 
greptimedb data directory. `/opt/greptimedb` should be replaced with the actual 
local directory.
+
+   `-v "$(pwd)/greptimedb:/tmp/greptimedb"` is local persistent mount of 
greptimedb data directory. `$(pwd)/greptimedb` should be replaced with the 
actual local directory, default is the `greptimedb` directory under the current 
directory.
    use```$ docker ps``` to check if the database started successfully
 
 ### Configure the database connection in hertzbeat `application.yml` 
configuration file  
 
 1. Configure HertzBeat's configuration file   
-   Modify `hertzbeat/config/application.yml` configuration file         
-   Note⚠️The docker container way need to mount application.yml file locally, 
while you can use installation package way to unzip and modify 
`hertzbeat/config/application.yml`     
+   Modify `hertzbeat/config/application.yml` configuration file 
[/script/application.yml](https://github.com/apache/hertzbeat/raw/master/script/application.yml)
+   Note⚠️The docker container way need to mount application.yml file locally, 
while you can use installation package way to unzip and modify 
`hertzbeat/config/application.yml`
    Replace `warehouse.store.greptime` data source parameters, URL account and 
password.
 
 ```yaml
@@ -52,9 +55,15 @@ warehouse:
       # enable greptime   
       greptime:
          enabled: true
-         endpoint: localhost:4001
+         grpc-endpoints: localhost:4001
+         url: 
jdbc:mysql://localhost:4002/hertzbeat?connectionTimeZone=Asia/Shanghai&forceConnectionTimeZoneToSession=true
+         driver-class-name: com.mysql.cj.jdbc.Driver
+         username: greptime
+         password: greptime
 ```
 
+The default database is `hertzbeat` in the `url`.
+
 2. Restart HertzBeat
 
 ### FAQ
diff --git 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/start/greptime-init.md 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/start/greptime-init.md
index 5b3279b1f..ab9997786 100644
--- 
a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/start/greptime-init.md
+++ 
b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/start/greptime-init.md
@@ -1,14 +1,14 @@
 ---
 id: greptime-init  
-title: 依赖时序数据库服务GreptimeDB安装初始化(可选)        
-sidebar_label: 指标数据存储GreptimeDB    
+title: 依赖时序数据库服务 GreptimeDB 安装初始化(可选)
+sidebar_label: 指标数据存储 GreptimeDB
 ---
 
 Apache HertzBeat (incubating) 的历史数据存储依赖时序数据库,任选其一安装初始化即可,也可不安装(注意⚠️但强烈建议生产环境配置)
 
 > 我们推荐使用并长期支持 VictoriaMetrics 作为存储。
 
-GreptimeDB is an open-source time-series database with a special focus on 
scalability, analytical capabilities and efficiency.   
+[GreptimeDB](https://github.com/GreptimeTeam/greptimedb) is an open-source 
time-series database with a special focus on scalability, analytical 
capabilities and efficiency. 
 It's designed to work on infrastructure of the cloud era, and users benefit 
from its elasticity and commodity storage.
 
 **⚠️ 若不配置时序数据库,则只会留最近一小时历史数据**  
@@ -25,21 +25,24 @@ It's designed to work on infrastructure of the cloud era, 
and users benefit from
 2. Docker安装GreptimeDB  
 
 ```shell
-$ docker run -p 4000-4004:4000-4004 \
-    -p 4242:4242 -v /opt/greptimedb:/tmp/greptimedb \
-    --name greptime \
-    greptime/greptimedb standalone start \
-    --http-addr 0.0.0.0:4000 \
-    --rpc-addr 0.0.0.0:4001 
+$ docker run -p 127.0.0.1:4000-4003:4000-4003 \
+  -v "$(pwd)/greptimedb:/tmp/greptimedb" \
+  --name greptime --rm \
+  greptime/greptimedb:latest standalone start \
+  --http-addr 0.0.0.0:4000 \
+  --rpc-addr 0.0.0.0:4001 \
+  --mysql-addr 0.0.0.0:4002 \
+  --postgres-addr 0.0.0.0:4003
 ```
 
-   `-v /opt/greptimedb:/tmp/greptimedb` 
为greptimedb数据目录本地持久化挂载,需将`/opt/greptimedb`替换为实际本地存在的目录
+  `-v "$(pwd)/greptimedb:/tmp/greptimedb` 为 greptimedb 数据目录本地持久化挂载,需将 
`$(pwd)/greptimedb` 替换为实际本地存在的目录,默认使用执行命令的当前目录下的 `greptimedb` 目录作为数据目录。
+
    使用```$ docker ps```查看数据库是否启动成功
 
 ### 在hertzbeat的`application.yml`配置文件配置此数据库连接   
 
 1. 配置HertzBeat的配置文件
-   修改位于 `hertzbeat/config/application.yml` 的配置文件       
+   修改位于 `hertzbeat/config/application.yml` 的配置文件 
[/script/application.yml](https://github.com/apache/hertzbeat/raw/master/script/application.yml)
    注意⚠️docker容器方式需要将application.yml文件挂载到主机本地,安装包方式解压修改位于 
`hertzbeat/config/application.yml` 即可     
 
 **修改里面的`warehouse.store.jpa.enabled`参数为`false`, 
配置里面的`warehouse.store.greptime`数据源参数,URL账户密码,并启用`enabled`为`true`**    
@@ -52,9 +55,15 @@ warehouse:
          enabled: false
       greptime:
          enabled: true
-         endpoint: localhost:4001
+         grpc-endpoints: localhost:4001
+         url: 
jdbc:mysql://localhost:4002/hertzbeat?connectionTimeZone=Asia/Shanghai&forceConnectionTimeZoneToSession=true
+         driver-class-name: com.mysql.cj.jdbc.Driver
+         username: greptime
+         password: greptime
 ```
 
+默认数据库是 URL 中配置的  `hertzbeat` 。
+
 2. 重启 HertzBeat
 
 ### 常见问题   
diff --git a/manager/src/main/resources/application.yml 
b/manager/src/main/resources/application.yml
index e086e4952..053008a81 100644
--- a/manager/src/main/resources/application.yml
+++ b/manager/src/main/resources/application.yml
@@ -141,7 +141,11 @@ warehouse:
       password: taosdata
     greptime:
       enabled: false
-      endpoint: localhost:4001
+      grpc-endpoints: localhost:4001
+      url: 
jdbc:mysql://localhost:4002/hertzbeat?connectionTimeZone=Asia/Shanghai&forceConnectionTimeZoneToSession=true
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      username: greptime
+      password: greptime
     iot-db:
       enabled: false
       host: 127.0.0.1
diff --git a/warehouse/pom.xml b/warehouse/pom.xml
index c89770e37..0db938649 100644
--- a/warehouse/pom.xml
+++ b/warehouse/pom.xml
@@ -29,7 +29,8 @@
         <influxdb.version>2.23</influxdb.version>
         
<spring-cloud-starter-openfeign.version>3.0.5</spring-cloud-starter-openfeign.version>
         <taos-jdbcdriver.version>3.0.0</taos-jdbcdriver.version>
-        <greptimedb.version>0.4.0</greptimedb.version>
+        <greptimedb.version>0.7.3</greptimedb.version>
+        <mysql-jdbcdriver.version>8.0.33</mysql-jdbcdriver.version>
     </properties>
     <modelVersion>4.0.0</modelVersion>
 
@@ -81,10 +82,10 @@
             <artifactId>influxdb-java</artifactId>
             <version>${influxdb.version}</version>
         </dependency>
-
+        <!-- greptimedb -->
         <dependency>
             <groupId>io.greptime</groupId>
-            <artifactId>greptimedb-protocol</artifactId>
+            <artifactId>ingester-all</artifactId>
             <version>${greptimedb.version}</version>
             <exclusions>
                 <exclusion>
@@ -105,28 +106,11 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        <!-- mysql -->
         <dependency>
-            <groupId>io.greptime</groupId>
-            <artifactId>greptimedb-grpc</artifactId>
-            <version>${greptimedb.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>io.grpc</groupId>
-                    <artifactId>grpc-all</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.google.code.gson</groupId>
-                    <artifactId>gson</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.google.guava</groupId>
-                    <artifactId>guava</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.google.protobuf</groupId>
-                    <artifactId>protobuf-java</artifactId>
-                </exclusion>
-            </exclusions>
+             <groupId>mysql</groupId>
+             <artifactId>mysql-connector-java</artifactId>
+             <version>${mysql-jdbcdriver.version}</version>
         </dependency>
         <!-- kafka -->
         <dependency>
diff --git 
a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GrepTimeDbDataStorage.java
 
b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GrepTimeDbDataStorage.java
deleted file mode 100644
index 4109cf025..000000000
--- 
a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GrepTimeDbDataStorage.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * 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.warehouse.store.history.greptime;
-
-import io.greptime.GreptimeDB;
-import io.greptime.models.ColumnDataType;
-import io.greptime.models.Err;
-import io.greptime.models.QueryOk;
-import io.greptime.models.QueryRequest;
-import io.greptime.models.Result;
-import io.greptime.models.Row;
-import io.greptime.models.SelectExprType;
-import io.greptime.models.SelectRows;
-import io.greptime.models.SemanticType;
-import io.greptime.models.TableName;
-import io.greptime.models.TableSchema;
-import io.greptime.models.WriteOk;
-import io.greptime.models.WriteRows;
-import io.greptime.options.GreptimeOptions;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.time.Duration;
-import java.time.ZonedDateTime;
-import java.time.temporal.TemporalAmount;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.arrow.flight.FlightRuntimeException;
-import org.apache.hertzbeat.common.constants.CommonConstants;
-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.common.util.TimePeriodUtil;
-import org.apache.hertzbeat.warehouse.store.history.AbstractHistoryDataStorage;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.stereotype.Component;
-
-/**
- * greptimeDB data storage
- */
-@Component
-@ConditionalOnProperty(prefix = "warehouse.store.greptime", name = "enabled", 
havingValue = "true")
-@Slf4j
-public class GrepTimeDbDataStorage extends AbstractHistoryDataStorage {
-
-    /**
-     * storage database
-     */
-    private static final String STORAGE_DATABASE = "hertzbeat";
-    private static final String QUERY_HISTORY_SQL =
-            "SELECT CAST (ts AS Int64) ts, instance, \"%s\" FROM %s WHERE ts 
>= %s and monitor_id = %s order by ts desc;";
-    private static final String QUERY_HISTORY_WITH_INSTANCE_SQL =
-            "SELECT CAST (ts AS Int64) ts, instance, \"%s\" FROM %s WHERE ts 
>= %s and monitor_id = %s and instance = %s order by ts desc;";
-    private static final String QUERY_INSTANCE_SQL =
-            "SELECT DISTINCT instance FROM %s WHERE ts >= now() - interval '1' 
WEEK";
-    private static final String QUERY_HISTORY_INTERVAL_WITH_INSTANCE_SQL =
-            "SELECT first, avg ,max, min FROM (SELECT \"%s\" as first FROM %s 
WHERE monitor_id = %s and ts >= %s"
-                    + " and ts < %s ORDER BY ts LIMIT 1) LEFT JOIN (SELECT 
avg(\"%s\") as avg, min(\"%s\") as min, max(\"%s\") as max FROM %s WHERE ts >= 
%s and ts < %s) ON 1=1";
-    private static final String TABLE_NOT_EXIST = "not exist";
-    private static final String DATABASE_NOT_EXIST = "not exist";
-    private GreptimeDB greptimeDb;
-
-    public GrepTimeDbDataStorage(GreptimeProperties greptimeProperties) {
-        this.serverAvailable = this.initDbSession(greptimeProperties);
-    }
-
-    private boolean initDbSession(GreptimeProperties properties) {
-        String endpoint = properties.endpoint();
-        GreptimeOptions opts = GreptimeOptions.newBuilder(endpoint)
-                .writeMaxRetries(1)
-                .readMaxRetries(2)
-                .routeTableRefreshPeriodSeconds(-1)
-                .build();
-        greptimeDb = new GreptimeDB();
-        if (!greptimeDb.init(opts)) {
-            log.error("Fail to start Greptime client");
-            return false;
-        }
-        return createDatabase();
-    }
-
-    /**
-     * Checks if the database exists; if not, creates the Database.
-     */
-    private boolean createDatabase() {
-        // 查询现有数据库
-        QueryRequest showDatabases = QueryRequest.newBuilder()
-                .exprType(SelectExprType.Sql)
-                .ql("SHOW DATABASES;")
-                .build();
-        Result<QueryOk, Err> result = null;
-        try {
-            CompletableFuture<Result<QueryOk, Err>> future = 
greptimeDb.query(showDatabases);
-            result = future.get();
-        } catch (Exception e) {
-            log.info("TABLE_NOT_EXIST: {}", e.getMessage());
-            String msg = e.getMessage();
-            if (msg != null && !msg.contains(DATABASE_NOT_EXIST)) {
-                log.warn(msg);
-            }
-
-        }
-        // Check if the existing database includes“Hertzbeat”
-        boolean isDatabaseExist = false;
-        if (result != null && result.isOk()) {
-            QueryOk queryOk = result.getOk();
-            SelectRows rows = queryOk.getRows();
-            List<Row> rowsList = rows.collect();
-            for (Row row : rowsList) {
-                for (io.greptime.models.Value value : row.values()) {
-                    if (STORAGE_DATABASE.equals(value.value().toString())) {
-                        log.info("Exist Database {}", STORAGE_DATABASE);
-                        isDatabaseExist = true;
-                        break;
-                    }
-                }
-            }
-        }
-        // If it does not exist, create database
-        if (!isDatabaseExist) {
-            QueryRequest createDatabase = QueryRequest.newBuilder()
-                    .exprType(SelectExprType.Sql)
-                    .ql("CREATE DATABASE %s;", STORAGE_DATABASE)
-                    .build();
-            try {
-                CompletableFuture<Result<QueryOk, Err>> createFuture = 
greptimeDb.query(createDatabase);
-                isDatabaseExist = createFuture.get().isOk();
-                log.info("Database {} does not exist,and has been created", 
STORAGE_DATABASE);
-            } catch (InterruptedException | ExecutionException e) {
-                log.error("Error creating database");
-            }
-        }
-        return isDatabaseExist;
-    }
-
-    @Override
-    public void saveData(CollectRep.MetricsData metricsData) {
-        if (!isServerAvailable() || metricsData.getCode() != 
CollectRep.Code.SUCCESS) {
-            return;
-        }
-        if (metricsData.getValuesList().isEmpty()) {
-            log.info("[warehouse greptime] flush metrics data {} is null, 
ignore.", metricsData.getId());
-            return;
-        }
-        String monitorId = String.valueOf(metricsData.getId());
-        String table = metricsData.getApp() + "_" + metricsData.getMetrics();
-        TableSchema.Builder tableSchemaBuilder = 
TableSchema.newBuilder(TableName.with(STORAGE_DATABASE, table));
-
-        List<SemanticType> semanticTypes = new 
LinkedList<>(Arrays.asList(SemanticType.Tag, SemanticType.Tag, 
SemanticType.Timestamp));
-        List<ColumnDataType> dataTypes = new 
LinkedList<>(Arrays.asList(ColumnDataType.String, ColumnDataType.String, 
ColumnDataType.TimestampMillisecond));
-        List<String> columnNames = new 
LinkedList<>(Arrays.asList("monitor_id", "instance", "ts"));
-
-        List<CollectRep.Field> fieldsList = metricsData.getFieldsList();
-        for (CollectRep.Field field : fieldsList) {
-            semanticTypes.add(SemanticType.Field);
-            columnNames.add(field.getName());
-            // handle field type
-            if (field.getType() == CommonConstants.TYPE_NUMBER) {
-                dataTypes.add(ColumnDataType.Float64);
-            } else if (field.getType() == CommonConstants.TYPE_STRING) {
-                dataTypes.add(ColumnDataType.String);
-            }
-        }
-        tableSchemaBuilder.semanticTypes(semanticTypes.toArray(new 
SemanticType[0]));
-        tableSchemaBuilder.dataTypes(dataTypes.toArray(new ColumnDataType[0]));
-        tableSchemaBuilder.columnNames(columnNames.toArray(new String[0]));
-        WriteRows rows = 
WriteRows.newBuilder(tableSchemaBuilder.build()).build();
-        try {
-            long now = System.currentTimeMillis();
-            Object[] values = new Object[3 + fieldsList.size()];
-            values[0] = monitorId;
-            values[2] = now;
-            for (CollectRep.ValueRow valueRow : metricsData.getValuesList()) {
-                Map<String, String> labels = new HashMap<>(8);
-                for (int i = 0; i < fieldsList.size(); i++) {
-                    if 
(!CommonConstants.NULL_VALUE.equals(valueRow.getColumns(i))) {
-                        CollectRep.Field field = fieldsList.get(i);
-                        if (field.getType() == CommonConstants.TYPE_NUMBER) {
-                            values[3 + i] = 
Double.parseDouble(valueRow.getColumns(i));
-                        } else if (field.getType() == 
CommonConstants.TYPE_STRING) {
-                            values[3 + i] = valueRow.getColumns(i);
-                        }
-                        if (field.getLabel()) {
-                            labels.put(field.getName(), 
String.valueOf(values[3 + i]));
-                        }
-                    } else {
-                        values[3 + i] = null;
-                    }
-                }
-                values[1] = JsonUtil.toJson(labels);
-                rows.insert(values);
-            }
-            rows.finish();
-            CompletableFuture<Result<WriteOk, Err>> writeFuture = 
greptimeDb.write(rows);
-            try {
-                Result<WriteOk, Err> result = writeFuture.get(10, 
TimeUnit.SECONDS);
-                if (result.isOk()) {
-                    log.debug("[warehouse greptime]-Write successful");
-                } else {
-                    log.warn("[warehouse greptime]--Write failed: {}", 
result.getErr().getFailedQl());
-                }
-            } catch (Throwable throwable) {
-                log.error("[warehouse greptime]--Error occurred: {}", 
throwable.getMessage());
-            }
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
-                                                         String label, String 
history) {
-        Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
-        if (!isServerAvailable()) {
-            log.error("\n\t---------------Greptime Init 
Failed---------------\n"
-                    + "\t--------------Please Config Greptime--------------\n"
-                    + "\t----------Can Not Use Metric History 
Now----------\n");
-            return instanceValuesMap;
-        }
-        long expireTime = getExpireTimeFromToken(history);
-        String table = app + "_" + metrics;
-        String selectSql = label == null
-                ? String.format(QUERY_HISTORY_SQL, metric, table, expireTime, 
monitorId)
-                : String.format(QUERY_HISTORY_WITH_INSTANCE_SQL, metric, 
table, expireTime, monitorId, label);
-        log.debug("selectSql: {}", selectSql);
-        QueryRequest request = QueryRequest.newBuilder()
-                .exprType(SelectExprType.Sql)
-                .databaseName(STORAGE_DATABASE)
-                .ql(selectSql)
-                .build();
-        try {
-            CompletableFuture<Result<QueryOk, Err>> future = 
greptimeDb.query(request);
-            Result<QueryOk, Err> result = future.get();
-            if (result != null && result.isOk()) {
-                QueryOk queryOk = result.getOk();
-                SelectRows rows = queryOk.getRows();
-                List<Map<String, Object>> maps = rows.collectToMaps();
-                List<Value> valueList;
-                for (Map<String, Object> map : maps) {
-                    String instanceValue = map.get("instance") == null ? "" : 
map.get("instance").toString();
-                    Object valueObj = map.get(metric);
-                    if (valueObj == null) {
-                        continue;
-                    }
-                    String strValue = new 
BigDecimal(valueObj.toString()).setScale(4, 
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
-                    valueList = 
instanceValuesMap.computeIfAbsent(instanceValue, k -> new LinkedList<>());
-                    valueList.add(new Value(strValue, (long) map.get("ts")));
-                }
-            }
-        } catch (FlightRuntimeException e) {
-            String msg = e.getMessage();
-            if (msg != null && msg.contains(TABLE_NOT_EXIST)) {
-                List<Value> valueList = 
instanceValuesMap.computeIfAbsent(metric, k -> new LinkedList<>());
-                valueList.add(new Value(null, System.currentTimeMillis()));
-                log.info("[warehouse greptime]-TABLE_NOT_EXIST: {}", table);
-            }
-        } catch (Exception e) {
-            log.error(e.getMessage(), e);
-        }
-        return instanceValuesMap;
-    }
-
-    private long getExpireTimeFromToken(String history) {
-        long expireTime;
-        try {
-            TemporalAmount temporalAmount = 
TimePeriodUtil.parseTokenTime(history);
-            ZonedDateTime dateTime = ZonedDateTime.now().minus(temporalAmount);
-            expireTime = dateTime.toEpochSecond() * 1000L;
-        } catch (Exception e) {
-            log.error("parse history time error: {}. use default: 6h", 
e.getMessage());
-            ZonedDateTime dateTime = 
ZonedDateTime.now().minus(Duration.ofHours(6));
-            expireTime = dateTime.toEpochSecond() * 1000L;
-        }
-        return expireTime;
-    }
-
-    @Override
-    public Map<String, List<Value>> getHistoryIntervalMetricData(Long 
monitorId, String app, String metrics,
-                                                                 String 
metric, String label, String history) {
-        Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
-        if (!isServerAvailable()) {
-            log.error("\n\t---------------Greptime Init 
Failed---------------\n"
-                    + "\t--------------Please Config Greptime--------------\n"
-                    + "\t----------Can Not Use Metric History 
Now----------\n");
-            return instanceValuesMap;
-        }
-        String table = app + "_" + metrics;
-        List<String> instances = new LinkedList<>();
-        if (label != null) {
-            instances.add(label);
-        }
-        if (instances.isEmpty()) {
-            String selectSql = String.format(QUERY_INSTANCE_SQL, table);
-            log.debug("selectSql: {}", selectSql);
-            QueryRequest request = QueryRequest.newBuilder()
-                    .exprType(SelectExprType.Sql)
-                    .databaseName(STORAGE_DATABASE)
-                    .ql(selectSql)
-                    .build();
-            try {
-                CompletableFuture<Result<QueryOk, Err>> future = 
greptimeDb.query(request);
-                Result<QueryOk, Err> result = future.get();
-                if (result != null && result.isOk()) {
-                    QueryOk queryOk = result.getOk();
-                    SelectRows rows = queryOk.getRows();
-                    while (rows.hasNext()) {
-                        Row row = rows.next();
-                        if (row != null) {
-                            List<io.greptime.models.Value> values = 
row.values();
-                            for (io.greptime.models.Value value : values) {
-                                log.debug("value:{}", value.value());
-                                Object instanceValue = value.value();
-                                if (instanceValue == null || 
"".equals(instanceValue)) {
-                                    instances.add("''");
-                                } else {
-                                    instances.add(instanceValue.toString());
-                                }
-                            }
-                        }
-
-                    }
-                }
-            } catch (FlightRuntimeException e) {
-                String msg = e.getMessage();
-                if (msg != null && msg.contains(TABLE_NOT_EXIST)) {
-                    log.info("[warehouse greptime]-TABLE_NOT_EXIST: {}", 
table);
-                }
-            } catch (Exception e) {
-                log.error(e.getMessage(), e);
-            }
-        }
-        // TODO 'greptime' did not find the proper SQL function processing, 
temporarily using code implementation, future 'greptime' update documents using 
SQL implementation
-        long endTime;
-        long startTime = getExpireTimeFromToken(history);
-
-        Calendar cal = Calendar.getInstance();
-
-        long interval = System.currentTimeMillis() - startTime;
-        long fourHourCount = TimeUnit.MILLISECONDS.toHours(interval) / 4;
-        for (int i = 0; i < fourHourCount; i++) {
-            cal.clear();
-            cal.setTimeInMillis(startTime);
-            cal.add(Calendar.HOUR_OF_DAY, 4);
-            endTime = cal.getTimeInMillis();
-
-            for (String instanceValue : instances) {
-                String selectSql = 
String.format(QUERY_HISTORY_INTERVAL_WITH_INSTANCE_SQL, metric, table, 
monitorId, startTime, endTime, metric, metric, metric, table, startTime, 
endTime);
-
-                log.debug("selectSql: {}", selectSql);
-                QueryRequest request = QueryRequest.newBuilder()
-                        .exprType(SelectExprType.Sql)
-                        .databaseName(STORAGE_DATABASE)
-                        .ql(selectSql)
-                        .build();
-                List<Value> values = 
instanceValuesMap.computeIfAbsent(instanceValue, k -> new LinkedList<>());
-                try {
-                    CompletableFuture<Result<QueryOk, Err>> future = 
greptimeDb.query(request);
-                    Result<QueryOk, Err> result = future.get();
-                    log.debug("result:{}", result);
-                    if (result != null && result.isOk()) {
-                        QueryOk queryOk = result.getOk();
-                        SelectRows rows = queryOk.getRows();
-                        String[] col = new String[4];
-                        while (rows.hasNext()) {
-                            Row row = rows.next();
-                            if (!row.values().isEmpty()) {
-                                for (int j = 0; j < row.values().size(); j++) {
-                                    log.debug("value:{}", row.values().get(j));
-                                    String colStr = new 
BigDecimal(row.values().get(j).value().toString()).setScale(4, 
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
-                                    col[j] = colStr;
-                                }
-                                Value valueBuild = Value.builder()
-                                        .origin(col[0]).mean(col[1])
-                                        .min(col[2]).max(col[3])
-                                        .time(System.currentTimeMillis())
-                                        .build();
-                                values.add(valueBuild);
-                            }
-                        }
-                        log.debug("[warehouse greptime] values:{}", values);
-                    }
-                } catch (FlightRuntimeException e) {
-                    String msg = e.getMessage();
-                    if (msg != null && msg.contains(TABLE_NOT_EXIST)) {
-                        List<Value> valueList = 
instanceValuesMap.computeIfAbsent(metric, k -> new LinkedList<>());
-                        valueList.add(new Value(null, 
System.currentTimeMillis()));
-                        log.info("[warehouse greptime]-TABLE_NOT_EXIST: {}", 
table);
-                    }
-                } catch (Exception e) {
-                    log.error(e.getMessage(), e);
-                }
-            }
-            startTime = endTime;
-        }
-
-        return instanceValuesMap;
-    }
-
-    @Override
-    public void destroy() {
-        if (this.greptimeDb != null) {
-            this.greptimeDb.shutdownGracefully();
-        }
-    }
-}
diff --git 
a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
 
b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
new file mode 100644
index 000000000..a44417121
--- /dev/null
+++ 
b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeDbDataStorage.java
@@ -0,0 +1,423 @@
+/*
+ * 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.warehouse.store.history.greptime;
+
+import com.mysql.cj.jdbc.Driver;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import io.greptime.GreptimeDB;
+import io.greptime.models.AuthInfo;
+import io.greptime.models.DataType;
+import io.greptime.models.Err;
+import io.greptime.models.Result;
+import io.greptime.models.Table;
+import io.greptime.models.TableSchema;
+import io.greptime.models.WriteOk;
+import io.greptime.options.GreptimeOptions;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.hertzbeat.common.constants.CommonConstants;
+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.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+/**
+ * GreptimeDB data storage, only supports GreptimeDB version >= v0.5
+ *
+ */
+@Component
+@ConditionalOnProperty(prefix = "warehouse.store.greptime", name = "enabled", 
havingValue = "true")
+@Slf4j
+public class GreptimeDbDataStorage extends AbstractHistoryDataStorage {
+
+    private static final String QUERY_HISTORY_SQL = "SELECT CAST (ts AS Int64) 
ts, instance, `%s` FROM `%s` WHERE ts >= now() -  interval '%s' and monitor_id 
= %s order by ts desc;";
+
+    @SuppressWarnings("checkstyle:LineLength")
+    private static final String QUERY_HISTORY_WITH_INSTANCE_SQL = "SELECT CAST 
(ts AS Int64) ts, instance, `%s` FROM `%s` WHERE ts >= now() - interval '%s' 
and monitor_id = %s and instance = '%s' order by ts desc;";
+
+    private static final String QUERY_INSTANCE_SQL = "SELECT DISTINCT instance 
FROM `%s` WHERE ts >= now() - interval '1 WEEK'";
+
+    @SuppressWarnings("checkstyle:LineLength")
+    private static final String QUERY_HISTORY_INTERVAL_WITH_INSTANCE_SQL = 
"SELECT CAST (ts AS Int64) ts, first_value(`%s`) range '4h' first, avg(`%s`) 
range '4h' avg, min(`%s`) range '4h' min, max(`%s`) range '4h' max FROM `%s` 
WHERE instance = '%s' AND ts >= now() - interval '%s' ALIGN '4h'";
+
+    private static final String TABLE_NOT_EXIST = "not found";
+
+    private static final String CONSTANTS_CREATE_DATABASE = "CREATE DATABASE 
IF NOT EXISTS `%s`";
+
+    private static final Runnable INSTANCE_EXCEPTION_PRINT = () -> {
+       if (log.isErrorEnabled()) {
+           log.error("""
+               \t---------------GreptimeDB Init Failed---------------
+               \t--------------Please Config GreptimeDB--------------
+               t-----------Can Not Use Metric History Now-----------
+               """);
+       }
+    };
+
+    private HikariDataSource hikariDataSource;
+
+    private GreptimeDB greptimeDb;
+
+    public GreptimeDbDataStorage(GreptimeProperties greptimeProperties) {
+       if (greptimeProperties == null) {
+           log.error("init error, please config Warehouse GreptimeDB props in 
application.yml");
+           throw new IllegalArgumentException("please config Warehouse 
GreptimeDB props");
+       }
+       
+       serverAvailable = initGreptimeDbClient(greptimeProperties) && 
initGreptimeDbDataSource(greptimeProperties);
+    }
+
+    private void initGreptimeDb(final GreptimeProperties greptimeProperties) 
throws SQLException {
+       final DriverPropertyInfo[] properties = new 
Driver().getPropertyInfo(greptimeProperties.url(), null);
+       final String host = ObjectUtils.requireNonEmpty(properties[0].value);
+       final String port = ObjectUtils.requireNonEmpty(properties[1].value);
+       final String dbName = ObjectUtils.requireNonEmpty(properties[2].value);
+
+       try (final Connection tempConnection = 
DriverManager.getConnection("jdbc:mysql://" + host + ":" + port,
+               greptimeProperties.username(), greptimeProperties.password());
+               final PreparedStatement pstmt = tempConnection
+                       
.prepareStatement(String.format(CONSTANTS_CREATE_DATABASE, dbName))) {
+           log.info("[warehouse greptime] try to create database `{}` if not 
exists", dbName);
+           pstmt.execute();
+       }
+    }
+
+    private boolean initGreptimeDbClient(GreptimeProperties 
greptimeProperties) {
+       String endpoints = greptimeProperties.grpcEndpoints();
+       try {
+           final DriverPropertyInfo[] properties = new 
Driver().getPropertyInfo(greptimeProperties.url(), null);
+           final String dbName = 
ObjectUtils.requireNonEmpty(properties[2].value);
+          
+           GreptimeOptions opts = 
GreptimeOptions.newBuilder(endpoints.split(","), dbName) //
+                   .writeMaxRetries(3) //
+                   .authInfo(new AuthInfo(greptimeProperties.username(), 
greptimeProperties.password()))
+                   .routeTableRefreshPeriodSeconds(30) //
+                   .build();
+
+           this.greptimeDb = GreptimeDB.create(opts);
+       } catch (Exception e) {
+           log.error("[warehouse greptime] Fail to start GreptimeDB client");
+           return false;
+       }
+
+       return true;
+    }
+
+    private boolean initGreptimeDbDataSource(final GreptimeProperties 
greptimeProperties) {
+       try {
+           initGreptimeDb(greptimeProperties);
+       } catch (Exception e) {
+           if (log.isErrorEnabled()) {
+               log.error(e.getMessage(), e);
+           }
+
+           INSTANCE_EXCEPTION_PRINT.run();
+           return false;
+       }
+
+       final HikariConfig config = new HikariConfig();
+       // jdbc properties
+       config.setJdbcUrl(greptimeProperties.url());
+       config.setUsername(greptimeProperties.username());
+       config.setPassword(greptimeProperties.password());
+       config.setDriverClassName(greptimeProperties.driverClassName());
+       // minimum number of idle connection
+       config.setMinimumIdle(10);
+       // maximum number of connection in the pool
+       config.setMaximumPoolSize(10);
+       // maximum wait milliseconds for get connection from pool
+       config.setConnectionTimeout(30000);
+       // maximum lifetime for each connection
+       config.setMaxLifetime(0);
+       // max idle time for recycle idle connection
+       config.setIdleTimeout(0);
+       // validation query
+       config.setConnectionTestQuery("select 1");
+       try {
+           this.hikariDataSource = new HikariDataSource(config);
+       } catch (Exception e) {
+           INSTANCE_EXCEPTION_PRINT.run();
+           return false;
+       }
+       return true;
+    }
+
+    @Override
+    public void saveData(CollectRep.MetricsData metricsData) {
+       if (!isServerAvailable() || metricsData.getCode() != 
CollectRep.Code.SUCCESS) {
+           return;
+       }
+       if (metricsData.getValuesList().isEmpty()) {
+           log.info("[warehouse greptime] flush metrics data {} is null, 
ignore.", metricsData.getId());
+           return;
+       }
+       String monitorId = String.valueOf(metricsData.getId());
+       String tableName = getTableName(metricsData.getApp(), 
metricsData.getMetrics());
+       TableSchema.Builder tableSchemaBuilder = 
TableSchema.newBuilder(tableName);
+
+       tableSchemaBuilder.addTag("monitor_id", DataType.String) //
+               .addTag("instance", DataType.String) //
+               .addTimestamp("ts", DataType.TimestampMillisecond);
+
+       List<CollectRep.Field> fieldsList = metricsData.getFieldsList();
+       for (CollectRep.Field field : fieldsList) {
+           // handle field type
+           if (field.getType() == CommonConstants.TYPE_NUMBER) {
+               tableSchemaBuilder.addField(field.getName(), DataType.Float64);
+           } else if (field.getType() == CommonConstants.TYPE_STRING) {
+               tableSchemaBuilder.addField(field.getName(), DataType.String);
+           }
+       }
+       Table table = Table.from(tableSchemaBuilder.build());
+
+       try {
+           long now = System.currentTimeMillis();
+           Object[] values = new Object[3 + fieldsList.size()];
+           values[0] = monitorId;
+           values[2] = now;
+           for (CollectRep.ValueRow valueRow : metricsData.getValuesList()) {
+               Map<String, String> labels = new HashMap<>(8);
+               for (int i = 0; i < fieldsList.size(); i++) {
+                   if 
(!CommonConstants.NULL_VALUE.equals(valueRow.getColumns(i))) {
+                       CollectRep.Field field = fieldsList.get(i);
+                       if (field.getType() == CommonConstants.TYPE_NUMBER) {
+                           values[3 + i] = 
Double.parseDouble(valueRow.getColumns(i));
+                       } else if (field.getType() == 
CommonConstants.TYPE_STRING) {
+                           values[3 + i] = valueRow.getColumns(i);
+                       }
+                       if (field.getLabel()) {
+                           labels.put(field.getName(), String.valueOf(values[3 
+ i]));
+                       }
+                   } else {
+                       values[3 + i] = null;
+                   }
+               }
+               values[1] = JsonUtil.toJson(labels);
+               table.addRow(values);
+           }
+
+           CompletableFuture<Result<WriteOk, Err>> writeFuture = 
greptimeDb.write(table);
+           try {
+               Result<WriteOk, Err> result = writeFuture.get(10, 
TimeUnit.SECONDS);
+               if (result.isOk()) {
+                   log.debug("[warehouse greptime]-Write successful");
+               } else {
+                   log.warn("[warehouse greptime]--Write failed: {}", 
result.getErr());
+               }
+           } catch (Throwable throwable) {
+               log.error("[warehouse greptime]--Error occurred: {}", 
throwable.getMessage());
+           }
+       } catch (Exception e) {
+           log.error("[warehouse greptime]--Error: {}", e.getMessage(), e);
+       }
+    }
+
+    @Override
+    public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
+           String label, String history) {
+       Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
+       if (!isServerAvailable()) {
+           INSTANCE_EXCEPTION_PRINT.run();
+           return instanceValuesMap;
+       }
+
+       String table = getTableName(app, metrics);
+
+       String interval = history2interval(history);
+       String selectSql = label == null ? String.format(QUERY_HISTORY_SQL, 
metric, table, interval, monitorId)
+               : String.format(QUERY_HISTORY_WITH_INSTANCE_SQL, metric, table, 
interval, monitorId, label);
+
+       if (log.isDebugEnabled()) {
+           log.debug("[warehouse greptime] getHistoryMetricData SQL: {}", 
selectSql);
+       }
+
+       try (Connection connection = hikariDataSource.getConnection();
+               Statement statement = connection.createStatement();
+               ResultSet resultSet = statement.executeQuery(selectSql)) {
+           while (resultSet.next()) {
+               long ts = resultSet.getLong(1);
+               if (ts == 0) {
+                   if (log.isErrorEnabled()) {
+                       log.error("[warehouse greptime] getHistoryMetricData 
query result timestamp is 0, ignore. {}.",
+                               selectSql);
+                   }
+                   continue;
+               }
+               String instanceValue = resultSet.getString(2);
+               if (instanceValue == null || "".equals(instanceValue)) {
+                   instanceValue = "";
+               }
+               double value = resultSet.getDouble(3);
+               String strValue = double2decimalString(value);
+
+               List<Value> valueList = 
instanceValuesMap.computeIfAbsent(instanceValue, k -> new LinkedList<>());
+               valueList.add(new Value(strValue, ts));
+           }
+           return instanceValuesMap;
+       } catch (SQLException sqlException) {
+           String msg = sqlException.getMessage();
+           if (msg != null && !msg.contains(TABLE_NOT_EXIST)) {
+               if (log.isWarnEnabled()) {
+                   log.warn("[warehouse greptime] failed to 
getHistoryMetricData: " + sqlException.getMessage());
+               }
+           }
+       } catch (Exception e) {
+           if (log.isErrorEnabled()) {
+               log.error("[warehouse greptime] failed to 
getHistoryMetricData:" + e.getMessage(), e);
+           }
+       }
+       return instanceValuesMap;
+    }
+
+    private String getTableName(String app, String metrics) {
+       return app + "_" + metrics;
+    }
+
+    @Override
+    public Map<String, List<Value>> getHistoryIntervalMetricData(Long 
monitorId, String app, String metrics,
+           String metric, String label, String history) {
+       if (!isServerAvailable()) {
+           INSTANCE_EXCEPTION_PRINT.run();
+           return Collections.emptyMap();
+       }
+       String table = getTableName(app, metrics);
+       List<String> instances = new LinkedList<>();
+       if (label != null && !"".equals(label)) {
+           instances.add(label);
+       }
+       if (instances.isEmpty()) {
+           String selectSql = String.format(QUERY_INSTANCE_SQL, table);
+           if (log.isDebugEnabled()) {
+               log.debug("[warehouse greptime] getHistoryIntervalMetricData 
sql: {}", selectSql);
+           }
+
+           try (Connection connection = hikariDataSource.getConnection();
+                   Statement statement = connection.createStatement();
+                   ResultSet resultSet = statement.executeQuery(selectSql)) {
+               while (resultSet.next()) {
+                   String instanceValue = resultSet.getString(1);
+                   if (instanceValue == null || "".equals(instanceValue)) {
+                       instances.add("''");
+                   } else {
+                       instances.add(instanceValue);
+                   }
+               }
+           } catch (Exception e) {
+               if (log.isErrorEnabled()) {
+                   log.error("[warehouse greptime] failed to query instances" 
+ e.getMessage(), e);
+               }
+           }
+       }
+
+       Map<String, List<Value>> instanceValuesMap = new 
HashMap<>(instances.size());
+       for (String instanceValue : instances) {
+           String selectSql = 
String.format(QUERY_HISTORY_INTERVAL_WITH_INSTANCE_SQL, metric, metric, metric, 
metric,
+                   table, instanceValue, history2interval(history));
+
+           if (log.isDebugEnabled()) {
+               log.debug("[warehouse greptime] getHistoryIntervalMetricData 
sql: {}", selectSql);
+           }
+
+           List<Value> values = 
instanceValuesMap.computeIfAbsent(instanceValue, k -> new LinkedList<>());
+           try (Connection connection = hikariDataSource.getConnection();
+                   Statement statement = connection.createStatement();
+                   ResultSet resultSet = statement.executeQuery(selectSql);) {
+               while (resultSet.next()) {
+                   long ts = resultSet.getLong(1);
+                   if (ts == 0) {
+                       if (log.isErrorEnabled()) {
+                           log.error(
+                                   "[warehouse greptime] 
getHistoryIntervalMetricData query result timestamp is 0, ignore. {}.",
+                                   selectSql);
+                       }
+                       continue;
+                   }
+                   double origin = resultSet.getDouble(2);
+                   String originStr = double2decimalString(origin);
+                   double avg = resultSet.getDouble(3);
+                   String avgStr = double2decimalString(avg);
+                   double min = resultSet.getDouble(4);
+                   String minStr = double2decimalString(min);
+                   double max = resultSet.getDouble(5);
+                   String maxStr = double2decimalString(max);
+                   Value value = 
Value.builder().origin(originStr).mean(avgStr).min(minStr).max(maxStr).time(ts)
+                           .build();
+                   values.add(value);
+               }
+               resultSet.close();
+           } catch (Exception e) {
+               if (log.isErrorEnabled()) {
+                   log.error("[warehouse greptime] failed to 
getHistoryIntervalMetricData: " + e.getMessage(), e);
+               }
+           }
+       }
+       return instanceValuesMap;
+    }
+
+    // TODO(dennis): we can remove it when
+    // https://github.com/GreptimeTeam/greptimedb/issues/4168 is fixed.
+    // default 6h-6 hours: s-seconds, M-minutes, h-hours, d-days, w-weeks
+    private String history2interval(String history) {
+       if (history == null) {
+           return null;
+       }
+       history = history.trim().toLowerCase();
+
+       // Be careful, the order matters.
+       return history.replaceAll("d", " day") //
+               .replaceAll("s", " second") //
+               .replaceAll("w", " week") //
+               .replaceAll("h", " hour")//
+               .replaceAll("m", " minute");
+    }
+
+    private String double2decimalString(double d) {
+       return BigDecimal.valueOf(d).setScale(4, 
RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+    }
+
+    @Override
+    public void destroy() {
+       if (this.greptimeDb != null) {
+           this.greptimeDb.shutdownGracefully();
+           this.greptimeDb = null;
+       }
+       if (this.hikariDataSource != null) {
+           this.hikariDataSource.close();
+           hikariDataSource = null;
+       }
+    }
+}
diff --git 
a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
 
b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
index 0561af78d..ac8e29f9f 100644
--- 
a/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
+++ 
b/warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/greptime/GreptimeProperties.java
@@ -25,7 +25,7 @@ import 
org.springframework.boot.context.properties.bind.DefaultValue;
  */
 @ConfigurationProperties(prefix = "warehouse.store.greptime")
 public record GreptimeProperties(@DefaultValue("false") boolean enabled,
-                                 @DefaultValue("127.0.0.1:4001") String 
endpoint,
-                                 String username,
-                                 String password) {
+       @DefaultValue("127.0.0.1:4001") String grpcEndpoints,
+       
@DefaultValue("jdbc:mysql://127.0.0.1:4002/hertzbeat?connectionTimeZone=Asia/Shanghai&forceConnectionTimeZoneToSession=true")
 String url,
+       @DefaultValue("com.mysql.cj.jdbc.Driver") String driverClassName, 
String username, String password) {
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to