This is an automated email from the ASF dual-hosted git repository.
gongchao 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 f315bf960 [fix] Fixed Grafana visualization integration display issue
(#3666)
f315bf960 is described below
commit f315bf9607c70e0a19f9df0f5f7dbc6739690bef
Author: Duansg <[email protected]>
AuthorDate: Sun Aug 17 14:51:14 2025 +0800
[fix] Fixed Grafana visualization integration display issue (#3666)
Co-authored-by: Calvin <[email protected]>
Co-authored-by: tomsun28 <[email protected]>
---
.../grafana/service/DashboardService.java | 6 +-
.../grafana/service/DashboardServiceTest.java | 141 +++++++++++++++++++++
2 files changed, 142 insertions(+), 5 deletions(-)
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 9e4bc4420..7b4648585 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
@@ -128,11 +128,7 @@ public class DashboardService {
?
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("^/", "") : "");
+ String fullDashboardUrl =
grafanaProperties.exposeUrl().replaceAll("/$", "") + relativeDashboardUrl;
grafanaDashboard.setUrl(fullDashboardUrl + KIOSK + REFRESH
+ INSTANCE + monitorId + useDatasource);
diff --git
a/hertzbeat-grafana/src/test/java/org/apache/hertzbeat/grafana/service/DashboardServiceTest.java
b/hertzbeat-grafana/src/test/java/org/apache/hertzbeat/grafana/service/DashboardServiceTest.java
new file mode 100644
index 000000000..69af4249e
--- /dev/null
+++
b/hertzbeat-grafana/src/test/java/org/apache/hertzbeat/grafana/service/DashboardServiceTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.grafana.service;
+
+import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard;
+import org.apache.hertzbeat.grafana.config.GrafanaProperties;
+import org.apache.hertzbeat.grafana.dao.DashboardDao;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test case for {@link DashboardService}
+ */
+@ExtendWith(MockitoExtension.class)
+public class DashboardServiceTest {
+
+ @Mock
+ private ServiceAccountService serviceAccountService;
+
+ @Mock
+ private DashboardDao dashboardDao;
+
+ @Mock
+ private GrafanaProperties grafanaProperties;
+
+ @Mock
+ private RestTemplate restTemplate;
+
+ @Mock
+ private DatasourceService datasourceService;
+
+ @InjectMocks
+ private DashboardService dashboardService;
+
+ static final String GRAFANA_API_RESULT = "{"
+ + " \"folderUid\": \"\","
+ + " \"id\": 3,"
+ + " \"slug\": \"prometheus-dashboard\","
+ + " \"status\": \"success\","
+ + " \"uid\": \"5d7d89b0-b273-40fe-bb30-d652b82f47eb\","
+ + " \"url\":
\"/d/5d7d89b0-b273-40fe-bb30-d652b82f47eb/prometheus-dashboard\","
+ + " \"version\": 3"
+ + "}";
+
+ @BeforeEach
+ void setUp() {
+
when(datasourceService.getCurrentDatasourceName()).thenReturn("hertzbeat-vm-localhost-8428");
+ when(grafanaProperties.enabled()).thenReturn(Boolean.TRUE);
+ when(grafanaProperties.getPrefix()).thenReturn("");
+ when(grafanaProperties.getUrl()).thenReturn("http://127.0.0.1:3000");
+
when(grafanaProperties.exposeUrl()).thenReturn("http://127.0.0.1:3000");
+ when(serviceAccountService.getToken()).thenReturn("test-token");
+ }
+
+
+ @Test
+ void testCreateOrUpdateDashboard() {
+ ResponseEntity<String> responseEntity = new
ResponseEntity<>(GRAFANA_API_RESULT, HttpStatus.OK);
+
+ when(restTemplate.postForEntity(
+ eq("http://127.0.0.1:3000/api/dashboards/db"),
any(HttpEntity.class), eq(String.class)
+ )).thenReturn(responseEntity);
+
+ ArgumentCaptor<GrafanaDashboard> dashboardCaptor =
ArgumentCaptor.forClass(GrafanaDashboard.class);
+ dashboardService.createOrUpdateDashboard("{\"id\":11}", 1L);
+ verify(dashboardDao).save(dashboardCaptor.capture());
+
+ GrafanaDashboard savedDashboard = dashboardCaptor.getValue();
+ assertNotNull(savedDashboard);
+ assertNotNull(savedDashboard.getUrl());
+
+ String expectedBaseUrl =
"http://127.0.0.1:3000/d/5d7d89b0-b273-40fe-bb30-d652b82f47eb";
+
+ // Verify that the URL begins with the expected base URL.
+ assertTrue(savedDashboard.getUrl().startsWith(expectedBaseUrl), "URL
should start with: " + expectedBaseUrl + ", but was: " +
savedDashboard.getUrl());
+
+ assertTrue(savedDashboard.getUrl().contains("kiosk=tv"), "URL should
contain kiosk parameter");
+ assertTrue(savedDashboard.getUrl().contains("refresh=15s"), "URL
should contain refresh parameter");
+ assertTrue(savedDashboard.getUrl().contains("var-instance=1"), "URL
should contain instance parameter");
+ }
+
+ @Test
+ void testCreateOrUpdateDashboardWithTrailingSlash() {
+
when(grafanaProperties.exposeUrl()).thenReturn("http://127.0.0.1:3000/");
+
+ ResponseEntity<String> responseEntity = new
ResponseEntity<>(GRAFANA_API_RESULT, HttpStatus.OK);
+
+ when(restTemplate.postForEntity(
+ eq("http://127.0.0.1:3000/api/dashboards/db"),
any(HttpEntity.class), eq(String.class)
+ )).thenReturn(responseEntity);
+
+ ArgumentCaptor<GrafanaDashboard> dashboardCaptor =
ArgumentCaptor.forClass(GrafanaDashboard.class);
+ dashboardService.createOrUpdateDashboard("{\"id\":11}", 1L);
+ verify(dashboardDao).save(dashboardCaptor.capture());
+
+ GrafanaDashboard savedDashboard = dashboardCaptor.getValue();
+ assertNotNull(savedDashboard);
+ assertNotNull(savedDashboard.getUrl());
+
+ String expectedBaseUrl =
"http://127.0.0.1:3000/d/5d7d89b0-b273-40fe-bb30-d652b82f47eb";
+
+ // Verify that the URL begins with the expected base URL.
+ assertTrue(savedDashboard.getUrl().startsWith(expectedBaseUrl), "URL
should start with: " + expectedBaseUrl + ", but was: " +
savedDashboard.getUrl());
+
+ assertTrue(savedDashboard.getUrl().contains("kiosk=tv"), "URL should
contain kiosk parameter");
+ assertTrue(savedDashboard.getUrl().contains("refresh=15s"), "URL
should contain refresh parameter");
+ assertTrue(savedDashboard.getUrl().contains("var-instance=1"), "URL
should contain instance parameter");
+ }
+
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]