From 87f04a5ee14a4261fffb28da95f3c93ebbc37a9d Mon Sep 17 00:00:00 2001 From: donghun-cho Date: Tue, 25 Apr 2023 20:29:56 +0900 Subject: [PATCH] [#9903] add system metric host management function --- .../pinpoint/metric/web/MetricWebApp.java | 4 +- .../SystemMetricHostExclusionController.java | 90 +++++++++++++++++++ .../cache/MetricWebCacheConfiguration.java | 34 +++++++ .../MetricWebMysqlDaoConfiguration.java | 55 ++++++++++++ .../controller/SystemMetricController.java | 13 ++- .../web/dao/SystemMetricHostExclusionDao.java | 18 ++++ .../web/dao/model/HostInfoSearchKey.java | 12 ++- .../MysqlSystemMetricHostExclusionDao.java | 54 +++++++++++ .../SystemMetricHostExclusionCache.java | 43 +++++++++ .../SystemMetricHostExclusionService.java | 18 ++++ .../SystemMetricHostExclusionServiceImpl.java | 62 +++++++++++++ .../SystemMetricHostInfoServiceImpl.java | 11 ++- .../SystemMetricHostGroupExclusionInfo.java | 59 ++++++++++++ .../mysql/MetricHostExclusionMapper.xml | 47 ++++++++++ .../MetricWebCreateTableStateMent-mysql.sql | 17 ++++ .../SystemMetricHostExclusionCacheTest.java | 65 ++++++++++++++ ...temMetricHostExclusionServiceImplTest.java | 67 ++++++++++++++ .../SystemMetricHostInfoServiceImplTest.java | 60 +++++++++++-- .../metric/web/utill/metric/TagUtilsTest.java | 12 +++ 19 files changed, 731 insertions(+), 10 deletions(-) create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/authorization/controller/SystemMetricHostExclusionController.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/cache/MetricWebCacheConfiguration.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/config/MetricWebMysqlDaoConfiguration.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/SystemMetricHostExclusionDao.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/mysql/MysqlSystemMetricHostExclusionDao.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCache.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionService.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImpl.java create mode 100644 metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/view/SystemMetricHostGroupExclusionInfo.java create mode 100644 metric-module/metric/src/main/resources/pinot-web/mapper/mysql/MetricHostExclusionMapper.xml create mode 100644 metric-module/metric/src/main/resources/pinot-web/sql/MetricWebCreateTableStateMent-mysql.sql create mode 100644 metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCacheTest.java create mode 100644 metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImplTest.java diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/MetricWebApp.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/MetricWebApp.java index c41f4268e5e4..cb21a1fefd68 100644 --- a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/MetricWebApp.java +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/MetricWebApp.java @@ -1,6 +1,7 @@ package com.navercorp.pinpoint.metric.web; +import com.navercorp.pinpoint.metric.web.config.MetricWebMysqlDaoConfiguration; import com.navercorp.pinpoint.metric.web.config.MetricWebPinotDaoConfiguration; import com.navercorp.pinpoint.pinot.config.PinotConfiguration; import org.springframework.context.annotation.ComponentScan; @@ -14,7 +15,8 @@ @Import({ WebMetricPropertySources.class, MetricWebPinotDaoConfiguration.class, - PinotConfiguration.class + PinotConfiguration.class, + MetricWebMysqlDaoConfiguration.class }) @Profile("metric") public class MetricWebApp { diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/authorization/controller/SystemMetricHostExclusionController.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/authorization/controller/SystemMetricHostExclusionController.java new file mode 100644 index 000000000000..f60a2ce1f1bf --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/authorization/controller/SystemMetricHostExclusionController.java @@ -0,0 +1,90 @@ +package com.navercorp.pinpoint.metric.web.authorization.controller; + +import com.navercorp.pinpoint.metric.web.service.SystemMetricHostExclusionService; +import com.navercorp.pinpoint.pinot.tenant.TenantProvider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(value = "/admin/systemMetric") +public class SystemMetricHostExclusionController { + private final Logger logger = LogManager.getLogger(this.getClass()); + + private final SystemMetricHostExclusionService systemMetricHostExclusionService; + private final TenantProvider tenantProvider; + + public SystemMetricHostExclusionController(SystemMetricHostExclusionService systemMetricHostExclusionService, TenantProvider tenantProvider) { + this.systemMetricHostExclusionService = systemMetricHostExclusionService; + this.tenantProvider = tenantProvider; + } + + @RequestMapping(value = "/hostGroup/addExclusion") + public String excludeHostGroup(@RequestParam("hostGroupName") String hostGroupName) { + logger.info("add hostGroup exclusion - hostGroupName: [{}]", hostGroupName); + try { + String tenantId = tenantProvider.getTenantId(); + systemMetricHostExclusionService.insertHostGroupExclusion(tenantId, hostGroupName); + return "OK"; + } catch (Exception e) { + logger.error("error while excluding hostGroupName", e); + return e.getMessage(); + } + } + + @RequestMapping(value = "/hostGroup/host/addExclusion") + public String excludeHostGroup(@RequestParam("hostGroupName") String hostGroupName, + @RequestParam("hostName") String hostName) { + logger.info("add host exclusion - hostGroupName: [{}], hostName: [{}]", hostGroupName, hostName); + try { + String tenantId = tenantProvider.getTenantId(); + systemMetricHostExclusionService.insertHostExclusion(tenantId, hostGroupName, hostName); + return "OK"; + } catch (Exception e) { + logger.error("error while excluding hostName", e); + return e.getMessage(); + } + } + + @RequestMapping(value = "/hostGroup/removeExclusion") + public String acceptHostGroup(@RequestParam("hostGroupName") String hostGroupName) { + logger.info("remove host group exclusion - hostGroupName: [{}]", hostGroupName); + try { + String tenantId = tenantProvider.getTenantId(); + systemMetricHostExclusionService.deleteHostGroupExclusion(tenantId, hostGroupName); + return "OK"; + } catch (Exception e) { + logger.error("error while accepting hostGroupName", e); + return e.getMessage(); + } + } + + @RequestMapping(value = "/hostGroup/host/removeExclusion") + public String acceptHostGroup(@RequestParam("hostGroupName") String hostGroupName, + @RequestParam("hostName") String hostName) { + logger.info("remove host exclusion - hostGroupName: [{}], hostName: [{}]", hostGroupName, hostName); + try { + String tenantId = tenantProvider.getTenantId(); + systemMetricHostExclusionService.deleteHostExclusion(tenantId, hostGroupName, hostName); + return "OK"; + } catch (Exception e) { + logger.error("error while accepting hostName", e); + return e.getMessage(); + } + } + + @RequestMapping(value = "/hostGroup/removeUnusedExclusions") + public String cleanupUnusedExclusions(@RequestParam("hostGroupName") String hostGroupName) { + logger.info("remove unused hostGroup exclusion and host exclusions - hostGroupName: [{}]", hostGroupName); + try { + String tenantId = tenantProvider.getTenantId(); + systemMetricHostExclusionService.deleteUnusedHostExclusion(tenantId, hostGroupName); + return "OK"; + } catch (Exception e) { + logger.error("error while removing unused exclusions", e); + return e.getMessage(); + } + } +} diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/cache/MetricWebCacheConfiguration.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/cache/MetricWebCacheConfiguration.java new file mode 100644 index 000000000000..1d8f18d1189e --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/cache/MetricWebCacheConfiguration.java @@ -0,0 +1,34 @@ +package com.navercorp.pinpoint.metric.web.cache; + +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +@Configuration +@EnableCaching +public class MetricWebCacheConfiguration { + + public static final String METRIC_HOST_GROUP_EXCLUSION_CACHE_NAME = "metricHostGroupExclusion"; + public static final String METRIC_HOST_EXCLUSION_CACHE_NAME = "metricHostExclusion"; + + @Bean + public CacheManager metricHostGroupExclusion() { + CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(METRIC_HOST_GROUP_EXCLUSION_CACHE_NAME); + caffeineCacheManager.setCaffeine(Caffeine.newBuilder() + .expireAfterWrite(300, TimeUnit.SECONDS)); + return caffeineCacheManager; + } + + @Bean + public CacheManager metricHostExclusion() { + CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager(METRIC_HOST_EXCLUSION_CACHE_NAME); + caffeineCacheManager.setCaffeine(Caffeine.newBuilder() + .expireAfterWrite(300, TimeUnit.SECONDS)); + return caffeineCacheManager; + } +} diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/config/MetricWebMysqlDaoConfiguration.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/config/MetricWebMysqlDaoConfiguration.java new file mode 100644 index 000000000000..2c293037d635 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/config/MetricWebMysqlDaoConfiguration.java @@ -0,0 +1,55 @@ +package com.navercorp.pinpoint.metric.web.config; + +import com.navercorp.pinpoint.metric.collector.config.MyBatisRegistryHandler; +import com.navercorp.pinpoint.pinot.mybatis.MyBatisConfiguration; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.core.io.Resource; + +import javax.sql.DataSource; + +@org.springframework.context.annotation.Configuration +public class MetricWebMysqlDaoConfiguration { + private final Logger logger = LogManager.getLogger(MetricWebMysqlDaoConfiguration.class); + + @Bean + public SqlSessionFactoryBean metricSqlSessionFactory( + @Qualifier("dataSource") DataSource dataSource, + @Value("classpath*:/pinot-web/mapper/mysql/*Mapper.xml") Resource[] mappers) { + + for (Resource mapper : mappers) { + logger.info("Mapper location: {}", mapper.getDescription()); + } + + SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); + sessionFactoryBean.setDataSource(dataSource); + sessionFactoryBean.setMapperLocations(mappers); + + Configuration config = MyBatisConfiguration.defaultConfiguration(); + sessionFactoryBean.setConfiguration(config); + + MyBatisRegistryHandler registry = registryHandler(); + registry.registerTypeAlias(config.getTypeAliasRegistry()); + + sessionFactoryBean.setFailFast(true); + + return sessionFactoryBean; + } + + private MyBatisRegistryHandler registryHandler() { + return new WebRegistryHandler(); + } + + @Bean + public SqlSessionTemplate metricSqlSessionTemplate( + @Qualifier("metricSqlSessionFactory") SqlSessionFactory sessionFactory) { + return new SqlSessionTemplate(sessionFactory); + } +} diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/controller/SystemMetricController.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/controller/SystemMetricController.java index 40e45d30b55e..fd21fbce1684 100644 --- a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/controller/SystemMetricController.java +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/controller/SystemMetricController.java @@ -20,7 +20,9 @@ import com.navercorp.pinpoint.metric.web.model.MetricDataSearchKey; import com.navercorp.pinpoint.metric.web.model.MetricInfo; import com.navercorp.pinpoint.metric.web.model.SystemMetricData; +import com.navercorp.pinpoint.metric.web.view.SystemMetricHostGroupExclusionInfo; import com.navercorp.pinpoint.metric.web.service.SystemMetricDataService; +import com.navercorp.pinpoint.metric.web.service.SystemMetricHostExclusionService; import com.navercorp.pinpoint.metric.web.service.SystemMetricHostInfoService; import com.navercorp.pinpoint.metric.web.service.YMLSystemMetricBasicGroupManager; import com.navercorp.pinpoint.metric.web.util.Range; @@ -46,17 +48,20 @@ public class SystemMetricController { private final SystemMetricDataService systemMetricDataService; private final SystemMetricHostInfoService systemMetricHostInfoService; + private final SystemMetricHostExclusionService systemMetricHostExclusionService; private final YMLSystemMetricBasicGroupManager systemMetricBasicGroupManager; private final TenantProvider tenantProvider; private final TimeWindowSampler DEFAULT_TIME_WINDOW_SAMPLER = new TimeWindowSlotCentricSampler(10000L, 200); - + public SystemMetricController(SystemMetricDataService systemMetricDataService, SystemMetricHostInfoService systemMetricHostInfoService, + SystemMetricHostExclusionService systemMetricHostExclusionService, YMLSystemMetricBasicGroupManager systemMetricBasicGroupManager, TenantProvider tenantProvider) { this.systemMetricDataService = Objects.requireNonNull(systemMetricDataService, "systemMetricService"); this.systemMetricHostInfoService = Objects.requireNonNull(systemMetricHostInfoService, "systemMetricHostInfoService"); + this.systemMetricHostExclusionService = Objects.requireNonNull(systemMetricHostExclusionService, "systemMetricHostExclusionService"); this.systemMetricBasicGroupManager = Objects.requireNonNull(systemMetricBasicGroupManager, "systemMetricBasicGroupManager"); this.tenantProvider = Objects.requireNonNull(tenantProvider, "tenantProvider"); } @@ -102,4 +107,10 @@ public SystemMetricView getCollectedMetricData(@RequestParam("hostGroupName") St SystemMetricData systemMetricData = systemMetricDataService.getCollectedMetricData(metricDataSearchKey, timeWindow, tagList); return new SystemMetricView(systemMetricData); } + + @GetMapping(value = "/hostGroup/exclusionInfo") + public SystemMetricHostGroupExclusionInfo getHostGroupExclusionInfo(@RequestParam("hostGroupName") String hostGroupName) { + String tenantId = tenantProvider.getTenantId(); + return systemMetricHostExclusionService.getHostGroupExclusionInfo(tenantId, hostGroupName); + } } diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/SystemMetricHostExclusionDao.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/SystemMetricHostExclusionDao.java new file mode 100644 index 000000000000..e37cff78f6f3 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/SystemMetricHostExclusionDao.java @@ -0,0 +1,18 @@ +package com.navercorp.pinpoint.metric.web.dao; + +import java.util.List; + +public interface SystemMetricHostExclusionDao { + + List selectExcludedHostGroupNameList(String tenantId); + + void insertMetricHostGroupExclusion(String tenantId, String hostGroupName); + + void deleteMetricHostGroupExclusion(String tenantId, String hostGroupName); + + List selectExcludedHostNameList(String tenantId, String hostGroupName); + + void insertMetricHostExclusion(String tenantId, String hostGroupName, String hostName); + + void deleteMetricHostExclusion(String tenantId, String hostGroupName, String hostName); +} \ No newline at end of file diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/model/HostInfoSearchKey.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/model/HostInfoSearchKey.java index 96d368adc3be..d7d31dbe8461 100644 --- a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/model/HostInfoSearchKey.java +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/model/HostInfoSearchKey.java @@ -25,10 +25,16 @@ public class HostInfoSearchKey { private final String tenantId; private final String hostGroupName; + private final String hostName; - public HostInfoSearchKey(String tenantId, String hostGroupName) { + public HostInfoSearchKey (String tenantId, String hostGroupName) { + this(tenantId, hostGroupName, ""); + } + + public HostInfoSearchKey(String tenantId, String hostGroupName, String hostName) { this.tenantId = Objects.requireNonNull(tenantId, "tenantId"); this.hostGroupName = Objects.requireNonNull(hostGroupName, "hostGroupName"); + this.hostName = Objects.requireNonNull(hostName, "hostName"); } public String getTenantId() { @@ -38,4 +44,8 @@ public String getTenantId() { public String getHostGroupName() { return hostGroupName; } + + public String getHostName() { + return hostName; + } } diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/mysql/MysqlSystemMetricHostExclusionDao.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/mysql/MysqlSystemMetricHostExclusionDao.java new file mode 100644 index 000000000000..7224d6d32b47 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/dao/mysql/MysqlSystemMetricHostExclusionDao.java @@ -0,0 +1,54 @@ +package com.navercorp.pinpoint.metric.web.dao.mysql; + +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostExclusionDao; +import com.navercorp.pinpoint.metric.web.dao.model.HostInfoSearchKey; +import org.mybatis.spring.SqlSessionTemplate; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Objects; + +@Primary +@Repository +public class MysqlSystemMetricHostExclusionDao implements SystemMetricHostExclusionDao { + + private static final String NAMESPACE = MysqlSystemMetricHostExclusionDao.class.getName() + "."; + + private final SqlSessionTemplate sqlMetricSessionTemplate; + + public MysqlSystemMetricHostExclusionDao(@Qualifier("metricSqlSessionTemplate") SqlSessionTemplate sqlMetricSessionTemplate) { + this.sqlMetricSessionTemplate = Objects.requireNonNull(sqlMetricSessionTemplate, "sqlSessionTemplate"); + } + + @Override + public List selectExcludedHostGroupNameList(String tenantId) { + return sqlMetricSessionTemplate.selectList(NAMESPACE + "selectExcludedHostGroupNames", tenantId); + } + + @Override + public void insertMetricHostGroupExclusion(String tenantId, String hostGroupName) { + sqlMetricSessionTemplate.insert(NAMESPACE + "insertHostGroupExclusion", new HostInfoSearchKey(tenantId, hostGroupName)); + } + + @Override + public void deleteMetricHostGroupExclusion(String tenantId, String hostGroupName) { + sqlMetricSessionTemplate.delete(NAMESPACE + "deleteHostGroupExclusion", new HostInfoSearchKey(tenantId, hostGroupName)); + } + + @Override + public List selectExcludedHostNameList(String tenantId, String hostGroupName) { + return sqlMetricSessionTemplate.selectList(NAMESPACE + "selectExcludedHostNames", new HostInfoSearchKey(tenantId, hostGroupName)); + } + + @Override + public void insertMetricHostExclusion(String tenantId, String hostGroupName, String hostName) { + sqlMetricSessionTemplate.insert(NAMESPACE + "insertHostExclusion", new HostInfoSearchKey(tenantId, hostGroupName, hostName)); + } + + @Override + public void deleteMetricHostExclusion(String tenantId, String hostGroupName, String hostName) { + sqlMetricSessionTemplate.delete(NAMESPACE + "deleteHostExclusion", new HostInfoSearchKey(tenantId, hostGroupName, hostName)); + } +} diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCache.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCache.java new file mode 100644 index 000000000000..04d7a6493671 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCache.java @@ -0,0 +1,43 @@ +package com.navercorp.pinpoint.metric.web.service; + + +import com.navercorp.pinpoint.metric.web.cache.MetricWebCacheConfiguration; +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostExclusionDao; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +@Component +public class SystemMetricHostExclusionCache { + private final Logger logger = LogManager.getLogger(this.getClass()); + private final SystemMetricHostExclusionDao systemMetricHostExclusionDao; + + public SystemMetricHostExclusionCache(SystemMetricHostExclusionDao systemMetricHostExclusionDao) { + this.systemMetricHostExclusionDao = Objects.requireNonNull(systemMetricHostExclusionDao, "systemMetricHostExclusionDao"); + } + + @Cacheable(cacheNames = "metricHostGroupExclusion", key = "#tenantId", cacheManager = MetricWebCacheConfiguration.METRIC_HOST_GROUP_EXCLUSION_CACHE_NAME) + public List getExcludedHostGroupNameList(String tenantId) { + try { + return systemMetricHostExclusionDao.selectExcludedHostGroupNameList(tenantId); + } catch (Exception e) { + logger.warn("error getting excludedHostGroupNameList, return empty list.", e); + return Collections.emptyList(); + } + } + + @Cacheable(cacheNames = "metricHostExclusion", key = "{#tenantId, #hostGroupName}", cacheManager = MetricWebCacheConfiguration.METRIC_HOST_EXCLUSION_CACHE_NAME) + public List getExcludedHostNameList(String tenantId, String hostGroupName) { + try { + return systemMetricHostExclusionDao.selectExcludedHostNameList(tenantId, hostGroupName); + } catch (Exception e) { + logger.warn("error getting excludedHostNameList, return empty list.", e); + return Collections.emptyList(); + } + } +} diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionService.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionService.java new file mode 100644 index 000000000000..16ebbdb658a9 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionService.java @@ -0,0 +1,18 @@ +package com.navercorp.pinpoint.metric.web.service; + +import com.navercorp.pinpoint.metric.web.view.SystemMetricHostGroupExclusionInfo; + +public interface SystemMetricHostExclusionService { + + SystemMetricHostGroupExclusionInfo getHostGroupExclusionInfo(String tenantId, String hostGroupName); + + void insertHostGroupExclusion(String tenantId, String hostGroupName); + + void insertHostExclusion(String tenantId, String hostGroupName, String hostName); + + void deleteHostGroupExclusion(String tenantId, String hostGroupName); + + void deleteHostExclusion(String tenantId, String hostGroupName, String hostName); + + void deleteUnusedHostExclusion(String tenantId, String hostGroupName); +} \ No newline at end of file diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImpl.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImpl.java new file mode 100644 index 000000000000..732edc8af01a --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImpl.java @@ -0,0 +1,62 @@ +package com.navercorp.pinpoint.metric.web.service; + +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostExclusionDao; +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostInfoDao; +import com.navercorp.pinpoint.metric.web.view.SystemMetricHostGroupExclusionInfo; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional(rollbackFor = {Exception.class}) +public class SystemMetricHostExclusionServiceImpl implements SystemMetricHostExclusionService { + + private final SystemMetricHostInfoDao systemMetricHostInfoDao; + private final SystemMetricHostExclusionDao systemMetricHostExclusionDao; + + public SystemMetricHostExclusionServiceImpl(SystemMetricHostInfoDao systemMetricHostInfoDao, SystemMetricHostExclusionDao systemMetricHostExclusionDao) { + this.systemMetricHostInfoDao = systemMetricHostInfoDao; + this.systemMetricHostExclusionDao = systemMetricHostExclusionDao; + } + + @Override + public SystemMetricHostGroupExclusionInfo getHostGroupExclusionInfo(String tenantId, String hostGroupName) { + List excludedHostGroupNames = systemMetricHostExclusionDao.selectExcludedHostGroupNameList(tenantId); + List excludedHostNames = systemMetricHostExclusionDao.selectExcludedHostNameList(tenantId, hostGroupName); + List hostNames = systemMetricHostInfoDao.selectHostList(tenantId, hostGroupName); + + return new SystemMetricHostGroupExclusionInfo(hostGroupName, hostNames, excludedHostGroupNames, excludedHostNames); + } + + @Override + public void insertHostGroupExclusion(String tenantId, String hostGroupName) { + systemMetricHostExclusionDao.insertMetricHostGroupExclusion(tenantId, hostGroupName); + } + + @Override + public void deleteHostGroupExclusion(String tenantId, String hostGroupName) { + systemMetricHostExclusionDao.deleteMetricHostGroupExclusion(tenantId, hostGroupName); + } + + @Override + public void insertHostExclusion(String tenantId, String hostGroupName, String hostName) { + systemMetricHostExclusionDao.insertMetricHostExclusion(tenantId, hostGroupName, hostName); + } + + @Override + public void deleteHostExclusion(String tenantId, String hostGroupName, String hostName) { + systemMetricHostExclusionDao.deleteMetricHostExclusion(tenantId, hostGroupName, hostName); + } + + @Override + public void deleteUnusedHostExclusion(String tenantId, String hostGroupName) { + List excludedHostNames = systemMetricHostExclusionDao.selectExcludedHostNameList(tenantId, hostGroupName); + List hostNames = systemMetricHostInfoDao.selectHostList(tenantId, hostGroupName); + for (String excludedHostName : excludedHostNames) { + if (!hostNames.contains(excludedHostName)) { + systemMetricHostExclusionDao.deleteMetricHostExclusion(tenantId, hostGroupName, excludedHostName); + } + } + } +} \ No newline at end of file diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImpl.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImpl.java index 6eeea823ba85..002cccc0428b 100644 --- a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImpl.java +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImpl.java @@ -42,11 +42,14 @@ public class SystemMetricHostInfoServiceImpl implements SystemMetricHostInfoServ private final SystemMetricHostInfoDao systemMetricHostInfoDao; private final YMLSystemMetricBasicGroupManager systemMetricBasicGroupManager; + private final SystemMetricHostExclusionCache systemMetricHostExclusionCache; public SystemMetricHostInfoServiceImpl(SystemMetricHostInfoDao systemMetricHostInfoDao, - YMLSystemMetricBasicGroupManager systemMetricBasicGroupManager) { + YMLSystemMetricBasicGroupManager systemMetricBasicGroupManager, + SystemMetricHostExclusionCache systemMetricHostExclusionCache) { this.systemMetricHostInfoDao = Objects.requireNonNull(systemMetricHostInfoDao, "systemMetricHostInfoDao"); this.systemMetricBasicGroupManager = Objects.requireNonNull(systemMetricBasicGroupManager, "systemMetricBasicGroupManager"); + this.systemMetricHostExclusionCache = Objects.requireNonNull(systemMetricHostExclusionCache, "systemMetricHostExclusionCache"); } @Override @@ -54,6 +57,9 @@ public List getHostGroupNameList(String tenantId) { List hostGroupNameList = systemMetricHostInfoDao.selectHostGroupNameList(tenantId); hostGroupNameList.sort(Comparator.naturalOrder()); + List excludedHostGroupList = systemMetricHostExclusionCache.getExcludedHostGroupNameList(tenantId); + hostGroupNameList.removeAll(excludedHostGroupList); + return hostGroupNameList; } @@ -62,6 +68,9 @@ public List getHostList(String tenantId, String hostGroupName) { List hostList = systemMetricHostInfoDao.selectHostList(tenantId, hostGroupName); hostList.sort(Comparator.naturalOrder()); + List excludedHostList = systemMetricHostExclusionCache.getExcludedHostNameList(tenantId, hostGroupName); + hostList.removeAll(excludedHostList); + return hostList; } diff --git a/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/view/SystemMetricHostGroupExclusionInfo.java b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/view/SystemMetricHostGroupExclusionInfo.java new file mode 100644 index 000000000000..ca425a297707 --- /dev/null +++ b/metric-module/metric/src/main/java/com/navercorp/pinpoint/metric/web/view/SystemMetricHostGroupExclusionInfo.java @@ -0,0 +1,59 @@ +package com.navercorp.pinpoint.metric.web.view; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class SystemMetricHostGroupExclusionInfo { + private final String hostGroupName; + private final List hostNames; + private final List excludedHostGroupNames; + private final List excludedHostNames; + + public SystemMetricHostGroupExclusionInfo(String hostGroupName, List hostNames, + List excludedHostGroupNames, List excludedHostNames) { + this.hostGroupName = Objects.requireNonNull(hostGroupName, "hostGroupName"); + this.hostNames = Objects.requireNonNull(hostNames, "hostNames"); + this.excludedHostGroupNames = Objects.requireNonNull(excludedHostGroupNames, "excludedHostGroupNames"); + this.excludedHostNames = Objects.requireNonNull(excludedHostNames, "excludedHostNames"); + } + + public String getHostGroupName() { + return hostGroupName; + } + + public boolean isExcluded() { + return excludedHostGroupNames.contains(hostGroupName); + } + + public List getHostExclusionInfoList() { + return hostNames.stream() + .sorted() + .map(hostName -> new SystemMetricHostExclusionInfo(hostName, excludedHostNames.contains(hostName))) + .collect(Collectors.toList()); + } + + public List getExcludedHostNameList() { + return excludedHostNames.stream() + .sorted() + .collect(Collectors.toList()); + } + + public static class SystemMetricHostExclusionInfo { + private final String hostName; + private final boolean excluded; + + public SystemMetricHostExclusionInfo(String hostName, boolean excluded) { + this.hostName = hostName; + this.excluded = excluded; + } + + public String getHostName() { + return hostName; + } + + public boolean isExcluded() { + return excluded; + } + } +} diff --git a/metric-module/metric/src/main/resources/pinot-web/mapper/mysql/MetricHostExclusionMapper.xml b/metric-module/metric/src/main/resources/pinot-web/mapper/mysql/MetricHostExclusionMapper.xml new file mode 100644 index 000000000000..585ee7359920 --- /dev/null +++ b/metric-module/metric/src/main/resources/pinot-web/mapper/mysql/MetricHostExclusionMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + INSERT INTO system_metric_host_group_exclusion (tenantId, hostGroupName) + VALUES (#{tenantId}, #{hostGroupName}) + ON DUPLICATE KEY UPDATE saveTime = CURRENT_TIMESTAMP + + + + DELETE + FROM system_metric_host_group_exclusion + WHERE tenantId = #{tenantId} + AND hostGroupName = #{hostGroupName} + + + + + + + INSERT INTO system_metric_host_exclusion (tenantId, hostGroupName, hostName) + VALUES (#{tenantId}, #{hostGroupName}, #{hostName}) + ON DUPLICATE KEY UPDATE saveTime = CURRENT_TIMESTAMP + + + + DELETE + FROM system_metric_host_exclusion + WHERE tenantId = #{tenantId} + AND hostGroupName = #{hostGroupName} + AND hostName = #{hostName} + + + diff --git a/metric-module/metric/src/main/resources/pinot-web/sql/MetricWebCreateTableStateMent-mysql.sql b/metric-module/metric/src/main/resources/pinot-web/sql/MetricWebCreateTableStateMent-mysql.sql new file mode 100644 index 000000000000..4ae7162be6b7 --- /dev/null +++ b/metric-module/metric/src/main/resources/pinot-web/sql/MetricWebCreateTableStateMent-mysql.sql @@ -0,0 +1,17 @@ +-- DROP TABLE system_metric_host_Group_exclusion; +-- DROP TABLE system_metric_host_exclusion; + +CREATE TABLE system_metric_host_Group_exclusion ( + tenantId VARCHAR(50), + hostGroupName VARCHAR(50), + saveTime DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(tenantId, hostGroupName) +); + +CREATE TABLE system_metric_host_exclusion ( + tenantId VARCHAR(50), + hostGroupName VARCHAR(50), + hostName VARCHAR(50), + saveTime DATETIME DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY(tenantId, hostGroupName, hostName) +); \ No newline at end of file diff --git a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCacheTest.java b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCacheTest.java new file mode 100644 index 000000000000..ca7bfed5c858 --- /dev/null +++ b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionCacheTest.java @@ -0,0 +1,65 @@ +package com.navercorp.pinpoint.metric.web.service; + +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostExclusionDao; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class SystemMetricHostExclusionCacheTest { + + SystemMetricHostExclusionCache systemMetricHostExclusionCache; + + @Mock + SystemMetricHostExclusionDao systemMetricHostExclusionDao; + + @BeforeEach + public void setUp() { + systemMetricHostExclusionCache = new SystemMetricHostExclusionCache(systemMetricHostExclusionDao); + } + + @Test + public void getHostGroupExclusionListTest() { + List excludedHostGroupNames = List.of("excludedHostGroupName"); + when(systemMetricHostExclusionDao.selectExcludedHostGroupNameList("tenantId")).thenReturn(excludedHostGroupNames); + + List result = systemMetricHostExclusionCache.getExcludedHostGroupNameList("tenantId"); + + assertThat(result).isEqualTo(excludedHostGroupNames); + } + + @Test + public void getHostGroupExclusionListErrorTest() { + when(systemMetricHostExclusionDao.selectExcludedHostGroupNameList("tenantId")).thenThrow(new RuntimeException("Test Exception")); + + List result = systemMetricHostExclusionCache.getExcludedHostGroupNameList("tenantId"); + + assertThat(result).isEmpty(); + } + + @Test + public void getHostExclusionListTest() { + List excludedHostNames = List.of("excludedHostName"); + when(systemMetricHostExclusionDao.selectExcludedHostNameList("tenantId", "hostGroupName")).thenReturn(excludedHostNames); + + List result = systemMetricHostExclusionCache.getExcludedHostNameList("tenantId", "hostGroupName"); + + assertThat(result).isEqualTo(excludedHostNames); + } + + @Test + public void getHostExclusionListErrorTest() { + when(systemMetricHostExclusionDao.selectExcludedHostNameList("tenantId", "hostGroupName")).thenThrow(new RuntimeException("Test Exception")); + + List result = systemMetricHostExclusionCache.getExcludedHostNameList("tenantId", "hostGroupName"); + + assertThat(result).isEmpty(); + } +} diff --git a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImplTest.java b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImplTest.java new file mode 100644 index 000000000000..510229b2948e --- /dev/null +++ b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostExclusionServiceImplTest.java @@ -0,0 +1,67 @@ +package com.navercorp.pinpoint.metric.web.service; + +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostExclusionDao; +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostInfoDao; +import com.navercorp.pinpoint.metric.web.view.SystemMetricHostGroupExclusionInfo; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class SystemMetricHostExclusionServiceImplTest { + + SystemMetricHostExclusionService systemMetricHostExclusionService; + + @Mock + SystemMetricHostInfoDao systemMetricHostInfoDao; + + @Mock + SystemMetricHostExclusionDao systemMetricHostExclusionDao; + + @BeforeEach + void setUp() { + systemMetricHostExclusionService = new SystemMetricHostExclusionServiceImpl(systemMetricHostInfoDao, systemMetricHostExclusionDao); + } + + @Test + public void getHostGroupExclusionInfoTest() { + when(systemMetricHostExclusionDao.selectExcludedHostGroupNameList("tenantId")).thenReturn(List.of("excludedHostName")); + when(systemMetricHostExclusionDao.selectExcludedHostNameList("tenantId", "hostGroupName")).thenReturn(List.of("excludedHostName")); + when(systemMetricHostInfoDao.selectHostList("tenantId", "hostGroupName")).thenReturn(List.of("hostName", "excludedHostName")); + + SystemMetricHostGroupExclusionInfo hostGroupResult = systemMetricHostExclusionService.getHostGroupExclusionInfo("tenantId", "hostGroupName"); + List hostResult = hostGroupResult.getHostExclusionInfoList(); + + assertThat(hostGroupResult.getHostGroupName()).isEqualTo("hostGroupName"); + assertThat(hostGroupResult.isExcluded()).isFalse(); + //sorted + assertThat(hostResult.get(0).getHostName()).isEqualTo("excludedHostName"); + assertThat(hostResult.get(0).isExcluded()).isTrue(); + assertThat(hostResult.get(1).getHostName()).isEqualTo("hostName"); + assertThat(hostResult.get(1).isExcluded()).isFalse(); + } + + @Test + public void deleteUnusedHostExclusionTest() { + when(systemMetricHostExclusionDao.selectExcludedHostNameList("tenantId", "hostGroupName")).thenReturn(List.of("liveHostName","deadHostName")); + when(systemMetricHostInfoDao.selectHostList("tenantId", "hostGroupName")).thenReturn(List.of("liveHostName")); + lenient().doNothing().when(systemMetricHostExclusionDao).deleteMetricHostExclusion("tenantId", "hostGroupName", "liveHostName"); + doNothing().when(systemMetricHostExclusionDao).deleteMetricHostExclusion("tenantId", "hostGroupName", "deadHostName"); + + systemMetricHostExclusionService.deleteUnusedHostExclusion("tenantId", "hostGroupName"); + + verify(systemMetricHostExclusionDao, never()).deleteMetricHostExclusion("tenantId", "hostGroupName", "liveHostName"); + verify(systemMetricHostExclusionDao).deleteMetricHostExclusion("tenantId", "hostGroupName", "deadHostName"); + } +} diff --git a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImplTest.java b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImplTest.java index 74dfd73b09cc..d5b7a716f708 100644 --- a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImplTest.java +++ b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/service/SystemMetricHostInfoServiceImplTest.java @@ -1,29 +1,77 @@ package com.navercorp.pinpoint.metric.web.service; import com.navercorp.pinpoint.metric.common.model.Tag; +import com.navercorp.pinpoint.metric.web.dao.SystemMetricHostInfoDao; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; /** * @author minwoo.jung */ + +@ExtendWith(MockitoExtension.class) public class SystemMetricHostInfoServiceImplTest { private final Logger logger = LogManager.getLogger(this.getClass()); + SystemMetricHostInfoService systemMetricHostInfoService; + + @Mock + SystemMetricHostInfoDao systemMetricHostInfoDao; + + @Mock + YMLSystemMetricBasicGroupManager ymlSystemMetricBasicGroupManager; + + @Mock + SystemMetricHostExclusionCache systemMetricHostExclusionCache; + + @BeforeEach + void setUp() { + systemMetricHostInfoService = new SystemMetricHostInfoServiceImpl(systemMetricHostInfoDao, ymlSystemMetricBasicGroupManager, systemMetricHostExclusionCache); + } + + @Test + public void hostGroupExclusionTest() { + List hostGroupNames = new ArrayList<>(); + hostGroupNames.add("hostGroupName1"); + hostGroupNames.add("hostGroupName2"); + + List excludedHostGroupNames = new ArrayList<>(); + excludedHostGroupNames.add("hostGroupName2"); + + when(systemMetricHostInfoDao.selectHostGroupNameList("tenantId")).thenReturn(hostGroupNames); + when(systemMetricHostExclusionCache.getExcludedHostGroupNameList("tenantId")).thenReturn(excludedHostGroupNames); + + List result = systemMetricHostInfoService.getHostGroupNameList("tenantId"); + + verify(systemMetricHostInfoDao).selectHostGroupNameList("tenantId"); + verify(systemMetricHostExclusionCache).getExcludedHostGroupNameList("tenantId"); + assertThat(result).isEqualTo(List.of("hostGroupName1")); + } + @Test - public void test() { - List tagList = List.of( - new Tag("key", "value") - ); + public void hostExclusionTest() { + List hostNames = new ArrayList<>(); + hostNames.add("hostName1"); + hostNames.add("hostName2"); + when(systemMetricHostInfoDao.selectHostList("tenantId", "hostGroupName")).thenReturn(hostNames); + when(systemMetricHostExclusionCache.getExcludedHostNameList("tenantId", "hostGroupName")).thenReturn(List.of("hostName1", "hostName3")); - List comparedTagList = new ArrayList<>(); + List result = systemMetricHostInfoService.getHostList("tenantId", "hostGroupName"); - assertThat(tagList).containsAll(comparedTagList); + verify(systemMetricHostInfoDao).selectHostList("tenantId", "hostGroupName"); + verify(systemMetricHostExclusionCache).getExcludedHostNameList("tenantId", "hostGroupName"); + assertThat(result).isEqualTo(List.of("hostName2")); } } \ No newline at end of file diff --git a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/utill/metric/TagUtilsTest.java b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/utill/metric/TagUtilsTest.java index 5b1900aeb5ab..4a438cc7aebf 100644 --- a/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/utill/metric/TagUtilsTest.java +++ b/metric-module/metric/src/test/java/com/navercorp/pinpoint/metric/web/utill/metric/TagUtilsTest.java @@ -5,12 +5,24 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; public class TagUtilsTest { + @Test + public void emptyListCompareTest() { + List tagList = List.of( + new Tag("key", "value") + ); + + List comparedTagList = new ArrayList<>(); + + assertThat(tagList).containsAll(comparedTagList); + } + @Test public void parseTagTest() { List tagList = List.of(