mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 09:40:58 +00:00
[feat] Add Grafana to follow the system theme (#3920)
Co-authored-by: lynx009 <2030509072@qq.com>
This commit is contained in:
@@ -32,10 +32,10 @@
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- hertzbeat common -->
|
||||
<!-- hertzbeat base -->
|
||||
<dependency>
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-common</artifactId>
|
||||
<artifactId>hertzbeat-base</artifactId>
|
||||
</dependency>
|
||||
<!-- hertzbeat warehouse -->
|
||||
<dependency>
|
||||
|
||||
+3
-1
@@ -33,6 +33,8 @@ public interface GrafanaConstants {
|
||||
|
||||
String INSTANCE = "&var-instance=";
|
||||
|
||||
String THEME = "&theme=";
|
||||
|
||||
String CREATE_DASHBOARD_API = "/api/dashboards/db";
|
||||
|
||||
String DELETE_DASHBOARD_API = "/api/dashboards/uid/%s";
|
||||
@@ -92,4 +94,4 @@ public interface GrafanaConstants {
|
||||
static String generateUseDatasource(String datasourceName) {
|
||||
return "&var-ds=" + datasourceName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+52
-13
@@ -17,17 +17,15 @@
|
||||
|
||||
package org.apache.hertzbeat.grafana.service;
|
||||
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.CREATE_DASHBOARD_API;
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.DELETE_DASHBOARD_API;
|
||||
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 java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
import org.apache.hertzbeat.common.constants.ThemeEnum;
|
||||
import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.grafana.common.GrafanaConstants;
|
||||
import org.apache.hertzbeat.grafana.config.GrafanaProperties;
|
||||
@@ -42,7 +40,17 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.CREATE_DASHBOARD_API;
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.DELETE_DASHBOARD_API;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Service for managing Grafana dashboards.
|
||||
@@ -66,6 +74,11 @@ public class DashboardService {
|
||||
@Autowired
|
||||
private DatasourceService datasourceService;
|
||||
|
||||
@Autowired
|
||||
private GeneralConfigDao generalConfigDao;
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Creates or updates a dashboard in Grafana.
|
||||
* The "id" field will be removed from the dashboard JSON before sending
|
||||
@@ -225,7 +238,16 @@ public class DashboardService {
|
||||
* @return GrafanaDashboard object
|
||||
*/
|
||||
public GrafanaDashboard getDashboardByMonitorId(Long monitorId) {
|
||||
return dashboardDao.findByMonitorId(monitorId);
|
||||
GrafanaDashboard dashboard = dashboardDao.findByMonitorId(monitorId);
|
||||
if (null != dashboard
|
||||
&& StringUtils.isNotBlank(dashboard.getUrl())
|
||||
&& !dashboard.getUrl().contains(GrafanaConstants.THEME)) {
|
||||
String theme = loadThemeConfig();
|
||||
return dashboard.toBuilder()
|
||||
.url(dashboard.getUrl() + GrafanaConstants.THEME + theme)
|
||||
.build();
|
||||
}
|
||||
return dashboard;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,4 +270,21 @@ public class DashboardService {
|
||||
log.warn("No Grafana dashboard record found for monitorId {} to disable.", monitorId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String loadThemeConfig() {
|
||||
try {
|
||||
GeneralConfig config = generalConfigDao.findByType(GeneralConfigTypeEnum.system.name());
|
||||
if (config != null && config.getContent() != null) {
|
||||
JsonNode root = OBJECT_MAPPER.readTree(config.getContent());
|
||||
JsonNode node = root.get("theme");
|
||||
if (node != null && !node.isNull()) {
|
||||
return ThemeEnum.convert(node.asText());
|
||||
}
|
||||
return ThemeEnum.LIGHT.getValue();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to load database theme configuration", e);
|
||||
}
|
||||
return ThemeEnum.LIGHT.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
+45
-10
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.grafana.service;
|
||||
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard;
|
||||
import org.apache.hertzbeat.grafana.config.GrafanaProperties;
|
||||
import org.apache.hertzbeat.grafana.dao.DashboardDao;
|
||||
@@ -34,10 +35,12 @@ 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.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
|
||||
/**
|
||||
* Test case for {@link DashboardService}
|
||||
@@ -60,6 +63,9 @@ public class DashboardServiceTest {
|
||||
@Mock
|
||||
private DatasourceService datasourceService;
|
||||
|
||||
@Mock
|
||||
private GeneralConfigDao generalConfigDao;
|
||||
|
||||
@InjectMocks
|
||||
private DashboardService dashboardService;
|
||||
|
||||
@@ -73,25 +79,27 @@ public class DashboardServiceTest {
|
||||
+ " \"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");
|
||||
lenient().when(datasourceService.getCurrentDatasourceName()).thenReturn("hertzbeat-vm-localhost-8428");
|
||||
lenient().when(grafanaProperties.enabled()).thenReturn(Boolean.TRUE);
|
||||
lenient().when(grafanaProperties.getPrefix()).thenReturn("");
|
||||
lenient().when(grafanaProperties.getUrl()).thenReturn("http://127.0.0.1:3000");
|
||||
lenient().when(grafanaProperties.exposeUrl()).thenReturn("http://127.0.0.1:3000");
|
||||
lenient().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());
|
||||
@@ -109,7 +117,7 @@ public class DashboardServiceTest {
|
||||
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/");
|
||||
@@ -138,4 +146,31 @@ public class DashboardServiceTest {
|
||||
assertTrue(savedDashboard.getUrl().contains("var-instance=1"), "URL should contain instance parameter");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetDashboardByMonitorId() {
|
||||
Long monitorId = 1L;
|
||||
String originalUrl = "http://localhost:3000/d/123/my-dashboard?kiosk";
|
||||
GrafanaDashboard originalDashboard = GrafanaDashboard.builder()
|
||||
.monitorId(monitorId)
|
||||
.url(originalUrl)
|
||||
.build();
|
||||
|
||||
when(dashboardDao.findByMonitorId(eq(monitorId))).thenReturn(originalDashboard);
|
||||
|
||||
String themeConfigJson = "{\"theme\":\"light\"}";
|
||||
org.apache.hertzbeat.common.entity.manager.GeneralConfig runConfig = new org.apache.hertzbeat.common.entity.manager.GeneralConfig();
|
||||
runConfig.setContent(themeConfigJson);
|
||||
|
||||
when(generalConfigDao.findByType(eq(org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum.system.name())))
|
||||
.thenReturn(runConfig);
|
||||
|
||||
GrafanaDashboard resultDashboard = dashboardService.getDashboardByMonitorId(monitorId);
|
||||
|
||||
assertNotNull(resultDashboard);
|
||||
assertTrue(resultDashboard.getUrl().contains("&theme=light"));
|
||||
assertTrue(originalDashboard.getUrl().endsWith("?kiosk"));
|
||||
assertFalse(originalDashboard.getUrl().contains("&theme="));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user