Copilot commented on code in PR #3776:
URL: https://github.com/apache/hertzbeat/pull/3776#discussion_r2379395502


##########
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java:
##########
@@ -202,60 +208,148 @@ public void saveData(CollectRep.MetricsData metricsData) 
{
     @Override
     public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
                                                          String label, String 
history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        return getHistoryData(start, end, step, monitorId, app, metrics, 
metric);
+    }
+
+    private String getTableName(String metrics) {
+        return metrics;
+    }
+
+    @Override
+    public Map<String, List<Value>> getHistoryIntervalMetricData(Long 
monitorId, String app, String metrics,
+                                                                 String 
metric, String label, String history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        Map<String, List<Value>> instanceValuesMap = getHistoryData(start, 
end, step, monitorId, app, metrics, metric);
+
+        // Queries below this point may yield inconsistent results due to 
exceeding the valid data range.
+        // Therefore, we restrict the valid range by obtaining the post-query 
timeframe.
+        // Since `gretime`'s `end` excludes the specified time, we add 4 hours.
+        List<Value> values = 
instanceValuesMap.get(instanceValuesMap.keySet().stream().toList().get(0));

Review Comment:
   This code will throw an IndexOutOfBoundsException if instanceValuesMap is 
empty. Add a null check and ensure the map contains at least one entry before 
accessing the first key.



##########
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java:
##########
@@ -202,60 +208,148 @@ public void saveData(CollectRep.MetricsData metricsData) 
{
     @Override
     public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
                                                          String label, String 
history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        return getHistoryData(start, end, step, monitorId, app, metrics, 
metric);
+    }
+
+    private String getTableName(String metrics) {
+        return metrics;
+    }
+
+    @Override
+    public Map<String, List<Value>> getHistoryIntervalMetricData(Long 
monitorId, String app, String metrics,
+                                                                 String 
metric, String label, String history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        Map<String, List<Value>> instanceValuesMap = getHistoryData(start, 
end, step, monitorId, app, metrics, metric);
+
+        // Queries below this point may yield inconsistent results due to 
exceeding the valid data range.
+        // Therefore, we restrict the valid range by obtaining the post-query 
timeframe.
+        // Since `gretime`'s `end` excludes the specified time, we add 4 hours.
+        List<Value> values = 
instanceValuesMap.get(instanceValuesMap.keySet().stream().toList().get(0));
+        // effective time
+        long effectiveStart = values.get(0).getTime() / 1000;
+        long effectiveEnd = values.get(values.size() - 1).getTime() / 1000 + 
Duration.ofHours(4).getSeconds();
+
+        String name = getTableName(metrics);
+        String timeSeriesSelector = name + "{" + LABEL_KEY_INSTANCE + "=\"" + 
monitorId + "\"";
+        if (!CommonConstants.PROMETHEUS.equals(app)) {
+            timeSeriesSelector = timeSeriesSelector + "," + LABEL_KEY_FIELD + 
"=\"" + metric + "\"";
+        }
+        timeSeriesSelector = timeSeriesSelector + "}";
+
+        try {
+            // max
+            String finalTimeSeriesSelector = timeSeriesSelector;
+            URI uri = getUri(effectiveStart, effectiveEnd, step, uriComponents 
-> "max_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMax);
+            // min
+            uri = getUri(effectiveStart, effectiveEnd, step, uriComponents -> 
"min_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMin);
+            // avg
+            uri = getUri(effectiveStart, effectiveEnd, step, uriComponents -> 
"avg_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMean);
+        } catch (Exception e) {
+            log.error("query interval metrics data from greptime error. {}", 
e.getMessage(), e);
+        }
+
+        return instanceValuesMap;
+    }
+
+    /**
+     * Get time range
+     *
+     * @param history history range
+     * @return time range
+     */
+    private Map<String, Long> getTimeRange(String history) {
+        // Build start and end times
+        Instant now = Instant.now();
+        long start;
+        try {
+            if (NumberUtils.isParsable(history)) {
+                start = NumberUtils.toLong(history);
+                start = (ZonedDateTime.now().toEpochSecond() - start);
+            } else {
+                TemporalAmount temporalAmount = 
TimePeriodUtil.parseTokenTime(history);
+                assert temporalAmount != null;
+                Instant dateTime = now.minus(temporalAmount);
+                start = dateTime.getEpochSecond();
+            }
+        } catch (Exception e) {
+            log.error("history time error: {}. use default: 6h", 
e.getMessage());
+            start = now.minus(6, ChronoUnit.HOURS).getEpochSecond();
+        }
+        long end = now.getEpochSecond();
+        return Map.of("start", start, "end", end);

Review Comment:
   Using hardcoded string literals 'start' and 'end' here is inconsistent with 
the defined constants LABEL_KEY_START_TIME and LABEL_KEY_END_TIME. Use the 
constants for consistency.
   ```suggestion
           return Map.of(MetricDataConstants.LABEL_KEY_START_TIME, start, 
MetricDataConstants.LABEL_KEY_END_TIME, end);
   ```



##########
hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/store/history/tsdb/greptime/GreptimeDbDataStorage.java:
##########
@@ -202,60 +208,148 @@ public void saveData(CollectRep.MetricsData metricsData) 
{
     @Override
     public Map<String, List<Value>> getHistoryMetricData(Long monitorId, 
String app, String metrics, String metric,
                                                          String label, String 
history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        return getHistoryData(start, end, step, monitorId, app, metrics, 
metric);
+    }
+
+    private String getTableName(String metrics) {
+        return metrics;
+    }
+
+    @Override
+    public Map<String, List<Value>> getHistoryIntervalMetricData(Long 
monitorId, String app, String metrics,
+                                                                 String 
metric, String label, String history) {
+        Map<String, Long> timeRange = getTimeRange(history);
+        Long start = timeRange.get(LABEL_KEY_START_TIME);
+        Long end = timeRange.get(LABEL_KEY_END_TIME);
+
+        String step = getTimeStep(start, end);
+
+        Map<String, List<Value>> instanceValuesMap = getHistoryData(start, 
end, step, monitorId, app, metrics, metric);
+
+        // Queries below this point may yield inconsistent results due to 
exceeding the valid data range.
+        // Therefore, we restrict the valid range by obtaining the post-query 
timeframe.
+        // Since `gretime`'s `end` excludes the specified time, we add 4 hours.
+        List<Value> values = 
instanceValuesMap.get(instanceValuesMap.keySet().stream().toList().get(0));
+        // effective time
+        long effectiveStart = values.get(0).getTime() / 1000;
+        long effectiveEnd = values.get(values.size() - 1).getTime() / 1000 + 
Duration.ofHours(4).getSeconds();
+
+        String name = getTableName(metrics);
+        String timeSeriesSelector = name + "{" + LABEL_KEY_INSTANCE + "=\"" + 
monitorId + "\"";
+        if (!CommonConstants.PROMETHEUS.equals(app)) {
+            timeSeriesSelector = timeSeriesSelector + "," + LABEL_KEY_FIELD + 
"=\"" + metric + "\"";
+        }
+        timeSeriesSelector = timeSeriesSelector + "}";
+
+        try {
+            // max
+            String finalTimeSeriesSelector = timeSeriesSelector;
+            URI uri = getUri(effectiveStart, effectiveEnd, step, uriComponents 
-> "max_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMax);
+            // min
+            uri = getUri(effectiveStart, effectiveEnd, step, uriComponents -> 
"min_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMin);
+            // avg
+            uri = getUri(effectiveStart, effectiveEnd, step, uriComponents -> 
"avg_over_time(" + finalTimeSeriesSelector + "[" + step + "])");
+            requestIntervalMetricAndPutValue(uri, instanceValuesMap, 
Value::setMean);
+        } catch (Exception e) {
+            log.error("query interval metrics data from greptime error. {}", 
e.getMessage(), e);
+        }
+
+        return instanceValuesMap;
+    }
+
+    /**
+     * Get time range
+     *
+     * @param history history range
+     * @return time range
+     */
+    private Map<String, Long> getTimeRange(String history) {
+        // Build start and end times
+        Instant now = Instant.now();
+        long start;
+        try {
+            if (NumberUtils.isParsable(history)) {
+                start = NumberUtils.toLong(history);
+                start = (ZonedDateTime.now().toEpochSecond() - start);
+            } else {
+                TemporalAmount temporalAmount = 
TimePeriodUtil.parseTokenTime(history);
+                assert temporalAmount != null;
+                Instant dateTime = now.minus(temporalAmount);
+                start = dateTime.getEpochSecond();
+            }
+        } catch (Exception e) {
+            log.error("history time error: {}. use default: 6h", 
e.getMessage());
+            start = now.minus(6, ChronoUnit.HOURS).getEpochSecond();
+        }
+        long end = now.getEpochSecond();
+        return Map.of("start", start, "end", end);
+    }
+
+    /**
+     * Get time step
+     *
+     * @param start start time
+     * @param end   end time
+     * @return step
+     */
+    private String getTimeStep(long start, long end) {
+        // get step
+        String step = "60s";
+        if (end - start < Duration.ofDays(7).getSeconds() && end - start > 
Duration.ofDays(1).getSeconds()) {
+            step = "1h";
+        } else if (end - start >= Duration.ofDays(7).getSeconds()) {
+            step = "4h";
+        }
+        return step;
+    }
+
+    /**
+     * Get history metric data
+     *
+     * @param start     start time
+     * @param end       end time
+     * @param step      step
+     * @param monitorId monitor id
+     * @param app       monitor type
+     * @param metrics   metrics
+     * @param metric    metric
+     * @return history metric data
+     */
+    private Map<String, List<Value>> getHistoryData(long start, long end, 
String step, Long monitorId, String app, String metrics, String metric) {
         String name = getTableName(metrics);
         String timeSeriesSelector = LABEL_KEY_NAME + "=\"" + name + "\""
                 + "," + LABEL_KEY_INSTANCE + "=\"" + monitorId + "\"";
         if (!CommonConstants.PROMETHEUS.equals(app)) {
             timeSeriesSelector = timeSeriesSelector + "," + LABEL_KEY_FIELD + 
"=\"" + metric + "\"";
         }
+
         Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
         try {
-            HttpHeaders headers = new HttpHeaders();
-            headers.setContentType(MediaType.APPLICATION_JSON);
-            headers.setAccept(List.of(MediaType.APPLICATION_JSON));
-            if (StringUtils.hasText(greptimeProperties.username())
-                    && StringUtils.hasText(greptimeProperties.password())) {
-                String authStr = greptimeProperties.username() + ":" + 
greptimeProperties.password();
-                String encodedAuth = Base64Util.encode(authStr);
-                headers.add(HttpHeaders.AUTHORIZATION, BASIC + " " + 
encodedAuth);
-            }
-            Instant now = Instant.now();
-            long start;
-            try {
-                if (NumberUtils.isParsable(history)) {
-                    start = NumberUtils.toLong(history);
-                    start = (ZonedDateTime.now().toEpochSecond() - start);
-                } else {
-                    TemporalAmount temporalAmount = 
TimePeriodUtil.parseTokenTime(history);
-                    assert temporalAmount != null;
-                    Instant dateTime = now.minus(temporalAmount);
-                    start = dateTime.getEpochSecond();
+            HttpEntity<Void> httpEntity = getHttpEntity();
+
+            String finalTimeSeriesSelector = timeSeriesSelector;
+            URI uri = getUri(start, end, step, uriComponents -> {
+                MultiValueMap<String, String> queryParams = 
uriComponents.getQueryParams();
+                if (!queryParams.isEmpty()) {
+                    return "{" + finalTimeSeriesSelector + "}";
                 }
-            } catch (Exception e) {
-                log.error("history time error: {}. use default: 6h", 
e.getMessage());
-                start = now.minus(6, ChronoUnit.HOURS).getEpochSecond();
-            }
+                return null;
+            });
 
-            long end = now.getEpochSecond();
-            String step = "60s";
-            if (end - start < Duration.ofDays(7).getSeconds() && end - start > 
Duration.ofDays(1).getSeconds()) {
-                step = "1h";
-            } else if (end - start >= Duration.ofDays(7).getSeconds()) {
-                step = "4h";
+            ResponseEntity<PromQlQueryContent> responseEntity = null;
+            if (uri != null) {
+                responseEntity = restTemplate.exchange(uri,
+                        HttpMethod.GET, httpEntity, PromQlQueryContent.class);
             }

Review Comment:
   The null initialization and subsequent null check is unnecessary. Consider 
returning early from getHistoryData when uri is null, or restructure to avoid 
the null assignment.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to