diff options
332 files changed, 17153 insertions, 10990 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 47c39ea2..084aed2e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ variables: NZ_DB_HOST: "192.168.44.23" NZ_DB_USER: "nezha" NZ_DB_PASSWORD: "nezha02" - NZ_DB_NAME: "nz-dev-3.5" + NZ_DB_NAME: "nz-dev-3.6" # 定义全局依赖的docker服务,即 这条流水线 pipeline 中的任务都用这里的服务 services: - mariadb:10.2.14 diff --git a/nz-admin/pom.xml b/nz-admin/pom.xml index 4e667d3d..18957523 100644 --- a/nz-admin/pom.xml +++ b/nz-admin/pom.xml @@ -253,10 +253,16 @@ <!-- <!– <scope>test</scope> –>--> <!-- </dependency>--> + <!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core --> <dependency> <groupId>org.flywaydb</groupId> <artifactId>flyway-core</artifactId> - <version>5.2.4</version> + <version>8.5.13</version> + </dependency> + <dependency> + <groupId>org.flywaydb</groupId> + <artifactId>flyway-mysql</artifactId> + <version>8.5.13</version> </dependency> <dependency> <groupId>com.github.oshi</groupId> @@ -337,6 +343,12 @@ <artifactId>javase</artifactId> <version>3.3.3</version> </dependency> + <!--解析 html--> + <dependency> + <groupId>org.jsoup</groupId> + <artifactId>jsoup</artifactId> + <version>1.14.1</version> + </dependency> </dependencies> <build> @@ -513,4 +525,4 @@ </plugin> </plugins> </build> -</project>
\ No newline at end of file +</project> diff --git a/nz-admin/src/main/java/com/nis/AdminApplication.java b/nz-admin/src/main/java/com/nis/AdminApplication.java index 2b9b3561..e39e1a21 100644 --- a/nz-admin/src/main/java/com/nis/AdminApplication.java +++ b/nz-admin/src/main/java/com/nis/AdminApplication.java @@ -1,19 +1,14 @@ package com.nis; -import java.util.TimeZone; - +import cn.hutool.core.util.StrUtil; +import com.nis.AdminApplication.SetupAutoConfiguration; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.EnvironmentAware; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; -import org.springframework.context.annotation.Import; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.context.annotation.PropertySource; +import org.springframework.context.annotation.*; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -21,10 +16,7 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -import com.nis.AdminApplication.SetupAutoConfiguration; -import com.nis.modules.terminal.config.TerminalHandler; - -import cn.hutool.core.util.StrUtil; +import java.util.TimeZone; @EnableTransactionManagement @SpringBootApplication(scanBasePackages = { "com.nis.setup" }) @@ -35,8 +27,7 @@ public class AdminApplication { public static void main(String[] args) { // 默认为 UTC 时区 TimeZone.setDefault(TimeZone.getTimeZone("UTC")); - ConfigurableApplicationContext run = SpringApplication.run(AdminApplication.class, args); - TerminalHandler.setApplicationContext(run); + SpringApplication.run(AdminApplication.class, args); } static class SetupAutoConfiguration implements ImportBeanDefinitionRegistrar, EnvironmentAware { diff --git a/nz-admin/src/main/java/com/nis/common/aspect/SysLogAspect.java b/nz-admin/src/main/java/com/nis/common/aspect/SysLogAspect.java index 986a171c..e25df37d 100644 --- a/nz-admin/src/main/java/com/nis/common/aspect/SysLogAspect.java +++ b/nz-admin/src/main/java/com/nis/common/aspect/SysLogAspect.java @@ -181,7 +181,12 @@ public class SysLogAspect { String operationType = syslog.operation().getValue(); // 获取执行结果 - R r = (R) result; + R r = R.ok(); + if (result instanceof Map) { + Tool.BeanUtil.copyProperties(result, r, true); + } else { + r = (R) result; + } // 注解上的描述 sysLog.setOperation(operationType); diff --git a/nz-admin/src/main/java/com/nis/common/config/FlywayConfig.java b/nz-admin/src/main/java/com/nis/common/config/FlywayConfig.java index d3946922..235c144b 100644 --- a/nz-admin/src/main/java/com/nis/common/config/FlywayConfig.java +++ b/nz-admin/src/main/java/com/nis/common/config/FlywayConfig.java @@ -1,18 +1,11 @@ package com.nis.common.config; -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.PostConstruct; -import javax.sql.DataSource; - +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import org.apache.commons.lang3.time.StopWatch; import org.flywaydb.core.Flyway; -import org.flywaydb.core.api.FlywayException; +import org.flywaydb.core.api.callback.Callback; import org.flywaydb.core.api.configuration.FluentConfiguration; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; @@ -21,86 +14,110 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; -import com.nis.common.update.VersionUpdateInterface; -import com.nis.common.utils.Tool; - -import cn.hutool.core.util.ReflectUtil; -import cn.hutool.log.Log; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Configuration @DependsOn(value = {"dataSourceConfig"}) -public class FlywayConfig implements ApplicationContextAware{ +public class FlywayConfig implements ApplicationContextAware { + + private static final Log log = Log.get(); - private static Log log = Log.get(); + private List<Callback> migrateCallbackList; @Autowired private DataSource dataSource; @Autowired private FlywayProperties flywayProperties; - - private Collection<VersionUpdateInterface> versionUpdateBeans; - + @PostConstruct public void migrate() { - + log.info("[FlywayConfig] [migrate] [enable: {}]", flywayProperties.getEnabled()); if (!flywayProperties.getEnabled()) { + log.warn("[FlywayConfig] [migrate] [not enabled, do not execute flyway migrate]"); return; } - Map<String, String> map = new HashMap<String, String>(); + // build Fluent Configuration + FluentConfiguration configure = this.buildFluentConfiguration(); + + log.info("[FlywayConfig] [flyway migrate] [begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + Flyway flyway = configure.load(); + try { + flyway.migrate(); + } catch (Exception e) { + log.error(e, "[FlywayConfig] [migrate error.]"); + + // repair + flyway.repair(); + + // 停止服务,避免 systemd 服务重启机制,覆盖 flyway + Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); + } finally { + // stop + sw.stop(); + } + log.info("[FlywayConfig] [flyway migrate] [finshed] [Run time: {}]", sw.toString()); + } + + /** + * build Fluent Configuration + * + * @return A FluentConfiguration Object + */ + private FluentConfiguration buildFluentConfiguration() { + log.info("[buildFluentConfiguration] [begin]"); + + Map<String, String> configMap = Tool.MapUtil.newHashMap(); try { BeanInfo beanInfo = Introspector.getBeanInfo(flywayProperties.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); if (!"class".equals(key) && !"enabled".equals(key)) { - //Method getter = property.getReadMethod(); - //Object value = getter.invoke(flywayProperties); Object value = ReflectUtil.invoke(flywayProperties, property.getReadMethod(), key); - map.put("flyway." + key, value.toString()); + configMap.put("flyway." + key, value.toString()); } } } catch (IntrospectionException e) { - log.error("flyway执行脚本失败", e); + log.error(e, "[buildFluentConfiguration] [error]"); } FluentConfiguration configure = Flyway.configure(); configure.dataSource(dataSource); - configure.configuration(map); - Flyway flyway = configure.load(); - try { - flyway.migrate(); - } catch (FlywayException e) { - flyway.repair(); - log.error("Flyway migrate error,shutdown service{}", e); - // 停止服务,避免systemd服务重启机制,覆盖flyway - Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); - } - - if(Tool.CollUtil.isNotEmpty(versionUpdateBeans)) { - versionUpdateBeans.forEach((vu)->{ - //执行update 操作 - log.debug("version update start,name: {}",vu.getClass().getSimpleName()); - vu.update(); - log.debug("version update end,name: {}",vu.getClass().getSimpleName()); - }); + configure.configuration(configMap); + + // callbacks + log.info("[buildFluentConfiguration] [migrate callbacks List] [size: {}]", migrateCallbackList.size()); + if (Tool.CollUtil.isNotEmpty(migrateCallbackList)) { + log.info("[buildFluentConfiguration] [configure migrate callbacks]"); + configure.callbacks(migrateCallbackList.stream().toArray(Callback[]::new)); } + + log.info("[buildFluentConfiguration] [finshed]"); + return configure; } - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - //根据接口类型返回相应的所有bean - Map<String,VersionUpdateInterface> map = applicationContext.getBeansOfType(VersionUpdateInterface.class); - versionUpdateBeans = map.values(); - log.debug("version update size: {}",Tool.CollUtil.size(versionUpdateBeans)); - if(Tool.CollUtil.isNotEmpty(versionUpdateBeans)) { - //按照 class name 排序 - versionUpdateBeans = Tool.CollUtil.sort(versionUpdateBeans, (v1,v2)->{ - String name1 = v1.getClass().getSimpleName(); - String name2 = v2.getClass().getSimpleName(); - return name1.compareTo(name2); - }); - } - } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // org.flywaydb.core.api.callback; + Map<String, Callback> callbackMap = applicationContext.getBeansOfType(Callback.class); + callbackMap = Tool.MapUtil.defaultIfEmpty(callbackMap, Tool.MapUtil.newHashMap()); + + List<Callback> callbackList = callbackMap.values().stream().collect(Collectors.toList()); + migrateCallbackList = Tool.CollUtil.defaultIfEmpty(callbackList, Tool.ListUtil.list(true)); + if (log.isDebugEnabled()) { + log.debug("[FlywayConfig] [Migrate Callback List] [size: {}]", migrateCallbackList.size()); + } + } } diff --git a/nz-admin/src/main/java/com/nis/common/config/FlywayProperties.java b/nz-admin/src/main/java/com/nis/common/config/FlywayProperties.java index 88cb7684..e6cea836 100644 --- a/nz-admin/src/main/java/com/nis/common/config/FlywayProperties.java +++ b/nz-admin/src/main/java/com/nis/common/config/FlywayProperties.java @@ -34,4 +34,4 @@ public class FlywayProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } -}
\ No newline at end of file +} diff --git a/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java b/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java index 2cd6f384..bf5d127c 100644 --- a/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java +++ b/nz-admin/src/main/java/com/nis/common/config/SetupRunner.java @@ -10,8 +10,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.Constant; import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualPanelService; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.utils.DashboardConstant; import com.nis.modules.report.job.ReportJobManager; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.job.SysBackJobManager; @@ -68,7 +69,7 @@ public class SetupRunner implements CommandLineRunner{ SysBackJobManager sysBackJobManager; @Autowired - VisualPanelService visualPanelService; + VisualDashboardService dashboardService; @Autowired private VsysTaskConfigThread vsysTaskConfigThread; @@ -85,15 +86,15 @@ public class SetupRunner implements CommandLineRunner{ } log.info("Setup inited {}", inited); - // 加载已有 panel report job type = DASHBOARD + // 加载已有 dashboard report job type = DASHBOARD log.info("Setup dashboard report job begin..."); - List<VisualPanel> panelList = visualPanelService.list(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.DASHBOARD.getValue())); - for (VisualPanel panel : panelList) { - Map paramMap = JSONObject.parseObject(panel.getParam().toString(), Map.class); + List<VisualDashboard> dashboardList = dashboardService.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, DashboardConstant.Type.DASHBOARD.getValue())); + for (VisualDashboard dashboard : dashboardList) { + Map paramMap = JSONObject.parseObject(dashboard.getParam().toString(), Map.class); if (Tool.MapUtil.isNotEmpty(paramMap)) { - String reportEnable = JSONPath.read(panel.getParam().toString(), "report.enable").toString(); + String reportEnable = JSONPath.read(dashboard.getParam().toString(), "report.enable").toString(); if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { - reportJobManager.createReportJob(panel.getParam().toString(), panel.getId().toString()); + reportJobManager.createReportJob(dashboard.getParam().toString(), dashboard.getId().toString()); } } } diff --git a/nz-admin/src/main/java/com/nis/common/interceptor/ResultHandleInterceptor.java b/nz-admin/src/main/java/com/nis/common/interceptor/ResultHandleInterceptor.java index 0a077593..a0834fe3 100644 --- a/nz-admin/src/main/java/com/nis/common/interceptor/ResultHandleInterceptor.java +++ b/nz-admin/src/main/java/com/nis/common/interceptor/ResultHandleInterceptor.java @@ -74,14 +74,16 @@ public class ResultHandleInterceptor implements ResponseBodyAdvice { public Map<String,List<String>> contentFieldHandle(String param){ Map<String,List<String>> result = new HashMap<String,List<String>>(); - String[] split = StrUtil.split(param, ";"); - for(String s : split) { - String[] split2 = StrUtil.split(s, "="); - String fields = split2[1]; - List<String> filedList = StrUtil.split(fields, StrUtil.C_COMMA); - result.put(split2[0],filedList); - } - // include优先级高于exclude 去除exclude中间无用数值 + if (StrUtil.isNotEmpty(param)) { + List<String> split = StrUtil.split(param, ";"); + for (String s : split) { + List<String> split2 = StrUtil.split(s, "="); + String fields = split2.get(1); + List<String> filedList = StrUtil.split(fields, StrUtil.C_COMMA); + result.put(split2.get(0), filedList); + } + } + // include优先级高于exclude 去除exclude中间无用数值 if(ToolUtil.equals(result.size(), 2)) { /*List<String> includeFields = (List<String>) result.get(INCLUDE); List<String> excludeFields = (List<String>) result.get(EXCLUDE); @@ -146,20 +148,20 @@ public class ResultHandleInterceptor implements ResponseBodyAdvice { } for(String field : fields) { if(field.contains(StrUtil.DOT)) { - String[] split = StrUtil.split(field, StrUtil.DOT); - String attributeName = split[0]; + List<String> split = StrUtil.split(field, StrUtil.DOT); + String attributeName = split.get(0); Field declaredField = clazz.getDeclaredField(attributeName); Class<?> attributeType = declaredField.getType(); List<String> list = filterMap.get(attributeType); if(!isExclude) { - filterMap.get(clazz).add(split[0]); + filterMap.get(clazz).add(split.get(0)); } if(ToolUtil.isEmpty(list)) { List<String> s = new ArrayList<String>(); - s.add(split[1]); + s.add(split.get(1)); filterMap.put(attributeType, s); }else { - list.add(split[1]); + list.add(split.get(1)); } }else { filterMap.get(clazz).add(field); diff --git a/nz-admin/src/main/java/com/nis/common/job/JobConfig.java b/nz-admin/src/main/java/com/nis/common/job/JobConfig.java index d96af3b1..60c09afc 100644 --- a/nz-admin/src/main/java/com/nis/common/job/JobConfig.java +++ b/nz-admin/src/main/java/com/nis/common/job/JobConfig.java @@ -2,6 +2,7 @@ package com.nis.common.job; import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; +import com.nis.common.utils.Tool; import com.nis.modules.agent.job.AgentHealthCheckJob; import com.nis.modules.agent.job.AutoConfigAgentJob; import com.nis.modules.agent.job.CortexHistoryDataDelJob; @@ -14,10 +15,12 @@ import com.nis.modules.alert.job.AlertMessageHistoryPartitionManagementJob; import com.nis.modules.asset.job.AssetFeatureJob; import com.nis.modules.asset.job.AssetPingStatusJob; import com.nis.modules.asset.job.AssetTalonStatusJob; -import com.nis.modules.endpoint.job.EndpointStateJob; +import com.nis.modules.endpoint.job.MetricTypeEndpointStatusJob; import com.nis.modules.sys.job.CleanJob; import com.nis.modules.sys.job.SessionTimeOutJob; import com.nis.modules.sys.job.SysComponentJob; +import com.nis.modules.terminal.job.CleanExpiredTerminalRecordDataJob; +import com.nis.modules.terminal.job.CleanNoRealUseTerminalConnJob; import org.apache.commons.lang.StringUtils; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; @@ -88,8 +91,14 @@ public class JobConfig { @Value("${nezha.recordtRuleManagerJobCron:0/10 * * * * ?}") private String recordtRuleManagerJobCron; - - @Autowired + + @Value("${nezha.cleanNoRealUseTerminalConnJobCron:0 0/5 * * * ? *}") + private String cleanNoRealUseTerminalConnJobCron; + + @Value("${nezha.cleanExpiredTerminalRecordDataJobCron:0 0 1 * * ?}") + private String cleanExpiredTerminalRecordDataJobCron; + + @Autowired private Scheduler scheduler; // @Qualifier("costomSchedulerFactoryBean") //private SchedulerFactoryBean schedulerFactoryBean; @@ -111,7 +120,9 @@ public class JobConfig { private String lokiHistoryDataDelJobName = "LOKIHISTORYDATADELJOB_JOB"; private String alertMessageHistoryPartManJobName = "ALERTMESSAGEHISTORYPARTMAN_JOB"; private String recordtRuleManagerJobName = "RECORDTRULEMANAGER_JOB"; - + private String cleanNoRealUseTerminalConnJobName = "CLEANNOREALUSETERMINALCONN_JOB"; + private String cleanExpiredTerminalRecordDataJob = "CLEAN_EXPIRED_TERMINAL_RECORD_DATA_JOB"; + @Bean public JobDetail agentCronJobDetail() { return JobBuilder.newJob(AutoConfigAgentJob.class).withIdentity(JOB_NAME + agentJobName).storeDurably().build(); @@ -144,7 +155,7 @@ public class JobConfig { @Bean public JobDetail endpointStateJobDetail() { - return JobBuilder.newJob(EndpointStateJob.class).withIdentity(JOB_NAME + endpointStateJobName).storeDurably().build(); + return JobBuilder.newJob(MetricTypeEndpointStatusJob.class).withIdentity(JOB_NAME + endpointStateJobName).storeDurably().build(); } @Bean @@ -196,7 +207,17 @@ public class JobConfig { public JobDetail recordtRuleManagerJobDetail() { return JobBuilder.newJob(RecordManagerJob.class).withIdentity(JOB_NAME + recordtRuleManagerJobName).storeDurably().build(); } - + + @Bean + public JobDetail cleanNoRealUseTerminalConnJobDetail() { + return JobBuilder.newJob(CleanNoRealUseTerminalConnJob.class).withIdentity(JOB_NAME + cleanNoRealUseTerminalConnJobName).storeDurably().build(); + } + + @Bean + public JobDetail cleanExpiredTerminalRecordDataJobDetail() { + return JobBuilder.newJob(CleanExpiredTerminalRecordDataJob.class).withIdentity(JOB_NAME + cleanExpiredTerminalRecordDataJob).storeDurably().build(); + } + @PostConstruct public void init() throws SchedulerException { // agent 健康检查定时任务 @@ -250,6 +271,12 @@ public class JobConfig { // record rule 配置管理任务 createCronScheduleJob(recordtRuleManagerJobName, recordtRuleManagerJobDetail(), StringUtils.isEmpty(recordtRuleManagerJobCron) ? "0/10 * * * * ?" : recordtRuleManagerJobCron); + + // 清理没有真实使用的 terminal ssh/telnet 连接,以超过最后数据交互时间 30 分钟为准 (sys_config.session_timeout) + createCronScheduleJob(cleanNoRealUseTerminalConnJobName, cleanNoRealUseTerminalConnJobDetail(), StringUtils.isEmpty(cleanNoRealUseTerminalConnJobCron) ? "0 0/5 * * * ? *" : cleanNoRealUseTerminalConnJobCron); + + // terminal record expired data clean job + createCronScheduleJob(cleanExpiredTerminalRecordDataJob, cleanExpiredTerminalRecordDataJobDetail(), Tool.StrUtil.emptyToDefault(cleanExpiredTerminalRecordDataJobCron, "0 0 1 * * ?")); } /** diff --git a/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java b/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java index 7aadeeab..ec03aa2c 100644 --- a/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java +++ b/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java @@ -95,21 +95,21 @@ public class RedisCacheSubscribe implements MessageListener{ log.info("Report consumer message, report begin ..."); log.info("consumer message :{}", value); String reportEnable = JSONPath.read(value, "report.enable").toString(); - String panelId = JSONPath.read(value, "panelId").toString(); + String dashboardId = JSONPath.read(value, "dashboardId").toString(); if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { try { - reportJobManager.delJobByName(panelId); - reportJobManager.createReportJob(value, panelId); + reportJobManager.delJobByName(dashboardId); + reportJobManager.createReportJob(value, dashboardId); log.info("createReportJob success."); } catch (SchedulerException e) { - log.error("report job create or update error,panelId:{}", e, panelId); + log.error("report job create or update error,dashboardId:{}", e, dashboardId); } } else { try { - reportJobManager.delJobByName(panelId); + reportJobManager.delJobByName(dashboardId); } catch (SchedulerException e) { - log.error("delete report job error, panelId:{}", panelId, e); + log.error("delete report job error, dashboardId:{}", dashboardId, e); } } log.info("Report consumer message, report finished"); diff --git a/nz-admin/src/main/java/com/nis/common/update/DataFormatConversionInterface.java b/nz-admin/src/main/java/com/nis/common/update/DataFormatConversionInterface.java new file mode 100644 index 00000000..44ccf914 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/common/update/DataFormatConversionInterface.java @@ -0,0 +1,40 @@ +package com.nis.common.update; + +import cn.hutool.db.DbUtil; +import cn.hutool.db.SqlConnRunner; +import cn.hutool.log.Log; + +import java.sql.Connection; + +/** + * Data Format Conversion Interface + * + * @author shizhendong + * @date 2023/03/15 + */ +public interface DataFormatConversionInterface { + + Log log = Log.get(); + + /** + * init Sql Runner + * + * @param connection + * @return + */ + default SqlConnRunner initSqlRunner(Connection connection) { + log.info("[initSqlRunner] [begin]"); + SqlConnRunner sqlConnRunner = DbUtil.newSqlConnRunner(connection); + log.info("[initSqlRunner] [finshed]"); + return sqlConnRunner; + } + + /** + * data Format Conversion + * + * @param connection + * @throws Exception + */ + void dataFormatConversion(Connection connection) throws Exception; + +} diff --git a/nz-admin/src/main/java/com/nis/common/update/VersionUpdateInterface.java b/nz-admin/src/main/java/com/nis/common/update/VersionUpdateInterface.java deleted file mode 100644 index 8f710d2e..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/VersionUpdateInterface.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.nis.common.update; - -import cn.hutool.log.Log; -import com.nis.common.utils.Tool; - -public interface VersionUpdateInterface { - static final Log log = Log.get(); - /** - * 版本升级前操作内容 - * @return - */ - default boolean preUpdate() { - return true; - }; - - /** - * 执行版本升级 - */ - void excute() throws Exception; - - /** - * 版本升级 - * 1、升级前准备工作 - * 2、开始升级 - * 3、释放资源 - */ - default void update() { - try { - boolean pre = preUpdate(); - log.debug("prehandle result: {}", pre); - if (pre) { - excute(); - } - } catch (Exception e) { - onException(e); - } finally { - afterUpdate(); - } - }; - - default void onException(Exception e) { - log.error(e, "version update error,shutdown service"); - // 停止服务 - Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); - } - - - /** - * 升级后操作,可用于释放资源 - */ - default void afterUpdate() { - - }; - -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2Update.java b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2Update.java deleted file mode 100644 index bb0d235e..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2Update.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.nis.common.update.v3_0_to_3_2; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.nis.common.update.VersionUpdateInterface; -import com.nis.common.update.v3_0_to_3_2.service.DataFormatConversionService; - -/** - * 记录升级内容 - * 1、类名按照 版本号定义,如:V3_2_1 ,实际版本为 3.2.1 - * 2、flyway执行后将 按照 类名顺序执行 - * - */ -@Component -public class V3_2Update implements VersionUpdateInterface { - - @Autowired - private DataFormatConversionService service; - - @Override - public boolean preUpdate() { - - return VersionUpdateInterface.super.preUpdate(); - } - - @Override - public void excute() throws Exception { - service.visualChartDataFormatConversion(); - } - -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2_MigrateNotifierCallback.java b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2_MigrateNotifierCallback.java new file mode 100644 index 00000000..4903e13b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/V3_2_MigrateNotifierCallback.java @@ -0,0 +1,112 @@ +package com.nis.common.update.v3_0_to_3_2; + +import cn.hutool.log.Log; +import com.nis.common.update.v3_0_to_3_2.service.V3_2_DataFormatConversionService; +import com.nis.common.utils.Tool; +import org.apache.commons.lang3.time.StopWatch; +import org.flywaydb.core.api.MigrationInfo; +import org.flywaydb.core.api.MigrationVersion; +import org.flywaydb.core.api.callback.Callback; +import org.flywaydb.core.api.callback.Context; +import org.flywaydb.core.api.callback.Event; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.Connection; + +/** + * V3_2_MigrateNotifierCallback + * Flyway V2021.12.14__backup and add new visual_chart table.sql 回调类 + * 用于处理 3.0 - 3.2 visual_chart 表数据转换 + * <p> + * 1. 自动添加 chart element name + * 2. 根据图表类型处理 param 内容 + * 3. chart 新增 datasource + * 4. 删除 alertList 类型图表 + * + * @author shizhendong + * @date 2023/03/15 + */ +@Component +@Transactional +public class V3_2_MigrateNotifierCallback implements Callback { + + private static final Log log = Log.get(); + + /** + * callback_version: V2021.12.14__backup and add new visual_chart table.sql + */ + private static final String CALLBACK_VERSION = "2021.12.14"; + + @Autowired + private V3_2_DataFormatConversionService v3_2_dataFormatConversionService; + + @Override + public String getCallbackName() { + return "V3_2_MigrateNotifierCallback"; + } + + /** + * Not relevant if we don't interact with the database + * + * @param event + * @param context + * @return + */ + @Override + public boolean canHandleInTransaction(Event event, Context context) { + return true; + } + + /** + * Ensures that this callback handles events + * + * @param event + * @param context + * @return + */ + @Override + public boolean supports(Event event, Context context) { + // afterEachMigrate + if (Tool.ObjectUtil.equal(event, Event.AFTER_EACH_MIGRATE)) { + MigrationInfo migrationInfo = context.getMigrationInfo(); + MigrationVersion version = migrationInfo.getVersion(); + if (Tool.ObjectUtil.isNotNull(version)) { + if (Tool.StrUtil.equals(CALLBACK_VERSION, version.getVersion())) { + return true; + } + } + } + return false; + } + + /** + * Process data upgrade + * + * @param event + * @param context + */ + @Override + public void handle(Event event, Context context) { + log.info("[V3_2_MigrateNotifierCallback] [Data Format Conversion Begin] [migrate version: {}]", CALLBACK_VERSION); + + StopWatch sw = new StopWatch(); + sw.start(); + + try { + Connection connection = context.getConnection(); + // data Format Conversion + v3_2_dataFormatConversionService.dataFormatConversion(connection); + } catch (Exception e) { + log.error(e, "[V3_2_MigrateNotifierCallback] [error] [shutdown nz-web.service]"); + // 停止服务 + Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); + } finally { + sw.stop(); + } + + log.info("[V3_2_MigrateNotifierCallback] [Data Format Conversion Finshed] [Run time: {}]", sw.toString()); + } + +} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/dao/V3_0VisualChartDao.java b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/dao/V3_0VisualChartDao.java deleted file mode 100644 index 79e9c4e6..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/dao/V3_0VisualChartDao.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.nis.common.update.v3_0_to_3_2.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nis.modules.panel.entity.VisualChart; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Map; - -@Mapper -@Repository -public interface V3_0VisualChartDao extends BaseMapper<VisualChart> { - - Map checkTableExists(@Param("tableName") String tableName); - - List<VisualChart> queryList(); - - void dropTable(@Param("tableName")String tableName); -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/DataFormatConversionService.java b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/DataFormatConversionService.java deleted file mode 100644 index 96f6ff67..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/DataFormatConversionService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.nis.common.update.v3_0_to_3_2.service; - -public interface DataFormatConversionService { - - /** - * 3.0 - 3.2 visual_chart 表数据转换 - */ - void visualChartDataFormatConversion() throws Exception; - -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/impl/DataFormatConversionServiceImpl.java b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/V3_2_DataFormatConversionService.java index 6730060e..fcfb2e4d 100644 --- a/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/impl/DataFormatConversionServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/common/update/v3_0_to_3_2/service/V3_2_DataFormatConversionService.java @@ -1,123 +1,183 @@ -package com.nis.common.update.v3_0_to_3_2.service.impl; +package com.nis.common.update.v3_0_to_3_2.service; -import cn.hutool.core.map.MapUtil; +import cn.hutool.db.Entity; +import cn.hutool.db.SqlConnRunner; +import cn.hutool.db.handler.EntityListHandler; +import cn.hutool.db.handler.StringHandler; +import cn.hutool.db.sql.SqlExecutor; import cn.hutool.log.Log; +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.fastjson.JSONObject; -import com.nis.common.update.v3_0_to_3_2.dao.V3_0VisualChartDao; -import com.nis.common.update.v3_0_to_3_2.service.DataFormatConversionService; +import com.nis.common.exception.NZException; +import com.nis.common.update.DataFormatConversionInterface; import com.nis.common.utils.Constant; +import com.nis.common.utils.JSONUtil; +import com.nis.common.utils.RCode; import com.nis.common.utils.Tool; -import com.nis.modules.panel.dao.VisualChartDao; -import com.nis.modules.panel.dao.VisualChartElementDao; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualChartElement; -import org.apache.commons.lang3.time.StopWatch; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.sql.Connection; +import java.sql.SQLException; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; +/** + * V3_2_DataFormatConversionServiceImpl + * + * @author shizhendong + * @date 2023/03/15 + */ @Service -public class DataFormatConversionServiceImpl implements DataFormatConversionService { +public class V3_2_DataFormatConversionService implements DataFormatConversionInterface { - private static cn.hutool.log.Log logger = Log.get(); + private static final Log log = Log.get(); - @Autowired - private V3_0VisualChartDao v3_0VisualChartDao; + /** + * back up table name + */ + private static final String BACK_UP_TABLE_NAME = "visual_chart_v3_2"; - @Autowired - private VisualChartDao visualChartDao; + private Connection connection; - @Autowired - private VisualChartElementDao visualChartElementDao; + private SqlConnRunner sqlRunner; - static String[] LETTERS = new String[]{ + private static final String[] LETTERS = new String[]{ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; + /** + * before Data Format Conversion + * check backup table is exists + * + * @return + */ + private boolean beforeDataFormatConversion() throws SQLException { + String tableName = SqlExecutor.query(this.connection, "SHOW TABLES LIKE ?", new StringHandler(), BACK_UP_TABLE_NAME); + log.info("[beforeDataFormatConversion] [check the backup table exists] [query result: {}]", tableName); + + if (Tool.StrUtil.isEmpty(tableName)) { + log.warn("[beforeDataFormatConversion] [The backup table does not exist. Do not perform data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return true; + } + + log.info("[beforeDataFormatConversion] [The backup table exists, execute data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return true; + } + + @Override - public void visualChartDataFormatConversion() throws Exception { - // 1. 检查 visual_chart_V3_2 是否存在 - Map checkTableExists = v3_0VisualChartDao.checkTableExists("visual_chart_v3_2"); - if (Tool.CollectionUtil.isEmpty(checkTableExists)) { - logger.info("Table visual_chart_v3_2 does not exist. The chart data format processing will not be executed"); + public void dataFormatConversion(Connection connection) throws Exception { + // init sql conn runner + this.connection = connection; + sqlRunner = this.initSqlRunner(connection); + + boolean isConversion = this.beforeDataFormatConversion(); + if (!isConversion) { return; } - logger.info("Table visual_chart_v3_2 exists, execute chart data format processing"); - - StopWatch sw = new StopWatch(); - sw.start(); - try { - logger.info("Start processing visual_chart_element data and supplement the element name value."); - // 2. handle visual_chart_element name value (先处理 element name ,table chart handle 需要使用) - this.handleElementName(); - logger.info("The visual_chart_element name processing done."); - - // 3. 处理数据变化 - List<VisualChart> oldChartList = v3_0VisualChartDao.queryList(); - - // 再查询 element 内容,此时 name 已处理完成 - List<VisualChartElement> visualChartElements = visualChartElementDao.selectList(null); - Map<Integer, List<VisualChartElement>> chartIdAndElementListMap = visualChartElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); - - logger.info("Start processing visual_chart data format changes."); - // 排除 alertList ,alertList drop - Map<Integer, List<VisualChart>> oldChartListGroupByPanelId = oldChartList.stream().filter(visualChart -> !Tool.StrUtil.equals(visualChart.getType(), "alertList")).collect(Collectors.groupingBy(VisualChart::getPanelId)); - for (Map.Entry<Integer, List<VisualChart>> entry : oldChartListGroupByPanelId.entrySet()) { - Integer panelId = entry.getKey(); - List<VisualChart> oldChartListByPanelId = entry.getValue(); - - // 处理 chart param/datasource - this.handleChartParamFormat(oldChartListByPanelId, chartIdAndElementListMap); - - // 处理 xy 值 - this.handlePosition(panelId, oldChartListByPanelId); - - // 入库 visual_chart (新表) - visualChartDao.insertBatchChart(oldChartListByPanelId); - } - logger.info("The visual_chart data format change processing done."); - // 4. 删除 visual_chart_v3_2 表 - v3_0VisualChartDao.dropTable("visual_chart_v3_2"); - } finally { - sw.stop(); - } - logger.info("visual_chart data format conversion done Run Time: {}", sw.toString()); + + log.info("[dataFormatConversion] [conversion V3_0 to V3_2 Chart Data]"); + + // handle visual_chart_element name + this.handleElementName(); + + // conversion Visual Chart Data + this.conversionVisualChartData(); + + // remove back up table + log.info("[dataFormatConversion] [remove back up table] [table_name: {}]", BACK_UP_TABLE_NAME); + SqlExecutor.execute(this.connection, Tool.StrUtil.concat(true, "DROP TABLE ", BACK_UP_TABLE_NAME)); } /** - * chart element name 处理 初始化按照 每个chart数据 A-Z AA-AZ BA-BZ AAA-AAZ 顺序添加 + * chart element name 处理 + * 初始化规则: A-Z AA-AZ BA-BZ AAA-AAZ 顺序添加 */ - public void handleElementName() { - List<VisualChartElement> visualChartElements = visualChartElementDao.selectList(null); - Map<Integer, List<VisualChartElement>> collect = visualChartElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); - for (Map.Entry<Integer, List<VisualChartElement>> entry : collect.entrySet()) { - List<VisualChartElement> elementList = entry.getValue(); - for (int i = 0; i < elementList.size(); i++) { + private void handleElementName() throws SQLException { + log.info("[handleElementName] [insert chart element name auto] [begin]"); + log.info("[handleElementName] [insert chart element name auto] [rule: {}]", "A-Z AA-AZ BA-BZ AAA-AAZ..."); + + List<Entity> chartElementList = sqlRunner.findAll(this.connection, Entity.create("visual_chart_element")); + Map<Object, List<Entity>> elementGroupingByChartIdMap = chartElementList.stream().collect(Collectors.groupingBy(entity -> entity.get("chart_id"))); + for (Map.Entry<Object, List<Entity>> entry : elementGroupingByChartIdMap.entrySet()) { + List<Entity> elementListForChart = entry.getValue(); + for (int i = 0; i < elementListForChart.size(); i++) { String letter = this.transformNumToLetter(i); - VisualChartElement visualChartElement = elementList.get(i); - visualChartElement.setName(letter); + Entity chartElement = elementListForChart.get(i); + chartElement.set("name", letter); } } - List<VisualChartElement> allElementList = collect.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); - // visualChartElementService.saveOrUpdateBatch(allElementList); - if (Tool.CollectionUtil.isNotEmpty(allElementList)) { - // visualChartElementDao xml sql 为 updaet xx set name case when ... where id in xxx. 组合,防止 sql 过长,分割后拼接 sql 修改 + List<Entity> allElementList = elementGroupingByChartIdMap.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + log.info("[handleElementName] [update element size: {}]", allElementList.size()); + if (Tool.CollUtil.isNotEmpty(allElementList)) { + // 防止 sql 过长,分割后拼接 sql 修改 Integer batchSize = 1000; Integer limit = (allElementList.size() + batchSize - 1) / batchSize; - List<List<VisualChartElement>> splitVisualChartElementList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> allElementList.stream().skip(a * batchSize).limit(batchSize).parallel().collect(Collectors.toList())).collect(Collectors.toList()); - for (List<VisualChartElement> elements : splitVisualChartElementList) { - visualChartElementDao.updateNameBatch(elements); + List<List<Entity>> splitVisualChartElementList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> allElementList.stream().skip(a * batchSize).limit(batchSize).parallel().collect(Collectors.toList())).collect(Collectors.toList()); + + SQLUtils.FormatOption formatOption = new SQLUtils.FormatOption(false, false); + for (List<Entity> batchUpdateElementList : splitVisualChartElementList) { + List<String> list = Tool.ListUtil.list(true); + for (Entity entity : batchUpdateElementList) { + String sql = SQLUtils.format("update visual_chart_element set name = ? where id = ?", DbType.mariadb, Tool.ListUtil.of(entity.getStr("name"), entity.get("id")), formatOption); + list.add(sql); + } + // execute Batch + SqlExecutor.executeBatch(this.connection, list); + } + } + log.info("[handleElementName] [insert chart element name auto] [finshed]"); + } + + /** + * conversion Visual Chart Data + * + * @throws SQLException + */ + private void conversionVisualChartData() throws SQLException { + log.info("[conversionVisualChartData] [begin]"); + + List<Entity> backUpChartList = SqlExecutor.query(this.connection, "SELECT * FROM visual_chart_v3_2 ORDER BY panel_id, group_id, weight", new EntityListHandler()); + log.info("[conversionVisualChartData] [conversion size: {}]", backUpChartList.size()); + + // query element list. name has been processed + List<Entity> chartElementList = sqlRunner.findAll(this.connection, Entity.create("visual_chart_element")); + Map<String, List<Entity>> elementGroupingByChartIdMap = chartElementList.stream().collect(Collectors.groupingBy(entity -> entity.getStr("chart_id"))); + + // drop alertList type chart + // grouping by panel_id + Map<String, List<Entity>> chartGaroupingByPanelIdMap = backUpChartList.stream() + .filter(entity -> Tool.ObjectUtil.notEqual("alertList", entity.getStr("type"))) + .collect(Collectors.groupingBy(entity -> entity.getStr("panel_id"))); + + for (Map.Entry<String, List<Entity>> entry : chartGaroupingByPanelIdMap.entrySet()) { + String panelId = entry.getKey(); + List<Entity> chartListForPanel = entry.getValue(); + + // handle chart param/datasource + this.handleChartParamFormat(chartListForPanel, elementGroupingByChartIdMap); + + // handle Position chart.x y + this.handlePosition(panelId, chartListForPanel); + + // insert batch + if (Tool.CollUtil.isNotEmpty(chartListForPanel)) { + for (Entity entity : chartListForPanel) { + // reset table name + entity.setTableName("visual_chart"); + } + sqlRunner.insert(this.connection,chartListForPanel); } } + log.info("[conversionVisualChartData] [finshed]"); } /** - * 根据下标 获取对应 26 字母,如果超过 26 字母,按照 A-Z AA-AZ BA-BZ AAA-AAZ 顺序排 + * 根据下标 获取对应 26 字母,如果超过 26 字母,按照 A-Z AA-AZ BA -BZ AAA-AAZ 顺序排 * * @param num * @return @@ -138,22 +198,27 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ * @param panelId * @param chartList */ - private void handlePosition(Integer panelId, List<VisualChart> chartList) { - chartList = chartList.stream().sorted(Comparator.comparing(VisualChart::getWeight)).collect(Collectors.toList()); - - if (panelId == 0) { + private void handlePosition(String panelId, List<Entity> chartList) { + chartList = chartList.stream().sorted( + Comparator.comparing(entity -> { + String weightStr = Tool.StrUtil.emptyToDefault(entity.getStr("weight"), "0"); + return Integer.valueOf(weightStr); + }) + ).collect(Collectors.toList()); + + if (Tool.StrUtil.equals("0", panelId)) { // chart template 列表数据不需要处理 只需处理 group 内的 chart ,其他 chart 都设置为 0,0 - Map<Integer, List<VisualChart>> chartListGroupByGroupId = chartList.stream().collect(Collectors.groupingBy(VisualChart::getGroupId)); - for (Map.Entry<Integer, List<VisualChart>> entry : chartListGroupByGroupId.entrySet()) { - Integer groupId = entry.getKey(); - List<VisualChart> visualChartList = entry.getValue(); - if (groupId == 0) { - for (VisualChart visualChart : visualChartList) { - if (Tool.StrUtil.equals(visualChart.getType(), "group")) { - visualChart.setHeight(3d); + Map<String, List<Entity>> chartListGroupByGroupId = chartList.stream().collect(Collectors.groupingBy(entity -> entity.getStr("group_id"))); + for (Map.Entry<String, List<Entity>> entry : chartListGroupByGroupId.entrySet()) { + String groupId = entry.getKey(); + List<Entity> visualChartList = entry.getValue(); + if (Tool.StrUtil.equals("0", groupId)) { + for (Entity visualChart : visualChartList) { + if (Tool.StrUtil.equals(visualChart.getStr("type"), "group")) { + visualChart.set("height", 3); } - visualChart.setX(0d); - visualChart.setY(0d); + visualChart.set("x", 0); + visualChart.set("y", 0); } } else { // 根据 span and height 计算 XY @@ -162,12 +227,13 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ } } else { // 排序 ,按照 chart - group - chart 顺序排 (group inner chart) 排除在外 - List<VisualChart> list = new ArrayList<>(chartList.size()); - for (VisualChart visualChart : chartList) { - if (Tool.StrUtil.equals(visualChart.getType(), "group")) { + List<Entity> list = new ArrayList<>(chartList.size()); + for (Entity visualChart : chartList) { + if (Tool.StrUtil.equals(visualChart.getStr("type"), "group")) { // 添加 group list.add(visualChart); - } else if (!Tool.StrUtil.equals(visualChart.getType(), "group") && visualChart.getGroupId() == 0) { + } else if (!Tool.StrUtil.equals(visualChart.getStr("type"), "group") + && Tool.StrUtil.equals(visualChart.getStr("group_id"), "0")) { // 非 group & 非 group inner chart list.add(visualChart); } @@ -175,8 +241,11 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ // 根据 span and height 计算 XY this.calculateXYAccordingToSpanAndHeight(list); - Map<Integer, List<VisualChart>> chartListGroupByGroupId = chartList.stream().filter(visualChart -> visualChart.getGroupId() != 0).collect(Collectors.groupingBy(VisualChart::getGroupId)); - for (Map.Entry<Integer, List<VisualChart>> entry : chartListGroupByGroupId.entrySet()) { + Map<String, List<Entity>> chartListGroupByGroupId = chartList.stream() + .filter(entity -> Tool.ObjectUtil.notEqual("0", entity.getStr("group_id"))) + .collect(Collectors.groupingBy(entity -> entity.getStr("group_id"))); + + for (Map.Entry<String, List<Entity>> entry : chartListGroupByGroupId.entrySet()) { // 根据 span and height 计算 XY this.calculateXYAccordingToSpanAndHeight(entry.getValue()); } @@ -188,7 +257,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ * * @param list */ - private void calculateXYAccordingToSpanAndHeight(List<VisualChart> list) { + private void calculateXYAccordingToSpanAndHeight(List<Entity> list) { // 每行 x 计数 Integer colX = 0; // 每行 y 计数 @@ -196,11 +265,11 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ // 行内最高值 Integer highestValueInLine = 0; for (int i = 0; i < list.size(); i++) { - VisualChart chart = list.get(i); - Integer span = chart.getSpan().intValue(); + Entity chart = list.get(i); + Integer span = Integer.valueOf(chart.getStr("span")); // group 默认给 3 就 ok ,前端会根据 组内 chart 自动调整高度 - Integer height = Tool.StrUtil.equals(chart.getType(), "group") ? 3 : chart.getHeight().intValue(); - chart.setHeight(height.doubleValue()); + Integer height = Tool.StrUtil.equals(chart.getStr("type"), "group") ? 3 : Integer.valueOf(chart.getStr("height")); + chart.set("height", height); colX += span; // 一行结束 if (colX > 12) { @@ -208,18 +277,18 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ // 下一行第一个 Y 就是上一行 height 最大值 colY += highestValueInLine; Integer colXValue = colX - span.intValue(); - chart.setX(colXValue.doubleValue()); - chart.setY(colY.doubleValue()); + chart.set("x", colXValue); + chart.set("y", colY); highestValueInLine = 0; } else { // group - if (Tool.StrUtil.equals(chart.getType(), "group")) { - chart.setX(0d); + if (Tool.StrUtil.equals(chart.getStr("type"), "group")) { + chart.set("x", 0); } else { Integer colXValue = colX - span.intValue(); - chart.setX(colXValue.doubleValue()); + chart.set("x", colXValue); } - chart.setY(colY.doubleValue()); + chart.set("y", colY); } // 行内最高值 highestValueInLine = highestValueInLine < height ? height : highestValueInLine; @@ -240,30 +309,30 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ * logs * group * - * @param chartList - * @param chartIdAndElementListMap + * @param chartListForPanel + * @param elementGroupingByChartIdMap */ - private void handleChartParamFormat(List<VisualChart> chartList, Map<Integer, List<VisualChartElement>> chartIdAndElementListMap) { - Map<String, Object> enableMap = new HashMap(); + private void handleChartParamFormat(List<Entity> chartListForPanel, Map<String, List<Entity>> elementGroupingByChartIdMap) { + Map<String, Object> enableMap = Tool.MapUtil.newHashMap(); enableMap.put("thresholds", true); enableMap.put("valueMapping", true); enableMap.put("legend", true); - for (VisualChart visualChart : chartList) { + for (Entity visualChart : chartListForPanel) { try { - String type = visualChart.getType(); - if (visualChart.getParam() == null) { - visualChart.setParam(JSONObject.toJSONString(MapUtil.empty())); - } - if (Tool.StrUtil.isEmpty(visualChart.getParam().toString())) { - visualChart.setParam(JSONObject.toJSONString(MapUtil.empty())); - } - Map oldParamMap = JSONObject.parseObject(visualChart.getParam().toString(), Map.class); + // type + String type = visualChart.getStr("type"); + + String paramStr = visualChart.getStr("param"); + paramStr = Tool.StrUtil.emptyToDefault(paramStr, Tool.StrUtil.EMPTY_JSON); + visualChart.set("param", paramStr); + + Map oldParamMap = JSONObject.parseObject(paramStr, Map.class); String thresholdStrVal = Tool.ObjectUtil.defaultIfNull(oldParamMap.get("threshold"), "").toString(); String statisticsStrVal = Tool.ObjectUtil.defaultIfNull(oldParamMap.get("statistics"), "").toString(); - Map<String, Object> params = new HashMap<>(); + Map<String, Object> params = Tool.MapUtil.newHashMap(); // thresholds List<Map> thresholds = new ArrayList<>(); // valueMapping @@ -274,7 +343,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ case "stackArea": { // type value 变更 if (Tool.StrUtil.equalsIgnoreCase(type, "stackArea")) { - visualChart.setType("area"); + visualChart.set("type", "area"); // area 类型图表 stack 默认值 为 true params.put("stack", true); } else { @@ -289,15 +358,15 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ legendOnValueList = legendValueMap.entrySet().stream().filter(entry -> Tool.StrUtil.equals(entry.getValue(), "on")).map(entry -> entry.getKey()).collect(Collectors.toList()); } - params.put("style", visualChart.getType()); + params.put("style", visualChart.getStr("type")); // legend - Map legend = new HashMap<>(); + Map legend = Tool.MapUtil.newHashMap(); legend.put("placement", "bottom"); legend.put("values", legendOnValueList); params.put("legend", legend); if (Tool.StrUtil.isNotBlank(thresholdStrVal)) { - Map tempThresholdFirstMap = new HashMap(); + Map tempThresholdFirstMap = Tool.MapUtil.newHashMap(); tempThresholdFirstMap.put("color", "#d64f40"); tempThresholdFirstMap.put("value", thresholdStrVal); thresholds.add(tempThresholdFirstMap); @@ -305,7 +374,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ params.put("thresholds", thresholds); params.put("nullType", oldParamMap.get("nullType")); params.put("enable", enableMap); - visualChart.setDatasource(Constant.ChartDatasourceType.METRICS.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.METRICS.getValue()); break; } // chart-bar bar @@ -323,17 +392,17 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ legendOnValueList = legendValueMap.entrySet().stream().filter(entry -> Tool.StrUtil.equals(entry.getValue(), "on")).map(entry -> entry.getKey()).collect(Collectors.toList()); } // legend - Map legend = new HashMap<>(); + Map legend = Tool.MapUtil.newHashMap(); legend.put("placement", "bottom"); legend.put("values", legendOnValueList); params.put("legend", legend); params.put("enable", enableMap); - visualChart.setDatasource(Constant.ChartDatasourceType.METRICS.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.METRICS.getValue()); break; } // chart-value stat case "singleStat": { - visualChart.setType("stat"); + visualChart.set("type", "stat"); // none/null 赋默认值 last params.put("statistics", Tool.StrUtil.equals(statisticsStrVal, "null") || Tool.StrUtil.equals(statisticsStrVal, "") ? "last" : statisticsStrVal); params.put("nullType", oldParamMap.get("nullType")); @@ -343,7 +412,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ String valueMappingMapType = Tool.ObjectUtil.defaultIfNull(valueMappingMap.get("type"), "").toString(); List<Map> mappingList = JSONObject.parseArray(valueMappingMap.get("mapping").toString(), Map.class); for (Map map : mappingList) { - Map tempValueMappingMap = new HashMap(); + Map tempValueMappingMap = Tool.MapUtil.newHashMap(); tempValueMappingMap.put("type", valueMappingMapType); tempValueMappingMap.putAll(map); valueMappingList.add(tempValueMappingMap); @@ -352,7 +421,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ } params.put("valueMapping", valueMappingList); params.put("enable", enableMap); - visualChart.setDatasource(Constant.ChartDatasourceType.METRICS.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.METRICS.getValue()); break; } // chart-pie pie @@ -363,10 +432,10 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ params.put("display", "value"); params.put("valueMapping", valueMappingList); params.put("enable", enableMap); - visualChart.setDatasource(Constant.ChartDatasourceType.METRICS.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.METRICS.getValue()); break; } - // chart-table table TODO + // chart-table table case "table": { // none/null 赋默认值 last params.put("statistics", Tool.StrUtil.equals(statisticsStrVal, "null") || Tool.StrUtil.equals(statisticsStrVal, "") ? "last" : statisticsStrVal); @@ -374,22 +443,22 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ params.put("enable", enableMap); params.put("indexs", ""); - List<VisualChartElement> visualChartElements = chartIdAndElementListMap.get(visualChart.getId()); + List<Entity> visualChartElements = elementGroupingByChartIdMap.get(visualChart.getStr("id")); String elementDisplay = "", valueDisplay = ""; - for (VisualChartElement element : visualChartElements) { - elementDisplay += "{{" + element.getName() + ".$legend}}"; - valueDisplay += "{{" + element.getName() + ".$value}}"; + for (Entity element : visualChartElements) { + elementDisplay += "{{" + element.getStr("name") + ".$legend}}"; + valueDisplay += "{{" + element.getStr("name") + ".$value}}"; } // columns List<Map> columns = new ArrayList<>(); - Map elementMap = new HashMap(); + Map elementMap = Tool.MapUtil.newHashMap(); elementMap.put("title", "Element"); elementMap.put("show", true); elementMap.put("unit", 2); elementMap.put("display", elementDisplay); columns.add(elementMap); - Map valueMap = new HashMap(); + Map valueMap = Tool.MapUtil.newHashMap(); valueMap.put("title", "Value"); valueMap.put("show", true); valueMap.put("unit", 2); @@ -405,7 +474,7 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ String valueMappingMapType = Tool.ObjectUtil.defaultIfNull(valueMappingMap.get("type"), "").toString(); List<Map> mappingList = JSONObject.parseArray(valueMappingMap.get("mapping").toString(), Map.class); for (Map map : mappingList) { - Map tempValueMappingMap = new HashMap(); + Map tempValueMappingMap = Tool.MapUtil.newHashMap(); tempValueMappingMap.put("type", valueMappingMapType); tempValueMappingMap.put("columns", "Value"); tempValueMappingMap.putAll(map); @@ -414,29 +483,29 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ } } params.put("valueMapping", valueMappingList); - visualChart.setDatasource(Constant.ChartDatasourceType.METRICS.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.METRICS.getValue()); break; } case "group": { String collapseStr = Tool.ObjectUtil.defaultIfNull(oldParamMap.get("collapse"), "false").toString(); params.put("collapse", Tool.StrUtil.equals(collapseStr, "true") ? true : false); - visualChart.setDatasource(Constant.ChartDatasourceType.MISC.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.MISC.getValue()); break; } case "text": case "url": case "diagram": { - visualChart.setDatasource(Constant.ChartDatasourceType.MISC.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.MISC.getValue()); break; } case "logs": { - visualChart.setType("log"); - visualChart.setDatasource(Constant.ChartDatasourceType.LOGS.getValue()); + visualChart.set("type", "log"); + visualChart.set("datasource", Constant.ChartDatasourceType.LOGS.getValue()); break; } case "assetInfo": case "endpointInfo": { - visualChart.setDatasource(Constant.ChartDatasourceType.SYSTEM.getValue()); + visualChart.set("datasource", Constant.ChartDatasourceType.SYSTEM.getValue()); break; } default: { @@ -445,11 +514,11 @@ public class DataFormatConversionServiceImpl implements DataFormatConversionServ } // params 处理过 重新赋值 if (Tool.CollectionUtil.isNotEmpty(params)) { - visualChart.setParam(JSONObject.toJSONString(params)); + visualChart.set("param", JSONObject.toJSONString(params)); } } catch (Exception e) { - logger.error("Chart数据格式处理有误,原始数据:" + JSONObject.toJSONString(visualChart)); - logger.error(e); + log.error(e, "[handleChartParamFormat] [Data format processing error] [backUp data: {}]", JSONUtil.toJsonStr(visualChart)); + throw new NZException(RCode.ERROR); } } } diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3Update.java b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3Update.java deleted file mode 100644 index 5fd878a1..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3Update.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.nis.common.update.v3_2_to_3_3; - -import com.nis.common.update.VersionUpdateInterface; -import com.nis.common.update.v3_2_to_3_3.service.V3_3_DataFormatConversionService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class V3_3Update implements VersionUpdateInterface { - - @Autowired - private V3_3_DataFormatConversionService service; - - @Override - public boolean preUpdate() { - - return VersionUpdateInterface.super.preUpdate(); - } - - @Override - public void excute() throws Exception { - service.assetModelDataFormatConversion(); - } - -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3_MigrateNotifierCallback.java b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3_MigrateNotifierCallback.java new file mode 100644 index 00000000..674198f5 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/V3_3_MigrateNotifierCallback.java @@ -0,0 +1,111 @@ +package com.nis.common.update.v3_2_to_3_3; + +import cn.hutool.log.Log; +import com.nis.common.update.v3_2_to_3_3.service.V3_3_DataFormatConversionService; +import com.nis.common.utils.Tool; +import org.apache.commons.lang3.time.StopWatch; +import org.flywaydb.core.api.MigrationInfo; +import org.flywaydb.core.api.MigrationVersion; +import org.flywaydb.core.api.callback.Callback; +import org.flywaydb.core.api.callback.Context; +import org.flywaydb.core.api.callback.Event; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.Connection; + +/** + * V3_3_MigrateNotifierCallback + * Flyway V2022.03.11__modify_asset_model_table_structure.sql 回调类 + * 用于处理 3.2 - 3.3 asset_model 表数据转换 + * <p> + * 1. asset_model 新增 type_id、sys_object_id 列 + * 2. 根据 asset_asset 表关联 model_id & type_id 对应关系,处理 model.typeId + * 注:未被 asset 引用的 model 数据直接删除,不再保留 + * + * @author shizhendong + * @date 2023/03/15 + */ +@Component +@Transactional +public class V3_3_MigrateNotifierCallback implements Callback { + + private static final Log log = Log.get(); + + /** + * callback_version: V2022.03.11__modify_asset_model_table_structure.sql + */ + private static final String CALLBACK_VERSION = "2022.03.11"; + + @Autowired + private V3_3_DataFormatConversionService v3_3_dataFormatConversionService; + + @Override + public String getCallbackName() { + return "V3_3_MigrateNotifierCallback"; + } + + /** + * Not relevant if we don't interact with the database + * + * @param event + * @param context + * @return + */ + @Override + public boolean canHandleInTransaction(Event event, Context context) { + return true; + } + + /** + * Ensures that this callback handles events + * + * @param event + * @param context + * @return + */ + @Override + public boolean supports(Event event, Context context) { + // afterEachMigrate + if (Tool.ObjectUtil.equal(event, Event.AFTER_EACH_MIGRATE)) { + MigrationInfo migrationInfo = context.getMigrationInfo(); + MigrationVersion version = migrationInfo.getVersion(); + if (Tool.ObjectUtil.isNotNull(version)) { + if (Tool.StrUtil.equals(CALLBACK_VERSION, version.getVersion())) { + return true; + } + } + } + return false; + } + + /** + * Process data upgrade + * + * @param event + * @param context + */ + @Override + public void handle(Event event, Context context) { + log.info("[V3_3_MigrateNotifierCallback] [Trigger callback] [begin] [migrate version: {}]", CALLBACK_VERSION); + + StopWatch sw = new StopWatch(); + sw.start(); + + try { + Connection connection = context.getConnection(); + // data Format Conversion + v3_3_dataFormatConversionService.dataFormatConversion(connection); + } catch (Exception e) { + log.error(e, "[V3_3_MigrateNotifierCallback] [error] [shutdown nz-web.service]"); + // 停止服务 + Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); + } finally { + sw.stop(); + } + + log.info("[V3_3_MigrateNotifierCallback] [Data Format Conversion Finshed] [Run time: {}]", sw.toString()); + } + +} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/dao/V3_2_AssetModelDao.java b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/dao/V3_2_AssetModelDao.java deleted file mode 100644 index 54c14ad6..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/dao/V3_2_AssetModelDao.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.nis.common.update.v3_2_to_3_3.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nis.modules.asset.entity.AssetModel; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Map; - -@Mapper -@Repository -public interface V3_2_AssetModelDao extends BaseMapper<AssetModel> { - - Map checkTableExists(@Param("tableName") String tableName); - - void dropTable(@Param("tableName") String tableName); - - List<Map<String, Object>> queryAssetModelIdAndTypesMapping(); - - List<AssetModel> queryList(); - -} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/V3_3_DataFormatConversionService.java b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/V3_3_DataFormatConversionService.java index 7b76adfa..96b5e002 100644 --- a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/V3_3_DataFormatConversionService.java +++ b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/V3_3_DataFormatConversionService.java @@ -1,10 +1,149 @@ package com.nis.common.update.v3_2_to_3_3.service; -public interface V3_3_DataFormatConversionService { +import cn.hutool.db.Entity; +import cn.hutool.db.SqlConnRunner; +import cn.hutool.db.handler.EntityListHandler; +import cn.hutool.db.handler.StringHandler; +import cn.hutool.db.sql.SqlExecutor; +import cn.hutool.log.Log; +import com.nis.common.update.DataFormatConversionInterface; +import com.nis.common.utils.Tool; +import org.springframework.stereotype.Service; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * V3_3_DataFormatConversionServiceImpl + * + * @author shizhendong + * @date 2023/03/15 + */ +@Service +public class V3_3_DataFormatConversionService implements DataFormatConversionInterface { + + private static final Log log = Log.get(); + + /** + * back up table name + */ + private static final String BACK_UP_TABLE_NAME = "asset_model_v3_2"; + + private Connection connection; + + private SqlConnRunner sqlRunner; + + /** + * before Data Format Conversion + * check backup table is exists + * + * @return + */ + private boolean beforeDataFormatConversion() throws SQLException { + String tableName = SqlExecutor.query(this.connection, "SHOW TABLES LIKE ?", new StringHandler(), BACK_UP_TABLE_NAME); + log.info("[beforeDataFormatConversion] [check the backup table exists] [query result: {}]", tableName); + + if (Tool.StrUtil.isEmpty(tableName)) { + log.warn("[beforeDataFormatConversion] [The backup table does not exist. Do not perform data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return false; + } + + log.info("[beforeDataFormatConversion] [The backup table exists, execute data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return true; + } + + @Override + public void dataFormatConversion(Connection connection) throws Exception { + // init sql conn runner + this.connection = connection; + sqlRunner = this.initSqlRunner(connection); + + boolean isConversion = this.beforeDataFormatConversion(); + if (!isConversion) { + return; + } + + log.info("[dataFormatConversion] [conversion V3_2 to V3_3 Asset Model Data]"); + + // conversion Asset Model Data + this.conversionAssetModelData(); + + // remove back up table + log.info("[dataFormatConversion] [remove back up table] [table_name: {}]", BACK_UP_TABLE_NAME); + SqlExecutor.execute(this.connection, Tool.StrUtil.concat(true, "DROP TABLE ", BACK_UP_TABLE_NAME)); + } /** - * 3.2 - 3.3 asset_model 表数据转换 + * conversion Asset Model Data + * 注:未被 asset 引用的 model 数据直接删除,不再保留 + * + * @throws SQLException */ - void assetModelDataFormatConversion() throws Exception; + private void conversionAssetModelData() throws SQLException { + log.info("[conversionAssetModelData] [begin]"); + + List<Entity> backUpModelList = sqlRunner.findAll(this.connection, Entity.create("asset_model_v3_2")); + Map<String, Entity> backUpModelIdAndEntityMap = backUpModelList.stream().collect(Collectors.toMap(entity -> entity.getStr("id"), Function.identity())); + log.info("[conversionAssetModelData] [conversion size: {}]", backUpModelList.size()); + + List<Entity> assetTypeConfList = sqlRunner.findAll(this.connection, Entity.create("asset_type_conf")); + Map<String, String> assetTypeIdAndNameMap = assetTypeConfList.stream() + .collect(Collectors.toMap(entity -> entity.getStr("id"), entity -> entity.getStr("name"))); + + // 统计 asset_asset 表 model_id 与 type_id 关联关系 + // 注:未被 asset 引用的 model 数据直接删除,不再保留 + List<Entity> modelIdAndTypeIdsMapList = SqlExecutor.query(this.connection, "SELECT model_id, GROUP_CONCAT( DISTINCT type_id ) AS type_ids FROM asset_asset GROUP BY model_id", new EntityListHandler()); + Map<String, String> modelIdAndTypeIdsMap = modelIdAndTypeIdsMapList.stream() + .collect(Collectors.toMap(entity -> entity.getStr("model_id"), entity -> entity.getStr("type_ids"))); + + // 判断 typeids 是否包含 ',' + // 包含',': model 对应多个的 asset_type_conf + // 不包含 ',': model 对应唯一的 asset_type_conf + for (Map.Entry<String, String> entry : modelIdAndTypeIdsMap.entrySet()) { + String modelId = entry.getKey(); + String typeIds = entry.getValue(); + if (Tool.StrUtil.contains(typeIds, ",")) { + // 包含',': model 对应多个的 asset_type_conf + // 新增 model,并设置不同的 type_id,model.name = model.name-type.name + List<String> typeIdStrList = Tool.StrUtil.split(typeIds, ','); + for (String typeIdStr : typeIdStrList) { + Entity entity = backUpModelIdAndEntityMap.get(modelId); + + entity.remove("id"); + entity.set("type_id", Integer.valueOf(typeIdStr)); + entity.set("sys_object_id", Tool.StrUtil.EMPTY); + + // save model.name = oldModelName - typeConfName + String typeConfName = assetTypeIdAndNameMap.get(typeIdStr); + entity.set("name", Tool.StrUtil.concat(true, entity.getStr("name"), "-", typeConfName)); + + // insert model + entity.setTableName("asset_model"); + Long saveEntityId = sqlRunner.insertForGeneratedKey(this.connection, entity); + + // 修改 asset 对应 model_id + // sql: update asset_asset set model_id = {newModelID} where model_id = {oldModelID} and type_id = {typeID} + sqlRunner.update(this.connection, + Entity.create().set("model_id", saveEntityId), + Entity.create("asset_asset").set("model_id", modelId).set("type_id", typeIdStr)); + } + } else { + // 不包含 ',' model 对应唯一的 asset_type_conf, set model.typeId = typeId + Entity entity = backUpModelIdAndEntityMap.get(modelId); + entity.set("type_id", Integer.valueOf(typeIds)); + entity.set("sys_object_id", Tool.StrUtil.EMPTY); + + // insert model + entity.setTableName("asset_model"); + sqlRunner.insert(this.connection, entity); + } + } + log.info("[conversionAssetModelData] [finshed]"); + } } + diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/impl/V3_3_DataFormatConversionServiceImpl.java b/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/impl/V3_3_DataFormatConversionServiceImpl.java deleted file mode 100644 index 71705541..00000000 --- a/nz-admin/src/main/java/com/nis/common/update/v3_2_to_3_3/service/impl/V3_3_DataFormatConversionServiceImpl.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.nis.common.update.v3_2_to_3_3.service.impl; - -import cn.hutool.log.Log; -import com.nis.common.update.v3_2_to_3_3.dao.V3_2_AssetModelDao; -import com.nis.common.update.v3_2_to_3_3.service.V3_3_DataFormatConversionService; -import com.nis.common.utils.Tool; -import com.nis.modules.asset.dao.AssetAssetDao; -import com.nis.modules.asset.dao.AssetModelDao; -import com.nis.modules.asset.entity.AssetModel; -import com.nis.modules.asset.entity.AssetTypeConf; -import com.nis.modules.asset.service.AssetTypeConfService; -import org.apache.commons.lang3.time.StopWatch; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Service -public class V3_3_DataFormatConversionServiceImpl implements V3_3_DataFormatConversionService { - - private static Log logger = Log.get(); - - @Autowired - private V3_2_AssetModelDao v3_2_assetModelDao; - - @Autowired - private AssetAssetDao assetAssetDao; - - @Autowired - private AssetTypeConfService typeConfService; - - @Autowired - private AssetModelDao assetModelDao; - - @Override - public void assetModelDataFormatConversion() throws Exception { - // 1. 检查 asset_model_v3_2 是否存在 - Map checkTableExists = v3_2_assetModelDao.checkTableExists("asset_model_v3_2"); - if (Tool.CollectionUtil.isEmpty(checkTableExists)) { - logger.info("Table asset_model_v3_2 does not exist. The asset_model data format processing will not be executed"); - return; - } - - StopWatch sw = new StopWatch(); - sw.start(); - try { - // 2. 处理数据变化 - logger.info("The asset_model data format change processing start."); - - List<AssetModel> oldAssetModels = v3_2_assetModelDao.queryList(); - Map<Integer, AssetModel> oldAssetModelMap = oldAssetModels.stream().collect(Collectors.toMap(AssetModel::getId, Function.identity())); - - List<AssetTypeConf> typeConfList = typeConfService.list(); - Map<Integer, String> typeConfMap = typeConfList.stream().collect(Collectors.toMap(AssetTypeConf::getId, AssetTypeConf::getName)); - - // 统计 asset_asset 表 model_id 与 type_id 关联关系 注:未被 asset 引用的 model 数据直接删除,不再保留 - List<Map<String, Object>> modelIdAndTypeIdsMapList = v3_2_assetModelDao.queryAssetModelIdAndTypesMapping(); - Map<Integer, String> modelIdAndTypeIdssMap = modelIdAndTypeIdsMapList.stream().collect(Collectors.toMap(o -> Integer.valueOf(o.get("modelId").toString()), o -> o.get("typeId").toString())); - - // 保存之前的数据到 新表中 - for (Map.Entry<Integer, String> entry : modelIdAndTypeIdssMap.entrySet()) { - Integer oldModelId = entry.getKey(); - String typeIds = entry.getValue(); - // 判断 typeids 是否包含 , 包含则证明 部分 asset 选择了多个 type 对应同一个 model - if (!typeIds.contains(",")) { - // typeids 未包含 , asset 引用 model_id 和 type_id 一一对应,修改 model 对应 type_id 为该 type_id 即可 - AssetModel assetModel = oldAssetModelMap.get(oldModelId); - assetModel.setTypeId(Integer.valueOf(typeIds)); - assetModel.setSysObjectId(Tool.StrUtil.EMPTY); - assetModelDao.insertModel(assetModel); - } - } - - for (Map.Entry<Integer, String> entry : modelIdAndTypeIdssMap.entrySet()) { - Integer oldModelId = entry.getKey(); - String typeIds = entry.getValue(); - // 判断 typeids 是否包含 , 包含则证明 部分 asset 选择了多个 type 对应同一个 model - if (typeIds.contains(",")) { - // 新增 model 并 处理 asset 对应关系 - List<Integer> typeIdList = Tool.StrUtil.split(typeIds, ',').stream().map(Integer::parseInt).collect(Collectors.toList()); - for (Integer typeId : typeIdList) { - // 新增 model name = oldModelName-typeConfName - String typeConfName = typeConfMap.get(typeId); - AssetModel assetModel = oldAssetModelMap.get(oldModelId); - - AssetModel saveAssetModel = new AssetModel(); - Tool.BeanUtil.copyProperties(assetModel, saveAssetModel); - saveAssetModel.setId(null); - saveAssetModel.setTypeId(typeId); - saveAssetModel.setName(String.format("%s-%s", saveAssetModel.getName(), typeConfName)); - saveAssetModel.setSysObjectId(Tool.StrUtil.EMPTY); - assetModelDao.insert(saveAssetModel); - - // 修改 asset 对应 model_id sql: update asset_asset set model_id = {newModelID} where model_id = {oldModelID} and type_id = {typeID} - assetAssetDao.updateModelId(saveAssetModel.getId(), oldModelId, typeId); - } - } - } - - logger.info("The asset_model data format change processing done."); - // 4. 删除 asset_model_v3_2 表 - v3_2_assetModelDao.dropTable("asset_model_v3_2"); - } finally { - sw.stop(); - } - logger.info("asset_model data format conversion done Run Time: {}", sw.toString()); - } - -} - diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/V3_6_MigrateNotifierCallback.java b/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/V3_6_MigrateNotifierCallback.java new file mode 100644 index 00000000..d7bb7c97 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/V3_6_MigrateNotifierCallback.java @@ -0,0 +1,118 @@ +package com.nis.common.update.v3_5_to_3_6; + +import cn.hutool.log.Log; +import com.nis.common.update.v3_5_to_3_6.service.V3_6_DataFormatConversionService; +import com.nis.common.utils.Tool; +import org.apache.commons.lang3.time.StopWatch; +import org.flywaydb.core.api.MigrationInfo; +import org.flywaydb.core.api.MigrationVersion; +import org.flywaydb.core.api.callback.Callback; +import org.flywaydb.core.api.callback.Context; +import org.flywaydb.core.api.callback.Event; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.sql.Connection; + +/** + * V3_3_MigrateNotifierCallback + * Flyway V2022.11.26__backup and modify asset_model table.sql 回调类 + * <p> + * 支持自动将 已有asset model 配置的 chart template 转换为 dashboard template 实现。 + * 1、复制 asset_model_v3.6 表格 + * 2、遍历 asset model + * 新建 dashboard template,,name: [assetModel.name] + template, 例: TSG-X template + * 新建 chart (复制 asset model 已关联) + * 更新使用 chart template 创建的图表 pid + * 更新 asset panel tmpl_id + * 3、更新 asset model panel id + * 4、删除 chart.panel_id == 0 的历史数据 + * 5、删除 asset_model_v3.6 + * + * @author shizhendong + * @date 2023/03/15 + */ +@Component +@Transactional +public class V3_6_MigrateNotifierCallback implements Callback { + + private static final Log log = Log.get(); + + /** + * callback_version: V2022.11.26__backup and modify asset_model table.sql + */ + private static final String CALLBACK_VERSION = "2022.11.26"; + + @Autowired + private V3_6_DataFormatConversionService v3_6_dataFormatConversionService; + + @Override + public String getCallbackName() { + return "V3_6_MigrateNotifierCallback"; + } + + /** + * Not relevant if we don't interact with the database + * + * @param event + * @param context + * @return + */ + @Override + public boolean canHandleInTransaction(Event event, Context context) { + return true; + } + + /** + * Ensures that this callback handles events + * + * @param event + * @param context + * @return + */ + @Override + public boolean supports(Event event, Context context) { + // afterEachMigrate + if (Tool.ObjectUtil.equal(event, Event.AFTER_EACH_MIGRATE)) { + MigrationInfo migrationInfo = context.getMigrationInfo(); + MigrationVersion version = migrationInfo.getVersion(); + if (Tool.ObjectUtil.isNotNull(version)) { + if (Tool.StrUtil.equals(CALLBACK_VERSION, version.getVersion())) { + return true; + } + } + } + return false; + } + + + /** + * Process data upgrade + * + * @param event + * @param context + */ + @Override + public void handle(Event event, Context context) { + log.info("[V3_6_MigrateNotifierCallback] [Data Format Conversion Begin] [migrate version: {}]", CALLBACK_VERSION); + + StopWatch sw = new StopWatch(); + sw.start(); + + try { + Connection connection = context.getConnection(); + // data Format Conversion + v3_6_dataFormatConversionService.dataFormatConversion(connection); + } catch (Exception e) { + log.error(e, "[V3_6_MigrateNotifierCallback] [error] [shutdown nz-web.service]"); + // 停止服务 + Tool.RuntimeUtil.exec("systemctl stop nz-web.service"); + } finally { + sw.stop(); + } + + log.info("[V3_6_MigrateNotifierCallback] [Data Format Conversion Finshed] [Run time: {}]", sw.toString()); + } + +} diff --git a/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/service/V3_6_DataFormatConversionService.java b/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/service/V3_6_DataFormatConversionService.java new file mode 100644 index 00000000..ed947ded --- /dev/null +++ b/nz-admin/src/main/java/com/nis/common/update/v3_5_to_3_6/service/V3_6_DataFormatConversionService.java @@ -0,0 +1,349 @@ +package com.nis.common.update.v3_5_to_3_6.service; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.db.Entity; +import cn.hutool.db.SqlConnRunner; +import cn.hutool.db.handler.EntityListHandler; +import cn.hutool.db.handler.StringHandler; +import cn.hutool.db.sql.SqlExecutor; +import cn.hutool.log.Log; +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.fastjson.JSONObject; +import com.nis.common.update.DataFormatConversionInterface; +import com.nis.common.utils.Constant; +import com.nis.common.utils.JSONUtil; +import com.nis.common.utils.Tool; +import org.springframework.stereotype.Service; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * V3_6_DataFormatConversionServiceImpl + * + * @author shizhendong + * @date 2023/03/15 + */ +@Service +public class V3_6_DataFormatConversionService implements DataFormatConversionInterface { + + private static final Log log = Log.get(); + + /** + * back up table name + */ + private static final String BACK_UP_TABLE_NAME = "asset_model_v3_6"; + + private Connection connection; + + private SqlConnRunner sqlRunner; + + /** + * before Data Format Conversion + * check backup table is exists + * + * @return + */ + private boolean beforeDataFormatConversion() throws SQLException { + String tableName = SqlExecutor.query(this.connection, "SHOW TABLES LIKE ?", new StringHandler(), BACK_UP_TABLE_NAME); + log.info("[beforeDataFormatConversion] [check the backup table exists] [query result: {}]", tableName); + + if (Tool.StrUtil.isEmpty(tableName)) { + log.warn("[beforeDataFormatConversion] [The backup table does not exist. Do not perform data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return false; + } + + log.info("[beforeDataFormatConversion] [The backup table exists, execute data conversion] [table: {}]", BACK_UP_TABLE_NAME); + return true; + } + + @Override + public void dataFormatConversion(Connection connection) throws Exception { + // init sql conn runner + this.connection = connection; + sqlRunner = this.initSqlRunner(connection); + + boolean isConversion = this.beforeDataFormatConversion(); + if (!isConversion) { + return; + } + + // conversion Asset Model Chart Data + log.info("[dataFormatConversion] [conversion Asset Model Chart Data]"); + this.conversionAssetModelChartData(); + + // remove old chart template + List<Entity> removeChartList = sqlRunner.findAll(this.connection, Entity.create("visual_chart").set("panel_id", 0)); + log.info("[dataFormatConversion] [remove old chart template] [size: {}]", removeChartList.size()); + + List<String> removeChartIdList = removeChartList.stream().map(entity -> entity.getStr("id")).collect(Collectors.toList()); + if (Tool.CollUtil.isNotEmpty(removeChartList)) { + sqlRunner.del(this.connection, Entity.create("visual_chart").set("id", removeChartIdList)); + sqlRunner.del(this.connection, Entity.create("visual_chart_element").set("chart_id", removeChartIdList)); + } + + // remove back up table + log.info("[dataFormatConversion] [remove back up table] [table_name: {}]", BACK_UP_TABLE_NAME); + SqlExecutor.execute(this.connection, Tool.StrUtil.concat(true, "DROP TABLE ", BACK_UP_TABLE_NAME)); + } + + /** + * conversion Asset Model Chart Data + */ + private void conversionAssetModelChartData() throws SQLException { + log.info("[conversionAssetModelChartData] [begin]"); + + // save chart element + List<Entity> saveBatchChartElementList = Tool.ListUtil.list(true); + + List<Entity> backUpModelList = sqlRunner.findAll(this.connection, Entity.create("asset_model_v3_6")); + log.info("[conversionAssetModelChartData] [conversion size: {}]", backUpModelList.size()); + for (Entity backUpAssetModel : backUpModelList) { + // model id + String modelId = backUpAssetModel.getStr("id"); + // model name + String modelName = backUpAssetModel.getStr("name"); + // chart id list + String chartIds = backUpAssetModel.getStr("chart_ids"); + + log.info("[conversionAssetModelChartData] [conversion data begin.] [model id: {}]", modelId); + if (Tool.StrUtil.isEmpty(chartIds)) { + log.warn("[conversionAssetModelChartData] [no config chart. no conversion] [model id: {}]", modelId); + } else { + List<String> chartIdList = Tool.StrUtil.split(Tool.StrUtil.emptyToDefault(chartIds, Tool.StrUtil.EMPTY), Tool.StrUtil.C_COMMA); + log.info("[conversionAssetModelChartData] [asset model chart list] [size: {}] [info: {}]", chartIdList.size(), JSONUtil.toJsonStr(chartIdList)); + + // add panel template + Long insertPanelId = this.addTemplateTypePanel(modelName); + + // model rel chart list + List<Entity> chartList = sqlRunner.findAll(this.connection, Entity.create("visual_chart").set("panel_id", 0).set("id", chartIdList)); + List<Entity> chartListUnderGroup = sqlRunner.findAll(this.connection, Entity.create("visual_chart").set("panel_id", 0).set("group_id", chartIdList)); + chartList.addAll(chartListUnderGroup); + + // distinct + chartList = chartList.stream().distinct().collect(Collectors.toList()); + log.info("[conversionAssetModelChartData] [conversion data] [model: {}] [chart size: {}]", modelName, chartList.size()); + + // assets panel id list + List<String> assetPanelIdListByTheModel = this.getAssetPanelListByTheModel(modelId); + + // group chart + Map<String, String> groupChartIdMapping = Tool.MapUtil.newHashMap(); + List<Entity> groupChartList = chartList.stream().filter(chart -> Tool.StrUtil.equals(Constant.CHART_GROUP_TYPE, chart.getStr("type"))).collect(Collectors.toList()); + for (Entity groupChart : groupChartList) { + Entity tempGroupChart = ObjectUtil.clone(groupChart); + tempGroupChart.remove("id"); + tempGroupChart.set("panel_id", insertPanelId); + + // save group chart + Long insertTempGroupChartId = sqlRunner.insertForGeneratedKey(this.connection, tempGroupChart); + String insertTempGroupChartIdStr = StrUtil.toString(insertTempGroupChartId); + + String groupChartId = groupChart.getStr("id"); + // save mapping + groupChartIdMapping.put(groupChartId, insertTempGroupChartIdStr); + // update chart pid val. only handle asset chart + this.updateAssetChartTemplateLinkValByTheModel(insertTempGroupChartIdStr, assetPanelIdListByTheModel, groupChartId); + } + + // other chart + List<Entity> otherChartList = chartList.stream().filter(chart -> !Tool.StrUtil.equals(Constant.CHART_GROUP_TYPE, chart.getStr("type"))).collect(Collectors.toList()); + for (Entity chart : otherChartList) { + Entity tempChart = ObjectUtil.clone(chart); + + tempChart.remove("id"); + tempChart.set("panel_id", insertPanelId); + // new group id + String groupId = groupChartIdMapping.get(tempChart.getStr("group_id")); + tempChart.set("group_id", StrUtil.emptyToDefault(groupId, "0")); + + // save chart + Long insertTempChartId = sqlRunner.insertForGeneratedKey(this.connection, tempChart); + String insertTempChartIdStr = StrUtil.toString(insertTempChartId); + + List<Entity> elementList = sqlRunner.findAll(this.connection, Entity.create("visual_chart_element").set("chart_id", chart.getStr("id"))); + for (Entity e : elementList) { + e.remove("id"); + e.set("chart_id", insertTempChartIdStr); + } + saveBatchChartElementList.addAll(elementList); + // update chart pid val. only handle asset chart + this.updateAssetChartTemplateLinkValByTheModel(insertTempChartIdStr, assetPanelIdListByTheModel, chart.getStr("id")); + } + // set panel id + backUpAssetModel.set("panel_id", insertPanelId); + // update asset panel temp_id + this.updateAssetPanelTempIdByTheModel(backUpAssetModel, assetPanelIdListByTheModel, insertPanelId); + } + // save model + backUpAssetModel.setTableName("asset_model"); + Long insertBackUpAssetModelId = sqlRunner.insertForGeneratedKey(this.connection, backUpAssetModel); + log.info("[conversionAssetModelChartData] [conversion data finshed.] [insert id: {}] [name: {}]", insertBackUpAssetModelId, backUpAssetModel.getStr("name")); + } + // save chart element + this.saveTheListOfNewChartElement(saveBatchChartElementList); + log.info("[conversionAssetModelChartData] [finshed]"); + } + + /** + * save Template Type Panel + * name format: 'model.name template' + * + * @param modelName + * @return + */ + private Long addTemplateTypePanel(String modelName) throws SQLException { + // panel name + String panelName = Tool.StrUtil.concat(true, modelName, Tool.StrUtil.SPACE, "template"); + List<Entity> panelListByTempName = SqlExecutor.query(this.connection, "SELECT * FROM visual_panel WHERE type = 'template' and name = ?", new EntityListHandler(), panelName); + if (Tool.CollUtil.isNotEmpty(panelListByTempName)) { + // 重复就拼上 4位 随机字符 + panelName = Tool.StrUtil.concat(true, panelName, "-", Tool.RandomUtil.randomString(4)); + } + + Entity panelEntity = Entity.create("visual_panel"); + panelEntity.set("name", panelName); + panelEntity.set("type", "template"); + panelEntity.set("pid", 0); + panelEntity.set("weight", 0); + panelEntity.set("build_in", 0); + + String initParamStr = "{\"chartShare\":\"none\",\"variables\":[],\"report\":{\"schedule\":{\"repeat\":1,\"etime\":\"\",\"stime\":\"\",\"type\":2,\"nums\":[]},\"receivers\":[],\"enable\":false,\"range\":{\"unit\":\"day\",\"interval\":1,\"type\":\"previous\"}}}"; + panelEntity.set("param", initParamStr); + + panelEntity.set("var_type", Constant.ChartVariableType.ASSET.getValue()); + panelEntity.set("tmpl_id", -1); + + panelEntity.set("create_by", -1); + panelEntity.set("uts", System.currentTimeMillis()); + + // save + Long insertPanelId = sqlRunner.insertForGeneratedKey(this.connection, panelEntity); + + // add Asset Info Chart + String assetInfoTemplJsonStr = SqlExecutor.query(this.connection, "SELECT param_value FROM sys_config WHERE param_key = ?", new StringHandler(), Constant.SYSCONFIG_KEY_ASSET_CHART_TPL); + + Entity chartEntity = Entity.create("visual_chart"); + + JSONObject chartTemplate = JSONObject.parseObject(assetInfoTemplJsonStr); + for (Map.Entry<String, Object> entry : chartTemplate.entrySet()) { + chartEntity.set(entry.getKey(), entry.getValue()); + } + chartEntity.set("panel_id", insertPanelId); + chartEntity.set("group_id", 0); + chartEntity.set("weight", 0); + chartEntity.set("datasource", Constant.ChartDatasourceType.SYSTEM.getValue()); + chartEntity.set("update_by", panelEntity.get("create_by")); + chartEntity.set("update_at", new Date()); + + // insert asset info chart + sqlRunner.insert(this.connection, chartEntity); + return insertPanelId; + } + + + /** + * get Asset Panel ID List By The Model + * + * @param modelId + * @return + * @throws SQLException + */ + private List<String> getAssetPanelListByTheModel(String modelId) throws SQLException { + List<Entity> assetList = sqlRunner.findAll(this.connection, Entity.create("asset_asset").set("model_id", modelId)); + if (Tool.CollUtil.isEmpty(assetList)) { + return Tool.ListUtil.empty(); + } + + List<String> assetIdList = assetList.stream().map(entity -> entity.getStr("id")).collect(Collectors.toList()); + + List<Entity> assetPanelList = sqlRunner.findAll(this.connection, Entity.create("visual_panel").set("type", "asset").set("link", assetIdList)); + List<String> assetPanelIdList = assetPanelList.stream().map(entity -> entity.getStr("id")).collect(Collectors.toList()); + return assetPanelIdList; + } + + + /** + * update Asset Chart Template Link Val By The Model + * + * @param newChartPid + * @param assetPanelIdList + * @param oldChartPid + */ + private void updateAssetChartTemplateLinkValByTheModel(String newChartPid, List<String> assetPanelIdList, String oldChartPid) throws SQLException { + if (Tool.CollUtil.isNotEmpty(assetPanelIdList)) { + sqlRunner.update(this.connection, + // record + Entity.create().set("pid", newChartPid), + // where + Entity.create("visual_chart").set("pid", oldChartPid).set("panel_id", assetPanelIdList)); + } + } + + + /** + * update Asset Panel Temp Id By The Model + * + * @param model + * @param assetPanelIdList + * @param templatePanelId + */ + private void updateAssetPanelTempIdByTheModel(Entity model, List<String> assetPanelIdList, Long templatePanelId) throws SQLException { + if (Tool.CollUtil.isEmpty(assetPanelIdList)) { + log.warn("[updateAssetPanelTempIdByTheModel] [no reference asset panel in this model. not update temp_id] [model info: {}]", model.getStr("id")); + } else { + log.info("[updateAssetPanelTempIdByTheModel] [model info: {}] [tempId: {}]", model.getStr("id"), templatePanelId); + sqlRunner.update(this.connection, + Entity.create().set("tmpl_id", templatePanelId), + Entity.create("visual_panel").set("id", assetPanelIdList) + ); + } + } + + /** + * save The List Of New Chart Element + * + * @param chartElementList + */ + private void saveTheListOfNewChartElement(List<Entity> chartElementList) throws SQLException { + log.info("[saveTheListOfNewChartElement] [size: {}]", chartElementList.size()); + if (Tool.CollUtil.isNotEmpty(chartElementList)) { + + // 防止 sql 过长,分割后拼接 sql 修改 + Integer batchSize = 1000; + Integer limit = (chartElementList.size() + batchSize - 1) / batchSize; + List<List<Entity>> splitVisualChartElementList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> chartElementList.stream().skip(a * batchSize).limit(batchSize).parallel().collect(Collectors.toList())).collect(Collectors.toList()); + + SQLUtils.FormatOption formatOption = new SQLUtils.FormatOption(false, false); + for (List<Entity> batchUpdateElementList : splitVisualChartElementList) { + List<String> list = Tool.ListUtil.list(true); + for (Entity entity : batchUpdateElementList) { + String sqlStr = "INSERT INTO visual_chart_element(`id`, `chart_id`, `expression`, `type`, `legend`, `build_in`, `seq`, `name`, `state`) VALUES (null, ?, ?, ?, ?, ?, ?, ?, ?)"; + List<Object> mappingValues = Tool.ListUtil.of( + entity.get("chart_id"), + entity.getStr("expression"), + entity.getStr("type"), + entity.getStr("legend"), + entity.get("build_in"), + entity.getStr("seq"), + entity.getStr("name"), + entity.get("state") + ); + String sql = SQLUtils.format(sqlStr, DbType.mariadb, mappingValues, formatOption); + list.add(sql); + } + // execute Batch + SqlExecutor.executeBatch(this.connection, list); + } + } + } + +} diff --git a/nz-admin/src/main/java/com/nis/common/utils/Constant.java b/nz-admin/src/main/java/com/nis/common/utils/Constant.java index e0a88bf9..dc49aaf0 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/Constant.java +++ b/nz-admin/src/main/java/com/nis/common/utils/Constant.java @@ -1,26 +1,13 @@ -/** - - * - - * - - */ - package com.nis.common.utils; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.poi.util.TempFile; - import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; +import org.apache.poi.util.TempFile; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.*; /** * 常量 @@ -306,6 +293,8 @@ public class Constant { CHART_SINGLESTAT_STATISTICS.add("last"); CHART_SINGLESTAT_STATISTICS.add("range"); CHART_SINGLESTAT_STATISTICS.add("different"); + CHART_SINGLESTAT_STATISTICS.add("first*"); + CHART_SINGLESTAT_STATISTICS.add("last*"); RULE_OPERATORS = Arrays.asList(new String[] { "==", "!=", ">", "<", ">=", "<=" }); @@ -627,25 +616,6 @@ public class Constant { } } - public enum PanelType { - DASHBOARD("dashboard"), ASSET("asset"), PROJECT("project"), MODULE("module"), ENDPOINT("endpoint"), - MODEL("model"), TEMPLATE("template"), OVERVIEW("overview"); - - private String value; - - PanelType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - /** * chart Variable type enum */ @@ -726,6 +696,25 @@ public class Constant { } } + public enum AssetPingFrom { + GLOBAL("1"), + PER_DATACENTER("2"); + + private String value; + + AssetPingFrom(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + // nz-web 新增常量 // 字典表中 chart 类型的 type 值 @@ -792,9 +781,15 @@ public class Constant { // cortex.yml 配置模板 public static final String SYSCONFIG_KEY_CORTEX_YML_TMPL = "cortex_yml_tmpl"; + // cortex.yml 初始文件配置模板 + public static final String SYSCONFIG_KEY_CORTEX_INIT_YML_TMPL = "cortex_init_yml_tmpl"; + // loki.yml 配置模板 public static final String SYSCONFIG_KEY_LOKI_YML_TMPL = "loki_yml_tmpl"; + // loki.yml 初始文件配置模板 + public static final String SYSCONFIG_KEY_LOKI_INIT_YML_TMPL = "loki_init_yml_tmpl"; + // promtail.yml 配置模板 public static final String SYSCONFIG_KEY_PROMTAIL_YML_TMPL = "promtail_yml_tmpl"; @@ -890,7 +885,8 @@ public class Constant { // alert rule 导入表头 public static final String SYSCONFIG_KEY_ALERTRULE_EXPORT_HEADER = "rule_export_header"; - // chart dashboard 类型导入表头 + // dashboard 类型导入表头 + public static final String SYSCONFIG_KEY_DASHBOARD_EXPORT_HEADER = "dashboard_export_header"; public static final String SYSCONFIG_KEY_CHART_EXPORT_HEADER = "chart_export_header"; // asset 类型导入表头 @@ -980,11 +976,8 @@ public class Constant { // 资产服务器类型 public static final String ASSET_SERVER_TYPE = "server"; - // panel chart link 链表结构 首位 prev 值 - public static final Integer START_PREV_VALUE = 0; - // panel chart link 链表结构 末尾 next 值 - public static final Integer END_NEXT_VALUE = -1; + // 连接smtp邮箱服务器超时时间 10秒 public static final String CONNECTION_SMTP_TIMEOUT = "10000"; @@ -1095,6 +1088,9 @@ public class Constant { public static final String SERVER_ID = Tool.IdUtil.fastUUID(); public static final String SYS_HA_LOCK = "sys_ha_lock"; + // sys_backup redis lock + public static final String SYS_BACKUP_LOCK = "lock_sys_backup"; + public static final String NEZHA_ROOT_PATH = StrUtil.subBefore(System.getProperty("user.dir"), StrUtil.C_SLASH, true); public static final String NZWEB_ROOT_PATH = NEZHA_ROOT_PATH + "/nz-web"; @@ -1178,7 +1174,7 @@ public class Constant { * 全局搜索范围 */ public static final List<String> SEARCH_SCOPE = Tool.ListUtil.of("asset", "datacenter", "project", "module", - "endpoint", "panel", "alertrule", "model", "user"); + "endpoint", "dashboard", "alertrule", "model", "user"); public static final List<String> MESSAGE_SCOPE = Tool.ListUtil.of("asset", "datacenter", "project", "module", "endpoint", "alertrule", "hash"); @@ -1200,25 +1196,52 @@ public class Constant { * 导入导出支持的文件类型 */ public enum ImportFileType { - EXCEL("1"), - CSV("2"), - JSON("3"); - - private String value; - - public String getValue() { - return value; - } - - ImportFileType(String value) { - this.value = value; - } - - public static ImportFileType getType(String value) { - for (ImportFileType v : values()) - if (v.getValue().equalsIgnoreCase(value)) return v; - throw new IllegalArgumentException(); - } + XLSX("xlsx", "1"), + XLS("xls", "1"), + CSV("csv", "2"), + JSON("json", "3"); + + private String type; + private String value; + + ImportFileType(String type, String value) { + this.type = type; + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public static ImportFileType getInstanceByType(String type) { + for (ImportFileType v : values()) { + if (StrUtil.equalsIgnoreCase(v.getType(), type)) { + return v; + } + } + throw new IllegalArgumentException(); + } + + public static ImportFileType getInstanceByValue(String value) { + for (ImportFileType v : values()) { + if (StrUtil.equalsIgnoreCase(v.getValue(), value)) { + return v; + } + } + throw new IllegalArgumentException(); + } } public static final String ENDPOINT_METRICS_STATE_CACHE_KEY = "endpoint_metrics_state"; @@ -1261,4 +1284,46 @@ public class Constant { return value; } } + + /** + * prometheus 代理 path + */ + public static final String PROMETHEUS_READY_PATH = "/prometheus/proxy/-/ready"; + + public static final String PROMETHEUS_CONFIG_PATH = "/prometheus/proxy/api/v1/status/config"; + + public static final String PROMETHEUS_FLAGS_PATH = "/prometheus/proxy/api/v1/status/flags"; + + public static final String PROMETHEUS_BUILD_INFO_PATH = "/prometheus/proxy/api/v1/status/buildinfo"; + + public static final String PROMETHEUS_RUN_TIME_INFO_PATH = "/prometheus/proxy/api/v1/status/runtimeinfo"; + + public static final String PROMETHEUS_TSDB_PATH = "/prometheus/proxy/api/v1/status/tsdb"; + + /** + * cortex 代理 path + */ + public static final String CORTEX_READY_PATH = "/cortex/proxy/ready"; + + public static final String CORTEX_CONFIG_PATH = "/cortex/proxy/config"; + + public static final String CORTEX_SERVICES_PATH = "/cortex/proxy/services"; + + public static final String CORTEX_USER_STATS_PATH = "/cortex/proxy/api/v1/user_stats"; + + public static final String CORTEX_INGESTER_RING_PATH = "/cortex/proxy/ingester/ring"; + + public static final String CORTEX_STORE_GATEWAY_RING_PATH = "/cortex/proxy/store-gateway/ring"; + + /** + * loki 代理 path + */ + public static final String LOKI_READY_PATH = "/loki/proxy/ready"; + + public static final String LOKI_CONFIG_PATH = "/loki/proxy/config"; + + public static final String LOKI_SERVICES_PATH = "/loki/proxy/services"; + + public static final String LOKI_BUILD_INFO_PATH = "/loki/proxy/loki/api/v1/status/buildinfo"; + } diff --git a/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java b/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java index 58e5e190..df61699d 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java +++ b/nz-admin/src/main/java/com/nis/common/utils/ExcelUtils.java @@ -19,7 +19,6 @@ import java.io.InputStream; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.Map; @@ -37,6 +36,7 @@ public class ExcelUtils { static { numberFormat.setGroupingUsed(false); + numberFormat.setMaximumFractionDigits(7); } /** diff --git a/nz-admin/src/main/java/com/nis/common/utils/HaspUtil.java b/nz-admin/src/main/java/com/nis/common/utils/HaspUtil.java index b80009f8..312865f3 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/HaspUtil.java +++ b/nz-admin/src/main/java/com/nis/common/utils/HaspUtil.java @@ -21,7 +21,11 @@ public class HaspUtil { + "<haspscope>\n" + "<hasp id=\"%s\" />\n" + "</haspscope>\n";; - + protected final static String KEY_FEATURE_ID_SCOPE = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + + "<haspscope>\n" + + "<feature id=\"%s\" />\n" + + "</haspscope>\n"; + /** Runtime query view */ protected final static String KEY_VIEW = "<haspformat format=\"host_fingerprint\"/>"; @@ -159,12 +163,18 @@ public class HaspUtil { return licenseInfo; }else { hasp = new Hasp(featureId); - String infos = hasp.getInfo(KEY_SCOPE, KEY_VIEW, vendorCode); + //先通过 feature id 尝试获取,包含 hasp id + String infos = hasp.getInfo(KEY_SCOPE, KEY_C2V_FORMAT, vendorCode); status = hasp.getLastError(); - log.info("license status: {}", status); - if(status != HaspStatus.HASP_STATUS_OK) { - log.error("Error: getLicense c2v Fails with status code :{}",status); - throw new NZException(RCode.LICENSE_ERROR_CODE.setParam(status)); + if(status != HaspStatus.HASP_STATUS_OK || Tool.StrUtil.isBlank(infos)) { + // feature 获取失败,只获取机器指纹 + infos = hasp.getInfo(KEY_SCOPE, KEY_VIEW, vendorCode); + status = hasp.getLastError(); + log.info("license status: {}", status); + if(status != HaspStatus.HASP_STATUS_OK) { + log.error("Error: getLicense c2v Fails with status code :{}",status); + throw new NZException(RCode.LICENSE_ERROR_CODE.setParam(status)); + } } return infos; } diff --git a/nz-admin/src/main/java/com/nis/common/utils/JSONUtil.java b/nz-admin/src/main/java/com/nis/common/utils/JSONUtil.java index 6117abfe..e6d476d4 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/JSONUtil.java +++ b/nz-admin/src/main/java/com/nis/common/utils/JSONUtil.java @@ -763,7 +763,7 @@ public class JSONUtil { * @since 3.1.2 */ public static String formatJsonStr(String jsonStr) { - return JSONStrFormater.format(jsonStr); + return JSONStrFormatter.format(jsonStr); } /** diff --git a/nz-admin/src/main/java/com/nis/common/utils/NzExpressionUtil.java b/nz-admin/src/main/java/com/nis/common/utils/NzExpressionUtil.java index 319b9785..5d8d828d 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/NzExpressionUtil.java +++ b/nz-admin/src/main/java/com/nis/common/utils/NzExpressionUtil.java @@ -77,7 +77,8 @@ public class NzExpressionUtil { Map<String, List<String>> map = fields.stream().collect(Collectors.toMap(AssetFieldMeta::getMetaKey, AssetFieldMeta::getValue)); Map<String, String> keyTypeMap = fields.stream().collect(Collectors.toMap(AssetFieldMeta::getMetaKey, AssetFieldMeta::getType)); if(expre.contains(StrUtil.DOT)) { - expre = StrUtil.split(expre, StrUtil.DOT)[1]; + List<String> split = StrUtil.split(expre, StrUtil.DOT); + expre = split.get(1); } try { Pattern pattern = Pattern.compile("(\\[)(.+?)(\\])"); @@ -129,7 +130,8 @@ public class NzExpressionUtil { Map<String, List<String>> map = fields.stream().collect(Collectors.toMap(AssetFieldMeta::getMetaKey, AssetFieldMeta::getValue)); Map<String, String> keyTypeMap = fields.stream().collect(Collectors.toMap(AssetFieldMeta::getMetaKey, AssetFieldMeta::getType)); if(expre.contains(StrUtil.DOT)) { - expre = StrUtil.split(expre, StrUtil.DOT)[1]; + List<String> split = StrUtil.split(expre, StrUtil.DOT); + expre = split.get(1); } try { Pattern pattern = Pattern.compile("(\\[)(.+?)(\\])"); diff --git a/nz-admin/src/main/java/com/nis/common/utils/LockUtils.java b/nz-admin/src/main/java/com/nis/common/utils/RedisLock.java index 83e45bc2..d6dbdb59 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/LockUtils.java +++ b/nz-admin/src/main/java/com/nis/common/utils/RedisLock.java @@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit; * redis 分布式锁 */ @Component -public class LockUtils { +public class RedisLock { @Autowired private StringRedisTemplate stringRedisTemplate; diff --git a/nz-admin/src/main/java/com/nis/common/utils/ResponseUtil.java b/nz-admin/src/main/java/com/nis/common/utils/ResponseUtil.java index 3935fd6c..c04a0ed9 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/ResponseUtil.java +++ b/nz-admin/src/main/java/com/nis/common/utils/ResponseUtil.java @@ -21,7 +21,7 @@ public class ResponseUtil { */ public static void downloadFile(HttpServletResponse response, File file) throws IORuntimeException, IOException { response.setContentType(ResponseUtil.getDownloadContentType(file.getName())); - String fileName = Tool.URLUtil.encode(file.getName(), Tool.CharsetUtil.UTF_8); + String fileName = Tool.URLUtil.encode(file.getName(), Tool.CharsetUtil.CHARSET_UTF_8); // response.addHeader("Content-Disposition", "attachment; filename=" + fileName); // response.addHeader("Content-Length", "" + file.length()); // response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); @@ -42,7 +42,7 @@ public class ResponseUtil { public static void downloadFile(HttpServletResponse response, String filename, byte[] data) throws IORuntimeException, IOException { response.setContentType(ResponseUtil.getDownloadContentType(filename)); - String fileName = Tool.URLUtil.encode(filename, Tool.CharsetUtil.UTF_8); + String fileName = Tool.URLUtil.encode(filename, Tool.CharsetUtil.CHARSET_UTF_8); // response.addHeader("Content-Disposition", "attachment; filename=" + fileName); // response.addHeader("Content-Length", "" + data.length); // response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); diff --git a/nz-admin/src/main/java/com/nis/common/utils/SshUtil.java b/nz-admin/src/main/java/com/nis/common/utils/SshUtil.java index 06623979..46ab7ba8 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/SshUtil.java +++ b/nz-admin/src/main/java/com/nis/common/utils/SshUtil.java @@ -4,9 +4,9 @@ import cn.hutool.core.io.FileUtil; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; -import com.jcraft.jsch.UserInfo; import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.terminal.config.SshUserInfo; +import com.nis.modules.terminal.utils.SshUserInfo; +import com.nis.modules.terminal.utils.TerminalConstant; import java.io.ByteArrayInputStream; import java.io.File; @@ -16,55 +16,68 @@ import static com.nis.common.utils.CommonUtils.notEmpty; /** * 该类用以提供程序进行ssh连接服务器 - * @author Th * + * @author Th */ public class SshUtil { - - public static Session getSshConnection(AssetAsset asset) throws JSchException { - JSch jSch =new JSch(); - Session session = jSch.getSession(asset.getAuthUsername(), asset.getManageIp(), asset.getAuthProtocolPort()); - Integer sshType = asset.getAuthType(); + + // session connectTimeout + public static final int SESSION_TIMEOUT = 60000; + + // session client Server Alive Interval + public static final int SESSION_SERVER_ALIVE_INTERVAL = 60 * 1000; + + /** + * get Ssh Connection + * + * @param asset + * @return + * @throws JSchException + */ + public static Session getSshConnection(AssetAsset asset) throws JSchException { + JSch jSch = new JSch(); + Session session = jSch.getSession(asset.getAuthUsername(), asset.getManageIp(), asset.getAuthProtocolPort()); + + TerminalConstant.SshAuthType sshType = TerminalConstant.SshAuthType.getEntityByType(asset.getAuthType()); switch (sshType) { - case 2: { + case KEY: { String privateKey = asset.getAuthPriKey(); String keyPassword = asset.getAuthPin(); if (notEmpty(privateKey)) { File keyFile = FileUtil.file(asset.getPrivateKeyPath()); if (!keyFile.exists()) { //将数据库中的私钥写到用户的机器上 - FileUtil.writeFromStream(new ByteArrayInputStream(privateKey.getBytes()),keyFile); + FileUtil.writeFromStream(new ByteArrayInputStream(privateKey.getBytes()), keyFile); } if (notEmpty(keyPassword)) { //设置带口令的密钥 - jSch.addIdentity(asset.getPrivateKeyPath(), keyPassword); + jSch.addIdentity(asset.getPrivateKeyPath(), StringUtils.str(Base64.getDecoder().decode(keyPassword))); } else { //设置不带口令的密钥 jSch.addIdentity(asset.getPrivateKeyPath()); } - UserInfo userInfo = new SshUserInfo(); - session.setUserInfo(userInfo); + session.setUserInfo(new SshUserInfo()); } session.setConfig("StrictHostKeyChecking", "no"); break; } - case 1: { + case PIN: { session.setConfig("StrictHostKeyChecking", "no"); session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password"); - session.setPassword(new String(Base64.getDecoder().decode(asset.getAuthPin()))); + session.setPassword(StringUtils.str(Base64.getDecoder().decode(asset.getAuthPin()))); break; } - default: { - } + default: + break; } -// session.setServerAliveInterval(SERVER_ALIVE_INTERVAL); - session.connect(5000); + session.setServerAliveInterval(SESSION_SERVER_ALIVE_INTERVAL); + session.connect(SESSION_TIMEOUT); return session; - } - - public static void close(Session session) { - if(ToolUtil.isNotEmpty(session)) { - session.disconnect(); - } - } + } + + public static void close(Session session) { + if (ToolUtil.isNotEmpty(session)) { + session.disconnect(); + } + } } diff --git a/nz-admin/src/main/java/com/nis/common/utils/Tool.java b/nz-admin/src/main/java/com/nis/common/utils/Tool.java index cae25770..08caf629 100644 --- a/nz-admin/src/main/java/com/nis/common/utils/Tool.java +++ b/nz-admin/src/main/java/com/nis/common/utils/Tool.java @@ -682,7 +682,7 @@ public class Tool { * @author xiaoleilu * @deprecated 使用TemplateUtil替代 */ - public static class VelocityUtil extends cn.hutool.extra.template.engine.velocity.VelocityUtil { + public static class VelocityEngine extends cn.hutool.extra.template.engine.velocity.VelocityEngine { } /** diff --git a/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentController.java b/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentController.java index 47ea2a41..9e8ff416 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentController.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentController.java @@ -1,54 +1,31 @@ package com.nis.modules.agent.controller; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ThreadPoolExecutor; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.HashOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.log.Log; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.CommonUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.TemplateUtil; -import com.nis.common.utils.Tool; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.AgentService; import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.sys.service.SysConfigService; - -import cn.hutool.core.net.url.UrlBuilder; -import cn.hutool.log.Log; import freemarker.template.Template; import freemarker.template.TemplateException; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ThreadPoolExecutor; @RestController @RequestMapping("/agent") diff --git a/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentProxyController.java b/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentProxyController.java new file mode 100644 index 00000000..81648dc9 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/agent/controller/AgentProxyController.java @@ -0,0 +1,471 @@ +package com.nis.modules.agent.controller; + +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.core.net.url.UrlPath; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.Constant; +import com.nis.common.utils.R; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.agent.util.AgentUtil; +import com.nis.modules.sys.service.SysConfigService; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.io.FileNotFoundException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/agent") +public class AgentProxyController { + + private Log log = Log.get(); + + + @Autowired + private AgentService agentService; + + @Autowired + private SysConfigService configService; + + /** + * prometheus ready 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/ready") + public R ready(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_READY_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + return R.ok().putData("status", result); + } else { + return R.error(500, "prometheus proxy request ready error"); + } + } + + /** + * prometheus config 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/api/v1/status/config") + public R config(@PathVariable("id") Integer id) throws FileNotFoundException { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_CONFIG_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + R resultObj = JSONObject.parseObject(result, R.class); + String config = JSONPath.read(resultObj.get("data").toString(),"yaml").toString(); + return R.ok().putData("content",config); + } else { + return R.error(500, "prometheus proxy request config error"); + } + + } + + /** + * prometheus flags 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/api/v1/status/flags") + public R flags(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_FLAGS_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + if (Tool.StrUtil.isNotEmpty(result)) { + return Tool.JSONUtil.toBean(result, R.class); + } else { + return R.error(500, "prometheus proxy request flags error"); + } + } + + /** + * prometheus buildinfo 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/api/v1/status/buildinfo") + public R buildInfo(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_BUILD_INFO_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + if (Tool.StrUtil.isNotEmpty(result)) { + return Tool.JSONUtil.toBean(result, R.class); + } else { + return R.error(500, "prometheus proxy request buildinfo error"); + } + } + + /** + * prometheus runtimeinfo 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/api/v1/status/runtimeinfo") + public R runTimeInfo(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_RUN_TIME_INFO_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + if (Tool.StrUtil.isNotEmpty(result)) { + return Tool.JSONUtil.toBean(result, R.class); + } else { + return R.error(500, "prometheus proxy request runtimeinfo error"); + } + } + + /** + * prometheus tsdb 接口 + * @param id + * @return + */ + @GetMapping("/{id}/prometheus/api/v1/status/tsdb") + public R tsdb(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.PROMETHEUS_TSDB_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + if (Tool.StrUtil.isNotEmpty(result)) { + return Tool.JSONUtil.toBean(result, R.class); + } else { + return R.error(500, "prometheus proxy request tsdb error"); + } + } + + + + /** + * cortex ready 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/ready") + public R cortexReady(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.CORTEX_READY_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + return R.ok().putData("status", result); + } else { + return R.error(500, "cortex proxy request ready error"); + } + } + + /** + * cortex config 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/config") + public R cortexConfig(@PathVariable("id") Integer id, @RequestParam(required = false, defaultValue = "") String mode) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String queryString = String.format("mode=%s" ,mode); + String result = AgentUtil.requestGet(agent, Constant.CORTEX_CONFIG_PATH, queryString, String.class); + // 响应结果 + if (Tool.ObjectUtil.isNotEmpty(result)) { + return R.ok().putData("content", result); + } else { + return R.error(500, "cortex proxy request config error"); + } + } + + /** + * cortex service 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/services") + public R cortexServices(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.CORTEX_SERVICES_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + List<Map> services = (List<Map>) JSONPath.read(result, "services"); + return R.ok().putData("list", services); + } else { + return R.error(500, "cortex proxy request services error"); + } + } + + /** + * cortex user_stats 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/api/v1/user_stats") + public R cortexUserStats(@PathVariable("id") Integer id, @RequestParam(required = false, defaultValue = "") String mode) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String queryString = String.format("mode=%s" ,mode); + String result = AgentUtil.requestGet(agent, Constant.CORTEX_USER_STATS_PATH, queryString, String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + Map map = JSONObject.parseObject(result, Map.class); + return R.ok(map); + } else { + return R.error(500, "cortex proxy request user stats error"); + } + } + + + /** + * cortex ingester ring 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/ingester/ring") + public R cortexIngesterRing(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.CORTEX_INGESTER_RING_PATH); + String result = AgentUtil.requestAgentProxy(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + List<Map> map = Tool.ListUtil.list(false); + //解析 html + Document parse = Jsoup.parse(result); + Elements tbody = parse.getElementsByTag("tbody"); + for (Element element : tbody) { + Elements trs = element.getElementsByTag("tr"); + for (Element tr : trs) { + Elements childrens = tr.children(); + Map<Object, Object> results = Tool.MapUtil.builder() + .put("instanceId", childrens.get(0).getElementsByTag("td").text()) + .put("zone", childrens.get(1).getElementsByTag("td").text()) + .put("state", childrens.get(2).getElementsByTag("td").text()) + .put("address", childrens.get(3).getElementsByTag("td").text()) + .put("registeredAt", childrens.get(4).getElementsByTag("td").text()) + .put("heartbeat", childrens.get(5).getElementsByTag("td").text()) + .put("tokens", childrens.get(6).getElementsByTag("td").text()) + .put("ownership", childrens.get(7).getElementsByTag("td").text()) + .build(); + map.add(results); + } + } + return R.ok().putData("list", map); + } else { + return R.error(500, "cortex proxy request ingester ring error"); + } + } + + /** + * cortex store-gateway ring 接口 + * @param id + * @return + */ + @GetMapping("/{id}/cortex/store-gateway/ring") + public R cortexStoreGatewayRing(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.CORTEX_STORE_GATEWAY_RING_PATH); + String result = AgentUtil.requestAgentProxy(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + List<Map> map = Tool.ListUtil.list(false); + //解析 html + Document parse = Jsoup.parse(result); + Elements tbody = parse.getElementsByTag("tbody"); + for (Element element : tbody) { + Elements trs = element.getElementsByTag("tr"); + for (Element tr : trs) { + //获取 td 标签集合 + Elements childrens = tr.children(); + Map<Object, Object> results = Tool.MapUtil.builder() + .put("instanceId", childrens.get(0).getElementsByTag("td").text()) + .put("zone", childrens.get(1).getElementsByTag("td").text()) + .put("state", childrens.get(2).getElementsByTag("td").text()) + .put("address", childrens.get(3).getElementsByTag("td").text()) + .put("registeredAt", childrens.get(4).getElementsByTag("td").text()) + .put("heartbeat", childrens.get(5).getElementsByTag("td").text()) + .put("tokens", childrens.get(6).getElementsByTag("td").text()) + .put("ownership", childrens.get(7).getElementsByTag("td").text()) + .build(); + map.add(results); + } + } + return R.ok().putData("list", map); + } else { + return R.error(500, "cortex proxy request store-gateway ring error"); + } + } + + + + /** + * loki ready + * @param id + * @return + */ + @GetMapping("/{id}/loki/ready") + public R lokiReady(@PathVariable("id") Integer id){ + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.LOKI_READY_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + return R.ok().putData("status", result); + } else { + return R.error(500, "loki proxy request ready error"); + } + } + + + /** + * loki config + * @param id + * @return + */ + @GetMapping("/{id}/loki/config") + public R lokiConfig(@PathVariable("id") Integer id, @RequestParam(required = false, defaultValue = "") String mode) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String result = AgentUtil.requestGet(agent, Constant.LOKI_CONFIG_PATH, String.format("mode=%s" ,mode), String.class); + // 响应结果 + if (Tool.ObjectUtil.isNotEmpty(result)) { + return R.ok().putData("content", result); + } else { + return R.error(500, "loki proxy request config error"); + } + } + + /** + * loki service + * @param id + * @return + */ + @GetMapping("/{id}/loki/services") + public R lokiServices(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.LOKI_SERVICES_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + List<String> lokiTargets = null; + // 响应结果 + if (Tool.StrUtil.isNotEmpty(result)) { + lokiTargets = Arrays.asList(result.split("\n")); + List<Map> services = lokiTargets.stream() + .map(target -> Tool.MapUtil.builder() + .put("service", Arrays.asList(target.split("=>")).get(0).trim()) + .put("status",Arrays.asList(target.split("=>")).get(1).trim()) + .build()) + .collect(Collectors.toList()); + return R.ok().putData("list", services); + } else { + return R.error(500, "loki proxy request services error"); + } + } + + + /** + * loki buildinfo + * @param id + * @return + */ + @GetMapping("/{id}/loki/api/v1/status/buildinfo") + public R lokiBuildInfo(@PathVariable("id") Integer id) { + ValidateUtils.is(id).notNull(RCode.AGENT_ID_ISNULL); + //获取可用的 agent + Agent agent = agentService.getOne(new LambdaUpdateWrapper<Agent>().eq(Agent::getId, id).eq(Agent::getStatus, "1")); + ValidateUtils.is(agent).notNull(RCode.AGENT_UNAVAILABLE); + + String url = this.buildUrl(agent, Constant.LOKI_BUILD_INFO_PATH); + String result = AgentUtil.requestGet(url, agent.getToken(), String.class); + if (Tool.StrUtil.isNotEmpty(result)) { + return R.ok(JSONObject.parseObject(result)); + } else { + return R.error(500, "loki proxy request buildinfo error"); + } + } + + + + /** + * 构造请求路径 + * @param server + * @param path + * @return + */ + public String buildUrl(Agent server, String path){ + String agentPath = configService.getValueOrDefault(Constant.CONFAGENT_PATH, ""); + path = path.startsWith("/") ? (String.format("%s%s", agentPath, path)) + : (String.format("%s/%s", agentPath, path)); + UrlBuilder urlString = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) + .setPort(server.getPort()).setPath(UrlPath.of(path, Charset.forName("UTF-8"))); + + return urlString.build(); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/agent/interceptor/EventLogSqlInterceptor.java b/nz-admin/src/main/java/com/nis/modules/agent/interceptor/EventLogSqlInterceptor.java index a4e402a4..e47157fb 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/interceptor/EventLogSqlInterceptor.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/interceptor/EventLogSqlInterceptor.java @@ -9,9 +9,9 @@ import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.stat.TableStat; import com.nis.common.utils.Constant; import com.nis.common.utils.Tool; -import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.AgentService; +import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.sys.entity.SysConfigEntity; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; diff --git a/nz-admin/src/main/java/com/nis/modules/agent/job/AgentConfigUtil.java b/nz-admin/src/main/java/com/nis/modules/agent/job/AgentConfigUtil.java index 411b43e3..f8b15d71 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/job/AgentConfigUtil.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/job/AgentConfigUtil.java @@ -13,7 +13,9 @@ import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.*; import com.nis.modules.agent.dao.MonitorEventLogDao; +import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.entity.MonitorEventLog; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.alert.entity.AlertRuleEntity; import com.nis.modules.alert.entity.AlertSeverityConf; @@ -29,8 +31,6 @@ import com.nis.modules.endpoint.service.MonitorEndpointStateService; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.module.service.MonitorModuleService; import com.nis.modules.project.entity.MonitorProject; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.AgentService; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.service.SysConfigService; import freemarker.template.Template; @@ -49,7 +49,7 @@ import java.util.stream.Collectors; @Component public class AgentConfigUtil { - private static Log log = Log.get(); + private static final Log log = Log.get(); @Value("${nezha.lokiDefaultPort:13100}") private Integer lokiDefaultPort; @@ -1460,4 +1460,71 @@ public class AgentConfigUtil { redisTemplate.opsForHash().put(Constant.AGENT_STATE_CACHE_KEY, agent.getId().toString(), JSON.toJSONString(agent)); agentService.updateById(agent); } + + /** + * generate Init Cortex Yml + * + * @return + */ + public Map generateInitCortexYml() { + List<SysConfigEntity> sysConfigList = sysConfigService.list(); + Map<String, String> sysConfiMap = sysConfigList.stream() + .collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + + // template variables + Map<Object, Object> params = Tool.MapUtil.builder() + .put("systemConfig", sysConfiMap) + .build(); + + log.info("[generateInitCortexYml] [begin]"); + String content = StrUtil.EMPTY; + try { + String cortexInitYmlTmpl = sysConfigService.getValue(Constant.SYSCONFIG_KEY_CORTEX_INIT_YML_TMPL); + // 渲染 + Template template = TemplateUtil.stringToTemplate(cortexInitYmlTmpl, Constant.SYSCONFIG_KEY_CORTEX_INIT_YML_TMPL); + content = FreeMarkerTemplateUtils.processTemplateIntoString(template, params); + + // JSON Str to JSON Obj + Map ymlMap = JSONObject.parseObject(content, LinkedHashMap.class, Feature.OrderedField); + log.info("[generateInitCortexYml] [finshed]"); + return ymlMap; + } catch (Exception e) { + log.error(e, "[generateInitCortexYml] [error] [content: {}]", content); + } + return Tool.MapUtil.empty(); + } + + /** + * generate Init Loki Yml + * + * @return + */ + public Map generateInitLokiYml() { + List<SysConfigEntity> sysConfigList = sysConfigService.list(); + Map<String, String> sysConfiMap = sysConfigList.stream() + .collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + + // template variables + Map<Object, Object> params = Tool.MapUtil.builder() + .put("systemConfig", sysConfiMap) + .build(); + + log.info("[generateInitLokiYml] [begin]"); + String content = StrUtil.EMPTY; + + try { + String cortexInitYmlTmpl = sysConfigService.getValue(Constant.SYSCONFIG_KEY_LOKI_INIT_YML_TMPL); + // 渲染 + Template template = TemplateUtil.stringToTemplate(cortexInitYmlTmpl, Constant.SYSCONFIG_KEY_LOKI_INIT_YML_TMPL); + content = FreeMarkerTemplateUtils.processTemplateIntoString(template, params); + + // JSON Str to JSON Obj + Map ymlMap = JSONObject.parseObject(content, LinkedHashMap.class, Feature.OrderedField); + log.info("[generateInitLokiYml] [finshed]"); + return ymlMap; + } catch (Exception e) { + log.error(e, "[generateInitLokiYml] [error] [content: {}]", content); + } + return Tool.MapUtil.empty(); + } } diff --git a/nz-admin/src/main/java/com/nis/modules/agent/job/AgentHealthCheckJob.java b/nz-admin/src/main/java/com/nis/modules/agent/job/AgentHealthCheckJob.java index a78ab9f1..45cdd726 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/job/AgentHealthCheckJob.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/job/AgentHealthCheckJob.java @@ -6,9 +6,9 @@ import cn.hutool.log.Log; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.nis.common.utils.*; -import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.AgentService; +import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.sys.service.SysConfigService; import org.apache.commons.lang3.time.StopWatch; import org.quartz.DisallowConcurrentExecution; diff --git a/nz-admin/src/main/java/com/nis/modules/agent/job/AutoConfigAgentJob.java b/nz-admin/src/main/java/com/nis/modules/agent/job/AutoConfigAgentJob.java index e24044cb..55408fca 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/job/AutoConfigAgentJob.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/job/AutoConfigAgentJob.java @@ -2,25 +2,26 @@ package com.nis.modules.agent.job; import cn.hutool.core.map.MapUtil; import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.*; +import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.entity.MonitorEventLog; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.service.MonitorEndpointService; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.AgentService; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.service.SysConfigService; import lombok.Data; -import org.apache.commons.lang3.time.StopWatch; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -44,7 +45,7 @@ import java.util.stream.Collectors; @Data public class AutoConfigAgentJob extends QuartzJobBean { - private static Log log = Log.get(); + private static final Log log = Log.get(); @Autowired private RedisTemplate redisTemplate; @@ -71,71 +72,136 @@ public class AutoConfigAgentJob extends QuartzJobBean { Map<String, String> sysConfigMap = new HashMap(); @SuppressWarnings("unchecked") - @Override + @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { - Thread.currentThread().setName("AutoConfigAgentJob"); + Thread.currentThread().setName("AutoConfigAgentJob"); // 检查 haMode String serverId = (String) redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); - if (!StrUtil.equals(serverId, Constant.SERVER_ID)) return; + log.info("[AutoConfigAgentJob] [Get ha lock from redis] [server id: {}]", serverId); + if (!StrUtil.equals(serverId, Constant.SERVER_ID)) { + log.warn("[AutoConfigAgentJob] [did not get the ha lock, not run job] [redis server id: {}] [system server id: {}]", serverId, Constant.SERVER_ID); + return; + } - log.info("agent job 开始执行"); - StopWatch sw = new StopWatch(); - sw.start(); + log.info("[AutoConfigAgentJob] [Begin]"); try { - // 获取健康的 agent - List<Agent> healthyAgents = null; - List<String> agentCaches = redisTemplate.opsForHash().values(Constant.AGENT_STATE_CACHE_KEY); - if(ToolUtil.isNotEmpty(agentCaches)) { + List<Agent> healthyAgents = Tool.ListUtil.empty(); + List<String> agentCaches = redisTemplate.opsForHash().values(Constant.AGENT_STATE_CACHE_KEY); + if (ToolUtil.isNotEmpty(agentCaches)) { healthyAgents = agentCaches.stream().map(agentCache -> JSON.parseObject(agentCache, Agent.class)).filter(p -> p.getStatus().equals(1)).collect(Collectors.toList()); - }else { + log.info("[AutoConfigAgentJob] [Get healthy agent list from redis] [size: {}]", healthyAgents.size()); + } else { healthyAgents = agentService.list(new LambdaQueryWrapper<Agent>().eq(Agent::getStatus, 1)); - } - log.debug("健康的 Agents: " + JSONObject.toJSONString(healthyAgents)); + log.info("[AutoConfigAgentJob] [Get healthy agent list from db] [size: {}]", healthyAgents.size()); + } - // 没有可用的 global 不下发配置 - List<Agent> globalAgentList = healthyAgents.stream().filter(pojo -> Constant.AgentType.GLOBAL.getValue().equals(pojo.getType())).collect(Collectors.toList()); - if (Tool.CollectionUtil.isEmpty(globalAgentList)) return; + // healthy agent info + Map<Integer, String> healthyAgentInfoMap = healthyAgents.stream().collect(Collectors.toMap(Agent::getId, Agent::getName)); + log.info("[AutoConfigAgentJob] [Healthy agent] [size: {}] [detail: {}]", healthyAgentInfoMap.size(), JSONUtil.toJsonStr(healthyAgentInfoMap)); + if (log.isDebugEnabled()) { + log.debug("[AutoConfigAgentJob] [Healthy agents] [detail: {}]", JSONUtil.toJsonStr(healthyAgents)); + } - // sys_config 配置表信息 - List<SysConfigEntity> configEntityList = sysConfigService.list(); - sysConfigMap = configEntityList.stream().collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + List<SysConfigEntity> sysConfigList = sysConfigService.list(); + sysConfigMap = sysConfigList.stream().collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); - // 配置下发 - this.setUpAgentConfig(healthyAgents); - } catch (RuntimeException e) { - log.error("agent 同步异常", e); - } finally { - sw.stop(); - log.info("agent 执行结束,Run Time: {}", sw.toString()); + // get global agent + List<Agent> globalAgentList = healthyAgents.stream().filter(pojo -> ObjectUtil.equal(Constant.AgentType.GLOBAL.getValue(), pojo.getType())).collect(Collectors.toList()); + log.info("[AutoConfigAgentJob] [healthy global agent list] [size: {}]", globalAgentList.size()); + + if (Tool.CollectionUtil.isEmpty(globalAgentList)) { + // no healthy global agent + log.info("[AutoConfigAgentJob] [try To Set Up Agent Config]"); + this.trySetUpAgentConfig(); + } else { + // config agent + log.info("[AutoConfigAgentJob] [Set Up Agent Config]"); + this.setUpAgentConfig(healthyAgents); + } + } catch (Exception e) { + log.error(e, "[AutoConfigAgentJob] [Error]"); + } + log.info("[AutoConfigAgentJob] [Finshed]"); + } + + + /** + * no healthy global agent + * try To Set Up Agent Config + */ + private void trySetUpAgentConfig() { + // get Cortex Component Down Agent List + List<Agent> cortexComponentDownAgentList = this.getCortexComponentDownAgentList(); + log.info("[trySetUpAgentConfig] [cortex Component Down Agent List] [size: {}]", cortexComponentDownAgentList.size()); + + if (Tool.CollUtil.isNotEmpty(cortexComponentDownAgentList)) { + ThreadUtil.execAsync(() -> { + boolean cortexChangeFlag = configUtil.compareDataChanges("cortex"); + log.info("[trySetUpAgentConfig] [conf_event cortex state] [change: {}]", cortexChangeFlag); + + if (cortexChangeFlag) { + log.info("[trySetUpAgentConfig] [try to set up config to the down agent of cortex] [size: {}]", cortexComponentDownAgentList.size()); + if (log.isDebugEnabled()) { + log.debug("[trySetUpAgentConfig] [try to set up config to the down agent of cortex] [size: {}] [agent info: {}]", cortexComponentDownAgentList.size(), JSONUtil.toJsonStr(cortexComponentDownAgentList)); + } + + // try Set Up Config To Down Agent Of Cortex + this.trySetUpConfigToDownAgentOfCortex(cortexComponentDownAgentList); + } + }); + } + + // get Loki Component Down Agent List + List<Agent> lokiComponentDownAgentList = this.getLokiComponentDownAgentList(); + log.info("[trySetUpAgentConfig] [loki Component Down Agent List] [size: {}]", lokiComponentDownAgentList.size()); + if (Tool.CollUtil.isNotEmpty(lokiComponentDownAgentList)) { + ThreadUtil.execAsync(() -> { + boolean lokiChangeFlag = configUtil.compareDataChanges("loki"); + log.info("[trySetUpAgentConfig] [conf_event loki state] [change: {}]", lokiChangeFlag); + + if (lokiChangeFlag) { + log.info("[trySetUpAgentConfig] [try to set up config to the down agent of loki] [size: {}]", lokiComponentDownAgentList.size()); + if (log.isDebugEnabled()) { + log.debug("[trySetUpAgentConfig] [try to set up config to the down agent of loki] [size: {}] [agent info: {}]", lokiComponentDownAgentList.size(), JSONUtil.toJsonStr(lokiComponentDownAgentList)); + } + + // try Set Up Config To Down Agent Of Loki + this.trySetUpConfigToDownAgentOfLoki(lokiComponentDownAgentList); + } + }); } } - // 配置下发 + /** + * set Up to healeht Agent Config + * + * @param healthyPromServers + */ public void setUpAgentConfig(List<Agent> healthyPromServers) { ThreadUtil.execAsync(() -> { boolean promtailChangeFlag = configUtil.compareDataChanges("promtail"); MonitorEventLog monitorEventLog = eventLogService.getOne(new LambdaQueryWrapper<MonitorEventLog>().eq(MonitorEventLog::getEvent, "promtail")); - log.debug("conf_event promtail change : {}, value: {}",promtailChangeFlag , monitorEventLog.getCounter()); + log.info("[setUpAgentConfig] [conf_event promtail state] [change: {}] [value: {}]", promtailChangeFlag, monitorEventLog.getCounter()); this.udpatePromtailsConf(healthyPromServers, monitorEventLog.getCounter()); }); ThreadUtil.execAsync(() -> { boolean snmpChangeFlag = configUtil.compareDataChanges("snmp"); - log.debug(String.format("conf_event snmp 数据 %s 发生变化", snmpChangeFlag ? "" : "没有")); + log.info("[setUpAgentConfig] [conf_event snmp state] [change: {}]", snmpChangeFlag); if (snmpChangeFlag) this.updateSnmpExporterConf(healthyPromServers); }); ThreadUtil.execAsync(() -> { boolean prometheusChangeFlag = configUtil.compareDataChanges("prometheus"); - log.debug(String.format("conf_event prometheus 数据 %s 发生变化", prometheusChangeFlag ? "" : "没有")); + log.info("[setUpAgentConfig] [conf_event prometheus state] [change: {}]", prometheusChangeFlag); if (prometheusChangeFlag) this.updatePrometheusConf(healthyPromServers); }); ThreadUtil.execAsync(() -> { boolean lokiChangeFlag = configUtil.compareDataChanges("loki"); - log.debug(String.format("conf_event loki 数据 %s 发生变化", lokiChangeFlag ? "" : "没有")); + log.info("[setUpAgentConfig] [conf_event loki state] [change: {}]", lokiChangeFlag); if (lokiChangeFlag) this.updateLokiConf(healthyPromServers); }); @@ -143,10 +209,10 @@ public class AutoConfigAgentJob extends QuartzJobBean { ThreadUtil.execAsync(() -> { boolean cortexChangeFlag = configUtil.compareDataChanges("cortex"); - log.debug(String.format("conf_event cortex 数据 %s 发生变化", cortexChangeFlag ? "" : "没有")); + log.info("[setUpAgentConfig] [conf_event cortex state] [change: {}]", cortexChangeFlag); boolean ruleChangeFlag = configUtil.compareDataChanges("rule"); - log.debug(String.format("conf_event rule 数据 %s 发生变化", ruleChangeFlag ? "" : "没有")); + log.info("[setUpAgentConfig] [conf_event rule state] [change: {}]", ruleChangeFlag); // 是否更新 rule.yml 配置 String alertConfUpdate = sysConfigMap.get("nz_alert_rule_eval_enable"); @@ -405,36 +471,20 @@ public class AutoConfigAgentJob extends QuartzJobBean { configUtil.updateEndpointPromInRedis(endpointIdAndPromIdMap); } - // object storage 标识 1: 本地文件存储,2:S3对象存储 - String objStroageEnable = sysConfigService.getValue(Constant.SYSCONFIG_KEY_METRICS_STORAGE_TYPE); - boolean isLocalStorage = StrUtil.equals("1", objStroageEnable); - - // global config 配置文件处理 联邦 告警 rule.yml cortex + // global config 配置文件处理 联邦 for (int i = 0; i < globalPromServers.size(); i++) { Agent agent = globalPromServers.get(i); - Map<String, Object> globalConfigBody = new LinkedHashMap(4); - List<Integer> assetIdListForThisAgent = assetIdAndPromIdMap.entrySet().stream().filter(entry -> agent.getId().equals(entry.getValue())).map(Map.Entry::getKey).collect(Collectors.toList()); List<AssetAsset> assetListForThisAgent = blackboxAssetInfoList.stream().filter(asset -> assetIdListForThisAgent.contains(asset.getId())).collect(Collectors.toList()); List<Integer> endpointIdListForThisAgent = endpointIdAndPromIdMap.entrySet().stream().filter(entry -> agent.getId().equals(entry.getValue())).map(Map.Entry::getKey).collect(Collectors.toList()); List<MonitorEndpoint> endpointListForThisAgent = endpointList.stream().filter(endpoint -> endpointIdListForThisAgent.contains(endpoint.getId())).collect(Collectors.toList()); - Boolean isAlert = false; - // prometheus 本地存储 && alert rule.yml 配置变更 && first global - /*if (isLocalStorage && agentConfigMap.get("alertYml") != null && i == 0) { - isAlert = true; - log.debug("支持告警的 agent :" + JSONObject.toJSONString(promserver)); - }*/ - - Map gloablAgentYmlMap = configUtil.generateGlobalYml(agent, globalPromServers, perDataCenterPromServers, assetListForThisAgent, endpointListForThisAgent, isAlert, i == 0); + Map gloablAgentYmlMap = configUtil.generateGlobalYml(agent, globalPromServers, perDataCenterPromServers, assetListForThisAgent, endpointListForThisAgent, false, i == 0); + Map<String, Object> globalConfigBody = new LinkedHashMap(4); globalConfigBody.put("config", gloablAgentYmlMap); - if (isAlert) { - // globalConfigBody.put("rule", (Map) agentConfigMap.get("alertYml")); - // redisTemplate.opsForValue().set(Constant.REDIS_KEY_SUPPORT_ALERT_PROMSERVER_ID, promserver.getId().toString()); - } Map<String, String> sysCmdLineMap = configUtil.generatePrometheusCmdLine(); boolean cmdFlag = this.compareCmdLineChanges(agent, sysCmdLineMap); @@ -443,15 +493,14 @@ public class AutoConfigAgentJob extends QuartzJobBean { globalConfigBody.put("cmdline", sysCmdLineMap); } - String result = null; String path = "/prometheus/config"; try { - result = AgentUtil.request(agent, HttpMethod.POST,path, null, globalConfigBody, String.class); + result = AgentUtil.request(agent, HttpMethod.POST, path, null, globalConfigBody, String.class); } catch (RuntimeException e) { - log.error(e,"request error,path:{},agent:{}",path,Tool.JSONUtil.toJsonStr(agent)); + log.error(e, "request error,path:{},agent:{}", path, Tool.JSONUtil.toJsonStr(agent)); } - + // 下发失败,更新 prom 状态,造成conf_event 变更,下个周期继续下发配置 if (result == null) { configUtil.updateAgentStatus(agent, 0); @@ -567,33 +616,51 @@ public class AutoConfigAgentJob extends QuartzJobBean { * @param healthyPromServers */ private void updateLokiConf(List<Agent> healthyPromServers) { - // 无论联邦与否 最终数据都会存在 Global 所以 per-datacenter 不必下发 loki 配置 - List<Agent> globalPromServerList = healthyPromServers.stream().filter(pojo -> Constant.AgentType.GLOBAL.getValue().equals(pojo.getType())).collect(Collectors.toList()); - for (Agent agent : globalPromServerList) { - // 生成 loki 配置模板 - Map lokiYml = configUtil.generateLokiYml(agent,globalPromServerList); - Map<String, Object> lokiConfigBody = new HashMap<>(2); - lokiConfigBody.put("config", lokiYml); - - String result = null; - String path = "/loki/config"; - try { - result = AgentUtil.request(agent, HttpMethod.POST,path, null, lokiConfigBody, String.class); - } catch (RuntimeException e) { - log.error(e,"request error,path:{},agent:{}",path,Tool.JSONUtil.toJsonStr(agent)); - } - - // 下发失败,更新 prom 状态,造成 conf_event 变更,下个周期继续下发配置 - if (result == null) { - configUtil.updateAgentStatus(agent, 0); - } else { - configUtil.afterRequestApi(path, result, agent); + // try Set Up Config To Down Agent Of Loki + ThreadUtil.execAsync(() -> { + // get Loki Component Down Agent List + List<Agent> lokiComponentDownAgentList = this.getLokiComponentDownAgentList(); + log.info("[updateLokiConf] [loki Component Down Agent List] [size: {}]", lokiComponentDownAgentList.size()); + + // try Set Up Config To Down Agent Of Loki + this.trySetUpConfigToDownAgentOfLoki(lokiComponentDownAgentList); + }); + + // healthy agent config loki.yml + ThreadUtil.execAsync(() -> { + // 无论联邦与否 最终数据都会存在 Global 所以 per-datacenter 不必下发 loki 配置 + List<Agent> globalPromServerList = healthyPromServers.stream().filter(pojo -> Constant.AgentType.GLOBAL.getValue().equals(pojo.getType())).collect(Collectors.toList()); + for (Agent agent : globalPromServerList) { + // generate Loki Yml + Map lokiYml = configUtil.generateLokiYml(agent, globalPromServerList); + Map<String, Object> lokiConfigBody = new HashMap<>(2); + lokiConfigBody.put("config", lokiYml); + + String result = null; + String path = "/loki/config"; + try { + log.info("[updateLokiConf] [request agent /loki/config api begin] [agent id: {}]", agent.getId()); + if (log.isDebugEnabled()) { + log.info("[updateLokiConf] [request agent /loki/config api begin] [agent id: {}] [request body: {}]", agent.getId(), JSONUtil.toJsonStr(lokiConfigBody)); + } + result = AgentUtil.request(agent, HttpMethod.POST, path, null, lokiConfigBody, String.class); + log.info("[updateLokiConf] [request agent /loki/config api finshed] [agent id: {}]", agent.getId()); + } catch (RuntimeException e) { + log.error(e, "request error,path:{},agent:{}", path, Tool.JSONUtil.toJsonStr(agent)); + } + + // 下发失败,更新 prom 状态,造成 conf_event 变更,下个周期继续下发配置 + if (result == null) { + configUtil.updateAgentStatus(agent, 0); + } else { + configUtil.afterRequestApi(path, result, agent); + } } - } - // 配置下发后向 redis 记录配置更新 默认五分钟 单位 s - String cortexUpdateTimeout = Tool.ObjectUtil.defaultIfNull(sysConfigMap.get(Constant.SYSCONFIG_KEY_LOKI_UPDATE_TIMEOUT), "300"); - redisTemplate.opsForValue().set(Constant.REDIS_KEY_LOKI_UPDATE, "1", Integer.valueOf(cortexUpdateTimeout), TimeUnit.SECONDS); + // 配置下发后向 redis 记录配置更新 默认五分钟 单位 s + String cortexUpdateTimeout = Tool.ObjectUtil.defaultIfNull(sysConfigMap.get(Constant.SYSCONFIG_KEY_LOKI_UPDATE_TIMEOUT), "300"); + redisTemplate.opsForValue().set(Constant.REDIS_KEY_LOKI_UPDATE, "1", Integer.valueOf(cortexUpdateTimeout), TimeUnit.SECONDS); + }); } /** @@ -668,46 +735,207 @@ public class AutoConfigAgentJob extends QuartzJobBean { * @param healthyAgents */ private void updateCortexConf(Map alertYmlMap, List<Agent> healthyAgents) { - // 1. 判断是否开启 object storage - //String objStroageEnable = sysConfigService.getValue(Constant.SYSCONFIG_KEY_METRICS_STORAGE_TYPE); - //if (StrUtil.equals("2", objStroageEnable)) { - // 获取当前支持 alert 的 agent id - Integer supportAlertPromId = configUtil.getSupportAlertPromId(healthyAgents); - // 调用 agent/cortex 接口 更新 cortex config and rule.yml - List<Agent> globalAgentList = healthyAgents.stream().filter(pojo -> Constant.AgentType.GLOBAL.getValue().equals(pojo.getType())).collect(Collectors.toList()); - for (Agent agent : globalAgentList) { - Boolean isAlert = agent.getId().equals(supportAlertPromId) ? true : false; - // 生成 cortex 配置模板 - Map cortexYml = configUtil.generateCortexYml(agent, globalAgentList, isAlert); - - Map<String, Object> cortexConfigBody = new HashMap<>(4); - cortexConfigBody.put("config", cortexYml); - if ((supportAlertPromId == null || agent.getId().equals(supportAlertPromId)) && MapUtil.isNotEmpty(alertYmlMap)) { - cortexConfigBody.put("rule", alertYmlMap); + // try Set Up Config To Down Agent Of Cortex + ThreadUtil.execAsync(() -> { + // get Cortex Component Down Agent List + List<Agent> cortexComponentDownAgentList = this.getCortexComponentDownAgentList(); + log.info("[updateCortexConf] [cortex Component Down Agent List] [size: {}]", cortexComponentDownAgentList.size()); + + // try Set Up Config To Down Agent Of Cortex + this.trySetUpConfigToDownAgentOfCortex(cortexComponentDownAgentList); + }); + + // healthy agent config cortex.yml + ThreadUtil.execAsync(() -> { + // 获取当前支持 alert 的 agent id + Integer supportAlertPromId = configUtil.getSupportAlertPromId(healthyAgents); + // 调用 agent/cortex 接口 更新 cortex config and rule.yml + List<Agent> globalAgentList = healthyAgents.stream().filter(pojo -> ObjectUtil.equal(Constant.AgentType.GLOBAL.getValue(), pojo.getType())).collect(Collectors.toList()); + for (Agent agent : globalAgentList) { + Boolean isAlert = ObjectUtil.equal(agent.getId(), supportAlertPromId); + // generate Cortex Yml + Map cortexYml = configUtil.generateCortexYml(agent, globalAgentList, isAlert); + + Map<String, Object> cortexConfigBody = new HashMap<>(4); + cortexConfigBody.put("config", cortexYml); + if ((supportAlertPromId == null || agent.getId().equals(supportAlertPromId)) && MapUtil.isNotEmpty(alertYmlMap)) { + cortexConfigBody.put("rule", alertYmlMap); + } + String result = null; + String path = "/cortex/config"; + try { + log.info("[updateCortexConf] [request agent /cortex/config api begin] [agent id: {}]", agent.getId()); + if (log.isDebugEnabled()) { + log.info("[updateCortexConf] [request agent /cortex/config api begin] [agent id: {}] [request body: {}]", agent.getId(), JSONUtil.toJsonStr(cortexConfigBody)); + } + result = AgentUtil.request(agent, HttpMethod.POST, path, null, cortexConfigBody, String.class); + log.info("[updateCortexConf] [request agent /cortex/config api finshed] [agent id: {}]", agent.getId()); + } catch (RuntimeException e) { + log.error(e, "request error,path:{},agent:{}", path, Tool.JSONUtil.toJsonStr(agent)); + } + // 下发失败,更新 prom 状态,造成 conf_event 变更,下个周期继续下发配置 + if (result == null) { + configUtil.updateAgentStatus(agent, 0); + } else { + configUtil.afterRequestApi(path, result, agent); + } } - String result = null; + + // 配置下发后向 redis 记录配置更新 默认五分钟 单位 s + String cortexUpdateTimeout = Tool.ObjectUtil.defaultIfNull(sysConfigMap.get(Constant.SYSCONFIG_KEY_CORTEX_UPDATE_TIMEOUT), "300"); + redisTemplate.opsForValue().set(Constant.REDIS_KEY_CORTEX_UPDATE, "1", Integer.valueOf(cortexUpdateTimeout), TimeUnit.SECONDS); + }); + } + + /** + * get Cortex Component Down Agent List + * + * @return + */ + private List<Agent> getCortexComponentDownAgentList() { + // allAgentList + List<Agent> allAgentList = agentService.list(); + + List<Agent> cortexComponentDownAgentList = allAgentList.stream().filter(agent -> { + String statusInfoJsonStr = agent.getStatusInfo(); + JSONObject jsonObject = JSONObject.parseObject(StrUtil.emptyToDefault(statusInfoJsonStr, StrUtil.EMPTY_JSON)); + + String confagentState = (String) jsonObject.get("confagent"); + String cortexState = (String) jsonObject.get("cortex"); + + return BooleanUtil.and( + StrUtil.equals("UP", confagentState), + StrUtil.equals("DOWN", cortexState) + ); + }).collect(Collectors.toList()); + log.info("[getCortexComponentDownAgentList] [cortex Component Down Agent List] [size: {}]", cortexComponentDownAgentList.size()); + return cortexComponentDownAgentList; + } + + /** + * get Loki Component Down Agent List + * + * @return + */ + private List<Agent> getLokiComponentDownAgentList() { + // allAgentList + List<Agent> allAgentList = agentService.list(); + + List<Agent> lokiComponentDownAgentList = allAgentList.stream().filter(agent -> { + String statusInfoJsonStr = agent.getStatusInfo(); + JSONObject jsonObject = JSONObject.parseObject(StrUtil.emptyToDefault(statusInfoJsonStr, StrUtil.EMPTY_JSON)); + + String confagentState = (String) jsonObject.get("confagent"); + String lokiState = (String) jsonObject.get("loki"); + + return BooleanUtil.and( + StrUtil.equals("UP", confagentState), + StrUtil.equals("DOWN", lokiState) + ); + }).collect(Collectors.toList()); + log.info("[getLokiComponentDownAgentList] [loki Component Down Agent List] [size: {}]", lokiComponentDownAgentList.size()); + return lokiComponentDownAgentList; + } + + /** + * try Set Up Config To Down Agent Of Cortex + * 尝试给因为 cortex down 导致 Agent 状态异常的 Agent 下发 init cortex.yml 配置,尝试使 cortex 正常 + * + * @param cortexComponentDownAgentList + */ + private void trySetUpConfigToDownAgentOfCortex(List<Agent> cortexComponentDownAgentList) { + for (Agent agent : cortexComponentDownAgentList) { + // generate Init Cortex Yml + Map initCortexYml = configUtil.generateInitCortexYml(); + + Map<Object, Object> requestBody = Tool.MapUtil.builder() + .put("config", initCortexYml) + .map(); + String path = "/cortex/config"; try { - result = AgentUtil.request(agent, HttpMethod.POST,path, null, cortexConfigBody, String.class); - } catch (RuntimeException e) { - log.error(e,"request error,path:{},agent:{}",path,Tool.JSONUtil.toJsonStr(agent)); - } - // 下发失败,更新 prom 状态,造成 conf_event 变更,下个周期继续下发配置 - if (result == null) { - configUtil.updateAgentStatus(agent, 0); - } else { - configUtil.afterRequestApi(path, result, agent); + log.info("[trySetUpConfigToDownAgentOfCortex] [request agent /cortex/config api begin] [agent id: {}]", agent.getId()); + if (log.isDebugEnabled()) { + log.info("[trySetUpConfigToDownAgentOfCortex] [request agent /cortex/config api begin] [agent id: {}] [request body: {}]", agent.getId(), JSONUtil.toJsonStr(requestBody)); + } + + // request + String result = AgentUtil.request(agent, HttpMethod.POST, path, null, requestBody, String.class); + + // after Request api + if (StrUtil.isEmpty(result)) { + // increment cortex + eventLogService.increment("cortex"); + + log.error("[trySetUpConfigToDownAgentOfCortex] [request error] [path: {}] [result: {}] [agent: {}]", path, result, JSONUtil.toJsonStr(agent)); + } else { + R parseObject = JSONObject.parseObject(result, R.class); + if (ObjectUtil.notEqual(RCode.SUCCESS.getCode(), parseObject.get("code"))) { + // increment cortex + eventLogService.increment("cortex"); + + log.error("[trySetUpConfigToDownAgentOfCortex] [request error] [path: {}] [result: {}] [agent: {}]", path, result, JSONUtil.toJsonStr(agent)); + } + } + log.info("[trySetUpConfigToDownAgentOfCortex] [request agent /cortex/config api finshed] [agent id: {}]", agent.getId()); + } catch (Exception e) { + // increment cortex + eventLogService.increment("cortex"); + + log.error(e, "[trySetUpConfigToDownAgentOfCortex] [request error] [path: {}] [agent: {}]", path, JSONUtil.toJsonStr(agent)); } } - - // 配置下发后向 redis 记录配置更新 默认五分钟 单位 s - String cortexUpdateTimeout = Tool.ObjectUtil.defaultIfNull(sysConfigMap.get(Constant.SYSCONFIG_KEY_CORTEX_UPDATE_TIMEOUT), "300"); - redisTemplate.opsForValue().set(Constant.REDIS_KEY_CORTEX_UPDATE, "1", Integer.valueOf(cortexUpdateTimeout), TimeUnit.SECONDS); - /*} else { - // 没有开启 对象存储 啥也不做 - }*/ } + /** + * try Set Up Config To Down Agent Of Loki + * 尝试给因为 loki down 导致 Agent 状态异常的 Agent 下发 init loki.yml 配置,尝试使 loki 正常 + * + * @param lokiComponentDownAgentList + */ + private void trySetUpConfigToDownAgentOfLoki(List<Agent> lokiComponentDownAgentList) { + for (Agent agent : lokiComponentDownAgentList) { + // generate Init Loki Yml + Map initLokiYml = configUtil.generateInitLokiYml(); + + Map<Object, Object> requestBody = Tool.MapUtil.builder() + .put("config", initLokiYml) + .map(); + + String path = "/loki/config"; + try { + log.info("[trySetUpConfigToDownAgentOfLoki] [request agent /loki/config api begin] [agent id: {}]", agent.getId()); + if (log.isDebugEnabled()) { + log.info("[trySetUpConfigToDownAgentOfLoki] [request agent /loki/config api begin] [agent id: {}] [request body: {}]", agent.getId(), JSONUtil.toJsonStr(requestBody)); + } + + // request + String result = AgentUtil.request(agent, HttpMethod.POST, path, null, requestBody, String.class); + + // after Request api + if (StrUtil.isEmpty(result)) { + // increment loki + eventLogService.increment("loki"); + + log.error("[trySetUpConfigToDownAgentOfLoki] [request error] [path: {}] [result: {}] [agent: {}]", path, result, JSONUtil.toJsonStr(agent)); + } else { + R parseObject = JSONObject.parseObject(result, R.class); + if (ObjectUtil.notEqual(RCode.SUCCESS.getCode(), parseObject.get("code"))) { + // increment loki + eventLogService.increment("loki"); + + log.error("[trySetUpConfigToDownAgentOfLoki] [request error] [path: {}] [result: {}] [agent: {}]", path, result, JSONUtil.toJsonStr(agent)); + } + } + log.info("[trySetUpConfigToDownAgentOfLoki] [request agent /loki/config api finshed] [agent id: {}]", agent.getId()); + } catch (Exception e) { + // increment loki + eventLogService.increment("loki"); + + log.error(e, "[trySetUpConfigToDownAgentOfLoki] [request error] [path: {}] [agent: {}]", path, JSONUtil.toJsonStr(agent)); + } + } + } /** * 对比 cmd 启动项 diff --git a/nz-admin/src/main/java/com/nis/modules/agent/service/impl/AgentServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/agent/service/impl/AgentServiceImpl.java index 75f0ae34..4a2c7381 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/service/impl/AgentServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/service/impl/AgentServiceImpl.java @@ -10,11 +10,11 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; -import com.nis.modules.asset.entity.Dc; -import com.nis.modules.asset.service.DcService; import com.nis.modules.agent.dao.AgentDao; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.AgentService; +import com.nis.modules.asset.entity.Dc; +import com.nis.modules.asset.service.DcService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -74,11 +74,10 @@ public class AgentServiceImpl extends ServiceImpl<AgentDao, Agent> implements Ag public void validateParam(Agent agentEntity) { - // host port type 唯一 + // host port 唯一 List<Agent> pList = this.list(new LambdaQueryWrapper<Agent>() .eq(Agent::getHost, agentEntity.getHost()) - .eq(Agent::getPort, agentEntity.getPort()) - .eq(Agent::getType, agentEntity.getType())); + .eq(Agent::getPort, agentEntity.getPort())); boolean flag = false; if ((pList == null || pList.size() == 0) || (pList != null && pList.size() == 1 && pList.get(0).getId().equals(agentEntity.getId()))) { diff --git a/nz-admin/src/main/java/com/nis/modules/agent/service/impl/MonitorEventLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/agent/service/impl/MonitorEventLogServiceImpl.java index b53b0a70..98abf022 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/service/impl/MonitorEventLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/service/impl/MonitorEventLogServiceImpl.java @@ -1,11 +1,5 @@ package com.nis.modules.agent.service.impl; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -import org.springframework.stereotype.Service; - import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.utils.Tool; @@ -13,6 +7,11 @@ import com.nis.common.utils.ToolUtil; import com.nis.modules.agent.dao.MonitorEventLogDao; import com.nis.modules.agent.entity.MonitorEventLog; import com.nis.modules.agent.service.MonitorEventLogService; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; @Service public class MonitorEventLogServiceImpl extends ServiceImpl<MonitorEventLogDao, MonitorEventLog> implements MonitorEventLogService { diff --git a/nz-admin/src/main/java/com/nis/modules/agent/util/AgentUtil.java b/nz-admin/src/main/java/com/nis/modules/agent/util/AgentUtil.java index 6aed4dd5..8bd9aaef 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/util/AgentUtil.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/util/AgentUtil.java @@ -1,40 +1,12 @@ package com.nis.modules.agent.util; -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.FileSystemResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; -import org.xerial.snappy.Snappy; - +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.core.net.url.UrlPath; +import cn.hutool.core.net.url.UrlQuery; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.http.Header; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import com.nis.common.exception.NZException; @@ -46,14 +18,32 @@ import com.nis.common.utils.Tool; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.PromApiService; import com.nis.modules.sys.service.SysConfigService; +import com.sun.javafx.fxml.builder.URLBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.*; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import org.xerial.snappy.Snappy; -import cn.hutool.core.net.url.UrlBuilder; -import cn.hutool.core.net.url.UrlPath; -import cn.hutool.core.net.url.UrlQuery; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.hutool.http.Header; -import cn.hutool.log.Log; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Configuration @SuppressWarnings("all") @@ -94,9 +84,18 @@ public class AgentUtil { String agentPath = sysConfigService.getValueOrDefault(Constant.CONFAGENT_PATH, ""); path = path.startsWith("/") ? (String.format("%s%s", agentPath, path)) : (String.format("%s/%s", agentPath, path)); - String urlString = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) + /*String urlString = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) .setPort(server.getPort()).setPath(UrlPath.of(path, Charset.forName("UTF-8"))) - .setQuery(UrlQuery.of(queryString, Charset.forName("UTF-8"))).toString(); + .setQuery(UrlQuery.of(queryString, Charset.forName("UTF-8"), false, true)).toString();*/ + String urlString = new UrlBuilder( + server.getProtocol(), + server.getHost(), + Integer.valueOf(server.getPort()), + UrlPath.of(path, Charset.forName("UTF-8")), + UrlQuery.of(queryString, Charset.forName("UTF-8"), false, true), + null, + StandardCharsets.UTF_8).toString(); + HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.AUTHORIZATION, server.getToken()); HttpEntity httpEntity = body == null ? new HttpEntity(headers) : new HttpEntity(body, headers); @@ -128,6 +127,34 @@ public class AgentUtil { } /** + * 返回 html + * @param url + * @param token + * @param responseType: String.class + * @param <T> + * @return + */ + public static <T> T requestAgentProxy(String url, String token, Class<T> responseType) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.AUTHORIZATION, token); + HttpEntity httpEntity = new HttpEntity(headers); + List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters(); + for(HttpMessageConverter<?> converter : converters){ + if(converter instanceof MappingJackson2HttpMessageConverter){ + try{ + ((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(Arrays.asList(MediaType.TEXT_HTML)); + }catch(Exception e){ + log.error(e); + } + } + } + // 发送 请求 + ResponseEntity<T> exchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, responseType); + return exchange.getBody(); + } + + /** * prometheus remote write * @param url * @param token @@ -176,10 +203,18 @@ public class AgentUtil { * @return */ public static JSONObject getForObject(Agent server, String url, Map requestParam) { - UrlBuilder urlBuilder = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) - .setPort(server.getPort()).setPath(UrlPath.of(url, Charset.forName("UTF-8"))); - - UrlQuery urlQuery = new UrlQuery(); + /*UrlBuilder urlBuilder = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) + .setPort(server.getPort()).setPath(UrlPath.of(url, Charset.forName("UTF-8")));*/ + + UrlBuilder urlBuilder = new UrlBuilder(server.getProtocol(), + server.getHost(), + Integer.valueOf(server.getPort()), + UrlPath.of(url, Charset.forName("UTF-8")), + null, + null, + StandardCharsets.UTF_8); + + UrlQuery urlQuery = new UrlQuery(true); Iterator<Map.Entry<String, Object>> iterator = ((Map<String, Object>) requestParam).entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); @@ -332,9 +367,18 @@ public class AgentUtil { queryString = StrUtil.isNotBlank(queryString) ? queryString : ""; queryString = URLUtil.decode(queryString); - String urlStr = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) + /*String urlStr = UrlBuilder.create().setScheme(server.getProtocol()).setHost(server.getHost()) .setPort(server.getPort()).setPath(UrlPath.of(url, Charset.forName("UTF-8"))) - .setQuery(UrlQuery.of(queryString, Charset.forName("UTF-8"))).toString(); + .setQuery(UrlQuery.of(queryString, Charset.forName("UTF-8"), false, true)).toString();*/ + + String urlStr = new UrlBuilder( + server.getProtocol(), + server.getHost(), + Integer.valueOf(server.getPort()), + UrlPath.of(url, Charset.forName("UTF-8")), + UrlQuery.of(queryString, Charset.forName("UTF-8"), false, true), + null, + StandardCharsets.UTF_8).toString(); String method = request.getMethod(); ResponseEntity<byte[]> exchange = restTemplate.exchange(new URI(urlStr), HttpMethod.resolve(method), diff --git a/nz-admin/src/main/java/com/nis/modules/agent/util/TalonUtil.java b/nz-admin/src/main/java/com/nis/modules/agent/util/TalonUtil.java index 4e88134f..4fb8c492 100644 --- a/nz-admin/src/main/java/com/nis/modules/agent/util/TalonUtil.java +++ b/nz-admin/src/main/java/com/nis/modules/agent/util/TalonUtil.java @@ -20,6 +20,7 @@ import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.*; @Configuration @@ -36,7 +37,7 @@ public class TalonUtil { * 构建 UrlQuery */ private static UrlQuery buildUrlQuery(Map requestParam) { - UrlQuery urlQuery = new UrlQuery(); + UrlQuery urlQuery = new UrlQuery(true); Iterator<Map.Entry<String, Object>> iterator = ((Map<String, Object>) requestParam).entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); @@ -118,12 +119,21 @@ public class TalonUtil { // build urlQuery UrlQuery urlQuery = TalonUtil.buildUrlQuery(requestParam); - UrlBuilder urlBuilder = UrlBuilder.create() + /*UrlBuilder urlBuilder = UrlBuilder.create() .setScheme("http") .setHost(targetUrl.split(":")[0]) .setPort(Integer.valueOf(targetUrl.split(":")[1])) .setQuery(urlQuery) - .setPath(UrlPath.of(String.format("%s%s", "/nz-talon", path), Charset.forName("UTF-8"))); + .setPath(UrlPath.of(String.format("%s%s", "/nz-talon", path), Charset.forName("UTF-8")));*/ + + UrlBuilder urlBuilder = new UrlBuilder( + "http", + targetUrl.split(":")[0], + Integer.valueOf(targetUrl.split(":")[1]), + UrlPath.of(String.format("%s%s", "/nz-talon", path), Charset.forName("UTF-8")), + urlQuery, + null, + StandardCharsets.UTF_8); String urlStr = urlBuilder.build(); HttpHeaders headers = new HttpHeaders(); @@ -157,12 +167,21 @@ public class TalonUtil { Agent server = promApiService.getOneAvaliableGlobalAgent(); String agentPath = sysConfigService.getValue(Constant.CONFAGENT_PATH); - UrlBuilder urlBuilder = UrlBuilder.create() + /*UrlBuilder urlBuilder = UrlBuilder.create() .setScheme(server.getProtocol()) .setHost(server.getHost()) .setPort(server.getPort()) .setQuery(urlQuery) - .setPath(UrlPath.of(String.format("%s%s%s", agentPath, "/talon/proxy", path), Charset.forName("UTF-8"))); + .setPath(UrlPath.of(String.format("%s%s%s", agentPath, "/talon/proxy", path), Charset.forName("UTF-8")));*/ + + UrlBuilder urlBuilder = new UrlBuilder( + server.getProtocol(), + server.getHost(), + Integer.valueOf(server.getPort()), + UrlPath.of(String.format("%s%s%s", agentPath, "/talon/proxy", path), Charset.forName("UTF-8")), + urlQuery, + null, + StandardCharsets.UTF_8); String urlStr = urlBuilder.build(); HttpHeaders headers = new HttpHeaders(); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertContext.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertContext.java index 2cb342c5..4d2b2911 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertContext.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertContext.java @@ -1,11 +1,10 @@ package com.nis.modules.alert.backend; -import java.util.Map; - +import cn.hutool.log.Log; import com.nis.common.utils.Tool; import com.nis.modules.alert.entity.AlertRuleEntity; -import cn.hutool.log.Log; +import java.util.Map; public class AlertContext { private static final Log log = Log.get(); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertHanlderThread.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertHanlderThread.java index d3ae5a30..23dc5849 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertHanlderThread.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertHanlderThread.java @@ -1,10 +1,17 @@ package com.nis.modules.alert.backend; -import java.time.Duration; -import java.util.List; -import java.util.concurrent.TimeUnit; - +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.alert.entity.AlertMessageEntity; +import com.nis.modules.alert.entity.AlertSilenceConf; +import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; +import com.nis.modules.alert.service.AlertHandlerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.QueryTimeoutException; @@ -13,18 +20,9 @@ import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; -import com.alibaba.fastjson.JSON; -import com.nis.common.utils.Constant; -import com.nis.common.utils.Tool; -import com.nis.modules.alert.entity.AlertMessageEntity; -import com.nis.modules.alert.entity.AlertSilenceConf; -import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; -import com.nis.modules.alert.service.AlertHandlerService; - -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.time.Duration; +import java.util.List; +import java.util.concurrent.TimeUnit; /** * 告警消息处理线程 diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertMessageExpiredJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertMessageExpiredJob.java index 3a7398d5..76a9b0e6 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertMessageExpiredJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertMessageExpiredJob.java @@ -1,9 +1,12 @@ package com.nis.modules.alert.backend; -import java.util.Date; -import java.util.List; - -import com.alibaba.fastjson.JSONObject; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.alert.entity.AlertMessageEntity; +import com.nis.modules.alert.service.AlertHandlerService; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -12,14 +15,8 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.quartz.QuartzJobBean; -import com.nis.common.utils.Constant; -import com.nis.common.utils.Tool; -import com.nis.modules.alert.entity.AlertMessageEntity; -import com.nis.modules.alert.service.AlertHandlerService; - -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.Date; +import java.util.List; /** * 告警消息 超时判断线程,主要用于处理因为alert message 未能正常改为 expired 状态的消息 diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleJudgeJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleJudgeJob.java index 92713450..fd930dea 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleJudgeJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleJudgeJob.java @@ -1,24 +1,8 @@ package com.nis.modules.alert.backend; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.HashOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.stereotype.Component; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.nis.common.exception.NZException; @@ -38,10 +22,19 @@ import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.alert.service.AlertRuleEvalLogService; import com.nis.modules.alert.service.RecordRuleService; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.*; +import java.util.concurrent.TimeUnit; @Component @DisallowConcurrentExecution diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleManagerJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleManagerJob.java index c4d67bf9..0d1063fe 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleManagerJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleManagerJob.java @@ -1,42 +1,24 @@ package com.nis.modules.alert.backend; -import java.util.Calendar; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TimeZone; - -import org.quartz.CronScheduleBuilder; -import org.quartz.CronTrigger; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobBuilder; -import org.quartz.JobDataMap; -import org.quartz.JobDetail; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.SimpleScheduleBuilder; -import org.quartz.SimpleTrigger; -import org.quartz.TriggerBuilder; -import org.quartz.impl.matchers.GroupMatcher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.stereotype.Component; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.Tool; import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.alert.entity.AlertRuleEntity; import com.nis.modules.alert.service.AlertRuleService; import com.nis.modules.sys.service.SysConfigService; +import org.quartz.*; +import org.quartz.impl.matchers.GroupMatcher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; -import cn.hutool.core.date.StopWatch; -import cn.hutool.log.Log; +import java.util.Calendar; +import java.util.*; +import java.util.Map.Entry; /** * 所有 nz-web 实例都执行此定时任务 diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleScheduleJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleScheduleJob.java index 5a2c5781..7f2bb5d6 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleScheduleJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertRuleScheduleJob.java @@ -1,13 +1,8 @@ package com.nis.modules.alert.backend; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.quartz.JobKey; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.quartz.QuartzJobBean; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.nis.common.utils.Constant; @@ -16,10 +11,13 @@ import com.nis.modules.alert.entity.AlertRuleEntity; import com.nis.modules.alert.entity.AlertRuleSchedLog; import com.nis.modules.alert.service.AlertRuleSchedLogService; import com.nis.modules.alert.service.AlertRuleService; - -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.quartz.JobKey; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; /** * alert rule 定时器job diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertSilenceStatusJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertSilenceStatusJob.java index 64064ecf..0dfa6aa7 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertSilenceStatusJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/AlertSilenceStatusJob.java @@ -1,7 +1,12 @@ package com.nis.modules.alert.backend; -import java.util.List; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.alert.entity.AlertSilenceConf; +import com.nis.modules.alert.service.AlertHandlerService; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -9,14 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.quartz.QuartzJobBean; -import com.nis.common.utils.Constant; -import com.nis.common.utils.Tool; -import com.nis.modules.alert.entity.AlertSilenceConf; -import com.nis.modules.alert.service.AlertHandlerService; - -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.List; /** * sliece 静默规则处理线程 diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordManagerJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordManagerJob.java index 012b1b8d..598302a5 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordManagerJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordManagerJob.java @@ -1,37 +1,24 @@ package com.nis.modules.alert.backend; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobBuilder; -import org.quartz.JobDataMap; -import org.quartz.JobDetail; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.quartz.JobKey; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.SimpleScheduleBuilder; -import org.quartz.SimpleTrigger; -import org.quartz.TriggerBuilder; -import org.quartz.impl.matchers.GroupMatcher; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.stereotype.Component; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.Tool; import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.alert.entity.RecordRuleEntity; import com.nis.modules.alert.service.RecordRuleService; import com.nis.modules.sys.service.SysConfigService; +import org.quartz.*; +import org.quartz.impl.matchers.GroupMatcher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; -import cn.hutool.core.date.StopWatch; -import cn.hutool.log.Log; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; /** * record rule 配置更新管理任务 diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordRuleEvalJob.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordRuleEvalJob.java index 0d39dc2e..2b4c6e0a 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordRuleEvalJob.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/RecordRuleEvalJob.java @@ -1,18 +1,8 @@ package com.nis.modules.alert.backend; -import java.util.List; -import java.util.Map; - -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.stereotype.Component; - +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.nis.common.exception.NZException; @@ -31,10 +21,18 @@ import com.nis.modules.alert.entity.RecordRuleEntity; import com.nis.modules.alert.entity.RecordRuleEvalLog; import com.nis.modules.alert.service.RecordRuleEvalLogService; import com.nis.modules.alert.service.RecordRuleService; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; -import cn.hutool.core.date.StopWatch; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.List; +import java.util.Map; @Component @DisallowConcurrentExecution diff --git a/nz-admin/src/main/java/com/nis/modules/alert/backend/SNMPTrapReceiver.java b/nz-admin/src/main/java/com/nis/modules/alert/backend/SNMPTrapReceiver.java index 09b1c264..ac09d055 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/backend/SNMPTrapReceiver.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/backend/SNMPTrapReceiver.java @@ -1,40 +1,21 @@ package com.nis.modules.alert.backend; -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Vector; - -import org.snmp4j.CommandResponder; -import org.snmp4j.CommandResponderEvent; -import org.snmp4j.MessageDispatcherImpl; -import org.snmp4j.PDU; -import org.snmp4j.PDUv1; -import org.snmp4j.Snmp; -import org.snmp4j.TransportMapping; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.alert.entity.AlertRuleEntity; +import com.nis.modules.alert.entity.AlertSeverityConf; +import com.nis.modules.alert.entity.Snmptrap; +import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; +import com.nis.modules.alert.service.AlertMessageService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.sys.service.SysConfigService; +import org.snmp4j.*; import org.snmp4j.mp.MPv1; import org.snmp4j.mp.MPv2c; import org.snmp4j.mp.MPv3; -import org.snmp4j.security.AuthMD5; -import org.snmp4j.security.Priv3DES; -import org.snmp4j.security.PrivAES128; -import org.snmp4j.security.PrivAES192; -import org.snmp4j.security.PrivAES256; -import org.snmp4j.security.SecurityModel; -import org.snmp4j.security.SecurityModels; -import org.snmp4j.security.SecurityProtocols; -import org.snmp4j.security.USM; -import org.snmp4j.security.UsmUser; -import org.snmp4j.smi.Address; -import org.snmp4j.smi.GenericAddress; -import org.snmp4j.smi.IpAddress; -import org.snmp4j.smi.OctetString; -import org.snmp4j.smi.TcpAddress; -import org.snmp4j.smi.TimeTicks; -import org.snmp4j.smi.UdpAddress; -import org.snmp4j.smi.VariableBinding; +import org.snmp4j.security.*; +import org.snmp4j.smi.*; import org.snmp4j.transport.DefaultTcpTransportMapping; import org.snmp4j.transport.DefaultUdpTransportMapping; import org.snmp4j.util.MultiThreadedMessageDispatcher; @@ -45,17 +26,12 @@ import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import com.nis.common.utils.Tool; -import com.nis.modules.alert.entity.AlertRuleEntity; -import com.nis.modules.alert.entity.AlertSeverityConf; -import com.nis.modules.alert.entity.Snmptrap; -import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; -import com.nis.modules.alert.service.AlertMessageService; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.asset.service.AssetAssetService; -import com.nis.modules.sys.service.SysConfigService; - -import cn.hutool.log.Log; +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Vector; /** * @author @@ -352,4 +328,4 @@ public class SNMPTrapReceiver implements CommandResponder,ApplicationRunner { public void setPort(int port) { this.port = port; } -}
\ No newline at end of file +} diff --git a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertMessageReceiveController.java b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertMessageReceiveController.java index c39d351d..7df65ac8 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertMessageReceiveController.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertMessageReceiveController.java @@ -1,23 +1,17 @@ package com.nis.modules.alert.controller; -import javax.servlet.http.HttpServletRequest; - +import cn.hutool.log.Log; +import com.nis.common.exception.NZException; +import com.nis.common.utils.R; +import com.nis.common.utils.RCode; +import com.nis.modules.alert.service.AlertMessageService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.nis.common.exception.NZException; -import com.nis.common.utils.Constant; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.modules.alert.service.AlertMessageService; - -import cn.hutool.log.Log; +import javax.servlet.http.HttpServletRequest; /** diff --git a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertNotifyMethodController.java b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertNotifyMethodController.java index e6d2cb87..f48804dc 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertNotifyMethodController.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertNotifyMethodController.java @@ -59,7 +59,7 @@ public class AlertNotifyMethodController { @SysLog(operation = OperationEnum.DELETE,type = TypeEnum.ALERTNOTIFYMETHOD) @RequiresPermissions({"alert:notify:delete"}) public R delete(@RequestParam(value = "ids",required = true)String ids){ - alertNotifyMethodService.deleteByIds(Arrays.asList(Tool.StrUtil.split(ids, ","))); + alertNotifyMethodService.deleteByIds(Tool.StrUtil.split(ids, ",")); return R.ok(); } } diff --git a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSeverityController.java b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSeverityController.java index f5a6131e..d7be3b9e 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSeverityController.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSeverityController.java @@ -1,7 +1,6 @@ package com.nis.modules.alert.controller; import cn.hutool.log.Log; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.nis.common.annotation.SysLog; import com.nis.common.utils.*; import com.nis.modules.alert.entity.AlertSeverityConf; @@ -71,7 +70,7 @@ public class AlertSeverityController { @SysLog(operation = OperationEnum.DELETE,type = TypeEnum.ALERTSEVERITY) @RequiresPermissions({"alert:severity:delete"}) public R delete(@RequestParam(value = "ids",required = true)String ids){ - alertSeverityService.removeByIds(Arrays.asList(Tool.StrUtil.split(ids, ","))); + alertSeverityService.removeByIds(Tool.StrUtil.split(ids, ",")); return R.ok(); } diff --git a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSilenceController.java b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSilenceController.java index 3c89ca62..f99559ba 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSilenceController.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/controller/AlertSilenceController.java @@ -1,33 +1,18 @@ package com.nis.modules.alert.controller; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - +import cn.hutool.log.Log; import com.alibaba.fastjson.JSON; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.Tool; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.alert.entity.AlertSilenceConf; import com.nis.modules.alert.service.AlertSilenceService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; -import cn.hutool.log.Log; +import java.util.Map; @RestController @RequestMapping("alert/silence") diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertMessageDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertMessageDao.java index e9668944..3ae10759 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertMessageDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertMessageDao.java @@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.alert.entity.AlertMessageEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; import java.util.List; diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertNotifyLogDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertNotifyLogDao.java index 4116d929..0c286505 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertNotifyLogDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertNotifyLogDao.java @@ -1,10 +1,9 @@ package com.nis.modules.alert.dao; - -import org.apache.ibatis.annotations.Mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.alert.entity.AlertNotifyLog; +import org.apache.ibatis.annotations.Mapper; @Mapper public interface AlertNotifyLogDao extends BaseMapper<AlertNotifyLog>{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleEvalLogDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleEvalLogDao.java index cf83c307..1e6f4f6a 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleEvalLogDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleEvalLogDao.java @@ -1,9 +1,8 @@ package com.nis.modules.alert.dao; -import org.apache.ibatis.annotations.Mapper; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.alert.entity.AlertRuleEvalLog; +import org.apache.ibatis.annotations.Mapper; /** * diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleSchedLogDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleSchedLogDao.java index d5a26cc5..c9f9ec18 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleSchedLogDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertRuleSchedLogDao.java @@ -1,9 +1,8 @@ package com.nis.modules.alert.dao; -import org.apache.ibatis.annotations.Mapper; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.alert.entity.AlertRuleSchedLog; +import org.apache.ibatis.annotations.Mapper; /** * diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertSilenceDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertSilenceDao.java index 0c242b92..2398c45d 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertSilenceDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/AlertSilenceDao.java @@ -1,14 +1,13 @@ package com.nis.modules.alert.dao; -import java.util.List; -import java.util.Map; - -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.nis.modules.alert.entity.AlertSilenceConf; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; @Mapper public interface AlertSilenceDao extends BaseMapper<AlertSilenceConf>{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/dao/ReocrdRuleEvalLogDao.java b/nz-admin/src/main/java/com/nis/modules/alert/dao/ReocrdRuleEvalLogDao.java index 9ef36f8f..0fa1a5fb 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/dao/ReocrdRuleEvalLogDao.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/dao/ReocrdRuleEvalLogDao.java @@ -1,9 +1,8 @@ package com.nis.modules.alert.dao; -import org.apache.ibatis.annotations.Mapper; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.alert.entity.RecordRuleEvalLog; +import org.apache.ibatis.annotations.Mapper; /** * diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertMessageEntity.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertMessageEntity.java index 2db77243..251d8645 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertMessageEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertMessageEntity.java @@ -1,9 +1,5 @@ package com.nis.modules.alert.entity; -import java.io.Serializable; -import java.util.Date; -import java.util.List; - import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -12,9 +8,12 @@ import com.nis.modules.asset.entity.Dc; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.project.entity.MonitorProject; - import lombok.Data; +import java.io.Serializable; +import java.util.Date; +import java.util.List; + /** * * diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertNotifyLog.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertNotifyLog.java index 3b685385..fe7430d6 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertNotifyLog.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertNotifyLog.java @@ -1,12 +1,11 @@ package com.nis.modules.alert.entity; -import java.util.Date; - import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.util.Date; + @Data @TableName("alert_notify_log") public class AlertNotifyLog { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleEvalLog.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleEvalLog.java index d758f919..423a358f 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleEvalLog.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleEvalLog.java @@ -1,13 +1,12 @@ package com.nis.modules.alert.entity; -import java.io.Serializable; -import java.util.List; - import com.baomidou.mybatisplus.annotation.TableName; import com.nis.modules.alert.entity.receive.AlertMessageReceiveDTO; - import lombok.Data; +import java.io.Serializable; +import java.util.List; + @Data @TableName("alert_rule_eval_log") public class AlertRuleEvalLog implements Serializable { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleSchedLog.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleSchedLog.java index 1c6afe56..d36b2d01 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleSchedLog.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertRuleSchedLog.java @@ -1,11 +1,10 @@ package com.nis.modules.alert.entity; -import java.io.Serializable; - import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.io.Serializable; + @Data @TableName("alert_rule_sched_log") public class AlertRuleSchedLog implements Serializable { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceConf.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceConf.java index 6207ef9c..9177cda9 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceConf.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceConf.java @@ -1,13 +1,12 @@ package com.nis.modules.alert.entity; -import java.util.Date; - import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.util.Date; + @Data @TableName("alert_silence_conf") public class AlertSilenceConf { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceMessageRel.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceMessageRel.java index dc21ed15..2b44171c 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceMessageRel.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/AlertSilenceMessageRel.java @@ -2,7 +2,6 @@ package com.nis.modules.alert.entity; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEntity.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEntity.java index 66deb18b..b056c5d0 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEntity.java @@ -1,17 +1,14 @@ package com.nis.modules.alert.entity; -import java.io.Serializable; - -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.nis.common.utils.Tool; import com.nis.modules.sys.entity.SysUserEntity; - import lombok.Data; +import java.io.Serializable; + @Data @TableName("record_rule") public class RecordRuleEntity implements Serializable { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEvalLog.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEvalLog.java index b6a639ea..253e8ec8 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEvalLog.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/RecordRuleEvalLog.java @@ -1,11 +1,10 @@ package com.nis.modules.alert.entity; -import java.io.Serializable; - import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.io.Serializable; + @Data @TableName("record_rule_eval_log") public class RecordRuleEvalLog implements Serializable { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/Snmptrap.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/Snmptrap.java index 48fead0b..920df14f 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/Snmptrap.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/Snmptrap.java @@ -1,13 +1,12 @@ package com.nis.modules.alert.entity; +import com.nis.common.utils.Tool; +import lombok.Data; + import java.util.ArrayList; import java.util.List; import java.util.Map; -import com.nis.common.utils.Tool; - -import lombok.Data; - @Data public class Snmptrap{ private String version; @@ -64,4 +63,4 @@ public class Snmptrap{ public void delVariable(String oid) { this.variables.remove(oid); } -}
\ No newline at end of file +} diff --git a/nz-admin/src/main/java/com/nis/modules/alert/entity/receive/AlertMessageReceiveDTO.java b/nz-admin/src/main/java/com/nis/modules/alert/entity/receive/AlertMessageReceiveDTO.java index 112e87b8..2541c42c 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/entity/receive/AlertMessageReceiveDTO.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/entity/receive/AlertMessageReceiveDTO.java @@ -1,15 +1,14 @@ package com.nis.modules.alert.entity.receive; +import cn.hutool.crypto.SecureUtil; +import com.nis.common.utils.Tool; +import lombok.Data; + import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.LinkedHashMap; import java.util.Map; -import com.nis.common.utils.Tool; - -import cn.hutool.crypto.SecureUtil; -import lombok.Data; - /** * 用来接收告警信息的DTO类 */ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertMessageService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertMessageService.java index d167741c..e99855dd 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertMessageService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertMessageService.java @@ -1,11 +1,11 @@ package com.nis.modules.alert.service; -import java.util.List; - import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.alert.entity.AlertMessageEntity; +import java.util.List; + /** * */ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleEvalLogService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleEvalLogService.java index e4b6ff87..6d858569 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleEvalLogService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleEvalLogService.java @@ -1,11 +1,11 @@ package com.nis.modules.alert.service; -import java.util.List; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.alert.entity.AlertRuleEvalLog; +import java.util.List; + public interface AlertRuleEvalLogService extends IService<AlertRuleEvalLog>{ List<AlertRuleEvalLog> queryListByRuleId(Integer id); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleSchedLogService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleSchedLogService.java index 7c91ba07..a1850f2f 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleSchedLogService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleSchedLogService.java @@ -1,11 +1,11 @@ package com.nis.modules.alert.service; -import java.util.List; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.alert.entity.AlertRuleSchedLog; +import java.util.List; + public interface AlertRuleSchedLogService extends IService<AlertRuleSchedLog>{ List<AlertRuleSchedLog> queryListByRuleId(Integer id); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleService.java index d3103f56..3cce9ee1 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertRuleService.java @@ -3,7 +3,6 @@ package com.nis.modules.alert.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.alert.entity.AlertRuleEntity; -import inet.ipaddr.format.validate.MACAddressProvider; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertSilenceService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertSilenceService.java index 966a2d46..7a15e8bf 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/AlertSilenceService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/AlertSilenceService.java @@ -1,11 +1,11 @@ package com.nis.modules.alert.service; -import java.util.Map; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.alert.entity.AlertSilenceConf; +import java.util.Map; + public interface AlertSilenceService extends IService<AlertSilenceConf>{ PageUtils queryPage(Map<String, Object> params); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/RecordRuleEvalLogService.java b/nz-admin/src/main/java/com/nis/modules/alert/service/RecordRuleEvalLogService.java index 9bc8355a..c29515f8 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/RecordRuleEvalLogService.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/RecordRuleEvalLogService.java @@ -1,11 +1,11 @@ package com.nis.modules.alert.service; -import java.util.List; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.alert.entity.RecordRuleEvalLog; +import java.util.List; + public interface RecordRuleEvalLogService extends IService<RecordRuleEvalLog>{ List<RecordRuleEvalLog> queryListByRuleId(Integer id); diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyLogServiceImpl.java index a70277f3..900cedfe 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyLogServiceImpl.java @@ -1,11 +1,10 @@ package com.nis.modules.alert.service.impl; -import org.springframework.stereotype.Service; - import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.modules.alert.dao.AlertNotifyLogDao; import com.nis.modules.alert.entity.AlertNotifyLog; import com.nis.modules.alert.service.AlertNotifyLogService; +import org.springframework.stereotype.Service; @Service("alertNotifyLogService") public class AlertNotifyLogServiceImpl extends ServiceImpl<AlertNotifyLogDao,AlertNotifyLog> implements AlertNotifyLogService{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyMethodServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyMethodServiceImpl.java index cfb7e179..7b4343ba 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyMethodServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertNotifyMethodServiceImpl.java @@ -39,7 +39,7 @@ public class AlertNotifyMethodServiceImpl extends ServiceImpl<AlertNotifyMethodD if(Tool.StrUtil.isEmpty(ids)){ return false; } - List<String> methodIds = Arrays.asList(Tool.StrUtil.split(ids,",")); + List<String> methodIds = Tool.StrUtil.split(ids,","); Collection<AlertNotifyMethod> methods = this.listByIds(methodIds); return methods != null && methods.size() == methodIds.size(); } diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleEvalLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleEvalLogServiceImpl.java index f6f0c6c2..3b9cd34d 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleEvalLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleEvalLogServiceImpl.java @@ -1,16 +1,5 @@ package com.nis.modules.alert.service.impl; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; - import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.utils.Tool; @@ -18,6 +7,16 @@ import com.nis.common.utils.ToolUtil; import com.nis.modules.alert.dao.AlertRuleEvalLogDao; import com.nis.modules.alert.entity.AlertRuleEvalLog; import com.nis.modules.alert.service.AlertRuleEvalLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; @Service("alertRuleEvalLogService") public class AlertRuleEvalLogServiceImpl extends ServiceImpl<AlertRuleEvalLogDao,AlertRuleEvalLog> implements AlertRuleEvalLogService{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleSchedLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleSchedLogServiceImpl.java index be475d6d..f1629246 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleSchedLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleSchedLogServiceImpl.java @@ -1,14 +1,13 @@ package com.nis.modules.alert.service.impl; -import java.util.List; - -import org.springframework.stereotype.Service; - import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.modules.alert.dao.AlertRuleSchedLogDao; import com.nis.modules.alert.entity.AlertRuleSchedLog; import com.nis.modules.alert.service.AlertRuleSchedLogService; +import org.springframework.stereotype.Service; + +import java.util.List; @Service("alertRuleSchedLogService") public class AlertRuleSchedLogServiceImpl extends ServiceImpl<AlertRuleSchedLogDao,AlertRuleSchedLog> implements AlertRuleSchedLogService{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleServiceImpl.java index 83b7f945..59094590 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertRuleServiceImpl.java @@ -31,6 +31,7 @@ import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -281,6 +282,9 @@ public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleDao, AlertRuleEnt // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveRulesFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -363,7 +367,7 @@ public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleDao, AlertRuleEnt if (StrUtil.isNotEmpty(receiver)) { validateUtil.validateRequired(method, lineNum, AlertRuleImportEnum.NOTICES_METHOD.getIndex()); - List<String> list = Arrays.stream(StrUtil.split(receiver, ",")).distinct().collect(Collectors.toList()); + List<String> list = StrUtil.split(receiver, ",").stream().distinct().collect(Collectors.toList()); List<String> receiverUserNameList = userList.stream().map(SysUserEntity::getName).distinct().filter(list::contains).collect(Collectors.toList()); if (ObjectUtil.notEqual(list.size(), receiverUserNameList.size())) @@ -372,7 +376,7 @@ public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleDao, AlertRuleEnt } if (StrUtil.isNotEmpty(method)) { - List<String> list = Arrays.stream(StrUtil.split(method, ",")).distinct().collect(Collectors.toList()); + List<String> list = StrUtil.split(method, ",").stream().distinct().collect(Collectors.toList()); List<String> receiverMethodNameList = methodList.stream().map(AlertNotifyMethod::getName).distinct().filter(list::contains).collect(Collectors.toList()); if (ObjectUtil.notEqual(list.size(), receiverMethodNameList.size())) @@ -410,7 +414,7 @@ public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleDao, AlertRuleEnt if(schedStime.length() < 5) schedStime = "0" + schedStime; if(schedEtime.length() < 5) schedEtime = "0" + schedEtime; - Arrays.stream(StrUtil.split(schedDays, ",")).distinct().forEach(s -> { + StrUtil.split(schedDays, ",").stream().distinct().forEach(s -> { validateUtil.validateRegex(s, "^[1-7]$", lineNum, AlertRuleImportEnum.SCHED_DAYS.getIndex()); }); @@ -495,7 +499,7 @@ public class AlertRuleServiceImpl extends ServiceImpl<AlertRuleDao, AlertRuleEnt } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_ALERTRULE_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSeverityServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSeverityServiceImpl.java index 8da5d17e..3b28e36d 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSeverityServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSeverityServiceImpl.java @@ -1,31 +1,23 @@ package com.nis.modules.alert.service.impl; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.Query; -import com.nis.common.utils.RCode; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; +import com.nis.common.utils.*; import com.nis.modules.alert.dao.AlertSeverityDao; -import com.nis.modules.alert.entity.AlertNotifyMethod; import com.nis.modules.alert.entity.AlertSeverityConf; import com.nis.modules.alert.service.AlertNotifyMethodService; import com.nis.modules.alert.service.AlertSeverityService; - -import cn.hutool.log.Log; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Map; + @Service("alertSeverityService") public class AlertSeverityServiceImpl extends ServiceImpl<AlertSeverityDao, AlertSeverityConf> implements AlertSeverityService { diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSilenceServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSilenceServiceImpl.java index b91c4c95..7bd1eb5b 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSilenceServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/AlertSilenceServiceImpl.java @@ -1,32 +1,26 @@ package com.nis.modules.alert.service.impl; -import java.text.ParseException; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.DateUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - +import cn.hutool.core.date.DateTime; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; -import com.nis.common.utils.Constant; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.Query; -import com.nis.common.utils.RCode; -import com.nis.common.utils.Tool; +import com.nis.common.utils.*; import com.nis.modules.alert.dao.AlertSilenceDao; import com.nis.modules.alert.entity.AlertSilenceConf; import com.nis.modules.alert.entity.AlertSilenceMatcher; import com.nis.modules.alert.service.AlertHandlerService; import com.nis.modules.alert.service.AlertSilenceService; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import cn.hutool.core.date.DateTime; -import cn.hutool.log.Log; +import java.text.ParseException; +import java.util.Date; +import java.util.List; +import java.util.Map; @Service("alertSilenceService") public class AlertSilenceServiceImpl extends ServiceImpl<AlertSilenceDao,AlertSilenceConf> implements AlertSilenceService{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleEvalLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleEvalLogServiceImpl.java index ea760fb1..f59d1606 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleEvalLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleEvalLogServiceImpl.java @@ -1,16 +1,5 @@ package com.nis.modules.alert.service.impl; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Service; - import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.utils.Tool; @@ -18,6 +7,16 @@ import com.nis.common.utils.ToolUtil; import com.nis.modules.alert.dao.ReocrdRuleEvalLogDao; import com.nis.modules.alert.entity.RecordRuleEvalLog; import com.nis.modules.alert.service.RecordRuleEvalLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.ListOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; @Service("recordRuleEvalLogService") public class RecordRuleEvalLogServiceImpl extends ServiceImpl<ReocrdRuleEvalLogDao,RecordRuleEvalLog> implements RecordRuleEvalLogService{ diff --git a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleServiceImpl.java index 556595fe..f705b516 100644 --- a/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/alert/service/impl/RecordRuleServiceImpl.java @@ -25,6 +25,7 @@ import com.nis.modules.sys.service.BasicImportAndExportServices; import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; @@ -309,6 +310,9 @@ public class RecordRuleServiceImpl extends ServiceImpl<RecordRuleDao, RecordRule // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(excelFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveRulesFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -412,7 +416,7 @@ public class RecordRuleServiceImpl extends ServiceImpl<RecordRuleDao, RecordRule } } String sysHeaderJsonStr = configService.getValue(Constant.SYSCONFIG_KEY_RUCORDRULE_IMPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldGroupController.java b/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldGroupController.java index 85b756aa..1f018961 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldGroupController.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldGroupController.java @@ -1,30 +1,16 @@ package com.nis.modules.asset.controller; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - import com.nis.common.annotation.SysLog; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.asset.entity.AssetFieldGroup; import com.nis.modules.asset.service.AssetFieldGroupService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; @RestController @RequestMapping("/asset/field/group") diff --git a/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldMetaController.java b/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldMetaController.java index e4118f46..5c7c0eec 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldMetaController.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/controller/AssetFieldMetaController.java @@ -1,30 +1,16 @@ package com.nis.modules.asset.controller; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - import com.nis.common.annotation.SysLog; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.asset.entity.AssetFieldMeta; import com.nis.modules.asset.service.AssetFieldMetaService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; @RestController @RequestMapping("/asset/field/meta") diff --git a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetAssetDao.java b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetAssetDao.java index 303fc9b4..1771d22f 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetAssetDao.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetAssetDao.java @@ -3,7 +3,6 @@ package com.nis.modules.asset.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.panel.entity.VisualChart; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Update; @@ -33,10 +32,6 @@ public interface AssetAssetDao extends BaseMapper<AssetAsset> { void updateAssetStateBatch(@Param("ids") List<Integer> ids,@Param("params")Map<String,Object> params); - List<VisualChart> getAssetsByChartIds(List<Integer> chartIds); - - void updateBrandIdByModelId(@Param("modelId") Integer modelId, @Param("brandId") Integer brandId); - /** * 根据 之前的 modelId & typeId update model_id * diff --git a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldGroupDao.java b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldGroupDao.java index 162fff65..fa0875d5 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldGroupDao.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldGroupDao.java @@ -1,10 +1,9 @@ package com.nis.modules.asset.dao; -import org.apache.ibatis.annotations.Mapper; -import org.springframework.stereotype.Repository; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.asset.entity.AssetFieldGroup; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; @Mapper @Repository diff --git a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldMetaDao.java b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldMetaDao.java index 0091b1ab..ff967543 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldMetaDao.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/dao/AssetFieldMetaDao.java @@ -1,15 +1,14 @@ package com.nis.modules.asset.dao; -import java.util.List; -import java.util.Map; - +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.asset.entity.AssetFieldMeta; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.nis.modules.asset.entity.AssetFieldMeta; +import java.util.List; +import java.util.Map; @Mapper @Repository diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetAsset.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetAsset.java index f593f910..c688c375 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetAsset.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetAsset.java @@ -3,7 +3,7 @@ package com.nis.modules.asset.entity; import com.baomidou.mybatisplus.annotation.*; import com.nis.modules.agent.entity.Agent; import com.nis.modules.sys.entity.SysUserEntity; -import com.nis.modules.terminal.config.Constants; +import com.nis.modules.terminal.utils.TerminalConstant; import lombok.Data; import java.io.Serializable; @@ -75,6 +75,14 @@ public class AssetAsset implements Serializable { private Integer dcId; /** + * 认证协议 + * SSH & TELNET + * equals AssetType.authProtocol + */ + @TableField(exist = false) + private Integer authProtocol; + + /** * 认证服务端口 */ @TableField(strategy = FieldStrategy.IGNORED) @@ -117,12 +125,6 @@ public class AssetAsset implements Serializable { private String authPinTip; /** - * 协议 SSH / TELNET - */ - @TableField(exist = false) - private String protocol; - - /** * snmp凭证id */ private Integer snmpCredentialId; @@ -150,6 +152,8 @@ public class AssetAsset implements Serializable { */ private String manageIp; + private String ipmiIp; + /** * 购买日期 */ @@ -309,7 +313,7 @@ public class AssetAsset implements Serializable { public String getPrivateKeyPath() { if (this.authType != null && this.authUsername != null) { - return Constants.NZ_USER_HOME.concat("/").concat(this.manageIp).concat("@").concat(this.authUsername).concat("_id_rsa"); + return TerminalConstant.NZ_USER_HOME.concat("/").concat(this.manageIp).concat("@").concat(this.authUsername).concat("_id_rsa"); } return null; } diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldGroup.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldGroup.java index 5037742b..a4ee7364 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldGroup.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldGroup.java @@ -1,7 +1,6 @@ package com.nis.modules.asset.entity; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldMeta.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldMeta.java index b058a915..95464c46 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldMeta.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldMeta.java @@ -1,12 +1,11 @@ package com.nis.modules.asset.entity; -import java.util.List; - import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.util.List; + @Data @TableName("asset_field_meta") public class AssetFieldMeta { diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldValue.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldValue.java index 28d1ac4b..d333192e 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldValue.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetFieldValue.java @@ -1,7 +1,6 @@ package com.nis.modules.asset.entity; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetImportEnum.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetImportEnum.java index 0d1b79d2..f6d12b5d 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetImportEnum.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetImportEnum.java @@ -10,29 +10,30 @@ public enum AssetImportEnum { SN("sn", 1), PARENT("parent", 2), MANAGE_IP("manageIp", 3), - BRAND("brand", 4), - MODEL("model", 5), - DC("dc", 6), - CABINET("cabinet", 7), - U_START("ustart", 8), - U_END("uend", 9), - STATE("stateConf", 10), - TYPE("typeConf", 11), - PURCHASE_DATE("purchaseDate", 12), - TAG("tag", 13), - AUTH_PROTOCOL_PORT("authProtocolPort", 14), - AUTH_TYPE("authType", 15), - AUTH_USER_NAME("authUsername", 16), - AUTH_PIN("authPin", 17), - AUTH_PRI_KEY("authPriKey", 18), - AUTH_USER_TIP("authUserTip", 19), - AUTH_PIN_TIP("authPinTip", 20), - SNMP_CREDENTIAL("snmpCredential", 21), - CLIENT_USER("clientUser", 22), - CLIENT_PIN("clientPin", 23), - CLIENT_TOKEN("clientToken", 24), - CLIENT_PORT("clientPort", 25), - CLIENT_ENABLE("clientEnable", 26); + IPMI_IP("ipmiIp", 4), + BRAND("brand", 5), + MODEL("model", 6), + DC("dc", 7), + CABINET("cabinet", 8), + U_START("ustart", 9), + U_END("uend", 10), + STATE("stateConf", 11), + TYPE("typeConf", 12), + PURCHASE_DATE("purchaseDate", 13), + TAG("tag", 14), + AUTH_PROTOCOL_PORT("authProtocolPort", 15), + AUTH_TYPE("authType", 16), + AUTH_USER_NAME("authUsername", 17), + AUTH_PIN("authPin", 18), + AUTH_PRI_KEY("authPriKey", 19), + AUTH_USER_TIP("authUserTip", 20), + AUTH_PIN_TIP("authPinTip", 21), + SNMP_CREDENTIAL("snmpCredential", 22), + CLIENT_USER("clientUser", 23), + CLIENT_PIN("clientPin", 24), + CLIENT_TOKEN("clientToken", 25), + CLIENT_PORT("clientPort", 26), + CLIENT_ENABLE("clientEnable", 27); private String name; private int index; diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModel.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModel.java index 632929ee..07af0b38 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModel.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModel.java @@ -1,11 +1,8 @@ package com.nis.modules.asset.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.nis.modules.panel.entity.VisualChart; - +import com.baomidou.mybatisplus.annotation.*; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualDashboard; import lombok.Data; import java.io.Serializable; @@ -26,7 +23,7 @@ public class AssetModel implements Serializable { /** * 主键 */ - @TableId(type = IdType.AUTO) + @TableId(type = IdType.INPUT) private Integer id; /** @@ -65,6 +62,12 @@ public class AssetModel implements Serializable { */ private String sysObjectId; + /** + * template id + */ + @TableField(strategy = FieldStrategy.IGNORED) + private Integer dashboardId; + /** * TSG 产品 @@ -84,7 +87,10 @@ public class AssetModel implements Serializable { @TableField(exist = false) private List<VisualChart> charts; - + + @TableField(exist = false) + private VisualDashboard dashboard; + @TableField(exist = false) private Integer assetNum; diff --git a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModelImportEnum.java b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModelImportEnum.java index d98191ec..35c58665 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModelImportEnum.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/entity/AssetModelImportEnum.java @@ -8,7 +8,7 @@ public enum AssetModelImportEnum { NAME("model name", 0), BRAND("brand name", 1), - CHART_TEMPLATES("chart templates", 2), + DASHBOARD_TEMPLATE("dashboard template", 2), DESCRIPTION("description", 3), ASSET_TYPE_NAME("asset type name", 4), OID("oid", 5); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetFeatureJob.java b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetFeatureJob.java index 2a904c80..79601367 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetFeatureJob.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetFeatureJob.java @@ -1,20 +1,18 @@ package com.nis.modules.asset.job; -import java.util.List; - +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSON; +import com.nis.common.utils.Constant; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.quartz.QuartzJobBean; -import com.alibaba.fastjson.JSON; -import com.nis.common.utils.Constant; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.asset.service.AssetAssetService; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.List; @DisallowConcurrentExecution public class AssetFeatureJob extends QuartzJobBean { diff --git a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetPingStatusJob.java b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetPingStatusJob.java index 43396f27..fcaac8aa 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetPingStatusJob.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetPingStatusJob.java @@ -8,14 +8,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.nis.common.utils.Constant; import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.PromApiService; import com.nis.modules.asset.dao.AssetAssetDao; import com.nis.modules.asset.dao.AssetPingDao; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.AssetPing; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.asset.service.AssetPingService; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.PromApiService; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.service.SysConfigService; import org.apache.commons.lang3.time.StopWatch; @@ -24,7 +24,6 @@ import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpEntity; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.transaction.annotation.Transactional; diff --git a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetTalonStatusJob.java b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetTalonStatusJob.java index b60cdf6c..dc35904b 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/job/AssetTalonStatusJob.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/job/AssetTalonStatusJob.java @@ -259,7 +259,7 @@ public class AssetTalonStatusJob extends QuartzJobBean { } else if (dcState && clientEnable.equals(1) && enabled.equals(0)) { state = 12; } - logStateList.add(new MonitorEndpointState(conf.getEndpointId(), conf.getId(), conf.getType(), state, talonStatus.getVersion(), new Date())); + logStateList.add(new MonitorEndpointState(conf.getEndpointId(), conf.getId(), conf.getType(), state, talonStatus.getVersion(), StrUtil.EMPTY, new Date())); } //判断查询数据与缓存中变化的信息 Map endpointStates = redisTemplate.opsForHash().entries(Constant.ENDPOINT_LOGS_STATE_CACHE_KEY); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetAssetService.java b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetAssetService.java index 82dcd794..2feecb3e 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetAssetService.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetAssetService.java @@ -7,7 +7,6 @@ import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.AssetFieldMeta; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.module.entity.MonitorModule; -import com.nis.modules.panel.entity.VisualChart; import com.nis.modules.project.entity.MonitorProject; import org.springframework.web.multipart.MultipartFile; @@ -74,8 +73,6 @@ public interface AssetAssetService extends IService<AssetAsset> { */ List<AssetAsset> getOpenPingAssets(); - List<VisualChart> getAssetsWithTagByChartIds(List<Integer> idList); - /** * 根据ip获取 asset * @param ip diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldGroupService.java b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldGroupService.java index 046624ba..ef9f1e41 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldGroupService.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldGroupService.java @@ -1,12 +1,12 @@ package com.nis.modules.asset.service; -import java.util.List; -import java.util.Map; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.asset.entity.AssetFieldGroup; +import java.util.List; +import java.util.Map; + public interface AssetFieldGroupService extends IService<AssetFieldGroup>{ PageUtils queryList(Map<String,Object> params); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldMetaService.java b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldMetaService.java index d70bf06d..74757b8c 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldMetaService.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/AssetFieldMetaService.java @@ -1,12 +1,12 @@ package com.nis.modules.asset.service; -import java.util.List; -import java.util.Map; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.asset.entity.AssetFieldMeta; +import java.util.List; +import java.util.Map; + public interface AssetFieldMetaService extends IService<AssetFieldMeta>{ AssetFieldMeta queryAssetFieldMeta(Integer id); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetAssetServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetAssetServiceImpl.java index 3167aa25..bc588c31 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetAssetServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetAssetServiceImpl.java @@ -13,6 +13,7 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.parser.Feature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -26,24 +27,23 @@ import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.asset.dao.AssetAssetDao; import com.nis.modules.asset.entity.*; import com.nis.modules.asset.service.*; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.entity.MonitorEndpointState; import com.nis.modules.endpoint.service.MonitorEndpointService; import com.nis.modules.endpoint.service.MonitorEndpointStateService; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualChartElement; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualChartElementService; -import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; import com.nis.modules.project.entity.MonitorProject; import com.nis.modules.project.service.MonitorProjectService; import com.nis.modules.stat.service.StatService; import com.nis.modules.sys.dao.SysUserDao; import com.nis.modules.sys.entity.SnmpCredential; -import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.entity.SysUserStarredEntity; import com.nis.modules.sys.service.BasicImportAndExportServices; @@ -54,6 +54,7 @@ import com.nis.modules.sys.shiro.ShiroUtils; import com.nis.modules.vsys.entity.VsysAssetRel; import com.nis.modules.vsys.service.VsysAssetRelService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.shiro.ShiroException; import org.snmp4j.smi.TimeTicks; import org.springframework.beans.factory.annotation.Autowired; @@ -80,7 +81,7 @@ import java.util.stream.Collectors; @Service public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset> implements AssetAssetService { - private static Log logger = Log.get(); + private static final Log log = Log.get(); @Autowired private RedisTemplate redisTemplate; @@ -134,15 +135,12 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset private SnmpCredentialService snmpCredentialService; @Autowired - private VisualPanelService panelService; + private VisualDashboardService dashboardService; @Autowired private VisualChartService chartService; @Autowired - private VisualChartElementService chartElementService; - - @Autowired private MonitorProjectService projectService; @Autowired @@ -166,10 +164,12 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset @Autowired private DataSourceTransactionManager dataSourceTransactionManager; - @Autowired private AssetCommentService assetCommentService; + @Autowired + private VisualService visualService; + @SuppressWarnings("unchecked") @Override public AssetAsset queryAssetInfo(Integer id) { @@ -837,11 +837,11 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 保存 asset 关联数据 this.saveAssetRelData(asset); - // asset panel & info chart - this.saveAssetInfoPanel(asset); + // asset dashboard & info chart + this.saveAssetInfoDashboard(asset); - // 通过 model chart tepmlate 新增 asset charts - this.saveAssetChartsViaModelChartTmpl(asset); + // sync Asset Dashboard Via Model + this.syncAssetDashboardViaModel(asset.getId(), asset.getModelId()); // 保存 默认 VSYS 和 Asset 关联关系 this.saveOrUpdateDefaultVsysAssetRel(asset.getId(), asset.getModelId()); @@ -890,78 +890,40 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset * * @param asset */ - private void saveAssetInfoPanel(AssetAsset asset) { - // 配置信息获取 - SysConfigEntity assetChartConfig = sysConfigService.getOne(new QueryWrapper<SysConfigEntity>().lambda().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_ASSET_CHART_TPL)); - // asset config - VisualChart chartTemplate = JSONObject.parseObject(assetChartConfig.getParamValue(), VisualChart.class); - // 新增时需要新增 panel chart - chartService.saveRelPanelAndChart(Constant.PanelType.ASSET.getValue(), asset.getId(), null, chartTemplate); + private void saveAssetInfoDashboard(AssetAsset asset) { + // get model template id + AssetModel model = modelService.getById(asset.getModelId()); + Integer templateId = model.getDashboardId(); + + Integer linkId = asset.getId(); + String name = asset.getName(); + String seq = asset.getSeq(); + + // save Rel Dashboard And Chart + chartService.saveRelDashboardAndChart(DashboardConstant.Type.ASSET.getValue(), linkId, name, templateId, seq); } /** - * 通过 model chart tepmlate 新增 asset charts + * sync Asset Dashboard Via Model * - * @param asset + * @param assetId + * @param modelId */ - private void saveAssetChartsViaModelChartTmpl(AssetAsset asset) { - // 通过关联 model charts 添加 asset charts - AssetModel model = modelService.getById(asset.getModelId()); - if (StringUtils.isNotEmpty(model.getChartIds())) { - List<String> list = Arrays.asList(model.getChartIds().split(",")); - List<Integer> chartIdList = list.stream().map(Integer::parseInt).collect(Collectors.toList()); - // 补充 group 下的 chart id - List<VisualChart> childCharts = chartService.list(new LambdaQueryWrapper<VisualChart>().in(VisualChart::getGroupId, chartIdList)); - List<Integer> childChartIdList = childCharts.stream().map(VisualChart::getId).distinct().collect(Collectors.toList()); - chartIdList.addAll(childChartIdList); - chartIdList = chartIdList.stream().distinct().collect(Collectors.toList()); - List<VisualChart> chartList = chartService.queryChartWithElementByIds(chartIdList); - - AssetAsset assetInfo = this.queryAssetInfo(asset.getId()); - - VisualPanel assetPanel = panelService.getOne(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ASSET.getValue()).eq(VisualPanel::getLink, asset.getId())); - - // model chart 组 和 asset 新增 chart 组关联关系,用来做 asset 新增 chart 组关系映射 - Map<Integer, Integer> groupIdMapping = new HashMap<>(); - - // 按照 group 升序,先添加组 - chartList = chartList.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); - - // 渲染新增 - for (VisualChart chart : chartList) { - VisualChart saveChart = new VisualChart(); - Tool.BeanUtil.copyProperties(chart, saveChart); - saveChart.setId(null); - saveChart.setPanelId(assetPanel.getId()); - saveChart.setUpdateAt(new Date()); - saveChart.setUpdateBy(ShiroUtils.getUserId().intValue()); - saveChart.setPid(chart.getId()); - - saveChart.setVarType(Constant.ChartVariableType.ASSET.getValue()); - saveChart.setVarId(asset.getId()); - - Integer newGroupId = groupIdMapping.get(saveChart.getGroupId()); - saveChart.setGroupId(newGroupId == null ? 0 : newGroupId); - - saveChart.setName(Tool.NzExpressionUtil.renderExpression(chart.getName(), assetInfo)); - saveChart.setParam(ToolUtil.isNotEmpty(chart.getParam()) ? Tool.NzExpressionUtil.renderExpression(chart.getParam().toString(), asset) : null); - - chartService.save(saveChart); - - if (Constant.CHART_GROUP_TYPE.equalsIgnoreCase(chart.getType())) { - groupIdMapping.put(chart.getId(), saveChart.getId()); - } - - if (CollectionUtils.isNotEmpty(saveChart.getElements())) { - for (VisualChartElement chartElement : saveChart.getElements()) { - chartElement.setId(null); - chartElement.setChartId(saveChart.getId()); - chartElement.setExpression(ToolUtil.isNotEmpty(chartElement.getExpression()) ? Tool.NzExpressionUtil.renderExpression(chartElement.getExpression(), asset) : null); - } - chartElementService.saveBatch(saveChart.getElements()); - } - } + private void syncAssetDashboardViaModel(Integer assetId, Integer modelId) { + AssetModel model = modelService.getById(modelId); + Integer modelDashboardTmplId = model.getDashboardId(); + if (ObjectUtil.isNull(modelDashboardTmplId)) { + log.warn("[syncAssetDashboardViaModel] [asset model not config dashboard template. no sync asset dashboard] [assetId: {}] [modelId: {}]", assetId, modelId); + return; } + + log.info("[syncAssetDashboardViaModel] [sync asset dashboard begin.] [assetId: {}] [modelId: {}]", assetId, modelId); + // sync dashboard + VisualDashboard assetDashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()) + .eq(VisualDashboard::getLink, assetId)); + visualService.syncTemplateDashboard(assetDashboard.getId(), null, null, null); + log.info("[syncAssetDashboardViaModel] [sync asset dashboard finshed.] [assetId: {}] [modelId: {}]", assetId, modelId); } @Override @@ -1001,7 +963,7 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset asset.setCabinetEnd(parent.getCabinetEnd()); } - // 留作对比是否更改 model + // 留作对比是否更改属性 AssetAsset oldAsset = this.getById(asset.getId()); // authPrivKey @@ -1012,9 +974,26 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 保存 this.updateById(asset); - // 如果修改了Model, 处理关联 charts 变化 - if (!oldAsset.getModelId().equals(asset.getModelId())) { - this.updateModelCharts(asset); + // if update asset model,use current model config dashboard template sync asset dashboard + if (ObjectUtil.notEqual(oldAsset.getModelId(), asset.getModelId())) { + // update asset dashboard tmpl_id + AssetModel model = modelService.getById(asset.getModelId()); + Integer modelDashboardTmplId = model.getDashboardId(); + dashboardService.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getTmplId, ObjectUtil.defaultIfNull(modelDashboardTmplId, -1)) + .eq(VisualDashboard::getLink, asset.getId()) + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()) + ); + // sync dashboard + this.syncAssetDashboardViaModel(asset.getId(), asset.getModelId()); + } + + // If the asset name is modified, the asset dashboard name is also modified + if (ObjectUtil.notEqual(oldAsset.getName(), asset.getName())) { + dashboardService.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getName, asset.getName()) + .eq(VisualDashboard::getLink, asset.getId()) + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue())); } // 如果没有指定 meta, 则视为删除 asset之前关联的 meta 信息 @@ -1045,29 +1024,6 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset redisTemplate.opsForHash().delete(Constant.ASSET_TALON_STATUS_CACHE_KEY, assetId.toString()); } - /** - * asset 更改了 model , 对应更新 asset charts,自己的 charts 保留 - * @param asset - */ - @Transactional(rollbackFor = Exception.class) - public void updateModelCharts(AssetAsset asset) { - VisualPanel assetPanel = panelService.getOne(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ASSET).eq(VisualPanel::getLink, asset.getId())); - List<VisualChart> chartList = chartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getPanelId, assetPanel.getId())); - List<Integer> delIds = chartList.stream().filter(chart -> chart.getPid() != null ? true : false).map(VisualChart::getId).collect(Collectors.toList()); - - // 删除之前 model 关联的图表 - Integer[] ids = new Integer[delIds.size()]; - delIds.toArray(ids); - - if (ToolUtil.isNotEmpty(ids)) { - // 删除旧 model 关联的 charts - chartService.delCharts(ids, null); - } - - // 通过 model chart tepmlate 新增 asset charts - this.saveAssetChartsViaModelChartTmpl(asset); - } - private void saveAssetRelData(AssetAsset asset) { // fields List<AssetFieldMeta> fields = asset.getFields(); @@ -1141,13 +1097,13 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset monitorEndpointService.deleteEndpointByIds(endpointIds); } - // panel chart chartElement - List<VisualPanel> panelList = panelService.list(new LambdaQueryWrapper<VisualPanel>() - .eq(VisualPanel::getType, Constant.PanelType.ASSET.getValue()) - .in(VisualPanel::getLink, removeAssetIdList)); - if (Tool.CollUtil.isNotEmpty(panelList)) { - Set<Integer> panelIds = panelList.stream().map(VisualPanel::getId).collect(Collectors.toSet()); - panelService.delPanelsAndChartInfoByPanelIds(panelIds); + // dashboard chart chartElement + List<VisualDashboard> dashboardList = dashboardService.list(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()) + .in(VisualDashboard::getLink, removeAssetIdList)); + if (Tool.CollUtil.isNotEmpty(dashboardList)) { + Set<Integer> dashboardIds = dashboardList.stream().map(VisualDashboard::getId).collect(Collectors.toSet()); + dashboardService.delDashboardsAndChartInfoByDashboardIds(dashboardIds); } // chart : create by asset chart tmplate @@ -1362,7 +1318,7 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 进行ssh采集 String sshCollectScript = assetType.getSshCollectScript(); if (StrUtil.isBlank(sshCollectScript)) { - logger.debug("asset sshCollectScript is empty asset info : %s", JSON.toJSON(asset)); + log.debug("asset sshCollectScript is empty asset info : %s", JSON.toJSON(asset)); return; } @@ -1374,8 +1330,8 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset this.getSshInfo(assetFeatureMap, results, sshCommondResult, asset); } catch (JSchException | IOException e) { - logger.error(e); - logger.error("asset feature get data error,assetId : {} info : {}", assetId, e); + log.error(e); + log.error("asset feature get data error,assetId : {} info : {}", assetId, e); throw new NZException(e.getMessage()); } finally { SshUtil.close(session); @@ -1387,13 +1343,13 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset try { SnmpCredential snmpCredential = snmpCredentialService.getById(asset.getSnmpCredentialId()); if (ToolUtil.isEmpty(snmpCredential)) { - logger.debug("asset snmpCredential is empty asset info : %s", JSON.toJSON(asset)); + log.debug("asset snmpCredential is empty asset info : %s", JSON.toJSON(asset)); return; } this.getSystemInfoBySnmp(assetFeatureMap, results, asset, snmpCredential); } catch (IOException e) { - logger.error("asset snmp collect error asset info : %s", JSON.toJSON(asset)); - logger.error(e); + log.error("asset snmp collect error asset info : %s", JSON.toJSON(asset)); + log.error(e); } } // 存入db 无则新增 有则修改 @@ -1706,6 +1662,9 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveAssetsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -1736,11 +1695,11 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // model modelService.remove(new LambdaQueryWrapper<AssetModel>().eq(AssetModel::getSeq, seq)); - // 删除关联的 panel chart chartElement信息 - List<VisualPanel> panels = panelService.list(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ASSET.getValue()).in(VisualPanel::getLink, assetIds)); - if (CollectionUtils.isNotEmpty(panels)) { - Set<Integer> panelIds = panels.stream().map(VisualPanel::getId).collect(Collectors.toSet()); - panelService.delPanelsAndChartInfoByPanelIds(panelIds); + // 删除关联的 dashboard chart chartElement信息 + List<VisualDashboard> dashboards = dashboardService.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()).in(VisualDashboard::getLink, assetIds)); + if (CollectionUtils.isNotEmpty(dashboards)) { + Set<Integer> dashboardIds = dashboards.stream().map(VisualDashboard::getId).collect(Collectors.toSet()); + dashboardService.delDashboardsAndChartInfoByDashboardIds(dashboardIds); } // 删除 field meta/value @@ -1751,22 +1710,17 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset @Override public List<AssetAsset> getBlackboxAssetInfoList() { - List<AssetAsset> assetList = this.list(); - - // 支持 ping 的 state_conf - List<AssetStateConf> stateConfList = stateConfService.list(new LambdaQueryWrapper<AssetStateConf>().eq(AssetStateConf::getPing, 1)); - List<Integer> enablePingStateConfIdList = stateConfList.stream().map(AssetStateConf::getId).collect(Collectors.toList()); - - // 支持 ping 的 asset - assetList = assetList.stream().filter(asset -> enablePingStateConfIdList.contains(asset.getStateId())).collect(Collectors.toList()); + // get assets with asset_state_conf ping is enabled + List<AssetAsset> assetList = this.getOpenPingAssets(); List<Dc> dcList = dcService.list(); Map<Integer, Dc> dcIdAndNameMap = dcList.stream().collect(Collectors.toMap(Dc::getId, Function.identity())); - SysConfigEntity assetPingIntervalConfig = sysConfigService.getOne(new LambdaQueryWrapper<SysConfigEntity>().eq(SysConfigEntity::getParamKey, Constant.SYSCONFIG_KEY_ASSET_PING_INTERVAL)); + // asset_ping_interval,default = 300 + String assetPingIntervalInConfig = sysConfigService.getValueOrDefault(Constant.SYSCONFIG_KEY_ASSET_PING_INTERVAL, "300"); for (AssetAsset entity : assetList) { entity.setDc(dcIdAndNameMap.get(entity.getDcId())); - entity.setAssetPingInterval(assetPingIntervalConfig.getParamValue()); + entity.setAssetPingInterval(assetPingIntervalInConfig); } return assetList; } @@ -1785,15 +1739,6 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset return assetList; } - @Override - public List<VisualChart> getAssetsWithTagByChartIds(List<Integer> chartIds) { - List<VisualChart> chartIdWithAssetEntity = this.baseMapper.getAssetsByChartIds(chartIds); - if (CollectionUtils.isEmpty(chartIdWithAssetEntity)) { - return Collections.emptyList(); - } - return chartIdWithAssetEntity; - } - private Map saveAssetsFromImportDataList(List<Map<Integer, String>> importDataList, List<String> headerInfos, Map<String, Object> params) { String seq = StrUtil.uuid(); params.put("seq", seq); @@ -1816,7 +1761,7 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset for (int i = 0; i < handleImportData.size(); i++) { Map saveEntitys = Tool.MapUtil.newHashMap(); Map<Integer, String> dataMap = handleImportData.get(i); - Integer lineNum = Integer.parseInt(dataMap.get(999)) + 1; + Integer lineNum = Integer.parseInt(dataMap.get(Tool.StrUtil.INDEX_NOT_FOUND)) + 1; // name, 以 name作为索引 标识该条记录是否存在 String assetName = dataMap.get(AssetImportEnum.NAME.getIndex()); validateUtil.validateRequired(assetName, lineNum, AssetImportEnum.NAME.getIndex()); @@ -1824,6 +1769,8 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 索引列重复 & 忽略标识,提示忽略本行 if (BooleanUtil.and(indexDuplicate, StrUtil.equals("2", existed))) { validateUtil.ignoreThisRow(lineNum, AssetImportEnum.NAME.getIndex()); + // 删除标记元素 + MapUtil.removeAny(dataMap, Tool.StrUtil.INDEX_NOT_FOUND); failContentList.add(dataMap); continue; } @@ -1837,6 +1784,10 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset validateUtil.validateRegex(manageIp, Constant.REGEX_IP, lineNum, AssetImportEnum.MANAGE_IP.getIndex()); validateUtil.validateDuplicate("asset_asset", "manage_ip", manageIp, assetName, lineNum, AssetImportEnum.MANAGE_IP.getIndex()); + String ipmiIp = dataMap.get(AssetImportEnum.IPMI_IP.getIndex()); + if(StrUtil.isNotEmpty(ipmiIp)) + validateUtil.validateRegex(ipmiIp, Constant.REGEX_IP, lineNum, AssetImportEnum.IPMI_IP.getIndex()); + // state conf 不自动添加 String stateName = dataMap.get(AssetImportEnum.STATE.getIndex()); validateUtil.validateRequired(stateName, lineNum, AssetImportEnum.STATE.getIndex()); @@ -2014,8 +1965,11 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset if (BooleanUtil.and(Tool.StrUtil.equals("0", ignoreError), Tool.CollUtil.isNotEmpty(errMsgForThisLine))) { // 结束本次导入,自导入行开始 到结尾数据行,提示错误信息 for (int j = i; j < handleImportData.size(); j++) { - validateUtil.recordImportAttrErr(Integer.parseInt(handleImportData.get(j).get(999)) + 1, RCode.IMPORT_ERROR_STOP); - failContentList.add(handleImportData.get(j)); + validateUtil.recordImportAttrErr(Integer.parseInt(handleImportData.get(j).get(Tool.StrUtil.INDEX_NOT_FOUND)) + 1, RCode.IMPORT_ERROR_STOP); + Map<Integer, String> tmap = handleImportData.get(j); + // 删除标记元素 + MapUtil.removeAny(tmap, Tool.StrUtil.INDEX_NOT_FOUND); + failContentList.add(tmap); } break; } @@ -2034,6 +1988,7 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset asset.setCreateAt(new Date()); asset.setCreateBy(ShiroUtils.getUserId()); asset.setManageIp(manageIp); + asset.setIpmiIp(ipmiIp); if (StrUtil.isNotEmpty(snmpCredentialName)) { SnmpCredential snmpCredential = snmpCredentialService.getOne(new LambdaQueryWrapper<SnmpCredential>().eq(SnmpCredential::getName, snmpCredentialName)); asset.setSnmpCredentialId(snmpCredential.getId()); @@ -2077,8 +2032,8 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset asset.setBrandId(parentAsset.getBrandId()); asset.setModelId(parentAsset.getModelId()); } - asset.setClientUser(ObjectUtil.defaultIfEmpty(clientUser, null)); - asset.setClientPin(ObjectUtil.defaultIfEmpty(clientPin, null)); + asset.setClientUser(StrUtil.emptyToDefault(clientUser, null)); + asset.setClientPin(StrUtil.emptyToDefault(clientPin, null)); asset.setClientAddress(asset.getManageIp()); asset.setClientPort(StringUtils.isNotEmpty(clientPort) ? Integer.valueOf(clientPort) : null); asset.setClientToken(clientToken); @@ -2096,17 +2051,21 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset updateNum++; } } catch (Exception e) { + // 删除标记元素 + MapUtil.removeAny(dataMap, Tool.StrUtil.INDEX_NOT_FOUND); failContentList.add(dataMap); dataSourceTransactionManager.rollback(transactionStatus); validateUtil.recordImportAttrErr(lineNum, RCode.ERROR); - logger.error("Asset import roll back the transaction failure", e); + log.error("Asset import roll back the transaction failure", e); } } else { + // 删除标记元素 + MapUtil.removeAny(dataMap, Tool.StrUtil.INDEX_NOT_FOUND); failContentList.add(dataMap); } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_ASSET_ASSET_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) @@ -2277,9 +2236,9 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset asset.setUpdateBy(ShiroUtils.getUserId()); this.updateById(asset); - // 如果修改了Model, 处理关联 charts 变化 - if (!oldAsset.getModelId().equals(asset.getModelId())) { - this.updateModelCharts(asset); + // if update asset model,use current model config dashboard template sync asset dashboard + if (ObjectUtil.notEqual(oldAsset.getModelId(), asset.getModelId())) { + this.syncAssetDashboardViaModel(asset.getId(), asset.getModelId()); } // 修改后处理 ping & Talon 数据 @@ -2288,14 +2247,11 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset // 是否同步更新关联的dashboard,可选值: 0:不同步 1:同步 默认值:1 String syncDashboard = Tool.ObjectUtil.defaultIfEmpty((String) params.get("syncDashboard"), "1"); if (StrUtil.equals("1", syncDashboard)) { - // asset info charts && dashboard charts - List<VisualChart> assetChartList = chartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getVarType, Constant.ChartVariableType.ASSET.getValue()).eq(VisualChart::getVarId, asset.getId())); - if (Tool.CollUtil.isNotEmpty(assetChartList)) { - List<Integer> assetChartIdList = assetChartList.stream().map(VisualChart::getId).collect(Collectors.toList()); - Map<String, Object> map = Tool.MapUtil.newHashMap(2); - map.put("ids", assetChartIdList); - chartService.syncTmpl(map); - } + // sync dashboard + VisualDashboard assetDashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()) + .eq(VisualDashboard::getLink, asset.getId())); + visualService.syncTemplateDashboard(assetDashboard.getId(), null, null, null); } // 是否同步更新关联的endpoint,可选值: 0:不同步 1:同步 默认值:1 String syncEndpoint = Tool.ObjectUtil.defaultIfEmpty((String) params.get("syncEndpoint"), "1"); @@ -2308,10 +2264,10 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset } else { params.put("save", true); this.save(asset); - // asset panel & info chart - this.saveAssetInfoPanel(asset); - // 通过 model chart tepmlate 新增 asset charts - this.saveAssetChartsViaModelChartTmpl(asset); + // asset dashboard & info chart + this.saveAssetInfoDashboard(asset); + // sync Asset Dashboard Via Model + this.syncAssetDashboardViaModel(asset.getId(), asset.getModelId()); } // 保存 默认 VSYS 和 Asset 关联关系 @@ -2331,8 +2287,8 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset List<Map<Integer, String>> childList = new ArrayList<>(); for (int i = 0; i < importDataList.size(); i++) { Map<Integer, String> dataMap = importDataList.get(i); - dataMap.put(999, i + "");// 实际数据行数 - if (StringUtils.isEmpty(dataMap.get(2))) { + dataMap.put(Tool.StrUtil.INDEX_NOT_FOUND, i + "");// 实际数据行数 + if (StringUtils.isEmpty(dataMap.get(AssetImportEnum.PARENT.getIndex()))) { list.add(dataMap); } else { childList.add(dataMap); @@ -2351,6 +2307,7 @@ public class AssetAssetServiceImpl extends ServiceImpl<AssetAssetDao, AssetAsset tempList.add(asset.getSn()); tempList.add(ToolUtil.isEmpty(asset.getParent()) ? "" : asset.getParent().getName()); tempList.add(asset.getManageIp()); + tempList.add(asset.getIpmiIp()); tempList.add(asset.getBrand().getName()); tempList.add(asset.getModel().getName()); tempList.add(asset.getDc().getName()); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldGroupServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldGroupServiceImpl.java index 83584d19..53962b71 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldGroupServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldGroupServiceImpl.java @@ -1,14 +1,6 @@ package com.nis.modules.asset.service.impl; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.nis.common.utils.Tool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; @@ -17,6 +9,7 @@ import com.nis.common.exception.NZException; import com.nis.common.utils.PageUtils; import com.nis.common.utils.Query; import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; import com.nis.modules.asset.dao.AssetFieldGroupDao; import com.nis.modules.asset.dao.AssetFieldMetaDao; import com.nis.modules.asset.dao.AssetFieldValueDao; @@ -24,8 +17,13 @@ import com.nis.modules.asset.entity.AssetFieldGroup; import com.nis.modules.asset.entity.AssetFieldMeta; import com.nis.modules.asset.entity.AssetFieldValue; import com.nis.modules.asset.service.AssetFieldGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import cn.hutool.core.util.ObjectUtil; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service("assetFieldGroupService") public class AssetFieldGroupServiceImpl extends ServiceImpl<AssetFieldGroupDao,AssetFieldGroup> implements AssetFieldGroupService{ diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldMetaServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldMetaServiceImpl.java index 0b104961..9205f2b1 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldMetaServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetFieldMetaServiceImpl.java @@ -1,40 +1,32 @@ package com.nis.modules.asset.service.impl; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nis.modules.sys.entity.SysUserStarredEntity; -import com.nis.modules.sys.service.SysUserStarredService; -import com.nis.modules.sys.shiro.ShiroUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; -import com.nis.common.utils.Constant; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.Query; -import com.nis.common.utils.RCode; -import com.nis.common.utils.ToolUtil; +import com.nis.common.utils.*; import com.nis.modules.asset.dao.AssetFieldMetaDao; import com.nis.modules.asset.dao.AssetFieldValueDao; import com.nis.modules.asset.entity.AssetFieldMeta; import com.nis.modules.asset.entity.AssetFieldValue; import com.nis.modules.asset.service.AssetFieldMetaService; -import com.nis.modules.sys.entity.SysApiKey; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; +import com.nis.modules.sys.entity.SysUserStarredEntity; +import com.nis.modules.sys.service.SysUserStarredService; +import com.nis.modules.sys.shiro.ShiroUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Service("assetFieldMetaService") public class AssetFieldMetaServiceImpl extends ServiceImpl<AssetFieldMetaDao,AssetFieldMeta> implements AssetFieldMetaService{ @Autowired diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetModelServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetModelServiceImpl.java index 7071da5c..71fa98d9 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetModelServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/AssetModelServiceImpl.java @@ -1,5 +1,6 @@ package com.nis.modules.asset.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.BooleanUtil; @@ -8,27 +9,30 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; -import com.nis.modules.asset.dao.AssetAssetDao; import com.nis.modules.asset.dao.AssetModelDao; import com.nis.modules.asset.entity.*; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.asset.service.AssetBrandService; import com.nis.modules.asset.service.AssetModelService; import com.nis.modules.asset.service.AssetTypeConfService; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.service.MonitorEndpointService; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.service.VisualChartService; import com.nis.modules.sys.entity.SysUserStarredEntity; import com.nis.modules.sys.service.BasicImportAndExportServices; import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.io.FilenameUtils; import org.snmp4j.util.SimpleOIDTextFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @@ -64,15 +68,6 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel private AssetBrandService brandService; @Autowired - private AssetModelDao assetModelDao; - - @Autowired - private VisualChartService visualChartService; - - @Autowired - private AssetAssetDao assetDao; - - @Autowired private AssetTypeConfService typeConfService; @Autowired @@ -90,6 +85,12 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel @Autowired private MonitorEndpointService monitorEndpointService; + @Autowired + private VisualService visualService; + + @Autowired + private VisualDashboardService dashboardService; + @Override public AssetModel queryModelInfo(Integer id) { AssetModel model = this.getById(id); @@ -97,14 +98,10 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel throw new NZException(RCode.ASSET_MODEL_NOTFOUND); } AssetBrand brand = brandService.getById(model.getBrandId()); - String chartIds = model.getChartIds(); - if(!StrUtil.isBlank(chartIds)) { - List<VisualChart> charts = new ArrayList<>(); - for (String chartId : Arrays.asList(chartIds.split(","))) { - VisualChart chartById = visualChartService.getById(chartId); - charts.add(chartById); - } - model.setCharts(charts); + Integer dashboardId = model.getDashboardId(); + if(ToolUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = dashboardService.getById(dashboardId); + model.setDashboard(dashboard); } AssetTypeConf typeConf = typeConfService.getById(model.getTypeId()); //获取资产数量 @@ -146,16 +143,12 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel // 当前登录用户 params.put("userId", ShiroUtils.getUserId().intValue()); - List<AssetModel> modelList = assetModelDao.queryList(page, params); + List<AssetModel> modelList = this.getBaseMapper().queryList(page, params); for(AssetModel model : modelList) { - String chartIds = model.getChartIds(); - if (!StrUtil.isBlank(chartIds)) { - List<VisualChart> charts = new ArrayList<>(); - for (String id : Arrays.asList(chartIds.split(","))) { - VisualChart chartById = visualChartService.getById(id); - charts.add(chartById); - } - model.setCharts(charts); + Integer dashboardId = model.getDashboardId(); + if(ToolUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = dashboardService.getById(dashboardId); + model.setDashboard(dashboard); } } page.setRecords(modelList); @@ -180,15 +173,15 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel if (!flag) { throw new NZException(RCode.ASSET_MODELNAME_DUPLICATE); } - - // 3. 校验chart是否为模板且存在 - String chartIds = model.getChartIds(); - if(StrUtil.isNotBlank(chartIds)) { - List<String> chartids = Arrays.asList(chartIds.split(",")); - List<VisualChart> charts = visualChartService.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getPanelId, 0).in(VisualChart::getId, chartids)); - if(!ToolUtil.equals(charts.size(), chartids.size())) { - throw new NZException(RCode.ASSET_MODEL_CHART_ERROR); - } + + // asset model dashboard, type = template & varType = asset + Integer dashboardId = model.getDashboardId(); + if (ToolUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getId, dashboardId) + .eq(VisualDashboard::getType, DashboardConstant.Type.TEMPLATE.getValue()) + .eq(VisualDashboard::getVarType, DashboardConstant.VariableType.ASSET.getValue())); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); } // 4. type 是否存在 @@ -253,9 +246,23 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel // 保存 this.updateById(model); - // 如果修改了Model, 处理关联 charts 变化 - if (!oldModel.getBrandId().equals(model.getBrandId())) { - assetDao.updateBrandIdByModelId(model.getId(), model.getBrandId()); + // change asset link brand + if (ObjectUtil.notEqual(oldModel.getBrandId(), model.getBrandId())) { + assetAssetService.update(new LambdaUpdateWrapper<AssetAsset>() + .set(AssetAsset::getBrandId, model.getBrandId()) + .eq(AssetAsset::getModelId, model.getId())); + } + + // If the dashboard template is modified, the asset dashboard template ID will also be modified + if (ObjectUtil.notEqual(oldModel.getDashboardId(), model.getDashboardId())) { + List<AssetAsset> assetList = assetAssetService.list(new LambdaQueryWrapper<AssetAsset>().eq(AssetAsset::getModelId, model.getId())); + if (CollUtil.isNotEmpty(assetList)) { + List<Integer> assetIdList = assetList.stream().map(AssetAsset::getId).collect(Collectors.toList()); + dashboardService.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getTmplId, ObjectUtil.defaultIfNull(model.getDashboardId(), -1)) + .in(VisualDashboard::getLink, assetIdList) + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue())); + } } return model.getId(); } @@ -373,6 +380,9 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveAssetModelsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -424,26 +434,19 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel } } - String chartNames = dataMap.get(AssetModelImportEnum.CHART_TEMPLATES.getIndex()); - StringBuilder relChartTemplateIds = new StringBuilder(); - if (StrUtil.isNotEmpty(chartNames)) { - // model 只能选择 asset 类型且 groupId = 0 的图表 - List<VisualChart> assetChartTemplateList = visualChartService.list(new LambdaQueryWrapper<VisualChart>() - .eq(VisualChart::getPanelId, 0).eq(VisualChart::getGroupId, 0) - .eq(VisualChart::getVarType, Constant.ChartVariableType.ASSET.getValue())); - - StrUtil.split(chartNames, StrUtil.C_COMMA).stream().forEach(chartName -> { - List<Integer> chartIdList = assetChartTemplateList.stream() - .filter(visualChart -> StrUtil.equals(visualChart.getName(), chartName)) - .map(VisualChart::getId).collect(Collectors.toList()); - if (Tool.CollUtil.isEmpty(chartIdList)) { - validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_RELATED_OBJ_NOT_EXIST.setParam(AssetModelImportEnum.CHART_TEMPLATES.getIndex())); - } else if (chartIdList.size() > 1) { - validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_DUPLICATE.setParam(AssetModelImportEnum.CHART_TEMPLATES.getIndex())); - } else if (chartIdList.size() == 1) { - relChartTemplateIds.append(StrUtil.concat(true, chartIdList.get(0).toString(), ",")); - } - }); + String dashboardTemplateName = dataMap.get(AssetModelImportEnum.DASHBOARD_TEMPLATE.getIndex()); + Integer dashboardTemplateId = null; + if (StrUtil.isNotEmpty(dashboardTemplateName)) { + // dashboard template, type = template varType = asset + VisualDashboard dashboardTemplate = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getName, dashboardTemplateName) + .eq(VisualDashboard::getType, DashboardConstant.Type.TEMPLATE.getValue()) + .eq(VisualDashboard::getVarType, DashboardConstant.VariableType.ASSET.getValue())); + if (ObjectUtil.isNull(dashboardTemplate)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_RELATED_OBJ_NOT_EXIST.setParam(AssetModelImportEnum.DASHBOARD_TEMPLATE.getIndex())); + } else { + dashboardTemplateId = dashboardTemplate.getId(); + } } String typeName = dataMap.get(AssetModelImportEnum.ASSET_TYPE_NAME.getIndex()); @@ -477,7 +480,7 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel model.setName(modelName); model.setSysObjectId(oid); model.setTypeId(typeConf.getId()); - model.setChartIds(StrUtil.isNotEmpty(relChartTemplateIds) ? relChartTemplateIds.substring(0, relChartTemplateIds.length() - 1) : ""); + model.setDashboardId(dashboardTemplateId); if (saveEntitys.get("brand") == null) { AssetBrand brand = brandService.getOne(new LambdaQueryWrapper<AssetBrand>().eq(AssetBrand::getName, brandName)); model.setBrandId(brand.getId()); @@ -506,7 +509,7 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_MODEL_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) @@ -551,10 +554,8 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel // 是否同步更新关联的 dashboard,可选值: 0:不同步 1:同步 默认值:1 String syncDashboard = Tool.ObjectUtil.defaultIfEmpty((String) params.get("syncDashboard"), "1"); - if (StrUtil.equals("1", syncDashboard)) { - Map<String, Object> syncChartParamMap = Tool.MapUtil.newHashMap(); - syncChartParamMap.put("models", ListUtil.of(model.getId())); - visualChartService.syncTmpl(syncChartParamMap); + if (StrUtil.equals("1", syncDashboard) && ObjectUtil.isNotNull(model.getDashboardId())) { + visualService.syncTemplateDashboard(null, null, model.getId(), null); } } else { params.put("save", true); @@ -596,19 +597,8 @@ public class AssetModelServiceImpl extends ServiceImpl<AssetModelDao, AssetModel List<String> tempList = new ArrayList<>(); tempList.add(model.getName()); tempList.add(model.getBrand().getName()); - String chartIds = model.getChartIds(); - String chartNames = ""; - if (StrUtil.isNotEmpty(chartIds)) { - List<String> chartIdList = Arrays.asList(chartIds.split(",")); - for (String chartIdStr : chartIdList) { - VisualChart chartServiceById = visualChartService.getById(chartIdStr); - if (chartServiceById != null) { - chartNames += chartServiceById.getName() + ","; - } - } - chartNames = StrUtil.isNotEmpty(chartNames) ? chartNames.substring(0, chartNames.length() - 1) : chartNames; - } - tempList.add(chartNames); + VisualDashboard dashboard = model.getDashboard(); + tempList.add(ObjectUtil.isNotNull(dashboard) ? dashboard.getName() : StrUtil.EMPTY); tempList.add(ObjectUtil.defaultIfNull(model.getRemark(), "")); AssetTypeConf typeConf = typeConfService.getById(model.getTypeId()); tempList.add(typeConf.getName()); diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/CabinetServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/CabinetServiceImpl.java index 5d744ff7..6425a6cc 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/CabinetServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/CabinetServiceImpl.java @@ -33,6 +33,7 @@ import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -393,6 +394,9 @@ public class CabinetServiceImpl extends ServiceImpl<CabinetDao, Cabinet> impleme // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveCabinetsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -516,7 +520,7 @@ public class CabinetServiceImpl extends ServiceImpl<CabinetDao, Cabinet> impleme } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_CABINET_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/DcServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/DcServiceImpl.java index 7c87a218..87c93645 100644 --- a/nz-admin/src/main/java/com/nis/modules/asset/service/impl/DcServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/asset/service/impl/DcServiceImpl.java @@ -45,6 +45,7 @@ import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -486,6 +487,9 @@ public class DcServiceImpl extends ServiceImpl<DcDao, Dc> implements DcService { // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveDatacentersFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -589,7 +593,7 @@ public class DcServiceImpl extends ServiceImpl<DcDao, Dc> implements DcService { } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_DC_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/panel/controller/ExpreTmplController.java b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/ExpreTmplController.java index a681da79..eeef58d3 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/controller/ExpreTmplController.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/ExpreTmplController.java @@ -1,12 +1,11 @@ -package com.nis.modules.panel.controller; +package com.nis.modules.dashboard.controller; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; -import com.nis.modules.panel.entity.VisualExpressionTmpl; -import com.nis.modules.panel.service.VisualExpreTmplService; - +import com.nis.modules.dashboard.entity.VisualExpressionTmpl; +import com.nis.modules.dashboard.service.VisualExpreTmplService; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; diff --git a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualPanelChartController.java b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualChartController.java index 222a3bae..48d02bef 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualPanelChartController.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualChartController.java @@ -1,42 +1,28 @@ -package com.nis.modules.panel.controller; - -import java.util.List; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +package com.nis.modules.dashboard.controller; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.TypeEnum; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.service.VisualChartService; +import com.nis.common.utils.*; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.service.VisualChartService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; -import cn.hutool.core.util.ObjectUtil; +import java.util.List; +import java.util.Map; @RestController -@RequestMapping("/visual/panel/chart") -public class VisualPanelChartController { - +@RequestMapping("/visual/dashboard/chart") +public class VisualChartController { + @Autowired private VisualChartService visualChartService; - + @GetMapping(value={"/{id}"}) @SysLog(operation = OperationEnum.QUERY,type = TypeEnum.VISUALCHART) public R chartInfo(@PathVariable Integer id){ @@ -50,7 +36,7 @@ public class VisualPanelChartController { PageUtils page = visualChartService.queryPage(params); return R.ok(page); } - + @PostMapping @SysLog(operation = OperationEnum.ADD,type = TypeEnum.VISUALCHART) @RequiresPermissions({"visual:chart:save"}) @@ -79,67 +65,69 @@ public class VisualPanelChartController { visualChartService.delCharts(ids, sync); return R.ok(); } - + /** * charts 调整大小接口 * - * @param panelId * @param chart * @return */ @PutMapping(value = {"/modify"}) - @SysLog(operation = OperationEnum.UPDATE,type = TypeEnum.VISUALCHART) + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.VISUALCHART) public R modify(@RequestBody VisualChart chart) { ValidateUtils.is(chart.getId()).notNull(RCode.CHART_ID_ISNULL) .and(chart.getSpan()).notNull(RCode.CHART_SPAN_ISNULL) .and(chart.getHeight()).notNull(RCode.CHART_HEIGHT_ISNULL); - + visualChartService.modify(chart); return R.ok(); } - + /** * 调整位置接口 - * @param panelId - * @param chartList + * + * @param params * @return */ @PutMapping(value = {"/weights"}) @SysLog(operation = OperationEnum.UPDATE,type = TypeEnum.VISUALCHART) public R weights(@RequestBody Map<String,Object> params) { - Integer panelId = (Integer)params.get("panelId"); + Integer dashboardId = (Integer)params.get("dashboardId"); Object data = params.get("charts"); List<VisualChart> chartList = JSON.parseArray(JSON.toJSONString(data),VisualChart.class); - if(ObjectUtil.isEmpty(panelId)) { - throw new NZException(RCode.CHART_PANEL_ISNULL); + if(ObjectUtil.isEmpty(dashboardId)) { + throw new NZException(RCode.DASHBOARD_NOT_EXIST); }else if(ObjectUtil.isEmpty(chartList)) { throw new NZException(RCode.CHART_WEIGHT_ISNULL); } - visualChartService.weights(panelId,chartList); + visualChartService.weights(dashboardId,chartList); return R.ok(); } - - /** - * charts 通过模板添加 - */ - @PostMapping(value = {"/fromTmpl"}) - @SysLog(operation = OperationEnum.ADD,type = TypeEnum.VISUALCHART) - @RequiresPermissions({"visual:chart:save"}) - public R fromTmpl(@RequestBody Map<String,Object> params) { - Integer total = visualChartService.fromTmpl(params); - return R.ok().putData("total", total); - } - + /** - * charts 通过模板添加 + * charts 模板同步接口 + * + * @param params pid & ids cannot be empty at the same time + * @return */ @PostMapping(value = {"/syncTmpl"}) - @SysLog(operation = OperationEnum.UPDATE,type = TypeEnum.VISUALCHART) + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.VISUALCHART) @RequiresPermissions({"visual:chart:save"}) - public synchronized R syncTmpl(@RequestBody Map<String,Object> params) { - Integer total = visualChartService.syncTmpl(params); - return R.ok().putData("total", total); + public synchronized R syncTmpl(@RequestBody Map<String, Object> params) { + // validate + // pid and chartIds cannot be empty at the same time + Integer pid = (Integer) params.get("pid"); + List<Integer> chartIdList = (List<Integer>) params.get("ids"); + + if (Tool.BooleanUtil.and(Tool.ObjectUtil.isNull(pid), + Tool.CollUtil.isEmpty(chartIdList))) { + return R.error(RCode.CHART_SYNCTMPL_ERROR); + } + + chartIdList = Tool.CollUtil.defaultIfEmpty(chartIdList, Tool.ListUtil.empty()); + Integer total = visualChartService.chartTmplSynch(pid, chartIdList); + return R.ok().putData("total", total); } } diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualController.java b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualController.java new file mode 100644 index 00000000..731ab8d0 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualController.java @@ -0,0 +1,189 @@ +package com.nis.modules.dashboard.controller; + +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.annotation.SysLog; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; + +@RestController +@RequestMapping("/visual") +public class VisualController { + + private final static Log log = Log.get(); + + @Autowired + private VisualService visualService; + + @Autowired + private RedisLock redisLock; + + /** + * explore 快照 + */ + @GetMapping("/explore/snapshot") + public void exploreSnapshot(HttpServletResponse response, HttpServletRequest request, String format, Integer type, Long start, + Long end, Integer unit, String limit, String direction, @RequestParam(value="expressions[]")String[] expressions) throws IOException { + ValidateUtils.is(type).notNull(RCode.AGENT_TYPE_ISNULL) + .and(start).notNull(RCode.AGENT_PARAM_START_ISNULL) + .and(end).notNull(RCode.AGENT_PARAM_END_ISNULL) + .and(expressions).notNull(RCode.AGENT_PARAM_QUERY_ISNULL); + String language = request.getHeader(Constant.LANGUAGE); + visualService.exploreSnapshot(response, format, type, start, end, language, unit, limit, direction, expressions); + } + + + /** + * create snapshot task + * + * @param language + * @param requestody + * @return + */ + @PostMapping("/dashboard/snapshot/task") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.DASHBOARD) + public R snapshotTask(@RequestHeader(required = false, defaultValue = "en") String language, + @RequestBody Map<String, Object> requestody) { + String format = (String) requestody.get("format"); + format = Tool.StrUtil.emptyToDefault(format, "html"); + + Object dashboardId = requestody.get("dashboardId"); + Object start = requestody.get("start"); + Object end = requestody.get("end"); + + ValidateUtils.is(dashboardId).notNull(RCode.DASHBOARD_ID_ISNULL) + .and(start).notNull(RCode.AGENT_PARAM_START_ISNULL) + .and(end).notNull(RCode.AGENT_PARAM_END_ISNULL); + + Object varsObj = requestody.get("vars"); + Object tvarListObj = Tool.ObjectUtil.defaultIfNull(varsObj, Tool.ListUtil.empty()); + String varsJsonStr = Tool.JSONUtil.toJsonStr(tvarListObj); + + String taskId = visualService.createSnapshotTask(format, Integer.valueOf(dashboardId.toString()), Long.valueOf(start.toString()), Long.valueOf(end.toString()), varsJsonStr); + + return R.ok().putData("tid", taskId); + } + + /** + * query snapshot task process + * + * @param tid + * @return + */ + @GetMapping("/dashboard/snapshot/result/{tid}") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.DASHBOARD) + public R snapshotResultProcess(@PathVariable(required = true) String tid) { + return R.ok().putData("taskId", visualService.snapshotResultProcess(tid)); + } + + /** + * cancel snapshot task + * + * @param tid + * @return + */ + @GetMapping("/dashboard/snapshot/cancel/{tid}") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.DASHBOARD) + public R cancelSnapshotTask(@PathVariable(required = true) String tid) { + visualService.cancelSnapshotTask(tid); + return R.ok(); + } + + /** + * download snmapshot file + * + * @param response + * @param language + * @param tid + */ + @GetMapping("/dashboard/snapshot/download/{tid}") + public void downloadSnapshotFile(HttpServletResponse response, + @RequestHeader(required = false, defaultValue = "en") String language, + @PathVariable(required = true) String tid) { + visualService.downloadSnapshotFile(response, language, tid); + } + + + /** + * dashboard sync Tmpl + * + * @param requestBody + * @return + */ + @PostMapping("/dashboard/syncTmpl") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.DASHBOARD) + public R syncTemplateDashboard(@RequestBody(required = false) Map<String, Integer> requestBody) { + // validate param + requestBody = Tool.MapUtil.defaultIfEmpty(requestBody, Tool.MapUtil.empty()); + + Integer id = requestBody.get("id"); + Integer tmplId = requestBody.get("tmplId"); + Integer modelId = requestBody.get("model"); + Integer moduleId = requestBody.get("module"); + + if (Tool.ObjectUtil.isAllEmpty(id, tmplId, modelId, moduleId)) + return R.error(RCode.DASHBOARD_TEMPLATE_SYNC_PARAM_ISNULL); + + // get lock + String uuid = Tool.StrUtil.uuid(); + try { + if (redisLock.lock(DashboardConstant.TEMPLATE_SYNC_LOCK_KEY, uuid, 5L)) { + log.info("[syncTemplateDashboard] [Get lock and start synchronization template]"); + + // sync Template On dashboard + visualService.syncTemplateDashboard(id, tmplId, modelId, moduleId); + return R.ok(); + } else { + log.warn("[syncTemplateDashboard] [Failed to get lock and do not perform template synchronization]"); + return R.error(RCode.DASHBOARD_TEMPLATE_SYNC_FAILED_GET_LOCK); + } + } finally { + redisLock.unlock(DashboardConstant.TEMPLATE_SYNC_LOCK_KEY, uuid); + } + } + + /** + * create Dashboard Using Template + * + * @param requestBody + * @return + */ + @PostMapping("/dashboard/fromTmpl") + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.DASHBOARD) + public R createDashboardUsingTemplate(@RequestBody(required = false) Map<String, Object> requestBody) { + // validate param + requestBody = Tool.MapUtil.defaultIfEmpty(requestBody, Tool.MapUtil.empty()); + + String name = StrUtil.str(requestBody.get("name"), CharsetUtil.CHARSET_UTF_8); + ValidateUtils.is(name).notNull(RCode.DASHBOARD_NAME_ISNULL); + + String type = StrUtil.str(requestBody.get("type"), CharsetUtil.CHARSET_UTF_8); + if (!StrUtil.equals(DashboardConstant.Type.DASHBOARD.getValue(), type)) { + throw new NZException(RCode.DASHBOARD_TYPE_INVALIDE); + } + + String description = StrUtil.str(requestBody.get("description"), CharsetUtil.CHARSET_UTF_8); + String tmplId = StrUtil.str(requestBody.get("tmplId"), CharsetUtil.CHARSET_UTF_8); + String link = StrUtil.str(requestBody.get("link"), CharsetUtil.CHARSET_UTF_8); + + Integer tmplIdIntVal = ObjectUtil.isNull(tmplId) ? null : Integer.valueOf(tmplId); + Integer linkIntVal = ObjectUtil.isNull(link) ? null : Integer.valueOf(link); + + // create Dashboard Using Template + Integer id = visualService.createDashboardUsingTemplate(StrUtil.trim(name), type, description, tmplIdIntVal, linkIntVal); + return R.ok().putData("id", id); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualDashboardController.java b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualDashboardController.java new file mode 100644 index 00000000..8ff21217 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/controller/VisualDashboardController.java @@ -0,0 +1,166 @@ +package com.nis.modules.dashboard.controller; + +import cn.hutool.core.util.StrUtil; +import com.nis.common.annotation.SysLog; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.utils.DashboardConstant; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequestMapping("/visual/dashboard") +public class VisualDashboardController { + + @Autowired + private VisualDashboardService dashboardService; + + @GetMapping("/{id}") + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.DASHBOARD) + public R dashboard(@PathVariable Integer id) { + VisualDashboard dashboard = dashboardService.queryInfo(id); + return R.ok(dashboard); + } + + @GetMapping + @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.DASHBOARD) + public R dashboardList(@RequestParam Map<String, Object> params) { + PageUtils pageUtils = dashboardService.queryList(params); + return R.ok(pageUtils); + } + + @RequestMapping(method = { RequestMethod.POST }) + @SysLog(operation = OperationEnum.ADD, type = TypeEnum.DASHBOARD) + @RequiresPermissions({ "visual:dashboard:save" }) + public R dashboardSave(@RequestBody VisualDashboard dashboard) { + ValidateUtils.is(dashboard.getName()).maxLength(64); + dashboardService.saveVisualDashboard(dashboard); + return R.ok().putData("dashboard", dashboard); + } + + @RequestMapping(method = { RequestMethod.PUT }) + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.DASHBOARD) + @RequiresPermissions({ "visual:dashboard:update" }) + public R dashboardUpdate(@RequestBody VisualDashboard dashboard) { + ValidateUtils.is(dashboard.getId()).notNull(RCode.DASHBOARD_ID_ISNULL) + .and(dashboard.getName()).maxLength(64); + + dashboardService.updateVisualDashboard(dashboard); + return R.ok().putData("dashboard", dashboard); + } + + @DeleteMapping + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.DASHBOARD) + @RequiresPermissions({ "visual:dashboard:delete" }) + public R panleDelete(@RequestParam Integer... ids) { + ValidateUtils.is(ids).notNull(RCode.DASHBOARD_ID_ISNULL); + + dashboardService.delDashboards(ids); + return R.ok(); + } + + /** + * 排序 + * + * @param dashboardList + * @return + */ + @PutMapping("/tree") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.DASHBOARD) + public R modify(@RequestBody List<VisualDashboard> dashboardList) { + dashboardService.modify(dashboardList); + return R.ok(); + } + + @GetMapping("/template") + public void getTemplateByLanguage(HttpServletResponse response, + @RequestParam(required = false, defaultValue = "dashboard") String type, + @RequestParam(required = false, defaultValue = "en") String language, + @RequestParam(required = false, defaultValue = "1") String format) throws IOException { + + // 校验 LANGUAGE + if (!Arrays.asList(Constant.LANGUAGE_VALUES).contains(language)) { + throw new NZException(RCode.EXCELFILE_HEADER_LANGUAGE_ERROR); + } + // 校验 FORMAT + List<String> supportImportingFileTypes = Arrays.asList(Constant.ImportFileType.values()).stream().map(Constant.ImportFileType::getValue).collect(Collectors.toList()); + if (!supportImportingFileTypes.contains(format)) { + throw new NZException(RCode.EXCELFILE_TYPE_ERROR); + } + + dashboardService.getTemplateByLanguage(response, format, type); + } + + @PostMapping("/import") + @SysLog(operation = OperationEnum.IMPORT, type = TypeEnum.CHART) + @RequiresPermissions({ "visual:dashboard:save"}) + public R importChartData(@RequestParam(value = "file") MultipartFile excelFile, @RequestParam Map<String, Object> params) throws IOException { + Object type = params.get("type"); + ValidateUtils.is(excelFile).notNull(RCode.EXCELFILE_IMPORT_FILE_ISNULL) + .and(type).notNull(RCode.DASHBOARD_CHART_TEMPLATE_TYPE_ISNULL); + if(!StrUtil.equalsAnyIgnoreCase(ToolUtil.toStr(type), DashboardConstant.Type.DASHBOARD.getValue(), DashboardConstant.Type.TEMPLATE.getValue())){ + throw new NZException(RCode.DASHBOARD_IMPORT_TYPE_INCORRECT); + } + return R.ok(dashboardService.importChartData(excelFile, params)); + } + + @GetMapping("/export") + @SysLog(operation = OperationEnum.EXPORT, type = TypeEnum.CHART) + public void export(HttpServletResponse response, @RequestParam Map<String, Object> params) throws IOException { + dashboardService.export(response, params); + } + + @DeleteMapping("/cancelImport") + @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.CHART) + public R cancelImport(String seq) { + ValidateUtils.is(seq).notNull(RCode.UNDO_IMPORT_SEQ_ISNULL); + + dashboardService.cancelImport(seq); + return R.ok(); + } + + /** + * 复制dashboard配置 + * @param id + * @return + */ + @PostMapping("/duplicate/{id}") + @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.DASHBOARD) + public R duplicate(@PathVariable Integer id) { + ValidateUtils.is(id).notNull(RCode.DASHBOARD_ID_ISNULL); + dashboardService.duplicate(id); + return R.ok(); + } + + /** + * dashboard 快照 + * @param response + * @param request + * @param format + * @param dashboardId + * @param start + * @param end + * @param vars + */ + @GetMapping("/snapshot") + public void snapshot(HttpServletResponse response, HttpServletRequest request, String format, Integer dashboardId, Long start, Long end, String vars) throws IOException { + ValidateUtils.is(dashboardId).notNull(RCode.DASHBOARD_ID_ISNULL) + .and(start).notNull(RCode.AGENT_PARAM_START_ISNULL) + .and(end).notNull(RCode.AGENT_PARAM_END_ISNULL); + String language = request.getHeader(Constant.LANGUAGE); + dashboardService.snapshot(response, format, dashboardId, start, end, language, vars); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualChartDao.java b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualChartDao.java index a4b0648e..56d336ce 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualChartDao.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualChartDao.java @@ -1,8 +1,8 @@ -package com.nis.modules.panel.dao; +package com.nis.modules.dashboard.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; -import com.nis.modules.panel.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualChart; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -18,20 +18,16 @@ public interface VisualChartDao extends BaseMapper<VisualChart> { void updateSizeById(@Param("chart") VisualChart chart); - void updateWeightBatch(@Param("panelId")Integer panelId , @Param("charts") List<VisualChart> charts); - - List<VisualChart> selectChartNum(); - - List<VisualChart> selectTmplCharts(@Param("params") Map<String,Object> params); + void updateWeightBatch(@Param("dashboardId")Integer dashboardId , @Param("charts") List<VisualChart> charts); List<VisualChart> queryPage(IPage page,@Param("params") Map<String, Object> params); List<VisualChart> queryPage(@Param("params") Map<String, Object> params); - List<VisualChart> queryChartWithElementByIds(@Param("list")List<Integer> chartIdList); - // 查询model和module实例化的图表数据信息 List<VisualChart> selectInstanceChart(@Param("type")Integer type,@Param("id")Integer id); - void insertBatchChart(@Param("list") List<VisualChart> oldChartListByPanelId); + void insertBatchChart(@Param("list") List<VisualChart> oldChartListByDashboardId); + + List<VisualChart> queryChartsIncludeElementInfo(@Param("dashboardId") Integer dashboardId); } diff --git a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualChartElementDao.java b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualChartElementDao.java index 27aa275f..9e3898de 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualChartElementDao.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualChartElementDao.java @@ -1,7 +1,7 @@ -package com.nis.modules.panel.dao; +package com.nis.modules.dashboard.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nis.modules.panel.entity.VisualChartElement; +import com.nis.modules.dashboard.entity.VisualChartElement; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualDashboardDao.java b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualDashboardDao.java new file mode 100644 index 00000000..98bacf18 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualDashboardDao.java @@ -0,0 +1,26 @@ +package com.nis.modules.dashboard.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.dashboard.entity.VisualDashboard; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +@Mapper +public interface VisualDashboardDao extends BaseMapper<VisualDashboard> { + + List<VisualDashboard> queryList(IPage page, @Param("params")Map<String, Object> params); + + List<VisualDashboard> queryListByType(@Param("type")String type); + + void updateWeightBatch(@Param("dashboards") List<VisualDashboard> updateDashboards); + + VisualDashboard queryInfo(Integer id); + + void delReceivers(List<String> idList); + + List<VisualDashboard> queryReportOfEmptyReceivers(); +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualExpreTmplDao.java b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualExpreTmplDao.java index feef411a..5f2e85c5 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualExpreTmplDao.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/dao/VisualExpreTmplDao.java @@ -1,8 +1,7 @@ -package com.nis.modules.panel.dao; +package com.nis.modules.dashboard.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nis.modules.panel.entity.VisualExpressionTmpl; - +import com.nis.modules.dashboard.entity.VisualExpressionTmpl; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/entity/ChartsImportEnum.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/ChartsImportEnum.java new file mode 100644 index 00000000..b8da7df2 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/ChartsImportEnum.java @@ -0,0 +1,35 @@ +package com.nis.modules.dashboard.entity; + +public enum ChartsImportEnum { + + NAME("name",0), + SPAN("span",1), + HEIGHT("height",2), + TYPE("type",3), + UNIT("unit",4), + WEIGHT("weight",5), + PARAM("param",6), + REMARK("remark",7), + X("x",8), + Y("y",9), + ELEMENTS("elements",10), + DATASOURCE("datasource",11), + CHILDREN("children",12); + + private String name; + private int index; + + ChartsImportEnum(String name, int index) { + this.name = name; + this.index = index; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/entity/DashboardImportEnum.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/DashboardImportEnum.java new file mode 100644 index 00000000..a94ea896 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/DashboardImportEnum.java @@ -0,0 +1,29 @@ +package com.nis.modules.dashboard.entity; + +public enum DashboardImportEnum { + + NAME("name", 0), + TYPE("type", 1), + VARTYPE("varType", 2), + PARAM("param", 3), + REMARK("remark", 4), + CHARTS("charts", 5), + CHILDREN("children",6); + + private String name; + private int index; + + DashboardImportEnum(String name, int index) { + this.name = name; + this.index = index; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/entity/ExprTmplImportEnum.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/ExprTmplImportEnum.java index c7b11160..9ba6c53f 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/entity/ExprTmplImportEnum.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/ExprTmplImportEnum.java @@ -1,4 +1,4 @@ -package com.nis.modules.panel.entity; +package com.nis.modules.dashboard.entity; /** diff --git a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualChart.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualChart.java index 4ac27653..b1d55ee7 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualChart.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualChart.java @@ -1,22 +1,25 @@ -package com.nis.modules.panel.entity; +package com.nis.modules.dashboard.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.nis.modules.asset.entity.AssetAsset; import lombok.Data; +import java.io.Serializable; import java.util.Date; import java.util.List; @Data @TableName("visual_chart") -public class VisualChart { +public class VisualChart implements Serializable { - private Integer id; + private static final long serialVersionUID = 1L; + + private Integer id; private String name; - private Integer panelId; + private Integer dashboardId; private Integer groupId; @@ -58,7 +61,7 @@ public class VisualChart { private Integer sync; @TableField(exist = false) - private VisualPanel panel; + private VisualDashboard dashboard; @TableField(exist = false) private VisualChart group; diff --git a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualChartElement.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualChartElement.java index 8782b7be..88c2baee 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualChartElement.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualChartElement.java @@ -1,12 +1,15 @@ -package com.nis.modules.panel.entity; +package com.nis.modules.dashboard.entity; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; +import java.io.Serializable; + @Data @TableName("visual_chart_element") -public class VisualChartElement { +public class VisualChartElement implements Serializable { + + private static final long serialVersionUID = 1L; private Integer id; diff --git a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualPanel.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualDashboard.java index 422da55d..170a1d97 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualPanel.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualDashboard.java @@ -1,16 +1,17 @@ -package com.nis.modules.panel.entity; - -import java.util.List; +package com.nis.modules.dashboard.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; -import com.nis.modules.sys.entity.SysUserEntity; - import lombok.Data; +import java.io.Serializable; +import java.util.List; + @Data -@TableName("visual_panel") -public class VisualPanel { +@TableName("visual_dashboard") +public class VisualDashboard implements Serializable { + + private static final long serialVersionUID = 1L; private Integer id; @@ -19,7 +20,11 @@ public class VisualPanel { private Integer createBy; private String type; - + + private Integer varType; + + private Integer tmplId; + private Integer link; private Integer pid; @@ -37,14 +42,17 @@ public class VisualPanel { private Long uts; @TableField(exist = false) - private List<VisualPanel> children; + private List<VisualDashboard> children; @TableField(exist = false) - private VisualPanel parent; + private VisualDashboard parent; @TableField(exist = false) private Integer chartNum; + @TableField(exist = false) + private List<VisualChart> charts; + /** * 是否收藏 0:未收藏 1:已收藏 */ diff --git a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualExpressionTmpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualExpressionTmpl.java index f6e84088..bdba2de0 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/entity/VisualExpressionTmpl.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/entity/VisualExpressionTmpl.java @@ -1,4 +1,4 @@ -package com.nis.modules.panel.entity; +package com.nis.modules.dashboard.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualChartElementService.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualChartElementService.java index 019ec3d7..4f0732ae 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualChartElementService.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualChartElementService.java @@ -1,7 +1,7 @@ -package com.nis.modules.panel.service; +package com.nis.modules.dashboard.service; import com.baomidou.mybatisplus.extension.service.IService; -import com.nis.modules.panel.entity.VisualChartElement; +import com.nis.modules.dashboard.entity.VisualChartElement; import java.util.List; diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualChartService.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualChartService.java new file mode 100644 index 00000000..25fcf37c --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualChartService.java @@ -0,0 +1,43 @@ +package com.nis.modules.dashboard.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.dashboard.entity.VisualChart; + +import java.util.List; +import java.util.Map; + +public interface VisualChartService extends IService<VisualChart> { + + PageUtils queryPage(Map<String, Object> params); + + VisualChart queryInfo(Integer id); + + void validateChart(VisualChart visualChart); + + Integer saveChart(VisualChart chart); + + Integer updateChart(VisualChart chart); + + void delCharts(Integer[] ids, Integer sync); + + void modify(VisualChart chart); + + void weights(Integer dashboardId, List<VisualChart> chartList); + + void delVisualChartsByDashboardId(Integer... dashboardId); + + Integer chartTmplSynch(Integer pid, List<Integer> chartIdList); + + void saveRelDashboardAndChart(String type, Integer linkId, String name, Integer tempId, String seq); + + /** + * 平铺 获取所有 chart 节点 + * + * @param sourceChartList + * @return + */ + List<VisualChart> getAllChartList(List<VisualChart> sourceChartList); + + List<VisualChart> queryChartsIncludeElementInfo(Integer dashboardId); +} diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualDashboardService.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualDashboardService.java new file mode 100644 index 00000000..0e926afb --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualDashboardService.java @@ -0,0 +1,54 @@ +package com.nis.modules.dashboard.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.dashboard.entity.VisualDashboard; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface VisualDashboardService extends IService<VisualDashboard> { + + VisualDashboard queryInfo(Integer id); + + void delDashboards(Integer... ids); + + void modify(List<VisualDashboard> visualDashboardList); + + PageUtils queryList(Map<String, Object> params); + + void delDashboardsAndChartInfoByDashboardIds(Set<Integer> dashboardIds); + + void saveVisualDashboard(VisualDashboard visualDashboard); + + void updateVisualDashboard(VisualDashboard visualDashboard); + + void getTemplateByLanguage(HttpServletResponse response, String format, String type) throws IOException; + + void cancelImport(String seq); + + void export(HttpServletResponse response, Map<String, Object> params) throws IOException; + + Map importChartData(MultipartFile excelFile, Map<String, Object> params) throws IOException; + + void duplicate(Integer id); + + void snapshot(HttpServletResponse response, String format, Integer dashboardId, Long start, Long end, String language, String vars) throws IOException; + + String genSnapshotByTemplate(Integer dashboardId, Long start, Long end, String lang, String vars); + + List<VisualDashboard> getTemplateSyncDashboard(Integer dashboardId, Integer tmplId, Integer modelId, Integer moduleId); + + VisualDashboard queryDashboardIncludeChartInfo(Integer dashboardId); + + void addReportConfigInRedis(VisualDashboard dashboard); + + void updateReportConfigInRedis(VisualDashboard oldDashboard, VisualDashboard newDashboard); + + // template dashboard , add assetInfo or endpointInfo chart + void addLinkObjectInfoChart(VisualDashboard dashboard); +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualExpreTmplService.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualExpreTmplService.java index f3120977..eb14b5b8 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualExpreTmplService.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualExpreTmplService.java @@ -1,9 +1,8 @@ -package com.nis.modules.panel.service; +package com.nis.modules.dashboard.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; -import com.nis.modules.panel.entity.VisualExpressionTmpl; - +import com.nis.modules.dashboard.entity.VisualExpressionTmpl; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualService.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualService.java new file mode 100644 index 00000000..c87940a6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/VisualService.java @@ -0,0 +1,28 @@ +package com.nis.modules.dashboard.service; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Map; + +public interface VisualService { + + String getTimeStep(Long start, Long end); + + void exploreSnapshot(HttpServletResponse response, String format, Integer type, Long start, Long end, String language, Integer unit, String limit, String direction, String[] expressions) throws IOException; + + Map<String, Object> snapshotResultMap(Long start, Long end, String language); + + String replaceSnapshotTemplate(Map<String, Object> resultMap); + + String createSnapshotTask(String format, Integer dashboardId, Long start, Long end, String varsJsonStr); + + Map snapshotResultProcess(String taskId); + + void cancelSnapshotTask(String taskId); + + void downloadSnapshotFile(HttpServletResponse response, String language, String taskId); + + void syncTemplateDashboard(Integer id, Integer tmplId, Integer modelId, Integer moduleId); + + Integer createDashboardUsingTemplate(String name, String type, String description, Integer tmplId, Integer link); +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualChartElementServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualChartElementServiceImpl.java index 7b360bde..b3efe197 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualChartElementServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualChartElementServiceImpl.java @@ -1,4 +1,4 @@ -package com.nis.modules.panel.service.impl; +package com.nis.modules.dashboard.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -7,9 +7,9 @@ import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.Constant; import com.nis.common.utils.RCode; import com.nis.common.utils.ToolUtil; -import com.nis.modules.panel.dao.VisualChartElementDao; -import com.nis.modules.panel.entity.VisualChartElement; -import com.nis.modules.panel.service.VisualChartElementService; +import com.nis.modules.dashboard.dao.VisualChartElementDao; +import com.nis.modules.dashboard.entity.VisualChartElement; +import com.nis.modules.dashboard.service.VisualChartElementService; import com.nis.modules.sys.entity.SysDictEntity; import com.nis.modules.sys.service.SysDictService; import org.springframework.beans.factory.annotation.Autowired; diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualChartServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualChartServiceImpl.java new file mode 100644 index 00000000..fec4aec5 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualChartServiceImpl.java @@ -0,0 +1,802 @@ +package com.nis.modules.dashboard.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.common.utils.Constant.ChartDatasourceType; +import com.nis.modules.asset.entity.AssetModel; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.asset.service.AssetModelService; +import com.nis.modules.dashboard.dao.VisualChartDao; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualChartElement; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualChartElementService; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.utils.DashboardConstant; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.sys.service.SysConfService; +import com.nis.modules.sys.service.SysDictService; +import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; + +import java.util.*; +import java.util.stream.Collectors; + +@Service("visualChartService") +public class VisualChartServiceImpl extends ServiceImpl<VisualChartDao, VisualChart> implements VisualChartService { + + private static final Log log = Log.get(); + + @Autowired + private SysDictService sysDictService; + + @Autowired + private SysConfService sysConfService; + + @Autowired + private VisualDashboardService dashboardService; + + @Autowired + private VisualChartElementService chartElementService; + + @Autowired + private AssetAssetService assetService; + + @Autowired + private AssetModelService assetModelService; + + @Autowired + private MonitorModuleService monitorModuleService; + + @Autowired + private MonitorEndpointService endpointService; + + @Override + public PageUtils queryPage(Map<String, Object> params) { + String ids = (String) params.get("ids"); + if(StrUtil.isNotBlank(ids)) { + List<String> listIds = Arrays.asList(ids.split(",")); + params.put("ids",listIds); + } + String pid = (String) params.get("pids"); + if(StrUtil.isNotBlank(pid)) { + List<String> listIds = Arrays.asList(pid.split(",")); + params.put("pids",listIds); + } + IPage page = new Query(VisualChart.class).getPage(params); + // 查询出chart信息 + List<VisualChart> result = this.baseMapper.queryPage(page,params); + //查询elements + List<Integer> chartIds = result.stream().map(VisualChart::getId).collect(Collectors.toList()); + List<VisualChartElement> chartElements = chartElementService.list(new QueryWrapper<VisualChartElement>().lambda().in(VisualChartElement::getChartId, chartIds)); + Map<Integer, List<VisualChartElement>> chartIdAndElement = chartElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); + + String param; + for (VisualChart chart : result) { + // param 格式处理 + param = (String) chart.getParam(); + if (StringUtils.isNotEmpty(param)) { + chart.setParam(JSONObject.parseObject(param, Map.class)); + } + chart.setElements(chartIdAndElement.get(chart.getId())); + } + + String returnChildren = (String) params.get("returnChildren"); + if(ToolUtil.isEmpty(returnChildren)) { + returnChildren = "1" ; + } + if(StrUtil.equals(returnChildren, "1")) { + List<Integer> fatherIds = result.stream().filter(chart->chart.getGroupId()==0).map(VisualChart::getId).collect(Collectors.toList()); + if(ToolUtil.isNotEmpty(fatherIds)) { + Map<String, Object> queryChildren =new HashMap<String,Object>(); + queryChildren.put(Constant.LIMIT, "-1"); + IPage childrenpage = new Query(VisualChart.class).getPage(queryChildren); + queryChildren.put("groupIds", fatherIds); + List<VisualChart> childrens = this.baseMapper.queryPage(childrenpage,queryChildren); + // 查询chart相关的element + if(ToolUtil.isNotEmpty(childrens)) { + List<Integer> childIds = childrens.stream().map(VisualChart::getId).collect(Collectors.toList()); + List<VisualChartElement> childElements = chartElementService.list(new QueryWrapper<VisualChartElement>().lambda().in(VisualChartElement::getChartId, childIds)); + Map<Integer, List<VisualChartElement>> childIdAndElement = childElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); + for (VisualChart chart : childrens) { + // param 格式处理 + param = (String) chart.getParam(); + if (StringUtils.isNotEmpty(param)) { + chart.setParam(JSONObject.parseObject(param, Map.class)); + } + chart.setElements(childIdAndElement.get(chart.getId())); + } + result.addAll(childrens); + result = this.getChartTreeList(result,0); + } + } + } + page.setRecords(result); + return new PageUtils(page); + } + + /** + * 递归获取树结构 + * + * @param chartList + * @param parentId + * @return + */ + private List<VisualChart> getChartTreeList(List<VisualChart> chartList, Integer parentId) { + List<VisualChart> resultList = new ArrayList<>(); + for (VisualChart chart : chartList) { + Integer id = chart.getId(); + Integer groupId = chart.getGroupId(); + if(parentId.equals(groupId)) { + chart.setChildren(this.getChartTreeList(chartList, id)); + resultList.add(chart); + } + } + return resultList; + } + + + @Override + public VisualChart queryInfo(Integer id) { + + return this.baseMapper.queryInfo(id); + } + + /** + * 校验 chart 信息 + * 1. dashboard 是否存在 + * 2. tyep 有效性校验 + * 3. param 校验 + * + * @param chart + */ + @Override + public void validateChart(VisualChart chart) { + + Integer dashboardId = chart.getDashboardId(); + ValidateUtils.is(dashboardId).notNull(RCode.DASHBOARD_ID_ISNULL); + // 1. dashboard 是否存在 + this.validateDashboard(dashboardId); + + // 校验vartype + if(dashboardId==0) { + ValidateUtils.is(chart.getVarType()).notNull(RCode.CHART_VARTYPE_ISNULL); + } + + String type = chart.getType(); + ValidateUtils.is(chart.getName()).notNull(RCode.CHART_TITLE_ISNULL).maxLength(64) + .and(chart.getSpan()).notNull(RCode.CHART_SPAN_ISNULL) + .and(chart.getHeight()).notNull(RCode.CHART_HEIGHT_ISNULL) + .and(type).notNull(RCode.CHART_TYPE_ISNULL) + .and(chart.getRemark()).maxLength(256); + + // 2. 验证type是否在枚举范围内 + sysDictService.checkSysDicValue(Constant.DICT_CHART_TYPE, type, RCode.CHART_TYPE_INVALIDE); + + // 3. 根据 type 校验 各项参数 + Map param = (Map) chart.getParam(); + List<VisualChartElement> elements = chart.getElements(); + switch (type) { + // url类型 + case Constant.CHART_URL_TYPE: { + ValidateUtils.is(param).notNull(RCode.CHART_URLPARAM_ISNULL); + Object url = param.get(Constant.CHART_URL_TYPE); + if (ToolUtil.isEmpty(url)) { + throw new NZException(RCode.CHART_URLPARAM_ISNULL); + } + + String urlStr = url.toString(); + // 如果是model dashboard添加charts url类型支持{{}}替换 + VisualDashboard dashboard = dashboardService.getById(dashboardId); + if(ObjectUtil.isNotEmpty(dashboard) && StrUtil.equals(DashboardConstant.Type.TEMPLATE.getValue(),dashboard.getType())) { + // 替换全部变量 替换为 a(任意字符) 不影响原来的数据格式 然后进行校验 + urlStr = urlStr.replaceAll("\\{\\{asset\\..*?\\}\\}", "a"); + + boolean b = CommonUtils.checkUrlInModel(urlStr); + boolean b1 = CommonUtils.checkUrl(urlStr); + + if (!b && !b1) { + throw new NZException(RCode.CHART_PARAMURL_FORMAT); + } + } else { + if (!CommonUtils.checkUrl(urlStr)) { + throw new NZException(RCode.CHART_PARAMURL_FORMAT); + } + } + break; + } + // stat 类型 + case Constant.CHART_SINGLESTAT_TYPE: { + ValidateUtils.is(param).notNull(RCode.CHART_SINGLESTATPARAM_ISNULL); + + Object statistics = param.get(Constant.CHART_SINGLESTAT_PARAMkEY); + if (ToolUtil.isEmpty(statistics)) { + throw new NZException(RCode.CHART_PARAMSINGLESTAT_ISNULL); + } + if (!Constant.CHART_SINGLESTAT_STATISTICS.contains(statistics.toString())) { + throw new NZException(RCode.CHART_PARAMSINGLESTAT_INVALIDE); + } + break; + } + // group 类型不需要校验 elements + case Constant.CHART_GROUP_TYPE:{ + chart.setElements(null); + break; + } + case Constant.CHART_TEXT_TYPE: { + ValidateUtils.is(param).notNull(RCode.CHART_TEXTPARAM_ISNULL); + Object text = param.get(Constant.CHART_TEXT_TYPE); + if (ToolUtil.isEmpty(text)) throw new NZException(RCode.CHART_TEXTPARAM_ISNULL); + break; + } + } + + + // 4. 校验 unit 是否合法 + Integer unit = chart.getUnit(); + if (unit != null) { + List<Integer> unitList = new ArrayList(Constant.ALERT_RULE_UNIT_MAP.values()); + if (unit < Collections.min(unitList) || unit > Collections.max(unitList)) { + throw new NZException(RCode.CHART_UNIT_NOTFOUND); + } + } + + // 5. 校验 groupId 是否有值 + Integer groupId = chart.getGroupId(); + if(ObjectUtils.isEmpty(groupId)) { + throw new NZException(RCode.CHART_GROUPID_ISNULL); + } + + // 6. 当前操作人信息赋值 + Long userId = ShiroUtils.getUserId(); + chart.setUpdateBy(userId.intValue()); + + // 7. 校验datasource是否为空 + if(StrUtil.isBlank(chart.getDatasource())) { + throw new NZException(RCode.CHART_DATASOURCE_ISNULL); + }else { + // 校验是否为内置类型 + sysDictService.checkSysDicValue(Constant.DICT_CHART_DATASOURCE, chart.getDatasource(), RCode.CHART_DATASOURCE_INVALIDE); + } + + // 8. 校验element参数 仅datasource类型为 logs metrics需要进行校验 + if (chart.getDatasource().equals(Constant.ChartDatasourceType.METRICS.getValue()) || chart.getDatasource().equals(Constant.ChartDatasourceType.LOGS.getValue())) { + ValidateUtils.is(elements).notNull(RCode.CHART_ELEMENT_ISNULL); + chartElementService.validateElements(elements); + } + } + + /** + * 校验 dashboard 是否存在 + * + * @param dashboardId + */ + public void validateDashboard(Integer dashboardId) { + if(dashboardId.equals(0)) { + return; + } + VisualDashboard dashboard = dashboardService.getById(dashboardId); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer saveChart(VisualChart chart) { + // 1. 新增 chart 自动追加至末尾 + chart.setName(StrUtil.trim(chart.getName())); + Object param = chart.getParam(); + if (param != null && param instanceof HashMap) { + chart.setParam(JSONObject.toJSONString(param)); + } + + // update info + chart.setUpdateAt(Tool.DateUtil.date()); + chart.setUpdateBy(ShiroUtils.getUserId().intValue()); + + // 2. 判断当前 dashboard 下是否已存在 charts + List<VisualChart> list = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getDashboardId, chart.getDashboardId())); + if (CollectionUtils.isEmpty(list)) { + // 不存在 charts + this.save(chart); + } else { + VisualChart endChart = this.getOne(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getDashboardId, chart.getDashboardId()).orderByDesc(VisualChart::getWeight).last("limit 0,1")); + Integer weight = endChart.getWeight(); + chart.setWeight(++weight); + this.save(chart); + } + + // 3. 保存 chart elements信息 + chartElementService.saveOrUpdateElements(chart.getId(), chart.getElements()); + return chart.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer updateChart(VisualChart chart) { + // 1. 校验 + chart.setName(StrUtil.trim(chart.getName())); + this.validateChart(chart); + + Object param = chart.getParam(); + if (param != null) { + chart.setParam(JSONObject.toJSONString(param)); + } + + // update info + chart.setUpdateAt(Tool.DateUtil.date()); + chart.setUpdateBy(ShiroUtils.getUserId().intValue()); + + this.updateById(chart); + + // 3. 修改 chart elements + chartElementService.saveOrUpdateElements(chart.getId(), chart.getElements()); + return chart.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delCharts(Integer[] ids, Integer sync) { + + // 内置chart不能删除 + this.validateBuildInCharts(Arrays.asList(ids)); + + List<VisualChart> deleteCharts = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getId, Arrays.asList(ids))); + + List<Integer> deleteIds =new ArrayList<Integer>(); + for(VisualChart deleteChart : deleteCharts) { + if(deleteChart.getDashboardId().equals(0)) { + deleteIds.add(deleteChart.getId()); + } + } + + if (CollectionUtils.isNotEmpty(deleteIds)) { + if (sync != null) { + // 同步删除 + if(sync.equals(1)) { + this.syncDeleteAssetsCharts(deleteIds); + } + } + } + + List<Integer> idList = new ArrayList<>(Arrays.asList(ids)); + + // 删除 Endpoint modules 引用的 chart templates + List<MonitorModule> monitorModuleList = monitorModuleService.list(new QueryWrapper<MonitorModule>().lambda().isNotNull(MonitorModule::getChartIds).ne(MonitorModule::getChartIds, "")); + for (MonitorModule monitorModule : monitorModuleList) { + monitorModule.setChartIds(this.delIds(monitorModule.getChartIds(), idList)); + } + if(Tool.CollUtil.isNotEmpty(monitorModuleList)) + monitorModuleService.saveOrUpdateBatch(monitorModuleList); + // 删除 Asset models 引用的 chart templates + List<AssetModel> assetModelList = assetModelService.list(new QueryWrapper<AssetModel>().lambda().isNotNull(AssetModel::getChartIds).ne(AssetModel::getChartIds, "")); + for (AssetModel assetModel : assetModelList) { + assetModel.setChartIds(this.delIds(assetModel.getChartIds(), idList)); + } + if(Tool.CollUtil.isNotEmpty(assetModelList)) + assetModelService.saveOrUpdateBatch(assetModelList); + + // 如果删除 ids 中 type 为 group ,则补充 group 包含的 chart ids + List<VisualChart> childrenCharts = this.list(new LambdaQueryWrapper<VisualChart>().in(VisualChart::getGroupId, Arrays.asList(ids))); + if(CollectionUtils.isNotEmpty(childrenCharts)){ + Set<Integer> idSet = childrenCharts.stream().map(VisualChart::getId).collect(Collectors.toSet()); + idList.addAll(idSet); + } + + // 删除自身 + this.baseMapper.deleteBatchIds(idList); + + // 删除char element + chartElementService.delElementByChartIds(idList); + } + + private String delIds(String chartIds, List<Integer> chartIdList){ + String str = ""; + for (String chartId : chartIds.split(",")) { + if(!chartIdList.contains(Integer.valueOf(chartId))){ + str += "," + chartId; + } + } + return StrUtil.isBlank(str) ? str : str.substring(1); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delVisualChartsByDashboardId(Integer... dashboardIds) { + if (ToolUtil.isEmpty(dashboardIds)) { + return; + } + + // 1. 再次通过 dashboardid 查询 是为了只删除当前 dashboard 下的 charts + List<VisualChart> charts = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getDashboardId, dashboardIds)); + List<Integer> chartIds = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); + + // 2. 内置chart不能删除 + this.validateBuildInCharts(chartIds); + + // 3. 不为空 则删除自身 同时删除关联的 element + if (CollectionUtils.isNotEmpty(chartIds)) { + this.removeByIds(chartIds); + chartElementService.delElementByChartIds(chartIds); + } + } + + /** + * 校验是否是内置chart + * + * @param chartIds + */ + private void validateBuildInCharts(List<Integer> chartIds) { + // 内置charts + List<VisualChart> buildInCharts = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getBuildIn, 1)); + Map<Integer, String> buildInChartIdAndTitleMap = buildInCharts.stream().collect(Collectors.toMap(VisualChart::getId, VisualChart::getName)); + + chartIds.forEach(id -> { + if (ToolUtil.isNotEmpty(buildInChartIdAndTitleMap.get(id))) { + throw new NZException(buildInChartIdAndTitleMap.get(id) + " chart is built-in and cannot be deleted", RCode.CHART_BUILDIN_CAN_NOT_REMOVE.getCode()); + } + }); + } + + /** + * 根据 chart.pid 查找引用自此chart,同步删除 + * + * @param deleteIds + */ + private void syncDeleteAssetsCharts(List<Integer> deleteIds) { + // 关联 charts + List<VisualChart> list = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getPid, deleteIds)); + if (CollectionUtils.isEmpty(list)) { + return; + } + Map<Integer, List<VisualChart>> listMap = list.stream().collect(Collectors.groupingBy(VisualChart::getDashboardId)); + + List<Integer> allDeleteChartIds = listMap.values().stream().flatMap(Collection::stream).map(VisualChart::getId).collect(Collectors.toList()); + // 删除自身 + this.removeByIds(allDeleteChartIds); + // 删除关联的 chart Elements + chartElementService.delElementByChartIds(allDeleteChartIds); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modify(VisualChart chart) { + + // 调整大小 + this.baseMapper.updateSizeById(chart); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void weights(Integer dashboardId,List<VisualChart> chartList) { + + if (CollectionUtils.isEmpty(chartList)) throw new NZException(RCode.CHART_WEIGHT_ISNULL); + for (VisualChart chart : chartList) { + if (chart.getId() == null) throw new NZException(RCode.CHART_ID_ISNULL); + if (chart.getWeight() == null) throw new NZException(RCode.CHART_WEIGHT_ISNULL); + } + + this.baseMapper.updateWeightBatch(dashboardId,chartList); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer chartTmplSynch(Integer pid, List<Integer> chartIdList) { + log.info("[chartTmplSynch] [begin]"); + + // get All Charts Need Be Synch By Params + List<VisualChart> chartListToBeSync = this.getAllChartsNeedBeSynchByParams(pid, chartIdList); + + if (Tool.CollUtil.isEmpty(chartListToBeSync)) { + log.warn("[chartTmplSynch] [No charts found need to be synchronized] [pid: {}] [chartIdList: {}]", pid, Tool.JSONUtil.toJsonStr(chartIdList)); + return chartListToBeSync.size(); + } + + // 获取所有模板数据 + List<Integer> allTmplChartIdList = chartListToBeSync.stream().map(VisualChart::getPid).distinct().collect(Collectors.toList()); + List<VisualChart> chartTemplateWithinGroup = this.list(new LambdaQueryWrapper<VisualChart>().in(VisualChart::getGroupId, allTmplChartIdList)); + if (Tool.CollUtil.isNotEmpty(chartTemplateWithinGroup)) { + List<Integer> chartTemplateIdListWithinGroup = chartTemplateWithinGroup.stream().map(VisualChart::getId).collect(Collectors.toList()); + allTmplChartIdList.addAll(chartTemplateIdListWithinGroup); + allTmplChartIdList = allTmplChartIdList.stream().distinct().collect(Collectors.toList()); + } + List<VisualChart> allChartTemplateList = this.baseMapper.queryList(allTmplChartIdList); + + // 将不必要的图表过滤掉,避免重复同步 + // Group A {Chart-1,Chart-2,Chart-3} 只需要同步 Group A 即可 + List<Integer> syncChartGroupIdList = chartListToBeSync.stream().filter(chart -> StrUtil.equals(Constant.CHART_GROUP_TYPE, chart.getType())).map(VisualChart::getId).collect(Collectors.toList()); + + // perform Sync Chart List + List<VisualChart> performSyncChartList = chartListToBeSync.stream().filter(chart -> BooleanUtil.negate(Tool.CollUtil.contains(syncChartGroupIdList, chart.getGroupId()))).collect(Collectors.toList()); + this.syncChart(performSyncChartList, allChartTemplateList); + + // delete + List<Integer> removeChartIdList = chartListToBeSync.stream().map(VisualChart::getId).collect(Collectors.toList()); + // del charts + this.removeByIds(removeChartIdList); + // del chart Elements + chartElementService.delElementByChartIds(removeChartIdList); + + log.info("[chartTmplSynch] [finshed]"); + // total + return removeChartIdList.size(); + } + + /** + * get All Charts Need Be Synch By Params + * + * @param pid + * @param chartIdList + * @return + */ + private List<VisualChart> getAllChartsNeedBeSynchByParams(Integer pid, List<Integer> chartIdList) { + log.info("[getAllChartsNeedBeSynchByParams] [pid: {}] [chartIdList: {}]", pid, Tool.JSONUtil.toJsonStr(chartIdList)); + + List<VisualChart> chartListToBeSync = Tool.ListUtil.list(true); + if (ObjectUtil.isNotNull(pid)) { + List<VisualChart> list = this.list(new LambdaQueryWrapper<VisualChart>().isNotNull(VisualChart::getPid).eq(VisualChart::getPid, pid)); + chartListToBeSync.addAll(list); + if (Tool.CollUtil.isNotEmpty(list)) { + List<Integer> tempChartIdList = list.stream().map(VisualChart::getId).collect(Collectors.toList()); + List<VisualChart> chaildChartList = this.list(new LambdaQueryWrapper<VisualChart>().isNotNull(VisualChart::getPid).in(VisualChart::getGroupId, tempChartIdList)); + chartListToBeSync.addAll(chaildChartList); + } + } + + if (Tool.CollUtil.isNotEmpty(chartIdList)) { + List<VisualChart> list = this.list(new LambdaQueryWrapper<VisualChart>().isNotNull(VisualChart::getPid).in(VisualChart::getId, chartIdList)); + List<VisualChart> chaildChartList = this.list(new LambdaQueryWrapper<VisualChart>().isNotNull(VisualChart::getPid).in(VisualChart::getGroupId, chartIdList)); + chartListToBeSync.addAll(list); + chartListToBeSync.addAll(chaildChartList); + } + // distinct data + chartListToBeSync = chartListToBeSync.stream().distinct().collect(Collectors.toList()); + + log.info("[getAllChartsNeedBeSynchByParams] [sync chart list] [size: {}]", chartListToBeSync.size()); + return chartListToBeSync; + } + + /** + * sync Chart + * + * @param performSyncChartList + * @param allChartTemplateList + */ + private void syncChart(List<VisualChart> performSyncChartList, List<VisualChart> allChartTemplateList) { + log.info("[syncChart] [begin] [perform Sync Chart List size: {}]", performSyncChartList.size()); + // 详情接口查询效率低,避免渲染时多次查询影响效率 + Map<VisualDashboard, Object> dashboardAndLinkObjectMap = Tool.MapUtil.newHashMap(); + performSyncChartList.stream().map(VisualChart::getDashboardId).distinct().forEach(dashboardId -> { + VisualDashboard syncChartDashboard = dashboardService.getById(dashboardId); + Object linkObject = null; + if (ObjectUtil.equal(DashboardConstant.VariableType.ASSET.getValue(), syncChartDashboard.getVarType())) { + linkObject = assetService.queryAssetInfo(syncChartDashboard.getLink()); + } else if (ObjectUtil.equal(DashboardConstant.VariableType.ENDPOINT.getValue(), syncChartDashboard.getVarType())) { + linkObject = endpointService.queryEndpointEntity(syncChartDashboard.getLink()); + } + dashboardAndLinkObjectMap.put(syncChartDashboard, linkObject); + }); + + // save batch + List<VisualChartElement> saveChartElementList = Tool.ListUtil.list(true); + + Map<Integer, Integer> groupIdMapping = Tool.MapUtil.newHashMap(); + // 先同步独立的 Chart 和 独立的 Group Chart(不包含 Group 包含的图表) + for (VisualChart syncChart : performSyncChartList) { + Integer chartId = syncChart.getId(); + // find template chart + VisualChart tmplChartForSync = allChartTemplateList.stream().filter(tmpl -> ObjectUtil.equal(tmpl.getId(), syncChart.getPid())).findFirst().orElse(null); + if (ObjectUtil.isNull(tmplChartForSync)) { + log.warn("[syncChart] [chart template does not exist] [sync chart id: {}] [pid: {}]", chartId, syncChart.getPid()); + tmplChartForSync = this.queryInfo(syncChart.getPid()); + } + + // 同步时,var_type, link 值取自 sync Dashboard + VisualDashboard syncChartDashboard = dashboardAndLinkObjectMap.keySet().stream().filter(visualDashboard -> ObjectUtil.equal(visualDashboard.getId(), syncChart.getDashboardId())).findFirst().get(); + Object linkObject = dashboardAndLinkObjectMap.get(syncChartDashboard); + + if (StrUtil.equals(Constant.CHART_GROUP_TYPE, tmplChartForSync.getType())) { + // group + VisualChart visualChart = this.performChartSync(tmplChartForSync, syncChartDashboard, linkObject, 0); + groupIdMapping.put(chartId, visualChart.getId()); + + saveChartElementList.addAll(Tool.CollUtil.defaultIfEmpty(visualChart.getElements(), Tool.ListUtil.empty())); + } else { + // 同步单个图表,group id 依旧为当前 group 下 + VisualChart visualChart = this.performChartSync(tmplChartForSync, syncChartDashboard, linkObject, syncChart.getGroupId()); + saveChartElementList.addAll(Tool.CollUtil.defaultIfEmpty(visualChart.getElements(), Tool.ListUtil.empty())); + } + } + + // 同步 Group Chart 含有的 Chart + List<VisualChart> syncGroupChartList = performSyncChartList.stream().filter(chart -> StrUtil.equals(Constant.CHART_GROUP_TYPE, chart.getType())).collect(Collectors.toList()); + for (VisualChart syncGroupChart : syncGroupChartList) { + Integer syncGroupChartId = syncGroupChart.getId(); + // 直接以 Group 模板内的图表进行渲染,保证同步后 Group 内图表完全一致 + List<VisualChart> chartTemplateListWithinGroup = this.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getGroupId, syncGroupChart.getPid())); + + // 同步时,var_type, link 值取自 sync dashboard + VisualDashboard syncChartDashboard = dashboardAndLinkObjectMap.keySet().stream().filter(visualDashboard -> ObjectUtil.equal(visualDashboard.getId(), syncGroupChart.getDashboardId())).findFirst().get(); + Object linkObject = dashboardAndLinkObjectMap.get(syncChartDashboard); + + for (VisualChart syncChart : chartTemplateListWithinGroup) { + // find template chart + VisualChart tmplChartForSync = allChartTemplateList.stream().filter(tmpl -> ObjectUtil.equal(tmpl.getId(), syncChart.getId())).findFirst().orElse(null); + if (ObjectUtil.isNull(tmplChartForSync)) { + log.warn("[syncChart] [chart template does not exist] [chart template id: {}] [sync group id: {}]", syncChart.getId(), syncGroupChart.getId()); + tmplChartForSync = this.queryInfo(syncChart.getId()); + } + + // group id is new group chart id + VisualChart visualChart = this.performChartSync(tmplChartForSync, syncChartDashboard, linkObject, groupIdMapping.get(syncGroupChartId)); + saveChartElementList.addAll(Tool.CollUtil.defaultIfEmpty(visualChart.getElements(), Tool.ListUtil.empty())); + } + } + + // save element + if (Tool.CollUtil.isNotEmpty(saveChartElementList)) { + chartElementService.saveBatch(saveChartElementList); + } + + log.info("[syncChart] [finshed]"); + } + + /** + * perform Chart Sync + * + * @param tmplChartForSync + * @param syncChartDashboard + * @param linkObject + * @param groupId + * @return + */ + private VisualChart performChartSync(VisualChart tmplChartForSync, VisualDashboard syncChartDashboard, Object linkObject, Integer groupId) { + Integer syncDashboardId = syncChartDashboard.getId(); + Integer syncDashboardVarType = syncChartDashboard.getVarType(); + Integer syncDashboardLink = syncChartDashboard.getLink(); + + // copy Properties + VisualChart saveChart = JSONUtil.toBean(JSONUtil.toJsonStr(tmplChartForSync), VisualChart.class); + + saveChart.setId(null); + saveChart.setDashboardId(syncDashboardId); + saveChart.setPid(tmplChartForSync.getId()); + saveChart.setVarId(syncDashboardLink); + saveChart.setVarType(syncDashboardVarType); + + saveChart.setUpdateAt(new Date()); + saveChart.setUpdateBy(ShiroUtils.getUserId().intValue()); + + saveChart.setName(Tool.NzExpressionUtil.renderExpression(saveChart.getName(), linkObject)); + saveChart.setParam(ToolUtil.isNotEmpty(saveChart.getParam()) ? Tool.NzExpressionUtil.renderExpression(saveChart.getParam().toString(), linkObject) : null); + + // group id + saveChart.setGroupId(ObjectUtil.defaultIfNull(groupId, 0)); + + // save chart + this.save(saveChart); + + // element + if (Tool.CollUtil.isNotEmpty(saveChart.getElements())) { + List<VisualChartElement> saveElementList = Tool.ListUtil.list(true); + for (VisualChartElement element : saveChart.getElements()) { + VisualChartElement saveElement = JSONUtil.toBean(JSONUtil.toJsonStr(element), VisualChartElement.class); + + saveElement.setId(null); + saveElement.setExpression(Tool.NzExpressionUtil.renderExpression(element.getExpression(), linkObject)); + saveElement.setChartId(saveChart.getId()); + saveElementList.add(saveElement); + } + saveChart.setElements(saveElementList); + } + return saveChart; + } + + @Override + public void saveRelDashboardAndChart(String type, Integer linkId, String name, Integer tempId, String seq) { + VisualDashboard dashboard = new VisualDashboard(); + dashboard.setName(name); + dashboard.setType(type); + dashboard.setPid(0); + dashboard.setLink(linkId); + // temp_id + // assetInfo dashboard from model.dashboard_id + // endpointInfo dashboard from module.dashboard_id + dashboard.setTmplId(ObjectUtil.defaultIfNull(tempId, -1)); + dashboard.setWeight(0); + dashboard.setCreateBy(ShiroUtils.getUserId().intValue()); + dashboard.setUts(System.currentTimeMillis()); + if (StrUtil.equals(DashboardConstant.Type.ASSET.getValue(), type)) { + dashboard.setVarType(DashboardConstant.VariableType.ASSET.getValue()); + } else if (StrUtil.equals(DashboardConstant.Type.ENDPOINT.getValue(), type)) { + dashboard.setVarType(DashboardConstant.VariableType.ENDPOINT.getValue()); + } + if (StrUtil.isNotEmpty(seq)) { + dashboard.setSeq(seq); + } + dashboardService.save(dashboard); + + // build-in chart include assetInfo and endpointInfo chart + String chartConfigTempJsonStr = StrUtil.EMPTY; + DashboardConstant.Type instanceByType = DashboardConstant.Type.getInstanceByType(type); + switch (instanceByType) { + case ASSET: { + chartConfigTempJsonStr = sysConfService.getValue(Constant.SYSCONFIG_KEY_ASSET_CHART_TPL); + break; + } + case ENDPOINT: { + chartConfigTempJsonStr = sysConfService.getValue(Constant.SYSCONFIG_KEY_ENDPOINT_CHART_TPL); + break; + } + default: + break; + } + + // assetInfo or endpointInfo + VisualChart chartTemplate = JSONObject.parseObject(chartConfigTempJsonStr, VisualChart.class); + + VisualChart target = new VisualChart(); + BeanUtils.copyProperties(chartTemplate, target); + target.setParam(ToolUtil.isNotEmpty(target.getParam()) ? JSONObject.toJSONString(target.getParam()) : null); + target.setDashboardId(dashboard.getId()); + target.setGroupId(0); + target.setDatasource(ChartDatasourceType.SYSTEM.getValue()); + target.setUpdateAt(new Date()); + target.setUpdateBy(ShiroUtils.getUserId().intValue()); + if (StrUtil.isNotEmpty(seq)) { + target.setSeq(seq); + } + this.save(target); + } + + @Override + public List<VisualChart> getAllChartList(List<VisualChart> sourceChartList) { + sourceChartList = Tool.CollUtil.defaultIfEmpty(sourceChartList, Tool.ListUtil.empty()); + + // 递归展开节点信息 + List<VisualChart> allChartList = Tool.ListUtil.list(true); + for (VisualChart entity : sourceChartList) { + this.getAllChildrenChartList(entity, allChartList); + } + return allChartList; + } + + @Override + public List<VisualChart> queryChartsIncludeElementInfo(Integer dashboardId) { + List<VisualChart> visualChartList = this.getBaseMapper().queryChartsIncludeElementInfo(dashboardId); + return Tool.CollUtil.defaultIfEmpty(visualChartList, Tool.ListUtil.empty()); + } + + /** + * 平铺 获取所有 chart 节点 + * + * @param chart + * @param chartList + */ + public void getAllChildrenChartList(VisualChart chart, List<VisualChart> chartList) { + chartList.add(chart); + if (CollectionUtils.isNotEmpty(chart.getChildren())) { + for (VisualChart pojo : chart.getChildren()) { + getAllChildrenChartList(pojo, chartList); + } + } + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualDashboardServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualDashboardServiceImpl.java new file mode 100644 index 00000000..579bb376 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualDashboardServiceImpl.java @@ -0,0 +1,1831 @@ +package com.nis.modules.dashboard.service.impl; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.thread.NamedThreadFactory; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.common.utils.Constant.ChartDatasourceType; +import com.nis.modules.agent.service.LokiApiService; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetModel; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.asset.service.AssetModelService; +import com.nis.modules.dashboard.dao.VisualDashboardDao; +import com.nis.modules.dashboard.entity.*; +import com.nis.modules.dashboard.service.VisualChartElementService; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.module.entity.MonitorModule; +import com.nis.modules.module.service.MonitorModuleService; +import com.nis.modules.report.job.ReportJobManager; +import com.nis.modules.stat.service.StatService; +import com.nis.modules.sys.entity.SysDictEntity; +import com.nis.modules.sys.entity.SysUserStarredEntity; +import com.nis.modules.sys.service.*; +import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.poi.util.TempFile; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.DefaultTransactionDefinition; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +@Service("visualDashboardService") +public class VisualDashboardServiceImpl extends ServiceImpl<VisualDashboardDao, VisualDashboard> implements VisualDashboardService { + + private Log log = Log.get(); + /** + * dashboard snapshot 查询超时时间,单位:ms + */ + @Value("${dashboard.snapshot.timeout:300000}") + private Integer timeout; + + @Value("${snapshot.concurrency:10}") + private Integer snapshotConcurrency; + + @Value("${snapshot.corePoolSize:5}") + private Integer snapshotCorePoolSize; + + @Value("${snapshot.keepAliveTime:30}") + private Long snapshotKeepAliveTime; + + @Value("${snapshot.capacity:10000}") + private Integer snapshotCapacity; + + // snapshot 执行线程池,避免大量请求访问 prometheus 服务 + private ExecutorService snapshotThreadPool; + + @Autowired + private VisualService visualService; + + @Autowired + private VisualChartService visualChartService; + + @Autowired + private VisualChartElementService chartElementService; + + @Autowired + private DataSourceTransactionManager dataSourceTransactionManager; + + @Autowired + private BasicImportAndExportServices basicImportAndExportServices; + + @Autowired + private PromApiService promApiService; + + @Autowired + private LokiApiService lokiApiService; + + @Autowired + private AssetModelService assetModelService; + + @Autowired + private AssetAssetService assetAssetService; + + @Autowired + private MonitorModuleService monitorModuleService; + + @Autowired + private MonitorEndpointService monitorEndpointService; + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private ReportJobManager reportJobManager; + + @Autowired + private SysI18nService sysI18nService; + + @Autowired + private SysDictService sysDictService; + + @Autowired + private SysConfigService sysConfigService; + + @Autowired + private SysUserStarredService starredService; + + @Autowired + private StatService statService; + + @Override + public VisualDashboard queryInfo(Integer id) { + VisualDashboard dashboard = this.baseMapper.queryInfo(id); + if (ToolUtil.isNotEmpty(dashboard.getParam())) + dashboard.setParam(JSONObject.parseObject(String.valueOf(dashboard.getParam()), Map.class)); + + // 当前用户收藏状态 1:收藏 0:未收藏 + int count = starredService.count(new LambdaQueryWrapper<SysUserStarredEntity>() + .eq(SysUserStarredEntity::getTid, dashboard.getId()).eq(SysUserStarredEntity::getType, "dashboard") + .eq(SysUserStarredEntity::getUid, ShiroUtils.getUserId().intValue())); + + dashboard.setStarred(count == 0 ? 0 : 1); + return dashboard; + } + + @Override + public PageUtils queryList(Map<String, Object> params) { + String ids = (String) params.get("ids"); + if (StrUtil.isNotBlank(ids)) { + List<String> listIds = Arrays.asList(ids.split(",")); + params.put("ids", listIds); + } + // 获取当前登录用户的id + Long currentLoginUserID = ShiroUtils.getUserId(); + params.put("currentLoginUserID", currentLoginUserID); + // 1. 查询时 type 为空则默认 dashboard 类型 + String type = (String) params.get("type"); + if (StringUtils.isEmpty(type)) { + type = DashboardConstant.Type.DASHBOARD.getValue(); + params.put("type", type); + } + boolean isDashboard = StrUtil.equals(DashboardConstant.Type.DASHBOARD.getValue(), type); + if (isDashboard && StrUtil.isBlank(ids)) params.put("pid", "0"); + + IPage page = new Query(VisualDashboard.class).getPage(params); + List<VisualDashboard> dashboardList = this.baseMapper.queryList(page, params); + for (VisualDashboard visualDashboard : dashboardList) { + if (ToolUtil.isNotEmpty(visualDashboard.getParam())) + visualDashboard.setParam(JSONObject.parseObject(String.valueOf(visualDashboard.getParam()), Map.class)); + + if (isDashboard) { + // 2. dashboard 类型 需要树形结构 + List<VisualDashboard> childrenList = this.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getPid, visualDashboard.getId())); + if (CollectionUtils.isNotEmpty(childrenList)) { + for (VisualDashboard childrenDashboard : childrenList) { + if (ToolUtil.isNotEmpty(childrenDashboard.getParam())) + childrenDashboard.setParam(JSONObject.parseObject(String.valueOf(childrenDashboard.getParam()), Map.class)); + + // 当前用户收藏状态 1:收藏 0:未收藏 + int count = starredService.count(new LambdaQueryWrapper<SysUserStarredEntity>() + .eq(SysUserStarredEntity::getTid, childrenDashboard.getId()).eq(SysUserStarredEntity::getType, "dashboard") + .eq(SysUserStarredEntity::getUid, currentLoginUserID.intValue())); + childrenDashboard.setStarred(count == 0 ? 0 : 1); + } + visualDashboard.setChildren(childrenList); + } + } + } + page.setRecords(dashboardList); + return new PageUtils(page); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delDashboardsAndChartInfoByDashboardIds(Set<Integer> dashboardIds) { + if (CollectionUtils.isNotEmpty(dashboardIds)) { + // 删除 dashboard + this.removeByIds(dashboardIds); + + // 删除 chart info + Integer[] removeDashboardIds = dashboardIds.stream().toArray(n -> new Integer[n]); + visualChartService.delVisualChartsByDashboardId(removeDashboardIds); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delDashboards(Integer... ids) { + if (ToolUtil.isEmpty(ids)) { + return; + } + + List<VisualDashboard> dashboards = this.list(); + + // 1. 校验内置dashboard不能被删除 + this.validateBuildInDashboards(dashboards, ids); + + // 获取这些节点的所有子节点 + List<Integer> idList = Arrays.stream(ids).collect(Collectors.toList()); + List<VisualDashboard> dashboardList = this.list(); + Set<Integer> allDashboardIds = new HashSet<>(); + for (Integer id : idList) { + allDashboardIds.add(id); + allDashboardIds.addAll(this.getChildrenIds(dashboardList, id)); + } + + // 2. 删除 dashboard ,如果包含子节点,也一并删除 + this.removeByIds(allDashboardIds); + + // 删除对应的收藏记录 + starredService.remove(new LambdaQueryWrapper<SysUserStarredEntity>().eq(SysUserStarredEntity::getType, "dashboard") + .in(SysUserStarredEntity::getTid, allDashboardIds)); + + // 3. 删除关联的 chart chartElement + Integer[] removeDashboardIds = allDashboardIds.stream().toArray(n -> new Integer[n]); + visualChartService.delVisualChartsByDashboardId(removeDashboardIds); + + // 4. template dashboard + // dashboard & asset model & monitor module + this.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getTmplId, -1) + .in(VisualDashboard::getTmplId, allDashboardIds)); + + assetModelService.update(new LambdaUpdateWrapper<AssetModel>() + .set(AssetModel::getDashboardId, null) + .in(AssetModel::getDashboardId, allDashboardIds)); + + monitorModuleService.update(new LambdaUpdateWrapper<MonitorModule>() + .set(MonitorModule::getDashboardId, null) + .in(MonitorModule::getDashboardId, allDashboardIds)); + try { + // 删除 Report job + for (Integer dashboardId : allDashboardIds) { + reportJobManager.delJobByName(dashboardId.toString()); + } + } catch (SchedulerException e) { + log.error("Delete dashboard report job error", e); + } + } + + /** + * 查询所有子节点 ID + * + * @param dashboardList + * @param parentId + * @return + */ + private List<Integer> getChildrenIds(List<VisualDashboard> dashboardList, Integer parentId) { + List<Integer> resultList = new ArrayList<>(); + for (VisualDashboard dashboard : dashboardList) { + Integer id = dashboard.getId(); + Integer pid = dashboard.getPid(); + if (parentId.equals(pid)) { + resultList.add(id); + resultList.addAll(this.getChildrenIds(dashboardList, id)); + } + } + return resultList; + } + + /** + * 校验内置 dashboard 不可删除 + * + * @param dashboards + * @param removeIds + */ + private void validateBuildInDashboards(List<VisualDashboard> dashboards, Integer... removeIds) { + // 内置 dashboard 不能删除 + List<Integer> buildInDashboards = dashboards.stream().filter(dashboard -> dashboard.getBuildIn() == 1).map(VisualDashboard::getId) + .collect(Collectors.toList()); + List<Integer> removeIdList = Arrays.stream(removeIds).collect(Collectors.toList()); + removeIdList.retainAll(buildInDashboards); + if (CollectionUtils.isNotEmpty(removeIdList)) { + List<String> dashboardNames = this.listByIds(removeIdList).stream().map(VisualDashboard::getName) + .collect(Collectors.toList()); + throw new NZException( + "These dashboard is built-in and cannot be deleted, dashboards info: " + dashboardNames.toString(), + RCode.DASHBOARD_BUILDIN_CAN_NOT_REMOVE.getCode()); + } + } + + /** + * 校验 dashboard 相关参数是否正确 + * + * @param dashboard + */ + public void validateDashboard(VisualDashboard dashboard) { + String name = dashboard.getName(); + ValidateUtils.is(name).notNull(RCode.DASHBOARD_NAME_ISNULL); + + if (name.contains("/")) { + throw new NZException(RCode.DASHBOARD_NAME_FORMAT_ERROR); + } + + Integer pid = dashboard.getPid(); + pid = (pid == null) ? 0 : pid; + // 校验name是否重复 + List<VisualDashboard> list = this.list(new QueryWrapper<VisualDashboard>().lambda().eq(VisualDashboard::getPid, pid) + .eq(VisualDashboard::getType, dashboard.getType()).eq(VisualDashboard::getName, dashboard.getName())); + boolean flag = false; + // 当只有一个结果并且这个结果是自身时,或没有结果时,说明名称不重复 + if ((list == null || list.size() == 0) + || (list != null && list.size() == 1 && list.get(0).getId().equals(dashboard.getId()))) { + flag = true; + } + + if (!flag) { + throw new NZException(RCode.DASHBOARD_NAME_DUPLICATE); + } + + // 校验 type 与 link、 varType + String type = dashboard.getType(); + if (StrUtil.isEmpty(type)) { + if(ToolUtil.isNotEmpty(dashboard.getLink())){ + throw new NZException(RCode.DASHBOARD_TYPE_ISNULL); + } + dashboard.setType(DashboardConstant.Type.DASHBOARD.getValue()); + } else if(StrUtil.equals(type, DashboardConstant.Type.TEMPLATE.getValue())){ + // 校验 varType + Integer varType = dashboard.getVarType(); + ValidateUtils.is(varType).notNull(RCode.DASHBOARD_VARTYPE_ISNULL); + if(!Arrays.asList(new Integer[]{0, 1, 2}).contains(varType)){ + throw new NZException(RCode.DASHBOARD_VARTYPE_INVALIDE); + } + } else { + List<DashboardConstant.Type> dashboardTypes = Arrays.asList(DashboardConstant.Type.values()); + List<String> types = dashboardTypes.stream().map(DashboardConstant.Type::getValue).filter(val -> !val.equals(DashboardConstant.Type.DASHBOARD.getValue())).collect(Collectors.toList()); + if(types.contains(type)){ + ValidateUtils.is(dashboard.getLink()).notNull(RCode.DASHBOARD_LINK_ISNULL); + } else if(!StrUtil.equals(type, DashboardConstant.Type.DASHBOARD.getValue())){ + throw new NZException(RCode.DASHBOARD_TYPE_INVALIDE); + } + } + + // pid 是否存在 + if (dashboard.getPid() != null && dashboard.getPid() != 0) { + VisualDashboard entity = this.getById(dashboard.getPid()); + ValidateUtils.is(entity).notNull(RCode.DASHBOARD_NOT_EXIST); + } + + // Dashboard param 校验 + RCode paramRCode = this.validateDashboardParam(dashboard); + if (paramRCode != null) { + throw new NZException(paramRCode); + } + } + + public RCode validateDashboardParam(VisualDashboard dashboard){ + if (ToolUtil.isNotEmpty(dashboard.getParam())) { + Map param = JSONObject.parseObject(JSONObject.toJSONString(dashboard.getParam()), Map.class); + if (ToolUtil.isNotEmpty(param.get("report"))) { + Map report = JSONObject.parseObject(JSONObject.toJSONString(param.get("report")), Map.class); + // enable 为 true 时 + if (ToolUtil.isNotEmpty(report.get("enable")) + && ToolUtil.equals("true", report.get("enable").toString())) { + if(ToolUtil.isEmpty(report.get("range"))){ + return RCode.DASHBOARD_PARAM_REPORTRANGE_ISNULL; + } + if(ToolUtil.isEmpty(report.get("schedule"))){ + return RCode.DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL; + } + if(ToolUtil.isEmpty(report.get("receivers"))){ + return RCode.DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL; + } + Map range = JSONObject.parseObject(JSONObject.toJSONString(report.get("range")), Map.class); + if(ToolUtil.isEmpty(range.get("type"))){ + return RCode.DASHBOARD_PARAM_RANGETYPE_ISNULL; + } + if(ToolUtil.isEmpty(range.get("interval"))){ + return RCode.DASHBOARD_PARAM_RANGEINTERVAL_ISNULL; + } + if(ToolUtil.isEmpty(range.get("unit"))){ + return RCode.DASHBOARD_PARAM_RANGEUNIT_ISNULL; + } + if (!Arrays.asList(new String[] { "previous", "last" }).contains(range.get("type"))) { + return RCode.DASHBOARD_PARAM_RANGETYPE_INVALIDE; + } else if (!Arrays.asList(new String[] { "hour", "day", "week", "month" }) + .contains(range.get("unit"))) { + return RCode.DASHBOARD_PARAM_RANGEUNIT_INVALIDE; + } + Map schedule = JSONObject.parseObject(JSONObject.toJSONString(report.get("schedule")), Map.class); + if(ToolUtil.isEmpty(schedule.get("type"))){ + return RCode.DASHBOARD_PARAM_SCHEDULETYPE_ISNULL; + } + if(ToolUtil.isEmpty(schedule.get("stime"))){ + return RCode.DASHBOARD_PARAM_SCHEDULESTIME_ISNULL; + } + if (!Arrays.asList(new Integer[] { 1, 2, 3, 4 }).contains(schedule.get("type"))) { + return RCode.DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE; + } + if (ToolUtil.equals(schedule.get("type").toString(), "2")) { + if(ToolUtil.isEmpty(schedule.get("repeat"))){ + return RCode.DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL; + } + } else if (ToolUtil.equals(schedule.get("type").toString(), "3")) { + if(ToolUtil.isEmpty(schedule.get("repeat"))){ + return RCode.DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL; + } + if(ToolUtil.isEmpty(schedule.get("nums"))){ + return RCode.DASHBOARD_PARAM_SCHEDULENUMS_ISNULL; + } + if (!Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7 }).containsAll( + JSONArray.parseObject(JSONObject.toJSONString(schedule.get("nums")), List.class))) { + return RCode.DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE; + } + } else if (ToolUtil.equals(schedule.get("type").toString(), "4")) { + if(ToolUtil.isEmpty(schedule.get("nums"))){ + return RCode.DASHBOARD_PARAM_SCHEDULENUMS_ISNULL; + } + List<Integer> monthlyList = new ArrayList<>(); + for (int i = 1; i < 32; i++) { + monthlyList.add(i); + } + monthlyList.add(-1); + if (!monthlyList.containsAll( + JSONArray.parseObject(JSONObject.toJSONString(schedule.get("nums")), List.class))) { + return RCode.DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE; + } + } + } else { + if (ToolUtil.isEmpty(report.get("enable"))) { + report.put("enable", false); + param.put("report", report); + } + } + } + if (ToolUtil.isNotEmpty(param.get("chartShare"))) { + if (!Arrays.asList(new String[] { "none", "crosshair", "tooltip" }).contains(param.get("chartShare"))) { + return RCode.DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE; + } + } else { + param.put("chartShare", "none"); + } + dashboard.setParam(JSONObject.toJSONString(param)); + } + return null; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveVisualDashboard(VisualDashboard dashboard) { + dashboard.setName(StrUtil.trim(dashboard.getName())); + this.validateDashboard(dashboard); + + Long userId = ShiroUtils.getUserId(); + dashboard.setCreateBy(userId.intValue()); + + dashboard.setUts(System.currentTimeMillis()); + if (ToolUtil.isNotEmpty(dashboard.getParam())) { + dashboard.setParam(String.valueOf(dashboard.getParam())); + } + + Integer pid = dashboard.getPid(); + pid = (pid == null) ? 0 : pid; + // 查询该父级节点下是否存在 dashboard 节点 + List<VisualDashboard> list = this.list(new QueryWrapper<VisualDashboard>().lambda() + .eq(VisualDashboard::getType, dashboard.getType()).eq(VisualDashboard::getPid, pid)); + if (CollectionUtils.isEmpty(list)) { + // 父级节点下暂无其他节点,直接保存 + this.save(dashboard); + } else { + // 找到当前末尾的 dashboard , 加到其后 + VisualDashboard endDashboard = list.stream().max(Comparator.comparingInt(VisualDashboard::getWeight)).get(); + Integer weight = endDashboard.getWeight(); + dashboard.setWeight(++weight); + this.save(dashboard); + } + + // add assetInfo or endpointInfo chart + this.addLinkObjectInfoChart(dashboard); + + // add Report Config In Redis + this.addReportConfigInRedis(dashboard); + } + + /** + * add Link Object Info Chart + * + * @param dashboard + */ + @Override + public void addLinkObjectInfoChart(VisualDashboard dashboard) { + String type = dashboard.getType(); + if (StrUtil.equals(DashboardConstant.Type.TEMPLATE.getValue(), type)) { + Integer varType = dashboard.getVarType(); + log.info("[addLinkObjectInfoChart] [add chart] [varType: {}]", varType); + + VisualChart chartTemplate = null; + if (ObjectUtil.equal(DashboardConstant.VariableType.ASSET.getValue(), varType)) { + String configValue = sysConfigService.getValue(Constant.SYSCONFIG_KEY_ASSET_CHART_TPL); + chartTemplate = JSONObject.parseObject(configValue, VisualChart.class); + } + + if (ObjectUtil.equal(DashboardConstant.VariableType.ENDPOINT.getValue(), varType)) { + String configValue = sysConfigService.getValue(Constant.SYSCONFIG_KEY_ENDPOINT_CHART_TPL); + chartTemplate = JSONObject.parseObject(configValue, VisualChart.class); + } + + if (ObjectUtil.isNotNull(chartTemplate)) { + chartTemplate.setDashboardId(dashboard.getId()); + chartTemplate.setGroupId(0); + chartTemplate.setDatasource(ChartDatasourceType.SYSTEM.getValue()); + chartTemplate.setUpdateBy(dashboard.getCreateBy()); + chartTemplate.setUpdateAt(new Date()); + visualChartService.save(chartTemplate); + } + } + } + + /** + * add Report Config In Redis + * + * @param dashboard + */ + @Override + public void addReportConfigInRedis(VisualDashboard dashboard) { + String type = dashboard.getType(); + if (StrUtil.equals(DashboardConstant.Type.TEMPLATE.getValue(), type)) { + log.warn("[addReportConfigInRedis] [template dashboard does not support report config] [dashboardId: {}] [type: {}]", dashboard.getId(), type); + return; + } + + String reportEnable = null; + if (ToolUtil.isNotEmpty(dashboard.getParam())) { + reportEnable = JSONPath.read(dashboard.getParam().toString(), "report.enable").toString(); + } + + log.info("[addReportConfigInRedis] [publish config to redis] [enable: {}]", reportEnable); + // publish report config when reportEnable is true + if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { + Map publishMap = new HashMap(4); + publishMap.put("dashboardId", dashboard.getId()); + publishMap.putAll(JSONObject.parseObject(dashboard.getParam().toString(), Map.class)); + + redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateVisualDashboard(VisualDashboard dashboard) { + dashboard.setName(StrUtil.trim(dashboard.getName())); + this.validateDashboard(dashboard); + + VisualDashboard oldDashboard = this.getById(dashboard.getId()); + + if (oldDashboard == null) { + throw new NZException(RCode.DASHBOARD_NOT_EXIST); + } + dashboard.setUts(System.currentTimeMillis()); + if (ToolUtil.isNotEmpty(dashboard.getParam())) + dashboard.setParam(String.valueOf(dashboard.getParam())); + + // 改变 pid 父级节点时,将该 Dashboard 加入到该 pid 下末尾位置 + if (!oldDashboard.getPid().equals(dashboard.getPid())) { + VisualDashboard endDashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getPid, dashboard.getPid()).orderByDesc(VisualDashboard::getWeight).last("limit 0,1")); + // 该 pid 下存在节点 + if (endDashboard != null) { + Integer weight = endDashboard.getWeight(); + dashboard.setWeight(++weight); + } else { + dashboard.setWeight(0); + } + } + + // 修改 + this.updateById(dashboard); + + // update Report Config In Redis + this.updateReportConfigInRedis(oldDashboard, dashboard); + } + + /** + * update Report Config In Redis + * + * @param oldDashboard + * @param newDashboard + */ + @Override + public void updateReportConfigInRedis(VisualDashboard oldDashboard, VisualDashboard newDashboard) { + String type = newDashboard.getType(); + if (StrUtil.equals(DashboardConstant.Type.TEMPLATE.getValue(), type)) { + log.warn("[updateReportConfigInRedis] [template dashboard does not support report config] [DashboardId: {}] [type: {}]", newDashboard.getId(), type); + return; + } + + // report + String oldParamStr = ToolUtil.isEmpty(oldDashboard.getParam()) ? JSONObject.toJSONString(Tool.MapUtil.empty()) + : oldDashboard.getParam().toString(); + Map oldParamMap = JSONObject.parseObject(oldParamStr, LinkedHashMap.class); + String newParamStr = ToolUtil.isEmpty(newDashboard.getParam()) ? JSONObject.toJSONString(Tool.MapUtil.empty()) + : newDashboard.getParam().toString(); + Map newParamMap = JSONObject.parseObject(newParamStr, LinkedHashMap.class); + + boolean isUpdate = !oldParamMap.equals(newParamMap); + + log.info("[updateReportConfigInRedis] [publish config to redis] [isUpdate: {}]", isUpdate); + if (isUpdate) { + Map publishMap = new HashMap(4); + publishMap.put("dashboardId", newDashboard.getId()); + publishMap.putAll(newParamMap); + + redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modify(List<VisualDashboard> dashboardList) { + if (CollectionUtils.isEmpty(dashboardList)) + throw new NZException(RCode.DASHBOARD_ID_ISNULL); + for (VisualDashboard dashboard : dashboardList) { + if (dashboard.getId() == null) + throw new NZException(RCode.DASHBOARD_ID_ISNULL); + if (dashboard.getPid() == null) + throw new NZException(RCode.DASHBOARD_PID_ISNULL); + if (dashboard.getWeight() == null) + throw new NZException(RCode.DASHBOARD_WEIGHT_ISNULL); + } + + this.getBaseMapper().updateWeightBatch(dashboardList); + } + + @Override + public void getTemplateByLanguage(HttpServletResponse response, String format, String type) throws IOException { + // 按类型获取表头模板信息 + String configKey = this.getChartTemplateConfigKeyByType(type); + String sysHeaderJsonStr = sysConfigService.getValue(configKey); + String fileName = "DashboardChartTemplate"; + basicImportAndExportServices.getTemplate(sysHeaderJsonStr, format, fileName, response); + } + + @Override + public Map importChartData(MultipartFile multipartFile, Map<String, Object> params) throws IOException { + String str = IoUtil.read(multipartFile.getInputStream(), CharsetUtil.charset("UTF-8")); + List<LinkedHashMap> importDataList = JSONObject.parseArray(str, LinkedHashMap.class); + + // 表头信息 国际化之后的 + String dashboardHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_DASHBOARD_EXPORT_HEADER); + List<String> dashboardHeaderInfos = new ArrayList<>(basicImportAndExportServices.getI18nHeaderMap(dashboardHeaderJsonStr).keySet()); + String chartHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_CHART_EXPORT_HEADER); + List<String> chartHeaderInfos = new ArrayList<>(basicImportAndExportServices.getI18nHeaderMap(chartHeaderJsonStr).keySet()); + + // 返回统计信息 + Map statMap = this.saveDashboardsFromImportDataList(importDataList, dashboardHeaderInfos, chartHeaderInfos, params); + return statMap; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void duplicate(Integer id) { + VisualDashboard dashboard = this.getById(id); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); + + dashboard.setName("copy from " + dashboard.getName()); + if (dashboard.getName().length() > 64) { + throw new NZException(RCode.DASHBOARD_NAME_TOO_LONG); + } + Long userId = ShiroUtils.getUserId(); + dashboard.setCreateBy(userId.intValue()); + dashboard.setId(null); + dashboard.setUts(System.currentTimeMillis()); + String reportEnable = null; + if (ToolUtil.isNotEmpty(dashboard.getParam()) && ToolUtil.contains(dashboard.getParam(), "enable")) { + reportEnable = JSONPath.read(dashboard.getParam().toString(), "report.enable").toString(); + dashboard.setParam(String.valueOf(dashboard.getParam())); + } + + Integer pid = dashboard.getPid(); + // 查询该父级节点下是否存在 dashboard 节点 + List<VisualDashboard> list = this.list(new QueryWrapper<VisualDashboard>().lambda() + .eq(VisualDashboard::getType, dashboard.getType()).eq(VisualDashboard::getPid, pid == null ? 0 : pid)); + // 找到当前末尾的 dashboard , 加到其后 + VisualDashboard endDashboard = list.stream().max(Comparator.comparingInt(VisualDashboard::getWeight)).get(); + Integer weight = endDashboard.getWeight(); + dashboard.setWeight(++weight); + this.save(dashboard); + + // publish report config when reportEnable is true + if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { + Map publishMap = new HashMap(4); + publishMap.put("dashboardId", dashboard.getId()); + publishMap.putAll(JSONObject.parseObject(dashboard.getParam().toString(), Map.class)); + + redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); + } + + // 复制dashboard 下的 charts + List<VisualChart> chartsGroupList = visualChartService.list(new QueryWrapper<VisualChart>().lambda() + .eq(VisualChart::getDashboardId, id).orderByAsc(VisualChart::getGroupId)); + Map<Integer, Integer> chartsGroupMap = new HashMap<>(); + Integer chartId; + if (!CollectionUtils.isEmpty(chartsGroupList)) { + for (VisualChart chart : chartsGroupList) { + chartId = chart.getId(); + chart.setId(null); + chart.setUpdateAt(new Date()); + chart.setUpdateBy(userId.intValue()); + chart.setDashboardId(dashboard.getId()); + if (ToolUtil.equals(chart.getType(), "group")) { + visualChartService.save(chart); + chartsGroupMap.put(chartId, chart.getId()); + } else { + if (!ToolUtil.equals(chart.getGroupId(), 0)) + chart.setGroupId(chartsGroupMap.get(chart.getGroupId())); + visualChartService.save(chart); + } + // 查询当前chart下的chartElement + List<VisualChartElement> elementList = chartElementService.list( + new QueryWrapper<VisualChartElement>().lambda().eq(VisualChartElement::getChartId, chartId)); + if (!CollectionUtils.isEmpty(elementList)) { + for (VisualChartElement element : elementList) { + element.setId(null); + element.setChartId(chart.getId()); + } + chartElementService.saveOrUpdateElements(chart.getId(), elementList); + } + } + } + } + + @Override + public void snapshot(HttpServletResponse response, String format, Integer dashboardId, Long start, Long end, + String language, String vars) throws IOException { + // 生成模板 + String snapshotStr = this.genSnapshotByTemplate(dashboardId, start, end, language, vars); + // 目前下载名称由前端控制 + // String downFileName = String.format("%s-%s.%s", "dashboard", dashboard.getName(), + // StrUtil.emptyToDefault(format, "html")); + ResponseUtil.downloadFile(response, "dashboard.html", snapshotStr.getBytes()); + } + + @Override + public String genSnapshotByTemplate(Integer dashboardId, Long start, Long end, String language, String vars) { + VisualDashboard dashboard = this.getById(dashboardId); + if (dashboard == null) { + throw new NZException(RCode.DASHBOARD_NOT_EXIST); + } + // 计算步长 + String step = visualService.getTimeStep(start, end); + // 封装返回结果 + Map<String, Object> resultMap = visualService.snapshotResultMap(start, end, language); + resultMap.put("step", step); + // charts 查询 + Map param = new HashMap<>(); + param.put("pageSize", "-1"); + param.put("dashboardId", dashboard.getId()); + param.put("groupId", 0); + PageUtils chartPageUtils = visualChartService.queryPage(param); + List<VisualChart> chartsList = (List<VisualChart>) chartPageUtils.getList(); + if (Tool.CollUtil.isEmpty(chartsList)) { + throw new NZException(RCode.CHART_NOTEXSITS); + } else { + List<Map> varList = StrUtil.isNotEmpty(vars) ? JSONObject.parseArray(vars, Map.class) + : Tool.ListUtil.empty(); + + // 将chartsData获取任务装入futureList + List<CompletableFuture<Map>> futureList = this.recursionChartsData(chartsList, resultMap, varList); + Map chartsDataMap = new HashMap(); + try { + CompletableFuture completableFuture = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])); + completableFuture.get(timeout,TimeUnit.MILLISECONDS); + } catch (Exception e) { + log.error(e, "snapshot query timeout"); + } + futureList.forEach(future -> { + Map<String, Object> result = future.getNow(null); + if (Tool.MapUtil.isNotEmpty(result)) { + chartsDataMap.put(StrUtil.concat(true, StrUtil.toString(result.get("chartId")), "_", + StrUtil.toString(result.get("eleIndex"))), result); + } + }); + resultMap.put("chartsData", chartsDataMap); + resultMap.remove("step"); + resultMap.put("dashboard", R.ok(dashboard)); + resultMap.put("charts", R.ok(chartPageUtils)); + } + return visualService.replaceSnapshotTemplate(resultMap); + } + + @Override + public List<VisualDashboard> getTemplateSyncDashboard(Integer dashboardId, Integer tmplId, Integer modelId, Integer moduleId) { + if (ObjectUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getId, dashboardId).ne(VisualDashboard::getTmplId, -1)); + return ObjectUtil.isNotEmpty(dashboard) ? ListUtil.of(dashboard) : ListUtil.empty(); + } + + if (ObjectUtil.isNotEmpty(tmplId)) { + List<VisualDashboard> dashboardList = this.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getTmplId, tmplId)); + return CollUtil.defaultIfEmpty(dashboardList, ListUtil.empty()); + } + + if (ObjectUtil.isNotEmpty(modelId)) { + AssetModel model = assetModelService.getOne(new LambdaQueryWrapper<AssetModel>().eq(AssetModel::getId, modelId).isNotNull(AssetModel::getDashboardId)); + if (ObjectUtil.isEmpty(model)) return ListUtil.empty(); + + List<AssetAsset> assetList = assetAssetService.list(new LambdaUpdateWrapper<AssetAsset>().eq(AssetAsset::getModelId, model.getId())); + if (CollUtil.isEmpty(assetList)) return ListUtil.empty(); + + List<Integer> assetIdList = assetList.stream().map(AssetAsset::getId).collect(Collectors.toList()); + List<VisualDashboard> dashboardList = this.list(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ASSET.getValue()) + .in(VisualDashboard::getLink, assetIdList)); + dashboardList.forEach(dashboard -> dashboard.setTmplId(model.getDashboardId())); + return CollUtil.defaultIfEmpty(dashboardList, ListUtil.empty()); + } + + if (ObjectUtil.isNotEmpty(moduleId)) { + MonitorModule module = monitorModuleService.getOne(new LambdaQueryWrapper<MonitorModule>().eq(MonitorModule::getId, moduleId).isNotNull(MonitorModule::getDashboardId)); + if (ObjectUtil.isEmpty(module)) return ListUtil.empty(); + + List<MonitorEndpoint> endpointList = monitorEndpointService.list(new LambdaUpdateWrapper<MonitorEndpoint>().eq(MonitorEndpoint::getModuleId, module.getId())); + if (CollUtil.isEmpty(endpointList)) return ListUtil.empty(); + + List<Integer> endpointIdList = endpointList.stream().map(MonitorEndpoint::getId).collect(Collectors.toList()); + List<VisualDashboard> dashboardList = this.list(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue()) + .in(VisualDashboard::getLink, endpointIdList)); + dashboardList.forEach(dashboard -> dashboard.setTmplId(module.getDashboardId())); + return CollUtil.defaultIfEmpty(dashboardList, ListUtil.empty()); + } + return ListUtil.empty(); + } + + @Override + public VisualDashboard queryDashboardIncludeChartInfo(Integer dashboardId) { + VisualDashboard dashboard = this.getById(dashboardId); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); + + // charts & chart element + List<VisualChart> chartList = visualChartService.queryChartsIncludeElementInfo(dashboardId); + dashboard.setCharts(chartList); + return dashboard; + } + + /** + * 根据 vars 渲染 element 表达式 + * + * @param expr + * @param varList + */ + private String replaceExprByVars(String expr, List<Map> varList) { + if (Tool.CollectionUtil.isEmpty(varList)) + return expr; + // 将 expr $xxx 变量渲染 + for (Map<String, String> map : varList) { + String name = map.get("name"); + String value = map.get("value"); + expr = expr.replaceAll("\\$" + name, value); + } + return expr; + } + + private List<CompletableFuture<Map>> recursionChartsData(List<VisualChart> chartsList, + Map<String, Object> basicQueryParam, List<Map> varList) { + String start = StrUtil.toString(basicQueryParam.get("start")); + String end = StrUtil.toString(basicQueryParam.get("end")); + String step = StrUtil.toString(basicQueryParam.get("step")); + List<CompletableFuture<Map>> futureList = new ArrayList<>(); + + for (VisualChart chart : chartsList) { + String chartName = this.replaceExprByVars(chart.getName(), varList); + chart.setName(chartName); + String datasource = chart.getDatasource(); + if (StrUtil.equals("misc", datasource)) { + if (Tool.CollUtil.isNotEmpty(chart.getChildren())) { + List<CompletableFuture<Map>> callables = this.recursionChartsData(chart.getChildren(), + basicQueryParam, varList); + if (Tool.CollUtil.isNotEmpty(callables)) + futureList.addAll(callables); + } + continue; + } + Map<String, Object> chartParam = (HashMap) chart.getParam(); + if (StrUtil.equals("system", datasource)) { + futureList.add(CompletableFuture.supplyAsync(() -> { + VisualDashboard visualDashboard = this.getById(chart.getDashboardId()); + R ok = R.ok(); + if (StrUtil.equals("assetInfo", chart.getType())) { + ok.put("data", assetAssetService.queryAssetInfo(visualDashboard.getLink())); + } else if (StrUtil.equals("endpointInfo", chart.getType())) { + ok.put("data", monitorEndpointService.queryEndpointEntity(visualDashboard.getLink())); + } else { + cn.hutool.json.JSONObject dataSource = JSONUtil.parseArray(chartParam.get("datasource")) + .getJSONObject(0); + dataSource.set("select", JSONUtil.createArray().put(dataSource.get("select"))); + ok.putAllData(statService.queryAnalyse( + JSONUtil.toBean(JSONUtil.createObj().set("q", dataSource.toString()), Map.class))); + } + ok.put("eleIndex", "0"); + ok.put("chartId", chart.getId()); + return ok; + }, this.getSnapshotThreadPool())); + } else { + if (Tool.CollUtil.isNotEmpty(chart.getElements())) { + Integer eleIndex = 0; + String limit = chartParam.get("limit") == null ? "100" : chartParam.get("limit").toString(); + for (VisualChartElement element : chart.getElements()) { + String indexStr = StrUtil.toString(eleIndex++); + // 将表达式进行变量渲染 + String expr = this.replaceExprByVars(element.getExpression(), varList); + futureList.add(CompletableFuture.supplyAsync(() -> { + JSONObject jsonObject = null; + try { + if (StrUtil.equals("metrics", datasource)) { + jsonObject = promApiService.query_range(expr, start, end, step, + ToolUtil.toStr(chartParam.get("nullType"), null), null); + } else if (StrUtil.equals("logs", datasource)) { + jsonObject = lokiApiService.query_range(expr, start, end, limit, step, null, + "backward", "1", null); + } + jsonObject.put("eleIndex", indexStr); + jsonObject.put("chartId", chart.getId()); + } catch (NZException e) { + log.error(e); + } + return jsonObject; + }, this.getSnapshotThreadPool())); + } + } else { + futureList.add(CompletableFuture.supplyAsync(() -> JSONUtil + .toBean(JSONUtil.createObj().set("eleIndex", 0).set("chartId", chart.getId()), Map.class), + this.getSnapshotThreadPool())); + } + } + } + return futureList; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelImport(String seq) { + List<VisualDashboard> dashboardList = this.list(new QueryWrapper<VisualDashboard>().lambda().eq(VisualDashboard::getType, + DashboardConstant.Type.DASHBOARD.getValue())); + List<Integer> delDashboardIds = dashboardList.stream().filter(dashboard -> seq.equals(dashboard.getSeq())) + .map(VisualDashboard::getId).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(delDashboardIds)) { + // 删除 dashboard + this.remove(new QueryWrapper<VisualDashboard>().lambda().eq(VisualDashboard::getSeq, seq)); + } + + List<VisualChart> delCharts = visualChartService + .list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getSeq, seq)); + if (CollectionUtils.isNotEmpty(delCharts)) { + // 删除 charts + visualChartService.remove(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getSeq, seq)); + } + chartElementService.remove(new QueryWrapper<VisualChartElement>().lambda().eq(VisualChartElement::getSeq, seq)); + } + + @Override + public void export(HttpServletResponse response, Map<String, Object> params) throws IOException { + String maxLine = sysConfigService.getValue(Constant.SYSCONFIG_KEY_EXPORT_MAX_LINE); + long exportMaxLine = Integer.parseInt(StrUtil.emptyToDefault(maxLine, "10000")); + // 导出最大条数限制 + Object limit = params.get(Constant.LIMIT) == null ? Constant.PAGESIZE : params.get(Constant.LIMIT); + Long pageSize = Long.parseLong(limit.toString()); + if (pageSize == -1) { + // 导出所有直接限制 pageSize + params.put(Constant.PAGE, "1"); + params.put(Constant.LIMIT, Long.toString(exportMaxLine)); + } else if (pageSize > exportMaxLine) { + // 分页超过最大限制 则设置最大限制为 系统配置值,和 pageSize == -1 判断区别在于 pageNo + params.put(Constant.LIMIT, Long.toString(exportMaxLine)); + } + // chart type 导出转换为 国际化之后的名称 + List<SysDictEntity> chartTypeList = sysDictService + .list(new LambdaQueryWrapper<SysDictEntity>().eq(SysDictEntity::getType, Constant.DICT_CHART_TYPE)); + Map<String, String> chartTypeAndI18nMap = chartTypeList.stream() + .collect(Collectors.toMap(SysDictEntity::getValue, SysDictEntity::getI18nCode)); + // 导出查询与列表查询一致 + List<VisualDashboard> dashboards = (List<VisualDashboard>) this.queryList(params).getList(); + List<Map<String, Object>> exportDataList = this.handleDashboardExportDataList(dashboards, chartTypeAndI18nMap); + + String fileName = "Dashboard.json"; + File file = FileUtil.writeUtf8String(JSONObject.toJSONString(exportDataList, SerializerFeature.PrettyFormat), Constant.TMP_ROOT_PATH + fileName); + try { + Tool.ResponseUtil.downloadFile(response, fileName, FileUtil.readBytes(file)); + } finally { + if (file != null && file.exists()) file.delete(); + } + } + + private String getChartTemplateConfigKeyByType(String type) { + // 默认 dashboard 类型 + type = StringUtils.isEmpty(type) ? DashboardConstant.Type.DASHBOARD.getValue() : type; + String chartTemplateTyep; + switch (type) { + case "dashboard": { + chartTemplateTyep = Constant.SYSCONFIG_KEY_CHART_EXPORT_HEADER; + break; + } + /* + * case "model": { chartTemplateTyep = + * Constant.SYSCONFIG_KEY_MODEL_CHART_EXPORT_HEADER; break; } + */ + case "asset": + case "template": + case "endpoint": { + chartTemplateTyep = Constant.SYSCONFIG_KEY_ASSET_CHART_EXPORT_HEADER; + break; + } + default: + throw new NZException(RCode.DASHBOARD_CHART_TEMPLATE_TYPE_INCORRECT); + } + return chartTemplateTyep; + } + + private String getUnitDescrByVal(Integer unitVal) { + String unitDescr = null; + for (Map.Entry<String, Integer> entry : Constant.ALERT_RULE_UNIT_MAP.entrySet()) { + if (entry.getValue().equals(unitVal)) { + unitDescr = entry.getKey(); + break; + } + } + return unitDescr; + } + + private Map saveDashboardsFromImportDataList(List<LinkedHashMap> importDataList, List<String> headerInfos, List<String> chartHeaderInfos, Map<String, Object> params) { + String seq = StrUtil.uuid(); + params.put("seq", seq); + // 已存在的内容处理方式,可选值:0:错误 error 1:覆盖 override 2:忽略 ignore + String existed = Tool.ObjectUtil.defaultIfEmpty((String) params.get("existed"), "1"); + + // 创建导入校验对象 + ImportValidateUtil validateUtil = ImportValidateUtil.builder() + .existed(existed).headerInfos(headerInfos) + .build(); + + Integer addNum = 0, updateNum = 0; + String type = ToolUtil.toStr(params.get("type")); + // 记录导入失败内容 + List<Map<String, Object>> failContentList = ListUtil.list(true); + + Integer dashboardMaxWeight; + List<VisualDashboard> dashboardTypeDashboardList = this.list(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, type)); + if (CollectionUtils.isEmpty(dashboardTypeDashboardList)) { + dashboardMaxWeight = 0; + } else { + VisualDashboard endDashboard = dashboardTypeDashboardList.stream().max(Comparator.comparingInt(VisualDashboard::getWeight)) + .get(); + dashboardMaxWeight = endDashboard.getWeight(); + } + + // 查询 chart datasource类型防止频繁查库 + List<SysDictEntity> chartDatasources = sysDictService.list( + new QueryWrapper<SysDictEntity>().lambda().eq(SysDictEntity::getType, Constant.DICT_CHART_DATASOURCE)); + List<String> datasources = chartDatasources.stream().map(SysDictEntity::getValue).collect(Collectors.toList()); + + // chart 导入 Type 是国际化后的,这里统一获取 chart type 可读名称 & 真实 type 值 + Map<String, String> typeReadableNameMap = this.getChartTypeReadableNameMap(); + + for (int i = 0; i < importDataList.size(); i++) { + Map<String, Object> dataMap = importDataList.get(i); + Integer lineNum = i + 1; + // name, 以 name作为索引 标识该条记录是否存在 + String dashboardName = ToolUtil.toStr(dataMap.get(DashboardImportEnum.NAME.getName())); + validateUtil.validateRequired(dashboardName, lineNum, DashboardImportEnum.NAME.getIndex()); + boolean indexDuplicate = false; + // 同类型下 name 不可重复 + VisualDashboard oldDashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, type).eq(VisualDashboard::getName, dashboardName)); + if(oldDashboard != null) { + indexDuplicate = true; + if(!StrUtil.equals("1", existed)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_DUPLICATE.setParam(DashboardImportEnum.NAME.getIndex())); + } + } + // 索引列重复 & 忽略标识,提示忽略本行 + if (BooleanUtil.and(indexDuplicate, StrUtil.equals("2", existed))) { + validateUtil.ignoreThisRow(lineNum, DashboardImportEnum.NAME.getIndex()); + failContentList.add(dataMap); + continue; + } + VisualDashboard dashboard = new VisualDashboard(); + String dashboardType = ToolUtil.toStr(dataMap.get(DashboardImportEnum.TYPE.getName())); + validateUtil.validateRequired(dashboardType, lineNum, DashboardImportEnum.TYPE.getIndex()); + validateUtil.validateEnumValArr(dashboardType, ListUtil.of(type), lineNum, DashboardImportEnum.TYPE.getIndex()); + + String varType = ToolUtil.toStr(dataMap.get(DashboardImportEnum.VARTYPE.getName())); + validateUtil.validateRequired(varType, lineNum, DashboardImportEnum.VARTYPE.getIndex()); + if(StrUtil.equalsIgnoreCase(ToolUtil.toStr(type), DashboardConstant.Type.DASHBOARD.getValue())){ + validateUtil.validateEnumValArr(varType, ListUtil.of("0"), lineNum, DashboardImportEnum.VARTYPE.getIndex()); + } else { + List<DashboardConstant.VariableType> variableTypes = Arrays.asList(DashboardConstant.VariableType.values()); + List<String> variableTypeValues = variableTypes.stream().map(variableType -> StrUtil.toString(variableType.getValue())).collect(Collectors.toList()); + validateUtil.validateEnumValArr(varType, variableTypeValues, lineNum, DashboardImportEnum.VARTYPE.getIndex()); + } + + Object dashboardParam = dataMap.get(DashboardImportEnum.PARAM.getName()); + if(ToolUtil.isNotEmpty(dashboardParam)){ + dashboard.setParam(dashboardParam); + RCode rCode = this.validateDashboardParam(dashboard); + if(rCode != null){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_SUPPORT.setParam(DashboardImportEnum.PARAM.getIndex())); + log.error("Dashboard " + dashboardName + " import param error: " + rCode.getMsg()); + } + } + + String remark = ToolUtil.toStr(dataMap.get(DashboardImportEnum.REMARK.getName())); + + String charts = ToolUtil.toStr(dataMap.get(DashboardImportEnum.CHARTS.getName())); + List<VisualChart> chartList = null; + if(StrUtil.isNotEmpty(charts)){ + boolean isJsonArray = validateUtil.validateJsonArray(charts, lineNum, DashboardImportEnum.CHARTS.getIndex()); + if(isJsonArray){ + List<String> groupNames; + if(oldDashboard == null){ + groupNames = ListUtil.list(false); + } else { + List<VisualChart> visualCharts = visualChartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getDashboardId, oldDashboard.getId()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE)); + groupNames = visualCharts.stream().map(VisualChart::getName).collect(Collectors.toList()); + } + chartList = this.validateDashboardCharts(charts, dashboardName, dashboardType, groupNames, typeReadableNameMap, lineNum, chartHeaderInfos, datasources, validateUtil, existed); + } else { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(DashboardImportEnum.CHARTS.getIndex())); + } + } + + String children = ToolUtil.toStr(dataMap.get(DashboardImportEnum.CHILDREN.getName())); + List<VisualDashboard> childrenList = null; + if(StrUtil.isNotEmpty(children)){ + boolean isJsonArray = validateUtil.validateJsonArray(children, lineNum, DashboardImportEnum.CHILDREN.getIndex()); + if(isJsonArray){ + childrenList = this.validateDashboardChildren(children, dashboardName, type, dashboardMaxWeight, typeReadableNameMap, lineNum, headerInfos, chartHeaderInfos, datasources, validateUtil, existed); + } else { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(DashboardImportEnum.CHILDREN.getIndex())); + } + } + + // 遇到错误是否继续导入,可选值: 0:不继续 1:继续 默认值:1 + String ignoreError = Tool.ObjectUtil.defaultIfEmpty((String) params.get("ignoreError"), "1"); + + List<Map<String, String>> errMsgForThisLine = validateUtil.getImportErrMsgForThisLine(lineNum); + if (BooleanUtil.and(Tool.StrUtil.equals("0", ignoreError), Tool.CollUtil.isNotEmpty(errMsgForThisLine))) { + // 结束本次导入,自导入行开始 到结尾数据行,提示错误信息 + for (int j = i; j < importDataList.size(); j++) { + validateUtil.recordImportAttrErr(j + 1, RCode.IMPORT_ERROR_STOP); + failContentList.add(importDataList.get(j)); + } + break; + } + + if (Tool.CollUtil.isEmpty(errMsgForThisLine)) { + dashboard.setName(dashboardName); + dashboard.setType(dashboardType); + dashboard.setVarType(Integer.valueOf(varType)); + dashboard.setRemark(remark); + dashboard.setWeight(++dashboardMaxWeight); + dashboard.setUts(System.currentTimeMillis()); + dashboard.setCreateBy(ShiroUtils.getUserId().intValue()); + dashboard.setSeq(seq); + dashboard.setPid(0); + dashboard.setChildren(childrenList); + dashboard.setCharts(chartList); + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition()); + try { + this.saveOrUpdateRowData(dashboard, params); + dataSourceTransactionManager.commit(transactionStatus); + // save or update + Object saveFlag = params.get("save"); + if (ObjectUtil.isNotNull(saveFlag)) { + addNum++; + } else { + updateNum++; + } + } catch (Exception e) { + failContentList.add(dataMap); + dataSourceTransactionManager.rollback(transactionStatus); + validateUtil.recordImportAttrErr(lineNum, RCode.ERROR); + log.error("Dashboard import roll back the transaction failure", e); + } + } else { + failContentList.add(dataMap); + } + } + + String failedContentFileBase64Str = null; + File tmplFile = null; + try { + tmplFile = TempFile.createTempFile("json-template", ".json"); + FileUtil.writeUtf8String(JSONObject.toJSONString(failContentList, SerializerFeature.PrettyFormat), tmplFile); + failedContentFileBase64Str = Base64.encode(tmplFile); + } catch (IOException e) { + log.error(e, "Could not create temporary file: " + tmplFile); + } finally { + if(tmplFile != null && !tmplFile.delete()) { + log.error(new IOException("Could not delete temporary file after processing: " + tmplFile)); + } + } + + // 返回统计信息 + Map<Object, Object> statMap = Tool.MapUtil.builder() + .put("seq", seq) + .put("totalNum", importDataList.size()) + .put("successNum", addNum + updateNum) + .put("failNum", failContentList.size()) + .put("addNum", addNum) + .put("updateNum", updateNum) + .put("failDetail", validateUtil.getImportErrMsg()) + .put("failContent", failedContentFileBase64Str) + .build(); + return statMap; + } + + public List<VisualDashboard> validateDashboardChildren(String children, String parentName, String type, Integer dashboardMaxWeight, Map<String, String> typeReadableNameMap, int lineNum, + List<String> headerInfos, List<String> chartHeaderInfos, List<String> datasources, ImportValidateUtil validateUtil, String existed){ + cn.hutool.json.JSONArray dashboardArray = JSONUtil.parseArray(children); + if(CollectionUtils.isEmpty(dashboardArray)){ + return null; + } + List<VisualDashboard> dashboardList = new ArrayList<>(); + for (int i = 0; i < dashboardArray.size(); i++) { + Map dataMap = dashboardArray.getBean(i, Map.class); + // name, 以 name作为索引 标识该条记录是否存在 + String dashboardName = ToolUtil.toStr(dataMap.get(DashboardImportEnum.NAME.getName())); + String validaName = parentName + "/" + dashboardName + " "; + if(StrUtil.isEmpty(dashboardName)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + headerInfos.get(DashboardImportEnum.NAME.getIndex()))); + } + // 同类型下 name 不可重复 + VisualDashboard oldDashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, type).eq(VisualDashboard::getName, dashboardName)); + if (oldDashboard != null && !StrUtil.equals("1", existed)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_DUPLICATE.setParam(validaName + headerInfos.get(DashboardImportEnum.NAME.getIndex()))); + } + VisualDashboard dashboard = new VisualDashboard(); + String dashboardType = ToolUtil.toStr(dataMap.get(DashboardImportEnum.TYPE.getName())); + if(StrUtil.isEmpty(dashboardType)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + headerInfos.get(DashboardImportEnum.TYPE.getIndex()))); + } + if(!StrUtil.equals(dashboardType, type)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + headerInfos.get(DashboardImportEnum.TYPE.getIndex()))); + } + + String varType = ToolUtil.toStr(dataMap.get(DashboardImportEnum.VARTYPE.getName())); + if(StrUtil.isEmpty(varType)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + headerInfos.get(DashboardImportEnum.VARTYPE.getIndex()))); + } + if (StrUtil.equalsIgnoreCase(ToolUtil.toStr(type), DashboardConstant.Type.DASHBOARD.getValue())) { + if(!StrUtil.equals(varType, "0")){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + headerInfos.get(DashboardImportEnum.VARTYPE.getIndex()))); + } + } else if(!ListUtil.of("1", "2").contains(varType)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + headerInfos.get(DashboardImportEnum.VARTYPE.getIndex()))); + } + + Object dashboardParam = dataMap.get(DashboardImportEnum.PARAM.getName()); + if (ToolUtil.isNotEmpty(dashboardParam)) { + dashboard.setParam(dashboardParam); + RCode rCode = this.validateDashboardParam(dashboard); + if (rCode != null) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_SUPPORT.setParam(validaName + headerInfos.get(DashboardImportEnum.PARAM.getIndex()))); + log.error("Dashboard child " + validaName + " param import error: " + rCode.getMsg()); + } + } + + String remark = ToolUtil.toStr(dataMap.get(DashboardImportEnum.REMARK.getName())); + + String charts = ToolUtil.toStr(dataMap.get(DashboardImportEnum.CHARTS.getName())); + List<VisualChart> chartList = null; + if (StrUtil.isNotEmpty(charts)) { + boolean isJsonArray = validateUtil.validateJsonArray(charts, lineNum, DashboardImportEnum.CHARTS.getIndex()); + if (isJsonArray) { + List<String> groupNames; + if (oldDashboard == null) { + groupNames = ListUtil.list(false); + } else { + List<VisualChart> visualCharts = visualChartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getDashboardId, oldDashboard.getId()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE)); + groupNames = visualCharts.stream().map(VisualChart::getName).collect(Collectors.toList()); + } + chartList = this.validateDashboardCharts(charts, parentName + "/" + dashboardName, dashboardType, groupNames, typeReadableNameMap, lineNum, chartHeaderInfos, datasources, validateUtil, existed); + } else { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + headerInfos.get(DashboardImportEnum.CHARTS.getIndex()))); + } + } + dashboard.setName(dashboardName); + dashboard.setType(dashboardType); + dashboard.setVarType(Integer.valueOf(varType)); + dashboard.setRemark(remark); + dashboard.setWeight(++dashboardMaxWeight); + dashboard.setUts(System.currentTimeMillis()); + dashboard.setCreateBy(ShiroUtils.getUserId().intValue()); + dashboard.setCharts(chartList); + dashboardList.add(dashboard); + } + return dashboardList; + } + + public List<VisualChart> validateDashboardCharts(String charts, String parentName, String dashboardType, List<String> groupNames, Map<String, String> typeReadableNameMap, int lineNum, + List<String> chartHeaderInfos, List<String> datasources, ImportValidateUtil validateUtil, String existed){ + cn.hutool.json.JSONArray chartsArray = JSONUtil.parseArray(charts); + List<VisualChart> chartList = new ArrayList<>(); + for (int i = 0; i < chartsArray.size(); i++) { + Map chartMap = chartsArray.getBean(i, Map.class); + VisualChart visualChart = new VisualChart(); + boolean typeFlag = true; + + String name = ToolUtil.toStr(chartMap.get(ChartsImportEnum.NAME.getName())); + String validaName = parentName + "/" + name + " "; + if(StrUtil.isEmpty(name)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(parentName + "/ " + chartHeaderInfos.get(ChartsImportEnum.NAME.getIndex()))); + } else if (name.length() > 64) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.NAME.getIndex()))); + } + String span = ToolUtil.toStr(chartMap.get(ChartsImportEnum.SPAN.getName())); + if(StrUtil.isEmpty(span)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.SPAN.getIndex()))); + } else { + Double width = null; + try { + width = Double.valueOf(span); + visualChart.setSpan(width); + } catch (NumberFormatException e) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.SPAN.getIndex()))); + } + if (width != null && (width < 1 || width > 12)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.SPAN.getIndex()))); + } + } + String height = ToolUtil.toStr(chartMap.get(ChartsImportEnum.HEIGHT.getName())); + if(StrUtil.isEmpty(height)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.HEIGHT.getIndex()))); + } else { + Double heightIntVal = null; + try { + heightIntVal = Double.valueOf(height); + visualChart.setHeight(heightIntVal); + } catch (NumberFormatException e) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.HEIGHT.getIndex()))); + } + if (heightIntVal != null && (heightIntVal < 1 || heightIntVal > 12)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.HEIGHT.getIndex()))); + } + } + String type = ToolUtil.toStr(chartMap.get(ChartsImportEnum.TYPE.getName())); + if(StrUtil.isEmpty(type)){ + typeFlag = false; + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.TYPE.getIndex()))); + } else { + type = typeReadableNameMap.get(type); + if(StrUtil.isEmpty(type)){ + typeFlag = false; + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.TYPE.getIndex()))); + } else if(StrUtil.equals(type, Constant.CHART_GROUP_TYPE)){ + if (groupNames.contains(name)) { + // chart group 不允许重复 + if(!StrUtil.equals("1", existed)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_DUPLICATE.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.NAME.getIndex()))); + } + } else { + groupNames.add(name); + } + + String children = ToolUtil.toStr(chartMap.get(ChartsImportEnum.CHILDREN.getName())); + if(StrUtil.isNotEmpty(children)){ + boolean isJsonArray = validateUtil.validateJsonArray(children, lineNum, DashboardImportEnum.CHARTS.getIndex()); + if(isJsonArray){ + List<VisualChart> childrenList = this.validateDashboardCharts(children, parentName + "/" + name, dashboardType, groupNames, typeReadableNameMap, lineNum, chartHeaderInfos, datasources, validateUtil, existed); + visualChart.setChildren(childrenList); + } else { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.CHILDREN.getIndex()))); + } + } + } + } + String unit = ToolUtil.toStr(chartMap.get(ChartsImportEnum.UNIT.getName())); + if (StringUtils.isNotEmpty(unit)) { + Integer unitInt = Constant.ALERT_RULE_UNIT_MAP.get(unit); + if (ToolUtil.isEmpty(unitInt)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.UNIT.getIndex()))); + } + visualChart.setUnit(unitInt); + } else { + visualChart.setUnit(Constant.ALERT_RULE_UNIT_MAP.get("short")); + } + String weight = ToolUtil.toStr(chartMap.get(ChartsImportEnum.WEIGHT.getName())); + if(StrUtil.isEmpty(weight)){ + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.WEIGHT.getIndex()))); + } else { + try { + Integer weightIntVal = Integer.valueOf(weight); + visualChart.setWeight(weightIntVal); + } catch (NumberFormatException e) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.WEIGHT.getIndex()))); + } + } + String param = ToolUtil.toStr(chartMap.get(ChartsImportEnum.PARAM.getName())); + if (typeFlag) { + String msg = this.validateChartParamForImport(type, param, dashboardType); + if (StrUtil.isNotEmpty(msg)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_SUPPORT.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.PARAM.getIndex()))); + log.error("Dashboard chart " + validaName + " param import error: " + msg); + } + } + String remark = ToolUtil.toStr(chartMap.get(ChartsImportEnum.REMARK.getName())); + String x = ToolUtil.toStr(chartMap.get(ChartsImportEnum.X.getName())); + if (StringUtils.isEmpty(x)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.X.getIndex()))); + } else { + Double xIntVal = null; + try { + xIntVal = Double.valueOf(x); + visualChart.setX(xIntVal); + } catch (NumberFormatException e) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.X.getIndex()))); + } + if (xIntVal != null && (xIntVal < 0 || xIntVal > 12)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.X.getIndex()))); + } + } + + // x和width之和不能大于12 + if (StringUtils.isNotEmpty(x) && StringUtils.isNotEmpty(span)) { + Double xVal = Double.valueOf(x); + Double widthVal = Double.valueOf(span); + if (xVal + widthVal > 12) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.SPAN.getIndex()) + "," + chartHeaderInfos.get(ChartsImportEnum.X.getIndex()))); + } + } + + String y = ToolUtil.toStr(chartMap.get(ChartsImportEnum.Y.getName())); + if (StringUtils.isEmpty(y)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FORMAT_ERROR.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.Y.getIndex()))); + } else { + try { + Double yIntVal = Double.valueOf(y); + visualChart.setY(yIntVal); + } catch (NumberFormatException e) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.Y.getIndex()))); + } + } + + String datasource = ToolUtil.toStr(chartMap.get(ChartsImportEnum.DATASOURCE.getName())); + if (StringUtils.isEmpty(datasource)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_REQUIRED.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.DATASOURCE.getIndex()))); + } else { + if (!datasources.contains(datasource)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_WITHIN_REASON.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.DATASOURCE.getIndex()))); + } + } + + String elements = ToolUtil.toStr(chartMap.get(ChartsImportEnum.ELEMENTS.getName())); + if (typeFlag) { + String msg = this.validateChartElementForImport(datasource, elements); + if (StrUtil.isNotEmpty(msg)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_NOT_SUPPORT.setParam(validaName + chartHeaderInfos.get(ChartsImportEnum.ELEMENTS.getIndex()))); + log.error("Dashboard chart " + validaName + " elements import error: " + msg); + } else { + List<VisualChartElement> elementsList = JSONArray.parseArray(elements, VisualChartElement.class); + visualChart.setElements(elementsList); + } + } + visualChart.setName(name); + visualChart.setType(type); + visualChart.setParam(param); + visualChart.setRemark(remark); + visualChart.setDatasource(datasource); + visualChart.setUpdateBy((ShiroUtils.getUserId()).intValue()); + visualChart.setUpdateAt(new Date()); + chartList.add(visualChart); + } + return chartList; + } + + private String validateChartElementForImport(String datasource, String elements) { + // datasource类型为metrics logs的需要校验elements + if (datasource.equals(Constant.ChartDatasourceType.METRICS.getValue()) + || datasource.equals(Constant.ChartDatasourceType.LOGS.getValue())) { + if (StringUtils.isEmpty(elements)) { + return RCode.CHART_ELEMENT_ISNULL.getMsg(); + } + List<VisualChartElement> elementsList = null; + try { + elementsList = JSONArray.parseArray(elements, VisualChartElement.class); + } catch (JSONException e) { + return RCode.CHART_ELEMENTS_FORMAT.getMsg(); + } + + if (CollectionUtils.isEmpty(elementsList)) { + return RCode.CHART_ELEMENT_ISNULL.getMsg(); + } + + for (VisualChartElement element : elementsList) { + if (ToolUtil.isEmpty(element.getExpression())) { + return RCode.CHARTELEMENT_EXPRESSION_ISNULL.getMsg(); + } + if (ToolUtil.isEmpty(element.getName())) { + return RCode.CHARTELEMENT_NAME_ISNULL.getMsg(); + } + } + } + return ""; + } + + private String validateChartParamForImport(String type, String param, String dashboardType) { + switch (type) { + // url + case Constant.CHART_URL_TYPE: { + if (StringUtils.isEmpty(param)) { + return RCode.CHART_URLPARAM_ISNULL.getMsg(); + } + Map map = null; + try { + map = JSONObject.parseObject(param, Map.class); + } catch (JSONException e) { + return RCode.CHART_PARAM_FORMAT.getMsg(); + } + Object url = map.get(Constant.CHART_URL_TYPE); + if (ToolUtil.isEmpty(url)) { + return RCode.CHART_URLPARAM_ISNULL.getMsg(); + } + + if (StrUtil.equals(DashboardConstant.Type.TEMPLATE.getValue(), dashboardType)) { + // 替换全部变量 替换为 a(任意字符) 不影响原来的数据格式 然后进行校验 + String urlStr = url.toString(); + urlStr = urlStr.replaceAll("\\{\\{asset\\..*?\\}\\}", "a"); + + boolean b = CommonUtils.checkUrlInModel(urlStr); + boolean b1 = CommonUtils.checkUrl(urlStr); + + if (!b && !b1) { + return RCode.CHART_PARAMURL_FORMAT.getMsg(); + } + } else { + if (!CommonUtils.checkUrl(url.toString())) { + return RCode.CHART_PARAMURL_FORMAT.getMsg(); + } + } + break; + } + // singleStat + case Constant.CHART_SINGLESTAT_TYPE: { + if (StringUtils.isEmpty(param)) { + return RCode.CHART_SINGLESTATPARAM_ISNULL.getMsg(); + } + Map map = null; + try { + map = JSONObject.parseObject(param, Map.class); + } catch (JSONException e) { + return RCode.CHART_PARAM_FORMAT.getMsg(); + } + Object statistics = map.get(Constant.CHART_SINGLESTAT_PARAMkEY); + if (ToolUtil.isEmpty(statistics)) { + return RCode.CHART_PARAMSINGLESTAT_ISNULL.getMsg(); + } + if (!Constant.CHART_SINGLESTAT_STATISTICS.contains(statistics.toString())) { + return RCode.CHART_PARAMSINGLESTAT_INVALIDE.getMsg(); + } + break; + } + case Constant.CHART_TEXT_TYPE: { + if (StringUtils.isEmpty(param)) { + return RCode.CHART_TEXTPARAM_ISNULL.getMsg(); + } + Map map = null; + try { + map = JSONObject.parseObject(param, Map.class); + } catch (JSONException e) { + return RCode.CHART_PARAM_FORMAT.getMsg(); + } + Object text = map.get(Constant.CHART_TEXT_TYPE); + if (ToolUtil.isEmpty(text)) { + return RCode.CHART_TEXTPARAM_ISNULL.getMsg(); + } + break; + } + default: { + if (StringUtils.isNotEmpty(param)) { + try { + JSONObject.parseObject(param, Map.class); + } catch (JSONException e) { + return RCode.CHART_PARAM_FORMAT.getMsg(); + } + } + } + } + return ""; + } + + private void saveOrUpdateRowData(VisualDashboard dashboard, Map<String, Object> params) { + MapUtil.removeAny(params, "save", "update"); + String seq = params.get("seq").toString(); + + // 已存在的内容处理方式,可选值:0:错误 error 1:覆盖 override 2:忽略 ignore 在此只需要处理更新即可 + String existed = Tool.ObjectUtil.defaultIfEmpty((String) params.get("existed"), "1"); + VisualDashboard oldDashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, dashboard.getType()).eq(VisualDashboard::getName, dashboard.getName())); + + if (StrUtil.equals("1", existed) && oldDashboard != null) { + params.put("update", true); + // update + dashboard.setId(oldDashboard.getId()); + dashboard.setWeight(oldDashboard.getWeight()); + this.updateById(dashboard); + + // update Report Config In Redis + this.updateReportConfigInRedis(oldDashboard, dashboard); + } else { + params.put("save", true); + // insert + this.save(dashboard); + + // add Report Config In Redis + this.addReportConfigInRedis(dashboard); + + // add assetInfo or endpointInfo chart + this.addLinkObjectInfoChart(dashboard); + } + + this.importSaveCharts(dashboard.getCharts(), 0, dashboard.getId(), seq); + this.importSaveChildPane(dashboard.getChildren(), dashboard.getId(), seq, existed); + } + + private void importSaveChildPane(List<VisualDashboard> childDashboardList, Integer dashboardId, String seq, String existed){ + if(CollectionUtils.isEmpty(childDashboardList) || dashboardId == null) { + return; + } + for (VisualDashboard dashboard : childDashboardList) { + dashboard.setSeq(seq); + dashboard.setPid(dashboardId); + VisualDashboard oldDashboard = this.getOne(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, dashboard.getType()).eq(VisualDashboard::getName, dashboard.getName())); + if (StrUtil.equals("1", existed) && oldDashboard != null) { + dashboard.setId(oldDashboard.getId()); + dashboard.setWeight(oldDashboard.getWeight()); + this.updateById(dashboard); + } else { + this.save(dashboard); + } + this.importSaveCharts(dashboard.getCharts(), 0, dashboard.getId(), seq); + } + } + + private void importSaveCharts(List<VisualChart> visualChart, Integer groupId, Integer dashboardId, String seq){ + if(CollectionUtils.isEmpty(visualChart) || dashboardId == null) { + return; + } + for (VisualChart chart : visualChart) { + boolean isGroup = false; + chart.setSeq(seq); + chart.setDashboardId(dashboardId); + chart.setUpdateAt(new Date()); + chart.setUpdateBy((ShiroUtils.getUserId()).intValue()); + chart.setGroupId(groupId); + if(StrUtil.equals(chart.getType(), Constant.CHART_GROUP_TYPE)){ + isGroup = true; + VisualChart oldChart = visualChartService.getOne(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getDashboardId, dashboardId) + .eq(VisualChart::getType, chart.getType()).eq(VisualChart::getName, chart.getName())); + if(oldChart != null){ + chart.setId(oldChart.getId()); + visualChartService.updateById(chart); + } + } + if(chart.getId() == null){ + visualChartService.save(chart); + } + + List<VisualChartElement> chartElements = chart.getElements(); + if (CollectionUtils.isNotEmpty(chartElements)) { + chartElements.forEach(chartElement -> { + chartElement.setChartId(chart.getId()); + chartElement.setSeq(seq); + chartElement.setType(Constant.CHART_ELEMENT_EXPERT_TYPE); + }); + chartElementService.saveBatch(chartElements); + } + if(isGroup){ + this.importSaveCharts(chart.getChildren(), chart.getId(), dashboardId, seq); + } + } + } + /** + * chart 导入 Type 是国际化后的,这里统一获取 chart type 可读名称 & 真实 type 值 + * + * @return + */ + private Map<String, String> getChartTypeReadableNameMap() { + List<SysDictEntity> chartTypeList = sysDictService.list(new LambdaQueryWrapper<SysDictEntity>().eq(SysDictEntity::getType, Constant.DICT_CHART_TYPE)); + Map<String, String> chartTypeI18nCodeAndValueMap = chartTypeList.stream() + .filter(sysDict -> StrUtil.isNotEmpty(sysDict.getI18nCode())) + .collect(Collectors.toMap(SysDictEntity::getI18nCode, SysDictEntity::getValue)); + + Map<String, String> map = Tool.MapUtil.newHashMap(); + + for (Map.Entry<String, String> entry : chartTypeI18nCodeAndValueMap.entrySet()) { + // chart type i18n code + String i18nCode = entry.getKey(); + // chart type real + String type = entry.getValue(); + + String chartReadableName = sysI18nService.queryValue(i18nCode); + map.put(chartReadableName, type); + } + return map; + } + + private List<Map<String, Object>> handleDashboardExportDataList(List<VisualDashboard> dashboardList, Map<String, String> chartTypeAndI18nMap) { + if(CollectionUtils.isEmpty(dashboardList)){ + return ListUtil.empty(); + } + List<Map<String, Object>> exportDataList = new ArrayList<>(); + Map<String, Object> tempMap; + for (VisualDashboard dashboard : dashboardList) { + if (dashboard == null) continue; + tempMap = new LinkedHashMap<>(); + tempMap.put(DashboardImportEnum.NAME.getName(), dashboard.getName()); + tempMap.put(DashboardImportEnum.TYPE.getName(), dashboard.getType()); + tempMap.put(DashboardImportEnum.VARTYPE.getName(), dashboard.getVarType()); + tempMap.put(DashboardImportEnum.PARAM.getName(), dashboard.getParam()); + tempMap.put(DashboardImportEnum.REMARK.getName(), dashboard.getRemark()); + // chartParams 不可复用 + Map<String, Object> chartParams = Tool.MapUtil.newHashMap(); + chartParams.put("returnChildren", "1"); + chartParams.put("groupId", 0); + chartParams.put("pageSize", "-1"); + chartParams.put("dashboardId", dashboard.getId()); + List<VisualChart> childChartList = (List<VisualChart>) visualChartService.queryPage(chartParams).getList(); + tempMap.put(DashboardImportEnum.CHARTS.getName(), this.handleChartsExportDataList(childChartList, chartTypeAndI18nMap)); + tempMap.put(DashboardImportEnum.CHILDREN.getName(), this.handleDashboardExportDataList(dashboard.getChildren(), chartTypeAndI18nMap)); + exportDataList.add(tempMap); + } + return exportDataList; + } + + private List<Map> handleChartsExportDataList(List<VisualChart> charts, Map<String, String> chartTypeAndI18nMap) { + if (CollectionUtils.isEmpty(charts)) { + return null; + } + List<Map> chartsMap = Tool.ListUtil.list(false); + Map tempMap; + for (VisualChart pChart : charts) { + // do not export type assetInfo & endpointInfo chart + if (StrUtil.equalsAny(pChart.getType(), Constant.CHART_ASSETINFO_TYPE, Constant.CHART_ENDPOINTINFO_TYPE)) { + continue; + } + tempMap = new LinkedHashMap<>(); + tempMap.put(ChartsImportEnum.NAME.getName(), pChart.getName()); + tempMap.put(ChartsImportEnum.SPAN.getName(), ObjectUtil.defaultIfNull(pChart.getSpan(), "").toString()); + tempMap.put(ChartsImportEnum.HEIGHT.getName(), ObjectUtil.defaultIfNull(pChart.getHeight(), "").toString()); + String chartType = pChart.getType(); + String typeI18nCode = chartTypeAndI18nMap.get(chartType); + tempMap.put(ChartsImportEnum.TYPE.getName(), sysI18nService.queryValue(typeI18nCode)); + if (StrUtil.equals(Constant.CHART_TEXT_TYPE, chartType)) { + tempMap.put(ChartsImportEnum.UNIT.getName(), ""); + } else { + tempMap.put(ChartsImportEnum.UNIT.getName(), this.getUnitDescrByVal(pChart.getUnit())); + } + tempMap.put(ChartsImportEnum.WEIGHT.getName(), pChart.getWeight()); + tempMap.put(ChartsImportEnum.PARAM.getName(), pChart.getParam()); + tempMap.put(ChartsImportEnum.REMARK.getName(), pChart.getRemark()); + tempMap.put(ChartsImportEnum.X.getName(), ObjectUtil.defaultIfNull(pChart.getX(), "").toString()); + tempMap.put(ChartsImportEnum.Y.getName(), ObjectUtil.defaultIfNull(pChart.getY(), "").toString()); + tempMap.put(ChartsImportEnum.ELEMENTS.getName(), this.handleChartElementForExport(pChart.getElements())); + tempMap.put(ChartsImportEnum.DATASOURCE.getName(), pChart.getDatasource()); + tempMap.put(ChartsImportEnum.CHILDREN.getName(), this.handleChartsExportDataList(pChart.getChildren(), chartTypeAndI18nMap)); + chartsMap.add(tempMap); + } + return chartsMap; + } + + private List<Map> handleChartElementForExport(List<VisualChartElement> chartElements) { + if (CollectionUtils.isEmpty(chartElements)) { + return null; + } + List<Map> handleMaps = new ArrayList<>(); + Map tempMap; + for (VisualChartElement element : chartElements) { + tempMap = new LinkedHashMap(4); + tempMap.put("expression", element.getExpression()); + tempMap.put("state", element.getState()); + if (ToolUtil.isNotEmpty(element.getLegend())) { + tempMap.put("legend", element.getLegend()); + } + if (ToolUtil.isNotEmpty(element.getName())) { + tempMap.put("name", element.getName()); + } + handleMaps.add(tempMap); + } + return handleMaps; + } + + private synchronized ExecutorService getSnapshotThreadPool() { + if (snapshotThreadPool == null) { + snapshotThreadPool = new ThreadPoolExecutor(snapshotCorePoolSize, snapshotConcurrency, + snapshotKeepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(snapshotCapacity), + new NamedThreadFactory("SNAPSHOT-", true)); + } + return snapshotThreadPool; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualExpreTmplServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualExpreTmplServiceImpl.java index 9c88614d..cb126129 100644 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualExpreTmplServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualExpreTmplServiceImpl.java @@ -1,4 +1,4 @@ -package com.nis.modules.panel.service.impl; +package com.nis.modules.dashboard.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.ListUtil; @@ -17,19 +17,20 @@ import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.Dc; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.asset.service.DcService; +import com.nis.modules.dashboard.dao.VisualExpreTmplDao; +import com.nis.modules.dashboard.entity.ExprTmplImportEnum; +import com.nis.modules.dashboard.entity.VisualExpressionTmpl; +import com.nis.modules.dashboard.service.VisualExpreTmplService; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.service.MonitorEndpointService; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.dao.VisualExpreTmplDao; -import com.nis.modules.panel.entity.ExprTmplImportEnum; -import com.nis.modules.panel.entity.VisualExpressionTmpl; -import com.nis.modules.panel.service.VisualExpreTmplService; import com.nis.modules.project.entity.MonitorProject; import com.nis.modules.project.service.MonitorProjectService; import com.nis.modules.sys.service.BasicImportAndExportServices; import com.nis.modules.sys.service.SysConfigService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -286,6 +287,9 @@ public class VisualExpreTmplServiceImpl extends ServiceImpl<VisualExpreTmplDao, // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveTmplsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -372,7 +376,7 @@ public class VisualExpreTmplServiceImpl extends ServiceImpl<VisualExpreTmplDao, } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_EXPRETMPL_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualServiceImpl.java new file mode 100644 index 00000000..7e39e8de --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/service/impl/VisualServiceImpl.java @@ -0,0 +1,938 @@ +package com.nis.modules.dashboard.service.impl; + +import cn.hutool.cache.impl.TimedCache; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.thread.NamedThreadFactory; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.*; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.agent.service.LokiApiService; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualChartElement; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualChartElementService; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.stat.service.impl.StatServiceImpl; +import com.nis.modules.sys.entity.Timezone; +import com.nis.modules.sys.service.SysConfigService; +import com.nis.modules.sys.service.TimezoneService; +import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.lang3.time.StopWatch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.stream.Collectors; + +@Service("visualService") +public class VisualServiceImpl implements VisualService { + + private final static Log log = Log.get(); + + @Value("${connect.timeout:30000}") + private Integer connectTimeout; + + /** + * dashboard snapshot 查询超时时间,单位:ms + */ + @Value("${dashboard.snapshot.timeout:300000}") + private Integer timeout; + + @Value("${snapshot.corePoolSize:5}") + private Integer snapshotCorePoolSize; + + @Value("${snapshot.concurrency:10}") + private Integer snapshotConcurrency; + + @Value("${snapshot.keepAliveTime:30}") + private Long snapshotKeepAliveTime; + + @Value("${snapshot.capacity:10000}") + private Integer snapshotCapacity; + + @Autowired + private SysConfigService sysConfigService; + + @Autowired + private PromApiService promApiService; + + @Autowired + private LokiApiService lokiApiService; + + @Autowired + private TimezoneService timezoneService; + + @Autowired + private StatServiceImpl statServiceImpl; + + @Autowired + private VisualDashboardService dashboardService; + + @Autowired + private VisualChartService visualChartService; + + @Autowired + private VisualChartElementService visualChartElementService; + + @Autowired + private AssetAssetService assetAssetService; + + @Autowired + private MonitorEndpointService monitorEndpointService; + + private static volatile TimedCache<String, Object> SNAPSHOT_CACHE; + + private ExecutorService snapshotThreadPool; + + @PostConstruct + public void init() { + log.info("Setup dashboard snapshot cache begin..."); + // 创建缓存,默认 snapshotTimeout * 5 + SNAPSHOT_CACHE = Tool.CacheUtil.newTimedCache(timeout * 5); + + // snapshot 执行线程池,避免大量请求访问 prometheus 服务 + snapshotThreadPool = new ThreadPoolExecutor( + snapshotCorePoolSize, + snapshotConcurrency, + snapshotKeepAliveTime, + TimeUnit.SECONDS, + new ArrayBlockingQueue<Runnable>(snapshotCapacity), + new NamedThreadFactory("SNAPSHOT-", true)); + + /*new ThreadPoolExecutor( + 10, + Integer.MAX_VALUE, + 0L, + TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<Runnable>(), + new ThreadFactoryBuilder().setNamePrefix("dashboard-snapshot-pool-").build());*/ + log.info("Setup dashboard snapshot cache finished"); + } + + + @Override + public void exploreSnapshot(HttpServletResponse response, String format, Integer type, Long start, Long end, String language, Integer unit, String limit, String direction, String[] expressions) throws IOException { + // 计算步长 + String step = this.getTimeStep(start, end); + if(!StrUtil.equals(direction, "forward")){ + direction = "backward"; + } + + List<CompletableFuture<JSONObject>> futureList = new ArrayList<>(); + for (int i = 0; i < expressions.length; i++) { + String expression = URLUtil.decode(expressions[i]); + String finalDirection = direction; + futureList.add(CompletableFuture.supplyAsync(() -> { + JSONObject queryData = null; + if (type == 1) { + queryData = promApiService.query_range(expression, StrUtil.toString(start), StrUtil.toString(end), step, "null", null); + } else if (type == 2) { + queryData = lokiApiService.query_range(expression, StrUtil.toString(start), StrUtil.toString(end), StrUtil.emptyToDefault(limit, "100"), null, null, finalDirection, "1", null); + } + queryData.put("expression", expression); + return queryData; + })); + } + List<JSONObject> dataList = new ArrayList(); + try { + CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(connectTimeout, TimeUnit.MILLISECONDS); + futureList.forEach(future -> { + JSONObject result = future.getNow(null); + if (Tool.MapUtil.isNotEmpty(result)) { + dataList.add(result); + } + }); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + log.error(e); + } + // 封装返回结果 + Map<String, Object> resultMap = this.snapshotResultMap(start, end, language); + resultMap.put("type", type); + resultMap.put("unit", unit); + resultMap.put("direction", direction); + resultMap.put("limit", limit); + resultMap.put("data", dataList); + + String snapshotTemplate = this.replaceSnapshotTemplate(resultMap); + // 目前下载名称由前端控制 + // String downFileName = String.format("%s-%s.%s", "explore", System.currentTimeMillis(), StrUtil.emptyToDefault(format, "html")); + ResponseUtil.downloadFile(response, "exploreSnapshot.html", snapshotTemplate.getBytes()); + } + + /** + * 模板基本返回参数 + */ + @Override + public Map<String, Object> snapshotResultMap(Long start, Long end, String language) { + Map<String, Object> resultMap = Tool.MapUtil.newHashMap(); + resultMap.put("language", language); + resultMap.put("start", start); + resultMap.put("end", end); + // 查询系统时区信息 + String timezone = sysConfigService.getValue("timezone"); + Timezone timezoneEntity = timezoneService.getOne(new LambdaUpdateWrapper<Timezone>().eq(Timezone::getName, timezone)); + resultMap.put("offset", timezoneEntity.getOffset()); + resultMap.put("timezone", timezone); + return resultMap; + } + + /** + * 读取快照模板,替换数据 + */ + @Override + public String replaceSnapshotTemplate(Map<String, Object> resultMap) { + BufferedReader reader = null; + StringBuffer sbf = new StringBuffer(); + try { + String path = sysConfigService.getValue("snapshot_template_path"); + reader = new BufferedReader(new FileReader(Tool.StrUtil.concat(true, path, File.separator, "snapshot_template.html"))); + String line; + while ((line = reader.readLine()) != null) { + if (Tool.StrUtil.startWith(line, "<script>window.dataJson")) + line = "<script>window.dataJson=" + JSONUtil.toJsonStr(resultMap) + "</script>"; + sbf.append(line + "\n"); + } + } catch (IOException e) { + log.error(e); + } finally { + if (reader != null) IoUtil.close(reader); + } + return sbf.toString(); + } + + /** + * 计算Dashboards step + */ + @Override + public String getTimeStep(Long start, Long end) { + Long timeDiff = (end - start) / (24 * 60 * 60); + if (timeDiff < 1) { + return "15s"; + } else if (timeDiff < 7) { + return "5m"; + } else if (timeDiff < 30) { + return "10m"; + } else { + return "30m"; + } + } + + @Override + public String createSnapshotTask(String format, Integer dashboardId, Long start, Long end, String varsJsonStr) { + VisualDashboard dashboard = dashboardService.getById(dashboardId); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); + + // 查询 charts + Map param = Tool.MapUtil.builder() + .put("pageSize", "-1") + .put("dashboardId", dashboard.getId()) + .put("groupId", 0) + .map(); + + PageUtils chartPageUtils = visualChartService.queryPage(param); + List<VisualChart> chartsList = (List<VisualChart>) chartPageUtils.getList(); + ValidateUtils.is(chartsList).notNull(RCode.CHART_NOTEXSITS); + + // render repeat chart + List<VisualChart> randeredRepeatChartList = this.renderRepeatChartVariables(chartsList, varsJsonStr); + chartPageUtils.setList(randeredRepeatChartList); + + // render single chart + List<VisualChart> allChartList = this.renderSingleChartVariables(randeredRepeatChartList, varsJsonStr); + + String taskId = StrUtil.uuid(); + Map taskStat = Tool.MapUtil.builder() + .put("total", allChartList.size()) + .put("done", 0) + .put("process", 0) + // repaired for snapshot template + .put("start", start) + .put("end", end) + .put("dashboard", R.ok(dashboard)) + .put("charts", R.ok(chartPageUtils)) + .map(); + + log.info("dashboard snapshot start. taskId: {}, dashboardId:{} total: {}", taskId, dashboardId, allChartList.size()); + String stat = StrUtil.concat(true, "snapshot_stat_", taskId); + SNAPSHOT_CACHE.put(stat, taskStat); + + ThreadUtil.execAsync(() -> { + // 计算步长 + String step = this.getTimeStep(start, end); + Map<String, String> basicQueryParam = Tool.MapUtil.newHashMap(); + basicQueryParam.put("start", StrUtil.toString(start)); + basicQueryParam.put("end", StrUtil.toString(end)); + basicQueryParam.put("step", StrUtil.toString(step)); + + // run Snapshot Runnable + ThreadGroup threadGroup = new ThreadGroup(taskId); + SNAPSHOT_CACHE.put(StrUtil.concat(true, "snapshot_threadGroup_", taskId), threadGroup); + + ReentrantReadWriteLock readWriteLock = Tool.LockUtil.createReadWriteLock(false); + ReentrantReadWriteLock.WriteLock lock = readWriteLock.writeLock(); + + allChartList.stream().forEach(chart -> { + SnapshotRunnable snapshotRunnable = new SnapshotRunnable(threadGroup, lock, chart, basicQueryParam); + + // add thredGroup & submit + ReflectUtil.invoke(threadGroup, "add", snapshotRunnable); + snapshotThreadPool.submit(snapshotRunnable); + }); + }); + log.info("dashboard snapshot task create finished. taskId: {}", taskId); + return taskId; + } + + + /** + * render Repeat Chart Variables + * + * @param chartList + * @param varsJsonStr + * @return + */ + private List<VisualChart> renderRepeatChartVariables(List<VisualChart> chartList, String varsJsonStr) { + log.info("[renderRepeatChartVariables] [begin] [variable config: {}]", varsJsonStr); + List<Map> varConfigList = StrUtil.isNotEmpty(varsJsonStr) ? JSONObject.parseArray(varsJsonStr, Map.class) : Tool.ListUtil.empty(); + if (Tool.CollUtil.isEmpty(varConfigList)) { + log.warn("[renderRepeatChartVariables] [no chart variable config] [vars size: {}]", varConfigList.size()); + return chartList; + } + + // multi variable + Map<String, List<String>> multiVariableMap = varConfigList.stream() + .filter(map -> { + List values = (List) map.get("values"); + if (Tool.CollUtil.isEmpty(values)) return false; + return values.size() > 1; + }) + .collect(Collectors.toMap(map -> (String) map.get("name"), map -> (List<String>) map.get("values"))); + log.info("[renderRepeatChartVariables] [multi variable] [info: {}]", JSONUtil.toJsonStr(multiVariableMap)); + + List<VisualChart> repeatConfGroupChartList = chartList.stream() + .filter(chart -> StrUtil.equals(Constant.CHART_GROUP_TYPE, chart.getType())) + .filter(chart -> { + String chartParamJsonStr = JSONUtil.toJsonStr(ObjectUtil.defaultIfNull(chart.getParam(), Tool.MapUtil.empty())); + // repeat enable + Object repeatEnable = JSONPath.read(chartParamJsonStr, "enable.repeat"); + String repeatEnableStr = StrUtil.toString(ObjectUtil.defaultIfNull(repeatEnable, false)); + // repeat var + Object repeatVariable = JSONPath.read(chartParamJsonStr, "repeat.variable"); + return BooleanUtil.and( + StrUtil.equals("true", repeatEnableStr), + ObjectUtil.isNotNull(repeatVariable) + ); + }) + .collect(Collectors.toList()); + + // copy group charts and render vars + Integer startTempId = -10; + for (VisualChart groupChart : repeatConfGroupChartList) { + String chartParamJsonStr = JSONUtil.toJsonStr(ObjectUtil.defaultIfNull(groupChart.getParam(), Tool.MapUtil.empty())); + String repeatVariable = JSONPath.read(chartParamJsonStr, "repeat.variable").toString(); + + List<String> varValues = multiVariableMap.get(repeatVariable); + if (Tool.CollUtil.isEmpty(varValues)) { + log.warn("[renderRepeatChartVariables] [group chart config variable not found, not repeat] [group chart variable: {}]", repeatVariable); + continue; + } + log.info("[renderRepeatChartVariables] [repeat group chart] [id: {}] [name: {}]", groupChart.getId(), groupChart.getName()); + // remove old chart + chartList.remove(groupChart); + List<VisualChart> copyGroupChartList = Tool.ListUtil.list(true); + for (String varValue : varValues) { + // 这里重新对 group_id 进行赋值 + Integer tempGroupId = startTempId--; + VisualChart tempGroupChart = new VisualChart(); + tempGroupChart = ObjectUtil.clone(groupChart); + // new temp group id + tempGroupChart.setId(tempGroupId); + // render group name + String name = tempGroupChart.getName(); + tempGroupChart.setName(name.replaceAll(StrUtil.concat(true, "\\$", repeatVariable), varValue)); + + // render repeatVariable + List<VisualChart> children = tempGroupChart.getChildren(); + children = Tool.CollUtil.defaultIfEmpty(children, Tool.ListUtil.list(true)); + for (VisualChart chart : children) { + Integer tempChartId = startTempId--; + // temp id + chart.setId(tempChartId); + chart.setGroupId(tempGroupId); + // chart name + String chartName = chart.getName(); + chart.setName(chartName.replaceAll(StrUtil.concat(true, "\\$", repeatVariable), varValue)); + + List<VisualChartElement> elements = chart.getElements(); + elements = Tool.CollUtil.defaultIfEmpty(elements, Tool.ListUtil.list(true)); + for (VisualChartElement element : elements) { + // temp chart id + element.setChartId(tempChartId); + String expression = element.getExpression(); + expression = expression.replaceAll(StrUtil.concat(true, "\\$", repeatVariable), varValue); + element.setExpression(expression); + } + } + copyGroupChartList.add(tempGroupChart); + } + // add new chart + chartList.addAll(copyGroupChartList); + } + log.info("[renderRepeatChartVariables] [finshed]"); + return chartList; + } + + /** + * render Single Chart Variables + * + * @param chartList + * @param varsJsonStr + * @return + */ + private List<VisualChart> renderSingleChartVariables(List<VisualChart> chartList, String varsJsonStr) { + log.info("[renderSingleChartVariables] [begin] [variable config: {}]", varsJsonStr); + List<Map> varConfigList = StrUtil.isNotEmpty(varsJsonStr) ? JSONObject.parseArray(varsJsonStr, Map.class) : Tool.ListUtil.empty(); + if (Tool.CollUtil.isEmpty(varConfigList)) { + log.warn("[renderSingleChartVariables] [no chart variable config] [vars size: {}]", varConfigList.size()); + List<VisualChart> allChartList = visualChartService.getAllChartList(chartList); + return allChartList; + } + + // all Chart List & render vars + List<VisualChart> allChartList = visualChartService.getAllChartList(chartList); + + // single Variables map + Map<String, String> singleVariableMap = Tool.MapUtil.newHashMap(); + for (Map map : varConfigList) { + String name = StrUtil.toString(map.get("name")); + List values = (List) map.get("values"); + values = Tool.CollUtil.defaultIfEmpty(values, Tool.ListUtil.list(true)); + if (Tool.CollUtil.isEmpty(values)) { + continue; + } + + singleVariableMap.put(name, Tool.CollUtil.join(values, "|")); + } + log.info("[renderSingleChartVariables] [single variable] [info: {}]", JSONUtil.toJsonStr(singleVariableMap)); + Set<Map.Entry<String, String>> singleVariableEntrySet = singleVariableMap.entrySet(); + + for (VisualChart chart : allChartList) { + for (Map.Entry<String, String> entry : singleVariableEntrySet) { + // chart name + String chartName = chart.getName(); + chart.setName(chartName.replaceAll(StrUtil.concat(true, "\\$", entry.getKey()), entry.getValue())); + } + + List<VisualChartElement> elements = chart.getElements(); + elements = Tool.CollUtil.defaultIfEmpty(elements, Tool.ListUtil.list(true)); + for (VisualChartElement element : elements) { + String expression = element.getExpression(); + for (Map.Entry<String, String> entry : singleVariableEntrySet) { + expression = expression.replaceAll(StrUtil.concat(true, "\\$", entry.getKey()), entry.getValue()); + } + element.setExpression(expression); + } + } + log.info("[renderSingleChartVariables] [finshed]"); + return allChartList; + } + + + @Override + public Map snapshotResultProcess(String taskId) { + String snapshotStatKey = StrUtil.concat(true, "snapshot_stat_", taskId); + Object obj = SNAPSHOT_CACHE.get(snapshotStatKey); + if (obj == null) { + log.warn("dashboard snapshot result process error, the task does not exist or has expired. task id: {}", taskId); + throw new NZException(RCode.DASHBOARD_SNAPSHOT_TASK_NOT_EXIST); + } + + Map<Object, Object> processMap = Tool.MapUtil.builder() + .put("total", ((Map) obj).get("total")) + .put("done", ((Map) obj).get("done")) + .put("process", ((Map) obj).get("process")) + .map(); + return processMap; + } + + @Override + public void cancelSnapshotTask(String taskId) { + log.info("dashboard snapshot cancel task id: {}", taskId); + String snapshotThreadGroupKey = StrUtil.concat(true, "snapshot_threadGroup_", taskId); + Object obj = SNAPSHOT_CACHE.get(snapshotThreadGroupKey); + + if (obj == null) { + log.warn("dashboard snapshot task cancel error, the task does not exist or has expired. task id: {}", taskId); + throw new NZException(RCode.DASHBOARD_SNAPSHOT_TASK_NOT_EXIST); + } else { + try { + ThreadGroup threadGroup = (ThreadGroup) obj; + log.info("dashboard snapshot task cancel, task id: {}, canceled task thread num: {}", taskId, threadGroup.activeCount()); + // thread interrupt + threadGroup.interrupt(); + + // remove cache data + String snapshotStatKey = StrUtil.concat(true, "snapshot_stat_", taskId); + String snapshotResultKey = StrUtil.concat(true, "snapshot_result_", taskId); + + SNAPSHOT_CACHE.remove(snapshotThreadGroupKey); + SNAPSHOT_CACHE.remove(snapshotStatKey); + SNAPSHOT_CACHE.remove(snapshotResultKey); + log.info("dashboard snapshot task is canceled, the cache data is cleared,task id {}", taskId); + } catch (Exception e) { + log.error("dashboard snapshot task cancel error", e); + } + } + } + + @Override + public void downloadSnapshotFile(HttpServletResponse response, String language, String taskId) { + String snapshotStatKey = StrUtil.concat(true, "snapshot_stat_", taskId); + String snapshotResultKey = StrUtil.concat(true, "snapshot_result_", taskId); + + Object obj = SNAPSHOT_CACHE.get(snapshotStatKey); + if (obj == null) { + throw new NZException(RCode.DASHBOARD_SNAPSHOT_TASK_NOT_EXIST); + } + + try { + Map snapshotInfoMap = (Map) obj; + Object start = snapshotInfoMap.get("start"); + Object end = snapshotInfoMap.get("end"); + Object dashboard = snapshotInfoMap.get("dashboard"); + Object charts = snapshotInfoMap.get("charts"); + + List<Object> snapshotResultList = (List<Object>) SNAPSHOT_CACHE.get(snapshotResultKey); + + Map<Object, Object> chartsDataMap = Tool.MapUtil.newHashMap(); + for (Object result : snapshotResultList) { + if (ObjectUtil.isEmpty(result)) continue; + + String chartId = Tool.MapUtil.getStr((Map) result, "chartId"); + String eleIndex = Tool.MapUtil.getStr((Map) result, "eleIndex"); + + String key = StrUtil.concat(true, chartId, StrUtil.UNDERLINE, eleIndex); + chartsDataMap.put(key, result); + } + + // handle snapshot file data + Map<String, Object> resultMap = this.snapshotResultMap(Long.valueOf(start.toString()), Long.valueOf(end.toString()), language); + resultMap.put("chartsData", chartsDataMap); + resultMap.put("dashboard", dashboard); + resultMap.put("charts", charts); + String snapshotTemplate = this.replaceSnapshotTemplate(resultMap); + + // download file + ResponseUtil.downloadFile(response, "exploreSnapshot.html", snapshotTemplate.getBytes()); + } catch (Exception e) { + log.error(e); + } finally { + String snapshotThreadGroupKey = StrUtil.concat(true, "snapshot_threadGroup_", taskId); + + Object tg = SNAPSHOT_CACHE.get(snapshotThreadGroupKey); + ThreadGroup threadGroup = (ThreadGroup) tg; + log.info("dashboard snapshot task cancel, task id: {}, canceled task thread num: {}", taskId, threadGroup.activeCount()); + // thread interrupt + threadGroup.interrupt(); + + // remove cache data + SNAPSHOT_CACHE.remove(snapshotThreadGroupKey); + SNAPSHOT_CACHE.remove(snapshotStatKey); + SNAPSHOT_CACHE.remove(snapshotResultKey); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void syncTemplateDashboard(Integer id, Integer tmplId, Integer modelId, Integer moduleId) { + // need Sync Dashboard lsit + List<VisualDashboard> needSyncDashboardList = dashboardService.getTemplateSyncDashboard(id, tmplId, modelId, moduleId); + log.info("[syncTemplateDashboard] [sync Dashboard List] [size: {}]", needSyncDashboardList.size()); + + if (Tool.CollUtil.isEmpty(needSyncDashboardList)) { + log.warn("[syncTemplateDashboard] [sync Dashboard not found] [dashboardId: {}] [tmplId: {}] [modelId: {}] [moduleId: {}]", id, tmplId, modelId, moduleId); + return; + } + + log.info("[syncTemplateDashboard] [sync Dashboard begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + // sync + Map<Integer, List<VisualDashboard>> needSyncDashboardMap = needSyncDashboardList.stream().collect(Collectors.groupingBy(VisualDashboard::getTmplId)); + for (Map.Entry<Integer, List<VisualDashboard>> entry : needSyncDashboardMap.entrySet()) { + Integer templateId = entry.getKey(); + VisualDashboard templateDashboard = dashboardService.queryDashboardIncludeChartInfo(templateId); + + List<VisualDashboard> syncDashboardList = entry.getValue(); + log.info("[syncTemplateDashboard] [sync Dashboard] [template: {}] [dashboard size: {}]", templateDashboard.getId(), syncDashboardList.size()); + + if (ObjectUtil.hasEmpty(templateDashboard, syncDashboardList)) { + log.warn("[syncTemplateDashboard] [do not perform template dashboard sync. sync object is empty]"); + continue; + } + + // perform synchronization + this.performSync(templateDashboard, syncDashboardList); + } + sw.stop(); + log.info("[syncTemplateDashboard] [sync Dashboard finshed] [Run time: {}]", sw.toString()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Integer createDashboardUsingTemplate(String name, String type, String description, Integer tmplId, Integer link) { + log.info("[createDashboardUsingTemplate] [name: {}] [tmplId: {}] [link: {}]", name, tmplId, link); + + VisualDashboard tDashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getName, name) + .eq(VisualDashboard::getType, type)); + if (ObjectUtil.isNotNull(tDashboard)) { + throw new NZException(RCode.DASHBOARD_NAME_DUPLICATE); + } + + // normal dashboard + VisualDashboard dashboard = new VisualDashboard(); + dashboard.setName(name); + dashboard.setCreateBy(ShiroUtils.getUserId().intValue()); + dashboard.setType(type); + dashboard.setRemark(description); + dashboard.setUts(System.currentTimeMillis()); + + // add new dashboard to the end + List<VisualDashboard> leafNodeDashboardList = dashboardService.list(new LambdaUpdateWrapper<VisualDashboard>().eq(VisualDashboard::getType, type).eq(VisualDashboard::getPid, 0)); + Integer maxWeight = leafNodeDashboardList.stream().sorted(Comparator.comparing(VisualDashboard::getWeight).reversed()).map(VisualDashboard::getWeight).findFirst().orElse(0); + dashboard.setWeight(++maxWeight); + + dashboardService.save(dashboard); + + if (ObjectUtil.isNotEmpty(tmplId)) { + // template Dashboard + VisualDashboard templateDashboard = dashboardService.queryDashboardIncludeChartInfo(tmplId); + + Integer varType = templateDashboard.getVarType(); + if (ObjectUtil.equal(DashboardConstant.VariableType.ASSET.getValue(), varType)) { + AssetAsset asset = assetAssetService.getById(link); + ValidateUtils.is(asset).notNull(RCode.ASSET_NOT_EXIST); + } else if (ObjectUtil.equal(DashboardConstant.VariableType.ENDPOINT.getValue(), varType)) { + MonitorEndpoint endpoint = monitorEndpointService.getById(link); + ValidateUtils.is(endpoint).notNull(RCode.ENDPOINT_NOTFOUND); + } else if (ObjectUtil.equal(DashboardConstant.VariableType.NONE.getValue(), varType)) { + // no validate link value, not using link + link = null; + } + + dashboard.setVarType(varType); + dashboard.setTmplId(tmplId); + dashboard.setLink(link); + + // sync by template + this.performSync(templateDashboard, Tool.ListUtil.of(dashboard)); + } + return dashboard.getId(); + } + + /** + * perform Sync dashboard + * + * @param templateDashboard + * @param syncDashboardList + */ + private void performSync(VisualDashboard templateDashboard, List<VisualDashboard> syncDashboardList) { + Integer templateDashboardId = templateDashboard.getId(); + Object templateDashboardParam = templateDashboard.getParam(); + List<VisualChart> templateDashboardCharts = templateDashboard.getCharts(); + templateDashboardCharts = templateDashboardCharts.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); + + for (VisualDashboard syncDashboard : syncDashboardList) { + // get link object + Integer varType = syncDashboard.getVarType(); + Integer link = syncDashboard.getLink(); + Object linkObject = null; + Integer chartVarType = DashboardConstant.VariableType.NONE.getValue(); + if (ObjectUtil.equal(DashboardConstant.VariableType.ASSET.getValue(), varType)) { + linkObject = assetAssetService.queryAssetInfo(link); + chartVarType = DashboardConstant.VariableType.ASSET.getValue(); + } else if (ObjectUtil.equal(DashboardConstant.VariableType.ENDPOINT.getValue(), varType)) { + linkObject = monitorEndpointService.queryEndpointEntity(link); + chartVarType = DashboardConstant.VariableType.ENDPOINT.getValue(); + } + + log.info("[syncTemplateDashboard] [performSync] [dashboard type: {}] [link id: {}] [link Object exist: {}]", DashboardConstant.VariableType.getVariableType(varType), link, ObjectUtil.isNotNull(linkObject)); + if (BooleanUtil.and( + ObjectUtil.notEqual(DashboardConstant.VariableType.NONE.getValue(), varType), + ObjectUtil.isNull(linkObject))) { + log.warn("[syncTemplateDashboard] [performSync] [link Object not exist] [link id: {}]", link); + continue; + } + + Integer syncDashboardId = syncDashboard.getId(); + + // remove chart. no remove buildin assetInfo endpointInfo chart + List<VisualChart> removeChartList = visualChartService.list(new LambdaUpdateWrapper<VisualChart>() + .eq(VisualChart::getDashboardId, syncDashboardId) + .eq(VisualChart::getBuildIn, 0)); + //.ne(VisualChart::getType, Constant.CHART_ASSETINFO_TYPE) + //.ne(VisualChart::getType, Constant.CHART_ENDPOINTINFO_TYPE)); + + List<Integer> removeChartIdList = removeChartList.stream().map(VisualChart::getId).collect(Collectors.toList()); + if (Tool.CollUtil.isNotEmpty(removeChartIdList)) { + visualChartService.removeByIds(removeChartIdList); + visualChartElementService.remove(new LambdaQueryWrapper<VisualChartElement>().in(VisualChartElement::getChartId, removeChartIdList)); + } + + // update dashboard param & tmplid + VisualDashboard updateDashboardObject = JSONUtil.toBean(JSONUtil.toJsonStr(syncDashboard), VisualDashboard.class); + + updateDashboardObject.setParam(Tool.NzExpressionUtil.renderExpression(templateDashboardParam.toString(), linkObject)); + updateDashboardObject.setTmplId(templateDashboardId); + updateDashboardObject.setUts(System.currentTimeMillis()); + dashboardService.updateById(updateDashboardObject); + + // update Report Config In Redis + dashboardService.updateReportConfigInRedis(syncDashboard, updateDashboardObject); + + // insert chart & chart element + List<VisualChartElement> saveChartElementList = Tool.ListUtil.list(true); + Map<Integer, Integer> groupIdMapping = new HashMap<>(); + for (VisualChart tempChart : templateDashboardCharts) { + VisualChart saveChart = JSONUtil.toBean(JSONUtil.toJsonStr(tempChart), VisualChart.class); + + saveChart.setId(null); + saveChart.setDashboardId(syncDashboardId); + saveChart.setPid(tempChart.getId()); + saveChart.setVarId(link); + saveChart.setVarType(chartVarType); + saveChart.setUpdateAt(new Date()); + saveChart.setUpdateBy(ShiroUtils.getUserId().intValue()); + + saveChart.setGroupId(ObjectUtil.defaultIfNull(groupIdMapping.get(saveChart.getGroupId()), 0)); + + saveChart.setName(Tool.NzExpressionUtil.renderExpression(saveChart.getName(), linkObject)); + saveChart.setParam(ToolUtil.isNotEmpty(saveChart.getParam()) ? Tool.NzExpressionUtil.renderExpression(saveChart.getParam().toString(), linkObject) : null); + + // save + visualChartService.save(saveChart); + if (Tool.CollUtil.isNotEmpty(saveChart.getElements())) { + for (VisualChartElement element : saveChart.getElements()) { + element.setId(null); + element.setExpression(Tool.NzExpressionUtil.renderExpression(element.getExpression(), linkObject)); + element.setChartId(saveChart.getId()); + } + saveChartElementList.addAll(saveChart.getElements()); + } + + // record group id mapping + if (StrUtil.equalsIgnoreCase(Constant.CHART_GROUP_TYPE, saveChart.getType())) { + groupIdMapping.put(tempChart.getId(), saveChart.getId()); + } + } + + // save element + if (Tool.CollUtil.isNotEmpty(saveChartElementList)) + visualChartElementService.saveBatch(saveChartElementList); + } + } + + private class SnapshotRunnable extends Thread { + + private VisualChart chart; + private ThreadGroup threadGroup; + private Map<String, String> basicQueryParam; + private Lock lock; + + private boolean isInterrupted = false; + + public SnapshotRunnable(ThreadGroup threadGroup, Lock lock, VisualChart chart, Map<String, String> basicQueryParam) { + // group & name + super(threadGroup, String.format("Snapshot-%s-%s", threadGroup.getName(), chart.getId())); + + this.threadGroup = threadGroup; + this.lock = lock; + this.chart = chart; + this.basicQueryParam = basicQueryParam; + } + + @Override + public void run() { + // get chart snapshot data according to datasource (system、metrics\logs) + Object resultData = this.getChartSnapshotData(); + lock.lock(); + try { + // update snapshot resule & process + if (!this.isInterrupted()) + this.updateSnapshotResultAndProcess(resultData); + } catch (Exception e) { + log.error(e); + } finally { + lock.unlock(); + ReflectUtil.invoke(threadGroup, "remove", this); + } + } + + @Override + public void interrupt() { + super.interrupt(); + isInterrupted = true; + log.warn("dashboard snapshot thread is interrupted. name: {}", this.getName()); + } + + @Override + public boolean isInterrupted() { + return isInterrupted; + } + + /** + * get chart snapshot data according to datasource (system、metrics\logs) + * + * @return Object or List<Object></> + */ + private Object getChartSnapshotData() { + Object resultData = null; + try { + String datasource = chart.getDatasource(); + Map<String, Object> chartParam = (HashMap) chart.getParam(); + + // system + if (StrUtil.equals(Constant.ChartDatasourceType.SYSTEM.getValue(), datasource)) { + VisualDashboard visualDashboard = chart.getDashboard(); + R r = R.ok(); + Map<String, Object> queryParams = MapUtil.newHashMap(); + queryParams.put("type", "total"); + queryParams.put("dimension", "priority"); + queryParams.put("step", "d"); + if (StrUtil.equals(Constant.CHART_ASSETINFO_TYPE, chart.getType())) { + queryParams.put("assetId", visualDashboard.getLink()); + Map<String, Object> alertMessageTrend = statServiceImpl.queryAlertMessageTrend(queryParams); + AssetAsset asset = assetAssetService.queryAssetInfo(visualDashboard.getLink()); + Map<String, Object> assetDataMap = BeanUtil.beanToMap(asset); + assetDataMap.put("alertMessageTrend", alertMessageTrend); + r.put("data", assetDataMap); + } else if (StrUtil.equals(Constant.CHART_ENDPOINTINFO_TYPE, chart.getType())) { + queryParams.put("endpointId", visualDashboard.getLink()); + Map<String, Object> alertMessageTrend = statServiceImpl.queryAlertMessageTrend(queryParams); + MonitorEndpoint endpoint = monitorEndpointService.queryEndpointEntity(visualDashboard.getLink()); + Map<String, Object> endpointDataMap = BeanUtil.beanToMap(endpoint); + endpointDataMap.put("alertMessageTrend", alertMessageTrend); + r.put("data", endpointDataMap); + } else { + cn.hutool.json.JSONObject dataSource = JSONUtil.parseArray(chartParam.get("datasource")).getJSONObject(0); + dataSource.set("select", JSONUtil.createArray().put(dataSource.get("select"))); + r.putAllData( + statServiceImpl.queryAnalyse( + JSONUtil.toBean(JSONUtil.createObj().set("q", dataSource.toString()), Map.class) + ) + ); + } + r.put("eleIndex", "0"); + r.put("chartId", chart.getId()); + + resultData = ObjectUtil.clone(r); + } else { + // metrics\logs + if (Tool.CollUtil.isNotEmpty(chart.getElements())) { + String start = basicQueryParam.get("start"); + String end = basicQueryParam.get("end"); + String step = basicQueryParam.get("step"); + String limit = ToolUtil.toStr(chartParam.get("limit"), "100"); + String nullType = ToolUtil.toStr(chartParam.get("nullType"), "null"); + String logsDirection = "backward"; + + List<Object> rList = Tool.ListUtil.list(true); + Integer eleIndex = 0; + for (VisualChartElement element : chart.getElements()) { + String indexStr = StrUtil.toString(eleIndex++); + JSONObject jsonObject = new JSONObject(); + if (StrUtil.equals(Constant.ChartDatasourceType.METRICS.getValue(), datasource)) { + jsonObject = promApiService.query_range(element.getExpression(), start, end, step, nullType, null); + } else if (StrUtil.equals(Constant.ChartDatasourceType.LOGS.getValue(), datasource)) { + jsonObject = lokiApiService.query_range(element.getExpression(), start, end, limit, step, null, logsDirection, "1", null); + } + jsonObject.put("eleIndex", indexStr); + jsonObject.put("chartId", chart.getId()); + rList.add(jsonObject); + } + + resultData = ObjectUtil.clone(rList); + } else { + // no element chart data + resultData = JSONUtil.toBean( + JSONUtil.createObj() + .set("eleIndex", 0) + .set("chartId", chart.getId()) + , Map.class); + } + } + } catch (Exception e) { + log.error("dashboard snapshot data get failed. taskId: {}, chartInfo: {}", e, JSONUtil.toJsonStr(chart)); + } + return resultData; + } + + /** + * update snapshot resule & process + * + * @param resultData + */ + private void updateSnapshotResultAndProcess(Object resultData) { + try { + // task id + String taskId = threadGroup.getName(); + + // snapshot result cache + String snapshotResultKey = StrUtil.concat(true, "snapshot_result_", taskId); + List<Object> snapshotResultList = (List<Object>) SNAPSHOT_CACHE.get(snapshotResultKey); + snapshotResultList = Tool.CollUtil.defaultIfEmpty(snapshotResultList, Tool.ListUtil.list(true)); + + Tool.CollUtil.addAll(snapshotResultList, resultData); + SNAPSHOT_CACHE.put(snapshotResultKey, snapshotResultList); + + // snapshot task process + String snapshotStatKey = StrUtil.concat(true, "snapshot_stat_", taskId); + Map snapshotStatMap = (Map) SNAPSHOT_CACHE.get(snapshotStatKey); + Integer total = (Integer) snapshotStatMap.get("total"); + Integer done = (Integer) snapshotStatMap.get("done"); + done = done + 1; + + // cal process + String percent = NumberUtil.formatPercent((double) done / total, 2); + snapshotStatMap.put("process", percent.replace("%", "")); + snapshotStatMap.put("done", done); + snapshotStatMap.put("total", total); + SNAPSHOT_CACHE.put(snapshotStatKey, snapshotStatMap); + + log.info("dashboard snapshot result updated, taskId: {}, total: {}, done: {}, process: {}", taskId, total, done, percent); + } catch (Exception e) { + log.error("dashboard snapshot result error,taskId: {}", e, threadGroup.getName()); + } + } + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/dashboard/utils/DashboardConstant.java b/nz-admin/src/main/java/com/nis/modules/dashboard/utils/DashboardConstant.java new file mode 100644 index 00000000..ff9f45e9 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/dashboard/utils/DashboardConstant.java @@ -0,0 +1,78 @@ +package com.nis.modules.dashboard.utils; + +import cn.hutool.core.util.StrUtil; +import com.nis.common.utils.Tool; + +public class DashboardConstant { + + /** + * dashboard 模板同步锁 key + */ + public static final String TEMPLATE_SYNC_LOCK_KEY = "dashboardTemplateSynchronizationLock"; + + + /** + * dashboard type + */ + public enum Type { + DASHBOARD("dashboard"), + ASSET("asset"), + PROJECT("project"), + MODULE("module"), + ENDPOINT("endpoint"), + TEMPLATE("template"); + + private String value; + + Type(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public static Type getInstanceByType(String type) { + for (Type v : values()) { + if (StrUtil.equalsIgnoreCase(v.getValue(), type)) { + return v; + } + } + throw new IllegalArgumentException("Failed to find dashboard type with parameter."); + } + } + + /** + * dashboard Variable type enum + */ + public enum VariableType { + NONE(0), + ASSET(1), + ENDPOINT(2); + + private Integer value; + + VariableType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + + public static VariableType getVariableType(Integer value) { + for (VariableType v : values()) + if (Tool.ObjectUtil.equal(v.getValue(), value)) return v; + throw new IllegalArgumentException(); + } + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java new file mode 100644 index 00000000..aa1480f0 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseClient.java @@ -0,0 +1,106 @@ +package com.nis.modules.diagnose.chain; + +import com.nis.common.utils.Tool; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * DiagnoseClient 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class DiagnoseClient { + + public static final ThreadLocal<List<Map<Object, Object>>> THREAD_LOCAL = new ThreadLocal(); + + /** + * 创建一个集合来存储拦截器 + */ + private List<DiagnoseInterceptor> interceptors = Tool.ListUtil.list(true); + + public DiagnoseClient(Builder builder) { + this.interceptors = builder.arrayList; + } + + public List<DiagnoseInterceptor> interceptors() { + return interceptors; + } + + public static class Builder { + + private List<DiagnoseInterceptor> arrayList = Tool.ListUtil.list(true); + + public Builder addInterceptor(DiagnoseInterceptor interceptor) { + arrayList.add(interceptor); + return this; + } + + public DiagnoseClient build() { + return new DiagnoseClient(this); + } + + } + + + /** + * diagnose + * + * @param obj + */ + public void diagnose(Object obj) { + List<DiagnoseInterceptor> interceptors = new ArrayList<>(); + interceptors.addAll(this.interceptors()); + + // proceed first interceptor + DiagnoseInterceptor.Chain chain = new RealDiagnoseChain(interceptors, 0, obj, true); + chain.proceed(obj); + } + + + /** + * query Diagnose Msg + * + * @return + */ + public static List<Map<Object, Object>> queryDiagnoseMsg() { + List<Map<Object, Object>> mapList = Tool.CollUtil.defaultIfEmpty(THREAD_LOCAL.get(), Tool.ListUtil.list(true)); + return mapList; + } + + + /** + * add Diagnose Msg + * + * @param diagnoseMsg + */ + public static void addDiagnoseMsg(Map<Object, Object> diagnoseMsg) { + // query Diagnose Msg + List<Map<Object, Object>> mapList = DiagnoseClient.queryDiagnoseMsg(); + mapList.add(diagnoseMsg); + + THREAD_LOCAL.set(mapList); + } + + /** + * add Diagnose Msg List + * + * @param diagnoseMsgList + */ + public static void addDiagnoseMsg(List<Map<Object, Object>> diagnoseMsgList) { + // query Diagnose Msg + List<Map<Object, Object>> mapList = DiagnoseClient.queryDiagnoseMsg(); + mapList.addAll(diagnoseMsgList); + + THREAD_LOCAL.set(mapList); + } + + /** + * clean Diagnose Msg + */ + public static void cleanDiagnoseMsg() { + THREAD_LOCAL.remove(); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseInterceptor.java new file mode 100644 index 00000000..574503df --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/DiagnoseInterceptor.java @@ -0,0 +1,74 @@ +package com.nis.modules.diagnose.chain; + + +/** + * DiagnoseInterceptor 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +public interface DiagnoseInterceptor { + + /** + * 拦截方法 + * + * @param chain + */ + void intercept(Chain chain); + + interface Chain { + + /** + * 停止诊断 + */ + void stopDiagnose(); + + /** + * 是否继续诊断 + * + * @return + */ + boolean isContinueDiagnosis(); + + /** + * 处理对象 + * + * @return + */ + Object object(); + + /** + * 继续执行下一个链 + * + * @param object + */ + void proceed(Object object); + } + + /** + * Diagnose State + */ + enum DiagnoseState { + // 检查通过 + PASS(1), + // 检查未通过 + DID_NOT_PASS(2), + // 未检查 + NOT_CHECKED(3); + + private Integer value; + + DiagnoseState(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/RealDiagnoseChain.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/RealDiagnoseChain.java new file mode 100644 index 00000000..8810bbf2 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/RealDiagnoseChain.java @@ -0,0 +1,56 @@ +package com.nis.modules.diagnose.chain; + +import com.nis.common.exception.NZException; +import com.nis.common.utils.RCode; + +import java.util.List; + +/** + * RealDiagnoseChain 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class RealDiagnoseChain implements DiagnoseInterceptor.Chain { + + private int index; + private List<DiagnoseInterceptor> interceptors; + private Object obj; + + private Boolean isContinue = true; + + + public RealDiagnoseChain(List<DiagnoseInterceptor> interceptors, int index, Object obj, Boolean isContinue) { + this.interceptors = interceptors; + this.index = index; + this.obj = obj; + this.isContinue = isContinue; + } + + @Override + public void stopDiagnose() { + isContinue = false; + } + + @Override + public boolean isContinueDiagnosis() { + return this.isContinue; + } + + @Override + public Object object() { + return this.obj; + } + + + @Override + public void proceed(Object obj) { + if (index >= interceptors.size()) { + throw new NZException(RCode.ERROR); + } + + RealDiagnoseChain next = new RealDiagnoseChain(interceptors, index + 1, obj, this.isContinue); + DiagnoseInterceptor interceptor = interceptors.get(index); + interceptor.intercept(next); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java new file mode 100644 index 00000000..796e1d3f --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentComponentsCheckInterceptor.java @@ -0,0 +1,160 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.util.AgentUtil; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; + +import java.util.List; +import java.util.Map; + +/** + * AgentComponentsCheckInterceptor + * 检查 Agent 组件状态 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentComponentsCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static final String AGENT_AUTH_SUCCESS = "TRUE"; + private static final String COMPONENT_AVAILABLE_STATUS = "UP"; + private static final String COMPONENT_UNAVAILABLE_STATUS = "DOWN"; + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AgentComponentsCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + Agent agent = (Agent) chain.object(); + + // check Components Status + List<Map<Object, Object>> diagnoseMsgList = this.checkComponentsStatus(agent); + + // update check msg + DiagnoseClient.addDiagnoseMsg(diagnoseMsgList); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.components") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + } + + /** + * check Components Status + * + * @param agent + * @return + */ + private List<Map<Object, Object>> checkComponentsStatus(Agent agent) { + String resultJsonStr = Tool.StrUtil.EMPTY_JSON; + try { + resultJsonStr = AgentUtil.requestGet(agent, "/healthy", null, String.class); + } catch (Exception e) { + log.error(e, "[checkComponentsStatus] [request agent healthy api error] [agent: {}]", Tool.JSONUtil.toJsonStr(agent)); + } + log.info("[checkComponentsStatus] [agent healthy api] [result: {}]", resultJsonStr); + + List<Map<Object, Object>> componentsStatusList = Tool.ListUtil.list(true); + + Map resultObj = JSONObject.parseObject(resultJsonStr, Map.class); + if (Tool.BooleanUtil.or( + Tool.MapUtil.isEmpty(resultObj), + Tool.ObjectUtil.notEqual(RCode.SUCCESS.getCode(), resultObj.get("code")))) { + // nzagent error + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.nzagent") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.nzagent") + .map()); + } else { + Object auth = JSONPath.read(resultJsonStr, "data.auth"); + if (Tool.ObjectUtil.notEqual(AGENT_AUTH_SUCCESS, auth)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.auth") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.auth") + .map()); + } + + Object cortex = JSONPath.read(resultJsonStr, "data.cortex"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, cortex)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.cortex") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.cortex") + .map()); + } + + Object loki = JSONPath.read(resultJsonStr, "data.loki"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, loki)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.loki") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.loki") + .map()); + } + + Object snmpExporter = JSONPath.read(resultJsonStr, "data.snmp_exporter"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, snmpExporter)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.snmpExporter") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.snmpExporter") + .map()); + } + + Object blackboxExporter = JSONPath.read(resultJsonStr, "data.blackbox_exporter"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, blackboxExporter)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.blackboxExporter") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.blackboxExporter") + .map()); + } + + Object prometheus = JSONPath.read(resultJsonStr, "data.prometheus"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, prometheus)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.prometheus") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.prometheus") + .map()); + } + + Object nzagent = JSONPath.read(resultJsonStr, "data.confagent"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, nzagent)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.nzagent") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.agent.resolution.nzagent") + .map()); + } + } + + // 所有检查通过 PASS + if (Tool.CollUtil.isEmpty(componentsStatusList)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.components") + .put("state", DiagnoseState.PASS.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map()); + } + return componentsStatusList; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java new file mode 100644 index 00000000..60a2f6f6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentConnectableCheckInterceptor.java @@ -0,0 +1,104 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.apache.commons.lang3.time.StopWatch; + +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Map; + +/** + * AgentConnectableCheckInterceptor + * 检查 Agent Host&Port 网络情况,端口是否开放 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentConnectableCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AgentConnectableCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + Agent agent = (Agent) chain.object(); + + // check Host Is Connectable + boolean isConnectable = this.checkHostIsConnectable(agent.getHost(), agent.getPort()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.connectable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (isConnectable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.agent.resolution.connectable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.connectable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Host Is Connectable + * + * @param host + * @param port + * @return + */ + public boolean checkHostIsConnectable(String host, int port) { + log.info("[checkHostIsConnectable] [begin] [host: {}] [port: {}]", host, port); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isConnectable = false; + + Socket socket = new Socket(); + try { + InetSocketAddress socketAddress = new InetSocketAddress(host, port); + socket.connect(socketAddress, 5000); + isConnectable = socket.isConnected(); + } catch (Exception e) { + log.error(e, "[checkHostIsConnectable] [error in check process] [host: {}] [port: {}]", host, port); + } finally { + Tool.IoUtil.close(socket); + sw.stop(); + } + + log.info("[checkHostIsConnectable] [check completed] [host: {}] [port: {}] [connected: {}] [Run Time: {}]", host, port, isConnectable, sw.toString()); + return isConnectable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java new file mode 100644 index 00000000..2013fdde --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/agent/AgentNetworkCheckInterceptor.java @@ -0,0 +1,84 @@ +package com.nis.modules.diagnose.chain.agent; + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.apache.commons.lang3.time.StopWatch; + +import java.net.InetAddress; +import java.util.Map; + +/** + * AgentNetworkCheckInterceptor + * 检查 Agent Host 网络情况,是否可达 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class AgentNetworkCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + // process object + Agent agent = (Agent) chain.object(); + + // check Ip IsR eachable + boolean ipIsReachable = this.checkIpIsReachable(agent.getHost()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.agent.item.reachable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (ipIsReachable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.agent.resolution.reachable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Ip IsR eachable + * + * @param host + * @return a {@code boolean} indicating if the address is reachable. + */ + private boolean checkIpIsReachable(String host) { + log.info("[checkIpIsReachable] [begin] [host: {}]", host); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isReachable = false; + try { + InetAddress inetAddress = InetAddress.getByName(host); + // timeout the time, in milliseconds, before the call aborts, default 5s + isReachable = inetAddress.isReachable(5000); + } catch (Exception e) { + log.error(e, "[checkIpIsReachable] [error in check process] [host: {}]", host); + } finally { + sw.stop(); + } + + log.info("[checkIpIsReachable] [check completed] [host: {}] [reachable: {}] [Run Time: {}]", host, isReachable, sw.toString()); + return isReachable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AgentStateCheckOfPingInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AgentStateCheckOfPingInterceptor.java new file mode 100644 index 00000000..a00c9c4b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AgentStateCheckOfPingInterceptor.java @@ -0,0 +1,142 @@ +package com.nis.modules.diagnose.chain.asset; + + +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.sys.service.SysConfService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AgentStateCheckOfPingInterceptor + * 检查负责采集 Asset Ping Metrics 数据的 Nz-Agent 是否健康 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class AgentStateCheckOfPingInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AgentService agentService; + + private static SysConfService sysConfService; + + @Autowired + public void initBean(AgentService agentService, SysConfService sysConfService) { + AgentStateCheckOfPingInterceptor.agentService = agentService; + AgentStateCheckOfPingInterceptor.sysConfService = sysConfService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AgentStateCheckOfPingInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + AssetAsset asset = (AssetAsset) chain.object(); + + // check Agent State Of Ping + Map<Object, Object> map = this.checkAgentStateOfPing(asset); + + Object state = map.get("state"); + if (Tool.ObjectUtil.equal(state, DiagnoseState.DID_NOT_PASS.getValue())) { + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(map); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.agent.status") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Agent State Of Ping + * + * @param asset + * @return + */ + private Map<Object, Object> checkAgentStateOfPing(AssetAsset asset) { + // blackbox source, 1: global 2: per-datacenter + String assetPingFromConf = sysConfService.getValueOrDefault(Constant.SYSCONFIG_KEY_ASSET_PING_FROM, Constant.AssetPingFrom.GLOBAL.getValue()); + log.info("[checkAgentStateOfPing] [asset_ping_from: {}]", assetPingFromConf); + + List<Agent> totalAgentList = Tool.ListUtil.list(true); + List<Agent> downAgentList = Tool.ListUtil.list(true); + + // ping source is global + if (Tool.StrUtil.equals(Constant.AssetPingFrom.GLOBAL.getValue(), assetPingFromConf)) { + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>() + .eq(Agent::getType, Constant.AgentType.GLOBAL.getValue())); + + downAgentList = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + log.info("[checkAgentStateOfPing] [asset ping from global] [total agent size: {}] [down agent size: {}]", totalAgentList.size(), downAgentList.size()); + } + + // ping source is per-datacenter + if (Tool.StrUtil.equals(Constant.AssetPingFrom.PER_DATACENTER.getValue(), assetPingFromConf)) { + Integer dcId = asset.getDcId(); + // per-datacenter agent list + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>() + .eq(Agent::getType, Constant.AgentType.PER_DATACENTER.getValue()) + .eq(Agent::getDcId, dcId)); + + List<Agent> downPerDcAgents = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + + // per-datacenter scrape asset_ping job, query prom_api by global agent, so down agent include global agent + List<Agent> downGlobalAgents = agentService.list(new LambdaUpdateWrapper<Agent>().eq(Agent::getType, Constant.AgentType.GLOBAL.getValue()).ne(Agent::getStatus, 1)); + log.info("[checkAgentStateOfPing] [asset ping from per-datacenter] [total per-datacenter agent size: {}] [down per-datacenter agent size: {}] [down global agent size: {}]", totalAgentList.size(), downPerDcAgents.size(), downGlobalAgents.size()); + + // down agent list include per-datacenter and global agent + downAgentList.addAll(downPerDcAgents); + downAgentList.addAll(downGlobalAgents); + } + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.agent.status") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isNotEmpty(downAgentList))) { + // has down agent + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.asset.resolution.agent.status"); + } else if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isEmpty(downAgentList))) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else if (Tool.CollUtil.isEmpty(totalAgentList)) { + // 没有配置 Agent 信息 + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.asset.resolution.agent.config"); + } + return resultMap; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetNetworkCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetNetworkCheckInterceptor.java new file mode 100644 index 00000000..3eb84f12 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetNetworkCheckInterceptor.java @@ -0,0 +1,102 @@ +package com.nis.modules.diagnose.chain.asset; + + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.apache.commons.lang3.time.StopWatch; +import org.springframework.stereotype.Component; + +import java.net.InetAddress; +import java.util.Map; + +/** + * AssetNetworkCheckInterceptor + * 检查 Asset Host 网络情况,是否可达 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class AssetNetworkCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[AssetNetworkCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + AssetAsset asset = (AssetAsset) chain.object(); + + // check Ip IsR eachable + boolean ipIsReachable = this.checkIpIsReachable(asset.getManageIp()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.reachable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (ipIsReachable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.asset.resolution.reachable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.reachable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + + /** + * check Ip IsR eachable + * + * @param host + * @return a {@code boolean} indicating if the address is reachable. + */ + private boolean checkIpIsReachable(String host) { + log.info("[checkIpIsReachable] [begin] [host: {}]", host); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isReachable = false; + try { + InetAddress inetAddress = InetAddress.getByName(host); + // timeout the time, in milliseconds, before the call aborts, default 5s + isReachable = inetAddress.isReachable(5000); + } catch (Exception e) { + log.error(e, "[checkIpIsReachable] [error in check process] [host: {}]", host); + } finally { + sw.stop(); + } + + log.info("[checkIpIsReachable] [check completed] [host: {}] [reachable: {}] [Run Time: {}]", host, isReachable, sw.toString()); + return isReachable; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetStateConfCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetStateConfCheckInterceptor.java new file mode 100644 index 00000000..8083b399 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/AssetStateConfCheckInterceptor.java @@ -0,0 +1,69 @@ +package com.nis.modules.diagnose.chain.asset; + + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetStateConf; +import com.nis.modules.asset.service.AssetStateConfService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * AssetStateConfCheckInterceptor + * 检查 Asset state_conf 是否支持 ping + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class AssetStateConfCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AssetStateConfService assetStateConfService; + + @Autowired + public void initBean(AssetStateConfService assetStateConfService) { + AssetStateConfCheckInterceptor.assetStateConfService = assetStateConfService; + } + + @Override + public void intercept(Chain chain) { + // process object + AssetAsset asset = (AssetAsset) chain.object(); + + AssetStateConf stateConf = assetStateConfService.getById(asset.getStateId()); + Integer ping = stateConf.getPing(); + log.info("[checkAssetStateConf] [asset id: {}] [state.ping: {}]", asset.getId(), ping); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.stateconf") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(0, ping)) { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.asset.resolution.stateconf"); + + // stopDiagnose + chain.stopDiagnose(); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + + // next chain + chain.proceed(asset); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/BlackboxConfigCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/BlackboxConfigCheckInterceptor.java new file mode 100644 index 00000000..a9c570e6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/asset/BlackboxConfigCheckInterceptor.java @@ -0,0 +1,99 @@ +package com.nis.modules.diagnose.chain.asset; + + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * BlackboxConfigCheckInterceptor + * 检查 是否下发 Asset ping 配置 blackbox_exporter 配置 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class BlackboxConfigCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + + private static PromApiService promApiService; + + @Autowired + public void initBean(PromApiService promApiService) { + BlackboxConfigCheckInterceptor.promApiService = promApiService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[BlackboxConfigCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + AssetAsset asset = (AssetAsset) chain.object(); + + // query Has Results + boolean queryHasResults = this.checkBlackboxConfig(asset); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.blackbox") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (queryHasResults) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.asset.resolution.blackbox"); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "diagnose.asset.item.blackbox") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + } + + /** + * check Black box Config + * + * @param asset + * @return + */ + private boolean checkBlackboxConfig(AssetAsset asset) { + String queryExpr = String.format("probe_success{host='%s',module='ping'}", asset.getManageIp()); + + log.info("[checkBlackboxConfig] [query prom api] [expr: {}]", queryExpr); + JSONObject jsonObject = promApiService.query(queryExpr, null, null); + Object read = JSONPath.read(Tool.JSONUtil.toJsonStr(jsonObject), "data.result"); + List list = (List) Tool.ObjectUtil.defaultIfNull(read, Tool.ListUtil.empty()); + + log.info("[checkBlackboxConfig] [probe_success result size: {}]", list.size()); + return Tool.CollUtil.isNotEmpty(list); + } + + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/AgentStateCheckOfLogsEndpointInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/AgentStateCheckOfLogsEndpointInterceptor.java new file mode 100644 index 00000000..0cbf3b3a --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/AgentStateCheckOfLogsEndpointInterceptor.java @@ -0,0 +1,136 @@ +package com.nis.modules.diagnose.chain.endpoint.logs; + + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.sys.service.SysConfService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AgentStateCheckOfLogsEndpointInterceptor + * 检查负责采集 Logs Endpoint 数据的 Nz-Agent 是否健康 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class AgentStateCheckOfLogsEndpointInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AgentService agentService; + + private static SysConfService sysConfService; + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AgentService agentService, SysConfService sysConfService, AssetAssetService assetService) { + AgentStateCheckOfLogsEndpointInterceptor.agentService = agentService; + AgentStateCheckOfLogsEndpointInterceptor.assetService = assetService; + AgentStateCheckOfLogsEndpointInterceptor.sysConfService = sysConfService; + } + + @Override + public void intercept(Chain chain) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // agent State Check Of Logs + Map<Object, Object> map = this.agentStateCheckOfLogs(endpoint); + + Object state = map.get("state"); + if (Tool.ObjectUtil.equal(state, DiagnoseState.DID_NOT_PASS.getValue())) { + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(map); + + // next chain + chain.proceed(chain.object()); + } + + /** + * agent State Check Of Logs Endpoint + * + * @param endpoint + * @return + */ + private Map<Object, Object> agentStateCheckOfLogs(MonitorEndpoint endpoint) { + // federation enable + String federationEnabled = sysConfService.getValueOrDefault(Constant.SYSCONFIG_KEY_PROM_FEDER_ENABLED, "1"); + log.info("[agentStateCheckOfLogs] [prometheus_federation_enabled] [value: {}]", federationEnabled); + + List<Agent> totalAgentList = Tool.ListUtil.list(true); + List<Agent> downAgentList = Tool.ListUtil.list(true); + + if (StrUtil.equals("0", federationEnabled)) { + // federation 模式关闭 ,Global scrape endpoint jobs + log.info("[agentStateCheckOfLogs] [federation is not enabled. get global agents]"); + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>().eq(Agent::getType, Constant.AgentType.GLOBAL.getValue())); + downAgentList = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + log.info("[agentStateCheckOfLogs] [global agent receive log data] [total agent size: {}] [down agent size: {}]", totalAgentList.size(), downAgentList.size()); + } + + if (StrUtil.equals("1", federationEnabled)) { + // federation 模式开启 ,Per-datacenter scrape endpoint jobs + Integer assetId = endpoint.getAssetId(); + AssetAsset asset = assetService.getById(assetId); + + // per-datacenter agent list + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>() + .eq(Agent::getType, Constant.AgentType.PER_DATACENTER.getValue()) + .eq(Agent::getDcId, asset.getDcId())); + + List<Agent> downPerDcAgents = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + + // per-datacenter receive log data, query prom_api by global agent, so down agent include global agent + List<Agent> downGlobalAgents = agentService.list(new LambdaUpdateWrapper<Agent>().eq(Agent::getType, Constant.AgentType.GLOBAL.getValue()).ne(Agent::getStatus, 1)); + + // down agent list include per-datacenter and global agent + downAgentList.addAll(downPerDcAgents); + downAgentList.addAll(downGlobalAgents); + + log.info("[agentStateCheckOfLogs] [per-datacenter agent receive log data] [total per-datacenter agent size: {}] [down per-datacenter agent size: {}] [down global agent size: {}]", totalAgentList.size(), downPerDcAgents.size(), downGlobalAgents.size()); + } + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.agent.status") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isNotEmpty(downAgentList))) { + // has down agent + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.agent.status"); + } else if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isEmpty(downAgentList))) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else if (Tool.CollUtil.isEmpty(totalAgentList)) { + // 没有配置 Agent 信息 + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.agent.config"); + } + return resultMap; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/EndpointLogClientStatusCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/EndpointLogClientStatusCheckInterceptor.java new file mode 100644 index 00000000..3eb34a80 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/EndpointLogClientStatusCheckInterceptor.java @@ -0,0 +1,164 @@ +package com.nis.modules.diagnose.chain.endpoint.logs; + + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.Dc; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * EndpointLogClientStatusCheckInterceptor + * 检查 Endpoint Logs 状态是否正常,检查项包括,DC、Asset、Endpoint config + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointLogClientStatusCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AssetAssetService assetService) { + EndpointLogClientStatusCheckInterceptor.assetService = assetService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointLogClientStatusCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + Integer assetId = endpoint.getAssetId(); + AssetAsset asset = assetService.queryAssetInfo(assetId); + + // check dc state + Map<Object, Object> checkDcStatusResultMap = this.checkDcStatus(asset.getDc()); + + // check asset client enable + Map<Object, Object> checkAssetMonitorStateResultMap = this.checkAssetClientStatus(asset); + + // check endpoint config enable + Map<Object, Object> checkEndpointConfigEnableResultMap = this.checkEndpointConfigEnable(endpoint); + + if (StrUtil.equalsAny(DiagnoseState.DID_NOT_PASS.getValue().toString(), + checkDcStatusResultMap.get("state").toString(), + checkAssetMonitorStateResultMap.get("state").toString(), + checkEndpointConfigEnableResultMap.get("state").toString())) { + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(checkDcStatusResultMap); + DiagnoseClient.addDiagnoseMsg(checkAssetMonitorStateResultMap); + DiagnoseClient.addDiagnoseMsg(checkEndpointConfigEnableResultMap); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.monitor.status") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Dc Status + * + * @param dc + * @return + */ + private Map<Object, Object> checkDcStatus(Dc dc) { + String dcState = dc.getState(); + log.info("[checkDcStatus] [dc state: {}]", dcState); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.monitor.dc") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (StrUtil.equals("OFF", dcState)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.monitor.dc"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } + + /** + * check Asset Client Status + * + * @param asset + * @return + */ + private Map<Object, Object> checkAssetClientStatus(AssetAsset asset) { + Integer clientEnable = asset.getClientEnable(); + log.info("[checkAssetClientStatus] [asset client enable: {}]", clientEnable); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.monitor.asset") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(0, clientEnable)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.client.asset"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } + + /** + * check Endpoint Config Enable + * + * @param endpoint + * @return + */ + private Map<Object, Object> checkEndpointConfigEnable(MonitorEndpoint endpoint) { + MonitorEndpointConfig endpointConfig = endpoint.getEndpointConfig(); + Integer enable = endpointConfig.getEnable(); + log.info("[checkEndpointConfigEnable] [endpoint config enable: {}]", enable); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.monitor.config") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(0, enable)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.monitor.config"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonNetworkCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonNetworkCheckInterceptor.java new file mode 100644 index 00000000..6e6a8258 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonNetworkCheckInterceptor.java @@ -0,0 +1,115 @@ +package com.nis.modules.diagnose.chain.endpoint.logs; + + +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.apache.commons.lang3.time.StopWatch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.net.InetAddress; +import java.util.Map; + +/** + * TalonNetworkCheckInterceptor + * 检查 NZ-Talon 组件 host,是否可达 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class TalonNetworkCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AssetAssetService assetService) { + TalonNetworkCheckInterceptor.assetService = assetService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[TalonNetworkCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + Integer assetId = endpoint.getAssetId(); + AssetAsset asset = assetService.queryAssetInfo(assetId); + + // check Ip IsR eachable + boolean ipIsReachable = this.checkIpIsReachable(asset.getManageIp()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.reachable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (ipIsReachable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.endpoint.resolution.reachable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.reachable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Ip IsR eachable + * + * @param host + * @return a {@code boolean} indicating if the address is reachable. + */ + private boolean checkIpIsReachable(String host) { + log.info("[checkIpIsReachable] [begin] [host: {}]", host); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isReachable = false; + try { + InetAddress inetAddress = InetAddress.getByName(host); + // timeout the time, in milliseconds, before the call aborts, default 5s + isReachable = inetAddress.isReachable(5000); + } catch (Exception e) { + log.error(e, "[checkIpIsReachable] [error in check process] [host: {}]", host); + } finally { + sw.stop(); + } + + log.info("[checkIpIsReachable] [check completed] [host: {}] [reachable: {}] [Run Time: {}]", host, isReachable, sw.toString()); + return isReachable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonStatusCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonStatusCheckInterceptor.java new file mode 100644 index 00000000..abeabc56 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/logs/TalonStatusCheckInterceptor.java @@ -0,0 +1,136 @@ +package com.nis.modules.diagnose.chain.endpoint.logs; + + +import cn.hutool.core.net.url.UrlBuilder; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.util.AgentUtil; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + + +/** + * TalonStatusCheckInterceptor + * 检查 NZ-Talon 组件状态 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class TalonStatusCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static final String TALON_AUTH_SUCCESS = "TRUE"; + private static final String COMPONENT_AVAILABLE_STATUS = "UP"; + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AssetAssetService assetService) { + TalonStatusCheckInterceptor.assetService = assetService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[TalonStatusCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // check Talon Status + List<Map<Object, Object>> diagnoseMsgList = this.checkTalonStatus(endpoint.getAssetId()); + + // update check msg + DiagnoseClient.addDiagnoseMsg(diagnoseMsgList); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.talon") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + } + + /** + * check Talon Status + * + * @param assetId + * @return + */ + private List<Map<Object, Object>> checkTalonStatus(Integer assetId) { + log.info("[checkTalonStatus] [check logs endpoint state] [assetId: {}]", assetId); + AssetAsset asset = assetService.getById(assetId); + + String resultJsonStr = Tool.StrUtil.EMPTY_JSON; + try { + UrlBuilder urlBuilder = UrlBuilder.create().setScheme("http") + .setHost(asset.getManageIp()).setPort(asset.getClientPort()) + .appendPath("nz-talon").appendPath("healthy"); + resultJsonStr = AgentUtil.requestGet(urlBuilder.build(), asset.getClientToken(), String.class); + } catch (Exception e) { + log.error(e, "[checkTalonStatus] [request talon healthy api error] [asset: {}]", Tool.JSONUtil.toJsonStr(asset)); + } + log.info("[checkTalonStatus] [talon healthy api] [result: {}]", resultJsonStr); + + List<Map<Object, Object>> componentsStatusList = Tool.ListUtil.list(true); + + Map resultObj = JSONObject.parseObject(resultJsonStr, Map.class); + if (Tool.BooleanUtil.or( + Tool.MapUtil.isEmpty(resultObj), + Tool.ObjectUtil.notEqual(RCode.SUCCESS.getCode(), resultObj.get("code")))) { + // talon error + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.talon") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.endpoint.resolution.talon") + .map()); + } else { + Object auth = JSONPath.read(resultJsonStr, "data.auth"); + if (Tool.ObjectUtil.notEqual(TALON_AUTH_SUCCESS, auth)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.endpoint.item.talon.auth") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.endpoint.resolution.talon.auth") + .map()); + } + + Object promtail = JSONPath.read(resultJsonStr, "data.promtail"); + if (Tool.ObjectUtil.notEqual(COMPONENT_AVAILABLE_STATUS, promtail)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "diagnose.endpoint.item.talon.promtail") + .put("state", DiagnoseState.DID_NOT_PASS.getValue()) + .put("resolution", "diagnose.endpoint.resolution.talon.promtail") + .map()); + } + } + + // 所有检查通过 PASS + if (Tool.CollUtil.isEmpty(componentsStatusList)) { + componentsStatusList.add(Tool.MapUtil.builder() + .put("item", "logs.diagnose.endpoint.item.talon") + .put("state", DiagnoseState.PASS.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map()); + } + return componentsStatusList; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/AgentStateCheckOfMetricsEndpointInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/AgentStateCheckOfMetricsEndpointInterceptor.java new file mode 100644 index 00000000..5f2a40d7 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/AgentStateCheckOfMetricsEndpointInterceptor.java @@ -0,0 +1,136 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.sys.service.SysConfService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * AgentStateCheckOfMetricsEndpointInterceptor + * 检查负责采集 Metrics Endpoint 数据的 Nz-Agent 是否健康 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class AgentStateCheckOfMetricsEndpointInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AgentService agentService; + + private static SysConfService sysConfService; + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AgentService agentService, SysConfService sysConfService, AssetAssetService assetService) { + AgentStateCheckOfMetricsEndpointInterceptor.agentService = agentService; + AgentStateCheckOfMetricsEndpointInterceptor.assetService = assetService; + AgentStateCheckOfMetricsEndpointInterceptor.sysConfService = sysConfService; + } + + @Override + public void intercept(Chain chain) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // agent State Check Of Metrics + Map<Object, Object> map = this.agentStateCheckOfMetrics(endpoint); + + Object state = map.get("state"); + if (Tool.ObjectUtil.equal(state, DiagnoseState.DID_NOT_PASS.getValue())) { + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(map); + + // next chain + chain.proceed(chain.object()); + } + + /** + * agent State Check Of Metrics Endpoint + * + * @param endpoint + * @return + */ + private Map<Object, Object> agentStateCheckOfMetrics(MonitorEndpoint endpoint) { + // federation enable + String federationEnabled = sysConfService.getValueOrDefault(Constant.SYSCONFIG_KEY_PROM_FEDER_ENABLED, "1"); + log.info("[agentStateCheckOfMetrics] [prometheus_federation_enabled] [value: {}]", federationEnabled); + + List<Agent> totalAgentList = Tool.ListUtil.list(true); + List<Agent> downAgentList = Tool.ListUtil.list(true); + + if (StrUtil.equals("0", federationEnabled)) { + // federation 模式关闭 ,Global scrape endpoint jobs + log.info("[agentStateCheckOfMetrics] [federation is not enabled. get global agents]"); + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>().eq(Agent::getType, Constant.AgentType.GLOBAL.getValue())); + downAgentList = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + log.info("[agentStateCheckOfMetrics] [global agent scrapes endpoint metrics] [total agent size: {}] [down agent size: {}]", totalAgentList.size(), downAgentList.size()); + } + + if (StrUtil.equals("1", federationEnabled)) { + // federation 模式开启 ,Per-datacenter scrape endpoint jobs + Integer assetId = endpoint.getAssetId(); + AssetAsset asset = assetService.getById(assetId); + + // per-datacenter agent list + totalAgentList = agentService.list(new LambdaUpdateWrapper<Agent>() + .eq(Agent::getType, Constant.AgentType.PER_DATACENTER.getValue()) + .eq(Agent::getDcId, asset.getDcId())); + + List<Agent> downPerDcAgents = totalAgentList.stream().filter(agent -> Tool.ObjectUtil.notEqual(1, agent.getStatus())).collect(Collectors.toList()); + + // per-datacenter scrape metrics endpoint job, query prom_api by global agent, so down agent include global agent + List<Agent> downGlobalAgents = agentService.list(new LambdaUpdateWrapper<Agent>().eq(Agent::getType, Constant.AgentType.GLOBAL.getValue()).ne(Agent::getStatus, 1)); + + // down agent list include per-datacenter and global agent + downAgentList.addAll(downPerDcAgents); + downAgentList.addAll(downGlobalAgents); + + log.info("[agentStateCheckOfMetrics] [per-datacenter agent scrapes endpoint metrics] [total per-datacenter agent size: {}] [down per-datacenter agent size: {}] [down global agent size: {}]", totalAgentList.size(), downPerDcAgents.size(), downGlobalAgents.size()); + } + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.agent.status") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isNotEmpty(downAgentList))) { + // has down agent + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.agent.status"); + } else if (Tool.BooleanUtil.and(Tool.CollUtil.isNotEmpty(totalAgentList), + Tool.CollUtil.isEmpty(downAgentList))) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else if (Tool.CollUtil.isEmpty(totalAgentList)) { + // 没有配置 Agent 信息 + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.agent.config"); + } + return resultMap; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointConnectableCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointConnectableCheckInterceptor.java new file mode 100644 index 00000000..a87d2d06 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointConnectableCheckInterceptor.java @@ -0,0 +1,164 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Tool; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import org.apache.commons.lang3.time.StopWatch; + +import java.net.*; +import java.util.Map; + +/** + * EndpointConnectableCheckInterceptor + * 检查 Endpoint Host&Port 网络情况,端口是否开放 + * + * @author shizhendong + * @date 2023/1/4 + */ +public class EndpointConnectableCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointConnectableCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + MonitorEndpointConfig endpointConfig = endpoint.getEndpointConfig(); + + String host = JSONPath.read(endpointConfig.getConfig(), "host").toString(); + String port = JSONPath.read(endpointConfig.getConfig(), "port").toString(); + + boolean isConnectable = false; + String protocol = JSONPath.read(endpointConfig.getConfig(), "protocol").toString(); + + // check Host Is Connectable + if (Tool.StrUtil.equalsAny(protocol, "http", "https")) { + // TCP + isConnectable = this.checkHttpHostIsConnectable(host, port); + } else if (Tool.StrUtil.equalsAny(protocol, "snmp")) { + // UDP + isConnectable = this.checkSnmpHostIsConnectable(host, port); + } + + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.connectable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (isConnectable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.endpoint.resolution.connectable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.connectable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Snmp Host Is Connectable + * + * @param host + * @param port + * @return + */ + private boolean checkSnmpHostIsConnectable(String host, String port) { + log.info("[checkSnmpHostIsConnectable] [begin] [host: {}] [port: {}]", host, port); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isConnectable = true; + + DatagramSocket d = null; + try { + d = new DatagramSocket(); + String msg = "\n"; + byte[] buffer = new byte[msg.length()]; + buffer = msg.getBytes(); + + InetAddress target = InetAddress.getByName(host); + d.connect(target, Integer.valueOf(port)); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, target, Integer.valueOf(port)); + + d.send(packet); + d.setSoTimeout(5000); + d.receive(packet); + } catch (PortUnreachableException e) { + log.error(e, "[checkSnmpHostIsConnectable] [ICMP Port Unreachable]"); + // Unreachable + isConnectable = false; + } catch (Exception e) { + // 只有明确的 PortUnreachableException 异常为端口不可用,捕获的其他异常均视为端口可用,只输出日志 + log.error(e, "[checkSnmpHostIsConnectable] [error]"); + } finally { + Tool.IoUtil.close(d); + sw.stop(); + } + + log.info("[checkSnmpHostIsConnectable] [check completed] [host: {}] [port: {}] [connected: {}] [Run Time: {}]", host, port, isConnectable, sw.toString()); + return isConnectable; + } + + + /** + * check http Host Is Connectable + * + * @param host + * @param port + * @return + */ + private boolean checkHttpHostIsConnectable(String host, String port) { + log.info("[checkHttpHostIsConnectable] [begin] [host: {}] [port: {}]", host, port); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isConnectable = false; + + Socket socket = new Socket(); + try { + InetSocketAddress socketAddress = new InetSocketAddress(host, Integer.valueOf(port)); + socket.connect(socketAddress, 5000); + isConnectable = socket.isConnected(); + } catch (Exception e) { + log.error(e, "[checkHttpHostIsConnectable] [error in check process] [host: {}] [port: {}]", host, port); + } finally { + Tool.IoUtil.close(socket); + sw.stop(); + } + + log.info("[checkHttpHostIsConnectable] [check completed] [host: {}] [port: {}] [connected: {}] [Run Time: {}]", host, port, isConnectable, sw.toString()); + return isConnectable; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointMonitorStatusCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointMonitorStatusCheckInterceptor.java new file mode 100644 index 00000000..038b73b6 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointMonitorStatusCheckInterceptor.java @@ -0,0 +1,166 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetStateConf; +import com.nis.modules.asset.entity.Dc; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * EndpointMonitorStatusCheckInterceptor + * 检查 Endpoint Monitor 状态是否正常,检查项包括,DC、Asset、Endpoint config + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointMonitorStatusCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static AssetAssetService assetService; + + @Autowired + public void initBean(AssetAssetService assetService) { + EndpointMonitorStatusCheckInterceptor.assetService = assetService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointMonitorStatusCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + Integer assetId = endpoint.getAssetId(); + AssetAsset asset = assetService.queryAssetInfo(assetId); + + // check dc state + Map<Object, Object> checkDcStatusResultMap = this.checkDcStatus(asset.getDc()); + + // check asset state conf + Map<Object, Object> checkAssetMonitorStateResultMap = this.checkAssetMonitorState(asset); + + // check endpoint config enable + Map<Object, Object> checkEndpointConfigEnableResultMap = this.checkEndpointConfigEnable(endpoint); + + if (StrUtil.equalsAny(DiagnoseState.DID_NOT_PASS.getValue().toString(), + checkDcStatusResultMap.get("state").toString(), + checkAssetMonitorStateResultMap.get("state").toString(), + checkEndpointConfigEnableResultMap.get("state").toString())) { + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(checkDcStatusResultMap); + DiagnoseClient.addDiagnoseMsg(checkAssetMonitorStateResultMap); + DiagnoseClient.addDiagnoseMsg(checkEndpointConfigEnableResultMap); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.monitor.status") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Dc Status + * + * @param dc + * @return + */ + private Map<Object, Object> checkDcStatus(Dc dc) { + String dcState = dc.getState(); + log.info("[checkDcStatus] [dc state: {}]", dcState); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.monitor.dc") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (StrUtil.equals("OFF", dcState)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.monitor.dc"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } + + /** + * check Asset Monitor State + * + * @param asset + * @return + */ + private Map<Object, Object> checkAssetMonitorState(AssetAsset asset) { + AssetStateConf stateConf = asset.getState(); + Integer monitor = stateConf.getMonitor(); + log.info("[checkAssetMonitorState] [asset monitor state: {}]", monitor); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.monitor.asset") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(0, monitor)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.monitor.asset"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } + + /** + * check Endpoint Config Enable + * + * @param endpoint + * @return + */ + private Map<Object, Object> checkEndpointConfigEnable(MonitorEndpoint endpoint) { + MonitorEndpointConfig endpointConfig = endpoint.getEndpointConfig(); + Integer enable = endpointConfig.getEnable(); + log.info("[checkEndpointConfigEnable] [endpoint config enable: {}]", enable); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.monitor.config") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(0, enable)) { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.monitor.config"); + } else { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } + return resultMap; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointNetworkCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointNetworkCheckInterceptor.java new file mode 100644 index 00000000..36c43fe3 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointNetworkCheckInterceptor.java @@ -0,0 +1,105 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Tool; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import org.apache.commons.lang3.time.StopWatch; +import org.springframework.stereotype.Component; + +import java.net.InetAddress; +import java.util.Map; + +/** + * EndpointNetworkCheckInterceptor + * 检查 Endpoint 配置的 host ,是否可达 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointNetworkCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointNetworkCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + MonitorEndpointConfig endpointConfig = endpoint.getEndpointConfig(); + + // check Ip IsR eachable + boolean ipIsReachable = this.checkIpIsReachable(JSONPath.read(endpointConfig.getConfig(), "host").toString()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.reachable") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (ipIsReachable) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + // set resolution + resultMap.put("resolution", "diagnose.endpoint.resolution.reachable"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.reachable") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Ip IsR eachable + * + * @param host + * @return a {@code boolean} indicating if the address is reachable. + */ + private boolean checkIpIsReachable(String host) { + log.info("[checkIpIsReachable] [begin] [host: {}]", host); + + StopWatch sw = new StopWatch(); + sw.start(); + + boolean isReachable = false; + try { + InetAddress inetAddress = InetAddress.getByName(host); + // timeout the time, in milliseconds, before the call aborts, default 5s + isReachable = inetAddress.isReachable(5000); + } catch (Exception e) { + log.error(e, "[checkIpIsReachable] [error in check process] [host: {}]", host); + } finally { + sw.stop(); + } + + log.info("[checkIpIsReachable] [check completed] [host: {}] [reachable: {}] [Run Time: {}]", host, isReachable, sw.toString()); + return isReachable; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointSNMPAgentCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointSNMPAgentCheckInterceptor.java new file mode 100644 index 00000000..671d986b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointSNMPAgentCheckInterceptor.java @@ -0,0 +1,116 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.SnmpUtil; +import com.nis.common.utils.Tool; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import com.nis.modules.sys.entity.SnmpCredential; +import com.nis.modules.sys.service.SnmpCredentialService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * EndpointSNMPAgentCheckInterceptor + * 检查 Endpoint SNMP Agent 服务是否可用 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointSNMPAgentCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static SnmpCredentialService snmpCredentialService; + + @Autowired + public void initBean(SnmpCredentialService snmpCredentialService) { + EndpointSNMPAgentCheckInterceptor.snmpCredentialService = snmpCredentialService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointSNMPAgentCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + MonitorEndpointConfig endpointConfig = endpoint.getEndpointConfig(); + + String host = JSONPath.read(endpointConfig.getConfig(), "host").toString(); + String port = JSONPath.read(endpointConfig.getConfig(), "port").toString(); + String snmpCredentialsId = JSONPath.read(endpointConfig.getConfig(), "snmpCredentialsId").toString(); + + boolean healthyStatus = this.checkSnmpAgentStatus(host, port, snmpCredentialsId); + log.info("[EndpointSNMPAgentCheckInterceptor] [snmp agent status] [healthy: {}]", healthyStatus); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.snmp.agent") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (healthyStatus) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.snmp.agent"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.snmp.agent") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Snmp Agent Status + * 通过执行 snmpwalk 判断 snmp agent 状态是否正常 + * + * @param host + * @param port + * @param snmpCredentialsId + * @return + */ + private boolean checkSnmpAgentStatus(String host, String port, String snmpCredentialsId) { + log.info("[checkSnmpAgentStatus] [host: {}] [port: {}] [credentialsId: {}]", host, port, snmpCredentialsId); + + SnmpCredential snmpCredential = snmpCredentialService.getById(snmpCredentialsId); + Map snmpInfos = JSONObject.parseObject((String) snmpCredential.getConfig(), Map.class); + List<Map> snmpResults = Tool.ListUtil.empty(); + try { + snmpResults = SnmpUtil.snmpWalk(host, Integer.valueOf(port), snmpCredential.getType(), (String) snmpInfos.get("readCommunity"), "", snmpInfos); + } catch (IOException e) { + log.error(e, "[checkSnmpAgentStatus] [snmp walk error.]"); + } + + log.info("[checkSnmpAgentStatus] [snmp walk reslut] [size: {}]", snmpResults.size()); + return Tool.CollUtil.isNotEmpty(snmpResults); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeErrorMsgCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeErrorMsgCheckInterceptor.java new file mode 100644 index 00000000..e0ca3de9 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeErrorMsgCheckInterceptor.java @@ -0,0 +1,129 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * EndpointScrapeErrorMsgCheckInterceptor + * 检查 Endpoint Scrape Job 失败原因 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointScrapeErrorMsgCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static RedisTemplate redisTemplate; + + private static PromApiService promApiService; + + @Autowired + public void initBean(RedisTemplate redisTemplate, PromApiService promApiService) { + EndpointScrapeErrorMsgCheckInterceptor.redisTemplate = redisTemplate; + EndpointScrapeErrorMsgCheckInterceptor.promApiService = promApiService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointScrapeErrorMsgCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // check Scrape Job Status + Map<Object, Object> resultMap = this.checkScrapeJobStatus(endpoint.getId()); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + // 未检查 + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.scrape.status") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + } + + /** + * check Scrape Job Status + * + * @param endpointId + * @return + */ + private Map<Object, Object> checkScrapeJobStatus(Integer endpointId) { + HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash(); + String agentId = opsForHash.get(Constant.REDIS_KEY_ENDPOINT_PROM, Tool.StrUtil.toString(endpointId)); + log.info("[checkScrapeJobStatus] [get agent id from redis] [key: {}] [agentId: {}]", Constant.REDIS_KEY_ENDPOINT_PROM, agentId); + + // nz 系统内已存在 agent & endpoint 对应关系,通过查询 /target api 确认是否为 timeout 问题 + JSONObject targets = promApiService.targets(null, agentId, null, null, Tool.ListUtil.empty(), null); + Object activeTargets = JSONPath.read(targets.toJSONString(), "data.activeTargets"); + List<JSONObject> activeTargetList = (List) Tool.ObjectUtil.defaultIfNull(activeTargets, Tool.ListUtil.empty()); + + JSONObject endpointTargetInfo = activeTargetList.stream() + .filter(Objects::nonNull) + .filter(jsonObject -> Tool.StrUtil.equals(Tool.StrUtil.toString(JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id")), endpointId.toString())) + .findFirst() + .orElse(new JSONObject()); + + log.info("[checkScrapeJobStatus] [target api result content] [endpointId: {}] [info: {}]", endpointId, Tool.JSONUtil.toJsonStr(endpointTargetInfo)); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.scrape.status") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (Tool.ObjectUtil.equal(endpointTargetInfo.get("health"), "up")) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + String lastError = Tool.StrUtil.toString(endpointTargetInfo.get("lastError")); + + log.warn("[checkScrapeJobStatus] [check failed] [endpointId: {}] [lastError: {}]", endpointId, lastError); + // DID NOT PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + + if (lastError.contains("connect: no route to host")) { + // 请求被防火墙阻止 + resultMap.put("resolution", "diagnose.endpoint.resolution.firewall"); + } else if (lastError.contains("context deadline exceeded") || lastError.contains("i/o timeout")) { + // 连接超时 + resultMap.put("resolution", "diagnose.endpoint.resolution.timeout"); + } else if (lastError.contains("server returned HTTP status 401 Unauthorized")) { + // 身份验证失败 + resultMap.put("resolution", "diagnose.endpoint.resolution.auth"); + } else if (lastError.contains("connect: connection refused")) { + // 端口无服务监听 + resultMap.put("resolution", "diagnose.endpoint.resolution.connectable"); + } else { + resultMap.put("resolution", "diagnose.endpoint.resolution.error"); + } + } + return resultMap; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeJobConfExistCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeJobConfExistCheckInterceptor.java new file mode 100644 index 00000000..2078133d --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointScrapeJobConfExistCheckInterceptor.java @@ -0,0 +1,126 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * EndpointScrapeJobConfExistCheckInterceptor + * 检查 Endpoint Scrape Job 是否已下发 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointScrapeJobConfExistCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static RedisTemplate redisTemplate; + + private static PromApiService promApiService; + + @Autowired + public void initBean(RedisTemplate redisTemplate, PromApiService promApiService) { + EndpointScrapeJobConfExistCheckInterceptor.redisTemplate = redisTemplate; + EndpointScrapeJobConfExistCheckInterceptor.promApiService = promApiService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointScrapeJobConfExistCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // check Scrape Job Config + boolean configured = this.checkScrapeJobConfig(endpoint.getId()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.scrape.config") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + if (configured) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.scrape.config"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.scrape.config") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Scrape Job Config + * + * @param endpointId + * @return + */ + private boolean checkScrapeJobConfig(Integer endpointId) { + HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash(); + String agentId = opsForHash.get(Constant.REDIS_KEY_ENDPOINT_PROM, Tool.StrUtil.toString(endpointId)); + log.info("[checkScrapeJobConfig] [get agent id from redis] [key: {}] [agentId: {}]", Constant.REDIS_KEY_ENDPOINT_PROM, agentId); + + boolean configured = false; + if (Tool.StrUtil.isNotEmpty(agentId)) { + // nz 系统内已存在 agent & endpoint 对应关系,通过查询 /target api 再次确认 + JSONObject targets = promApiService.targets(null, agentId, null, null, Tool.ListUtil.empty(), null); + Object activeTargets = JSONPath.read(targets.toJSONString(), "data.activeTargets"); + List<JSONObject> activeTargetList = (List) Tool.ObjectUtil.defaultIfNull(activeTargets, Tool.ListUtil.empty()); + + List<String> promServerConfiguredEndpoints = activeTargetList.stream() + .filter(Objects::nonNull) + .filter(jsonObject -> ObjectUtil.isNotNull(JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id"))) + .map(jsonObject -> JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id").toString()) + .collect(Collectors.toList()); + + if (promServerConfiguredEndpoints.contains(StrUtil.toString(endpointId))) { + configured = true; + } + } + + log.info("[checkScrapeJobConfig] [configuration exist in prometheus] [flag: {}]", configured); + return configured; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointTimeOutOfScrapeCheckInterceptor.java b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointTimeOutOfScrapeCheckInterceptor.java new file mode 100644 index 00000000..d05365a8 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/chain/endpoint/metrics/EndpointTimeOutOfScrapeCheckInterceptor.java @@ -0,0 +1,129 @@ +package com.nis.modules.diagnose.chain.endpoint.metrics; + + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.DiagnoseInterceptor; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * EndpointTimeOutOfScrapeCheckInterceptor + * 检查 Endpoint Scrape Job 失败原因是不是 timeout 问题 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Component +public class EndpointTimeOutOfScrapeCheckInterceptor implements DiagnoseInterceptor { + + private static final Log log = Log.get(); + + private static RedisTemplate redisTemplate; + + private static PromApiService promApiService; + + @Autowired + public void initBean(RedisTemplate redisTemplate, PromApiService promApiService) { + EndpointTimeOutOfScrapeCheckInterceptor.redisTemplate = redisTemplate; + EndpointTimeOutOfScrapeCheckInterceptor.promApiService = promApiService; + } + + @Override + public void intercept(Chain chain) { + boolean continueDiagnosis = chain.isContinueDiagnosis(); + log.info("[EndpointTimeOutOfScrapeCheckInterceptor] [continue diagnosis: {}]", continueDiagnosis); + + if (continueDiagnosis) { + // process object + MonitorEndpoint endpoint = (MonitorEndpoint) chain.object(); + + // check Scrape Time out + boolean timeOut = this.checkScrapeTimeOut(endpoint.getId()); + + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.timeout") + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + if (!timeOut) { + // PASS + resultMap.put("state", DiagnoseState.PASS.getValue()); + } else { + // DID_NOT_PASS + resultMap.put("state", DiagnoseState.DID_NOT_PASS.getValue()); + resultMap.put("resolution", "diagnose.endpoint.resolution.timeout"); + + // stopDiagnose + chain.stopDiagnose(); + } + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } else { + Map<Object, Object> resultMap = Tool.MapUtil.builder() + .put("item", "metric.diagnose.endpoint.item.timeout") + .put("state", DiagnoseState.NOT_CHECKED.getValue()) + .put("resolution", Tool.StrUtil.EMPTY) + .map(); + + // update check msg + DiagnoseClient.addDiagnoseMsg(resultMap); + } + + // next chain + chain.proceed(chain.object()); + } + + /** + * check Scrape Time Out + * + * @param endpointId + * @return + */ + private boolean checkScrapeTimeOut(Integer endpointId) { + HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash(); + String agentId = opsForHash.get(Constant.REDIS_KEY_ENDPOINT_PROM, Tool.StrUtil.toString(endpointId)); + log.info("[checkScrapeTimeOut] [get agent id from redis] [key: {}] [agentId: {}]", Constant.REDIS_KEY_ENDPOINT_PROM, agentId); + + boolean timeOut = false; + if (Tool.StrUtil.isNotEmpty(agentId)) { + // nz 系统内已存在 agent & endpoint 对应关系,通过查询 /target api 确认是否为 timeout 问题 + JSONObject targets = promApiService.targets(null, agentId, null, null, Tool.ListUtil.empty(), null); + Object activeTargets = JSONPath.read(targets.toJSONString(), "data.activeTargets"); + List<JSONObject> activeTargetList = (List) Tool.ObjectUtil.defaultIfNull(activeTargets, Tool.ListUtil.empty()); + + JSONObject endpointTargetInfo = activeTargetList.stream() + .filter(Objects::nonNull) + .filter(jsonObject -> Tool.StrUtil.equals(Tool.StrUtil.toString(JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id")), endpointId.toString())) + .findFirst() + .orElse(new JSONObject()); + + if (log.isDebugEnabled()) { + log.debug("[checkScrapeTimeOut] [target api result content] [endpointId: {}] [info: {}]", endpointId, Tool.JSONUtil.toJsonStr(endpointTargetInfo)); + } + + String health = Tool.StrUtil.toString(endpointTargetInfo.get("health")); + if (Tool.StrUtil.equalsIgnoreCase("down", health)) { + String lastError = Tool.StrUtil.toString(endpointTargetInfo.get("lastError")); + log.info("[checkScrapeTimeOut] [Error Msg] [endpointId: {}] [lastError: {}]", endpointId, lastError); + if (Tool.StrUtil.isNotEmpty(lastError) && (lastError.contains("context deadline exceeded") || lastError.contains("i/o timeout"))) { + timeOut = true; + } + } + } + return timeOut; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java b/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java new file mode 100644 index 00000000..e9adeb2e --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/controller/DiagnoseController.java @@ -0,0 +1,55 @@ +package com.nis.modules.diagnose.controller; + +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.R; +import com.nis.common.utils.RCode; +import com.nis.modules.diagnose.service.DiagnoseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; +import java.util.Map; + +/** + * DiagnoseController 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +@RestController +public class DiagnoseController { + + @Autowired + private DiagnoseService diagnoseService; + + @GetMapping("/asset/diagnose/{id}") + public R assetDiagnose(@PathVariable(value = "id", required = false) Integer assetId, + @RequestHeader(required = false, defaultValue = "en") String language) { + ValidateUtils.is(assetId).notNull(RCode.ASSET_ID_ISNULL); + + List<Map<Object, Object>> diagnoseMsgList = diagnoseService.assetErrorDiagnosis(assetId, language); + return R.ok().putData("list", diagnoseMsgList); + } + + @GetMapping("/agent/diagnose/{id}") + public R agentDiagnose(@PathVariable(value = "id", required = false) Integer agentId, + @RequestHeader(required = false, defaultValue = "en") String language) { + ValidateUtils.is(agentId).notNull(RCode.AGENT_ID_ISNULL); + + List<Map<Object, Object>> diagnoseMsgList = diagnoseService.agentErrorDiagnosis(agentId, language); + return R.ok().putData("list", diagnoseMsgList); + } + + @GetMapping("/monitor/endpoint/diagnose/{id}") + public R endpointDiagnose(@PathVariable(value = "id", required = false) Integer endpointId, + @RequestHeader(required = false, defaultValue = "en") String language) { + ValidateUtils.is(endpointId).notNull(RCode.ENDPOINT_ID_ISNULL); + + List<Map<Object, Object>> diagnoseMsgList = diagnoseService.endpointErrorDiagnosis(endpointId, language); + return R.ok().putData("list", diagnoseMsgList); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java b/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java new file mode 100644 index 00000000..f296ae5e --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/service/DiagnoseService.java @@ -0,0 +1,42 @@ +package com.nis.modules.diagnose.service; + +import java.util.List; +import java.util.Map; + + +/** + * DiagnoseService 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +public interface DiagnoseService { + + /** + * asset Diagnosis + * + * @param assetId + * @param language + * @return + */ + List<Map<Object, Object>> assetErrorDiagnosis(Integer assetId, String language); + + /** + * agent Diagnosis + * + * @param agentId + * @param language + * @return + */ + List<Map<Object, Object>> agentErrorDiagnosis(Integer agentId, String language); + + /** + * endpoint Diagnosis + * + * @param endpointId + * @param language + * @return + */ + List<Map<Object, Object>> endpointErrorDiagnosis(Integer endpointId, String language); +} + diff --git a/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java new file mode 100644 index 00000000..ebfd2118 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/diagnose/service/impl/DiagnoseServiceImpl.java @@ -0,0 +1,195 @@ +package com.nis.modules.diagnose.service.impl; + +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONPath; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.Constant.MonitorConfType; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.diagnose.chain.DiagnoseClient; +import com.nis.modules.diagnose.chain.agent.AgentComponentsCheckInterceptor; +import com.nis.modules.diagnose.chain.agent.AgentConnectableCheckInterceptor; +import com.nis.modules.diagnose.chain.agent.AgentNetworkCheckInterceptor; +import com.nis.modules.diagnose.chain.asset.AgentStateCheckOfPingInterceptor; +import com.nis.modules.diagnose.chain.asset.AssetNetworkCheckInterceptor; +import com.nis.modules.diagnose.chain.asset.AssetStateConfCheckInterceptor; +import com.nis.modules.diagnose.chain.asset.BlackboxConfigCheckInterceptor; +import com.nis.modules.diagnose.chain.endpoint.logs.AgentStateCheckOfLogsEndpointInterceptor; +import com.nis.modules.diagnose.chain.endpoint.logs.EndpointLogClientStatusCheckInterceptor; +import com.nis.modules.diagnose.chain.endpoint.logs.TalonNetworkCheckInterceptor; +import com.nis.modules.diagnose.chain.endpoint.logs.TalonStatusCheckInterceptor; +import com.nis.modules.diagnose.chain.endpoint.metrics.*; +import com.nis.modules.diagnose.service.DiagnoseService; +import com.nis.modules.endpoint.entity.MonitorEndpoint; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import com.nis.modules.endpoint.service.MonitorEndpointConfigService; +import com.nis.modules.endpoint.service.MonitorEndpointService; +import com.nis.modules.sys.service.SysI18nService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * DiagnoseServiceImpl 故障排查 + * + * @author shizhendong + * @date 2023/1/4 + */ +@Service +public class DiagnoseServiceImpl implements DiagnoseService { + + private static final Log log = Log.get(); + + @Autowired + private AgentService agentService; + + @Autowired + private AssetAssetService assetService; + + @Autowired + private SysI18nService sysI18nService; + + @Autowired + private MonitorEndpointService monitorEndpointService; + + @Autowired + private MonitorEndpointConfigService monitorEndpointConfigService; + + @Override + public List<Map<Object, Object>> assetErrorDiagnosis(Integer assetId, String language) { + try { + AssetAsset asset = assetService.getById(assetId); + ValidateUtils.is(asset).notNull(RCode.ASSET_NOT_EXIST); + + // diagnose client. set diagnose chain + DiagnoseClient diagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AssetStateConfCheckInterceptor()) + .addInterceptor(new AssetNetworkCheckInterceptor()) + .addInterceptor(new AgentStateCheckOfPingInterceptor()) + .addInterceptor(new BlackboxConfigCheckInterceptor()) + .build(); + + // diagnose + diagnoseClient.diagnose(asset); + + // Diagnose Msg List + List<Map<Object, Object>> diagnoseMsgList = this.queryDiagnoseMsgByLanguage(language); + return diagnoseMsgList; + } finally { + DiagnoseClient.cleanDiagnoseMsg(); + } + } + + @Override + public List<Map<Object, Object>> agentErrorDiagnosis(Integer agentId, String language) { + try { + Agent agent = agentService.getById(agentId); + ValidateUtils.is(agent).notNull(RCode.AGENT_NOTEXSITS); + + // diagnose client. set diagnose chain + DiagnoseClient diagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AgentNetworkCheckInterceptor()) + .addInterceptor(new AgentConnectableCheckInterceptor()) + .addInterceptor(new AgentComponentsCheckInterceptor()) + .build(); + + // diagnose + diagnoseClient.diagnose(agent); + + // Diagnose Msg List + List<Map<Object, Object>> diagnoseMsgList = this.queryDiagnoseMsgByLanguage(language); + return diagnoseMsgList; + } finally { + DiagnoseClient.cleanDiagnoseMsg(); + } + } + + @Override + public List<Map<Object, Object>> endpointErrorDiagnosis(Integer endpointId, String language) { + try { + MonitorEndpoint endpoint = monitorEndpointService.getById(endpointId); + ValidateUtils.is(endpoint).notNull(RCode.ENDPOINT_NOTFOUND); + + List<MonitorEndpointConfig> configList = monitorEndpointConfigService.list(new LambdaQueryWrapper<MonitorEndpointConfig>().eq(MonitorEndpointConfig::getEndpointId, endpoint.getId())); + + // metrics + MonitorEndpointConfig metricsEndpointConfig = configList.stream().filter(endpointConfig -> Tool.StrUtil.equals(endpointConfig.getType(), MonitorConfType.METRICS.getValue())).findFirst().get(); + endpoint.setEndpointConfig(metricsEndpointConfig); + + String protocol = JSONPath.read(metricsEndpointConfig.getConfig(), "protocol").toString(); + // diagnose + if (Tool.StrUtil.equalsAny(protocol, "http", "https")) { + DiagnoseClient metricsEndpointDiagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AgentStateCheckOfMetricsEndpointInterceptor()) + .addInterceptor(new EndpointMonitorStatusCheckInterceptor()) + .addInterceptor(new EndpointScrapeJobConfExistCheckInterceptor()) + .addInterceptor(new EndpointNetworkCheckInterceptor()) + .addInterceptor(new EndpointConnectableCheckInterceptor()) + .addInterceptor(new EndpointTimeOutOfScrapeCheckInterceptor()) + .addInterceptor(new EndpointScrapeErrorMsgCheckInterceptor()) + .build(); + metricsEndpointDiagnoseClient.diagnose(endpoint); + } else if (Tool.StrUtil.equalsAny(protocol, "snmp")) { + DiagnoseClient metricsEndpointDiagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AgentStateCheckOfMetricsEndpointInterceptor()) + .addInterceptor(new EndpointMonitorStatusCheckInterceptor()) + .addInterceptor(new EndpointScrapeJobConfExistCheckInterceptor()) + .addInterceptor(new EndpointNetworkCheckInterceptor()) + .addInterceptor(new EndpointConnectableCheckInterceptor()) + // snmp agent + .addInterceptor(new EndpointSNMPAgentCheckInterceptor()) + .addInterceptor(new EndpointTimeOutOfScrapeCheckInterceptor()) + .addInterceptor(new EndpointScrapeErrorMsgCheckInterceptor()) + .build(); + metricsEndpointDiagnoseClient.diagnose(endpoint); + } + + // logs + MonitorEndpointConfig logsEndpointConfig = configList.stream().filter(endpointConfig -> Tool.StrUtil.equals(endpointConfig.getType(), MonitorConfType.LOGS.getValue())).findFirst().get(); + endpoint.setEndpointConfig(logsEndpointConfig); + + DiagnoseClient logsEndpointDiagnoseClient = new DiagnoseClient.Builder() + .addInterceptor(new AgentStateCheckOfLogsEndpointInterceptor()) + .addInterceptor(new EndpointLogClientStatusCheckInterceptor()) + .addInterceptor(new TalonNetworkCheckInterceptor()) + .addInterceptor(new TalonStatusCheckInterceptor()) + .build(); + logsEndpointDiagnoseClient.diagnose(endpoint); + + // Diagnose Msg List + List<Map<Object, Object>> diagnoseMsgList = this.queryDiagnoseMsgByLanguage(language); + return diagnoseMsgList; + } finally { + DiagnoseClient.cleanDiagnoseMsg(); + } + } + + /** + * query Diagnose Msg By Language + * + * @param language + * @return + */ + private List<Map<Object, Object>> queryDiagnoseMsgByLanguage(String language) { + List<Map<Object, Object>> diagnoseMsgList = DiagnoseClient.queryDiagnoseMsg(); + + for (Map<Object, Object> map : diagnoseMsgList) { + String itemCode = map.get("item").toString(); + String itemValue = sysI18nService.queryValue(itemCode, language); + map.put("item", itemValue); + + String resolutionCode = map.get("resolution").toString(); + String resolutionValue = sysI18nService.queryValue(resolutionCode, language); + map.put("resolution", resolutionValue); + } + + return diagnoseMsgList; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java b/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java index 65f6aa8b..1e712b82 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/controller/MonitorEndpointController.java @@ -210,7 +210,7 @@ public class MonitorEndpointController { /** * endpoint 错误诊断 */ - @GetMapping( "/endpoint/diagnose/{id}") + // @GetMapping( "/endpoint/diagnose/{id}") @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.ENDPOINT) public R diagnose(@PathVariable("id") Integer id, HttpServletRequest request) throws IOException { ValidateUtils.is(id).notNull(RCode.ENDPOINT_ID_ISNULL); diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java index 4a9c24e4..e4334848 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointDao.java @@ -23,8 +23,6 @@ public interface MonitorEndpointDao extends BaseMapper<MonitorEndpoint> { */ List<MonitorEndpoint> getEnableMetricsEndpointInfoListForAgent(); - List<MonitorEndpoint> endpointDetailList(); - /** * agent logs 组织配置文件所需要的 endpoint 信息,包含 asset module project dc 等 * 目前获取的是启用状态的 endpoint diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointStateDao.java b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointStateDao.java index 6081256a..154b36d3 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointStateDao.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/dao/MonitorEndpointStateDao.java @@ -2,16 +2,13 @@ package com.nis.modules.endpoint.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.endpoint.entity.MonitorEndpointState; - -import java.util.List; - import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.util.List; + @Mapper public interface MonitorEndpointStateDao extends BaseMapper<MonitorEndpointState> { - void deleteConfStateByType(@Param("type") String type); - void updateBatchEndpointState(@Param("datas")List<MonitorEndpointState> datas,@Param("type")String type); } diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java index 53b4b314..8c018460 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpoint.java @@ -4,11 +4,11 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.nis.modules.agent.entity.Agent; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.Dc; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.project.entity.MonitorProject; -import com.nis.modules.agent.entity.Agent; import lombok.Data; import java.io.Serializable; diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpointState.java b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpointState.java index db0d0e2f..253c72c3 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpointState.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/entity/MonitorEndpointState.java @@ -33,7 +33,11 @@ public class MonitorEndpointState implements Serializable { private Integer ver; + /** + * 错误信息 + */ + private String msg; + @TableField(exist = false) private Date time; - } diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/job/EndpointStateJob.java b/nz-admin/src/main/java/com/nis/modules/endpoint/job/EndpointStateJob.java deleted file mode 100644 index 9baf4039..00000000 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/job/EndpointStateJob.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.nis.modules.endpoint.job; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nis.common.utils.Constant; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; -import com.nis.modules.endpoint.dao.MonitorEndpointStateDao; -import com.nis.modules.endpoint.entity.MonitorEndpointConfig; -import com.nis.modules.endpoint.entity.MonitorEndpointState; -import com.nis.modules.endpoint.service.MonitorEndpointConfigService; -import com.nis.modules.endpoint.service.MonitorEndpointStateService; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.PromApiService; -import org.apache.commons.lang3.time.StopWatch; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.http.HttpEntity; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.transaction.annotation.Transactional; - -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -@DisallowConcurrentExecution -public class EndpointStateJob extends QuartzJobBean { - - private Log log = Log.get(); - - @Autowired - private PromApiService promApiService; - - @Autowired - private MonitorEndpointConfigService endpointConfigService; - - @Autowired - private MonitorEndpointStateDao endpointStateDao; - - @Autowired - private MonitorEndpointStateService endpointStateService; - - @Autowired - private RedisTemplate redisTemplate; - - // 计数器,每 forceSync 个周期 执行一次强制执行 - private volatile static Integer counter = 1; - - @Value("${endpoint.state.force.sync:8}") - private Integer forceSync; - - @Override - protected void executeInternal(JobExecutionContext context) throws JobExecutionException { - Thread.currentThread().setName("EndpointStateJob"); - // 检查 haMode - String serverId = (String) redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); - if (!StrUtil.equals(serverId, Constant.SERVER_ID)) return; - log.info("Endpoint state job 开始执行"); - StopWatch sw = new StopWatch(); - sw.start(); - try { - this.updateEndpointStatus(); - } catch (RuntimeException e) { - log.error(e); - } finally { - sw.stop(); - log.info("Endpoint state 执行结束,Run Time: {}", sw.toString()); - } - } - - /** - * 更新 endpoint 状态 - */ - @SuppressWarnings("unlikely-arg-type") - @Transactional(rollbackFor = Exception.class) - public void updateEndpointStatus() { - // 随机获取一个 Global Prometheus - Agent agent = promApiService.getOneAvaliableGlobalAgent(); - if (agent == null) { - log.debug("Endpoint 状态为全部为 0 (DOWN),当前暂无可用 agent"); - this.allMetricsEndpointStateDown(); - return; - } - - // 所有的 metrics endpoint config - List<MonitorEndpointConfig> metricsEndpointConfigList = endpointConfigService.getEndpointConfigInfoListByType(Constant.MonitorConfType.METRICS.getValue()); - - // up 的 metrics / logs endpoint - List<MonitorEndpointState> upMetricsEndpointStateList = this.getUpMetricsEndpointStateList(metricsEndpointConfigList); - - // 处理 Down 掉的 endpoint / 设置对应的状态 - Set<Integer> upMetricsConfId = upMetricsEndpointStateList.stream().map(MonitorEndpointState::getConfigId).collect(Collectors.toSet()); - List<MonitorEndpointConfig> downEndpointList = metricsEndpointConfigList.stream().filter(conf -> !upMetricsConfId.contains(conf.getId())).collect(Collectors.toList()); - - // 设置 down state - List<MonitorEndpointState> downEndpointStateList = new ArrayList<>(); - for (MonitorEndpointConfig conf : downEndpointList) { - Integer state = 0; - // 0:关闭 1:开启 - Integer monitor = conf.getStateConf().getMonitor(); - // 0:停用 1:启用 - Integer enabled = conf.getEnable(); - // 开启:ON, 关闭:OFF - String dcStateStr = conf.getDc().getState(); - boolean dcState = dcStateStr.equals("ON") ? true : false; - if (!dcState && monitor.equals(0) && enabled.equals(1)) { - state = 2; - } else if (!dcState && monitor.equals(1) && enabled.equals(0)) { - state = 4; - } else if (dcState && monitor.equals(0) && enabled.equals(0)) { - state = 8; - } else if (!dcState && monitor.equals(1) && enabled.equals(1)) { - state = 6; - } else if (dcState && monitor.equals(0) && enabled.equals(1)) { - state = 10; - } else if (dcState && monitor.equals(1) && enabled.equals(0)) { - state = 12; - } - downEndpointStateList.add(new MonitorEndpointState(conf.getEndpointId(), conf.getId(), conf.getType(), state, conf.getVersion(), new Date())); - } - - List<MonitorEndpointState> allState = new ArrayList<MonitorEndpointState>(); - allState.addAll(upMetricsEndpointStateList); - allState.addAll(downEndpointStateList); - - //判断查询数据与缓存中变化的信息 - Map endpointStates = redisTemplate.opsForHash().entries(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY); - if(ToolUtil.isNotEmpty(endpointStates) && counter % forceSync != 0) { - for(int i=allState.size()-1;i>=0;i--) { - MonitorEndpointState endpointState = allState.get(i); - if(endpointStates.containsKey(endpointState.getEndpointId().toString())) { - MonitorEndpointState cacheEndpointState = JSON.parseObject((String)endpointStates.get(endpointState.getEndpointId().toString()),MonitorEndpointState.class); - redisTemplate.opsForHash().put(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, endpointState.getEndpointId().toString(), JSON.toJSONString(endpointState)); - if(cacheEndpointState.getState().equals(endpointState.getState())) { - // 如果状态相同则只更新缓存中的数据信息 - allState.remove(i); - } - }else{ - // 数据库存在 缓存中不存在 - redisTemplate.opsForHash().put(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, endpointState.getEndpointId().toString(), JSON.toJSONString(endpointState)); - } - } - }else { - for(MonitorEndpointState endpointState:allState) { - redisTemplate.opsForHash().put(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, endpointState.getEndpointId().toString(), JSON.toJSONString(endpointState)); - } - } - // 超时周期设置为两个endpointState周期 - redisTemplate.expire(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, 2, TimeUnit.MINUTES); - // 保存 根据类型以及endpointId进行新增或者修改 - if(ToolUtil.isNotEmpty(allState)) { - // 将数据分为新增或者修改 - List<Integer> endpointIds = allState.stream().map(MonitorEndpointState::getEndpointId).collect(Collectors.toList()); - List<MonitorEndpointState> existStates = endpointStateService.list(new LambdaQueryWrapper<MonitorEndpointState>() - .in(MonitorEndpointState::getEndpointId, endpointIds).eq(MonitorEndpointState::getType, Constant.MonitorConfType.METRICS.getValue())); - List<Integer> existIds = existStates.stream().map(MonitorEndpointState::getEndpointId).collect(Collectors.toList()); - List<MonitorEndpointState> batchUpdateStates = allState.stream().filter(s->existIds.contains(s.getEndpointId())).collect(Collectors.toList()); - List<MonitorEndpointState> batchAddStates = allState.stream().filter(s->!existIds.contains(s.getEndpointId())).collect(Collectors.toList()); - if(ToolUtil.isNotEmpty(batchAddStates)) { - log.debug("Endpoint state batch add datas info : %s ",JSON.toJSON(batchAddStates)); - endpointStateService.saveBatch(batchAddStates); - } - if(ToolUtil.isNotEmpty(batchUpdateStates)) { - log.debug("Endpoint state batch update datas info : %s ",JSON.toJSON(batchAddStates)); - endpointStateService.modifyBatchEndpointState(batchUpdateStates, Constant.MonitorConfType.METRICS.getValue()); - } - } - if(counter % forceSync == 0) { - counter = 1; - }else { - counter++; - } - } - - /** - * 返回 up metrics endpoint state list - * - * @param endpointConfigList - * @return - */ - private List<MonitorEndpointState> getUpMetricsEndpointStateList(List<MonitorEndpointConfig> endpointConfigList) { - Map<Integer, String> metricsEndpointIdAndState = getMetricsEndpointIdAndStateMapByPath(); - - List<MonitorEndpointState> upMetricsEndpointStateList = new ArrayList<>(); - for (Map.Entry<Integer, String> entry : metricsEndpointIdAndState.entrySet()) { - Integer endpointId = entry.getKey(); - String stateStr = entry.getValue(); - if ("1".equals(stateStr)) { - MonitorEndpointConfig endpointConfig = endpointConfigList.stream().filter(conf -> conf.getEndpointId().equals(endpointId) && StrUtil.equals(Constant.MonitorConfType.METRICS.getValue(), conf.getType())).findFirst().orElse(null); - if (endpointConfig == null) continue; - upMetricsEndpointStateList.add(new MonitorEndpointState(endpointId, endpointConfig.getId(), Constant.MonitorConfType.METRICS.getValue(), 1, endpointConfig.getVersion(), new Date())); - } - } - return upMetricsEndpointStateList; - } - - /** - * 全部 metrics endpoint 状态为 down - */ - private void allMetricsEndpointStateDown() { - endpointStateDao.deleteConfStateByType(Constant.MonitorConfType.METRICS.getValue()); - List<MonitorEndpointConfig> metricsEndpointConfigList = endpointConfigService.list(new LambdaQueryWrapper<MonitorEndpointConfig>().eq(MonitorEndpointConfig::getType, Constant.MonitorConfType.METRICS.getValue())); - List<MonitorEndpointState> stateList = new ArrayList<>(metricsEndpointConfigList.size()); - metricsEndpointConfigList.forEach(conf -> stateList.add(new MonitorEndpointState(conf.getEndpointId(), conf.getId(), conf.getType(), 0, conf.getVersion(), new Date()))); - endpointStateService.saveBatch(stateList); - } - - private Map<Integer, String> getMetricsEndpointIdAndStateMapByPath() { - JSONObject jsonObject = promApiService.query("up", null, null); - Map dataMap = (Map) jsonObject.get("data"); - List<Map> resultList = JSONObject.parseArray(JSONObject.toJSONString(dataMap.get("result")), Map.class); - - Map<Integer, String> map = new HashMap<>(); - for (Map pojo : resultList) { - Map metricMap = (Map) pojo.get("metric"); - Object endpointId = metricMap.get("endpoint_id"); - if (endpointId == null) continue; - List<String> timeAndData = (List<String>) pojo.get("value"); - map.put(Integer.valueOf(endpointId.toString()), timeAndData.get(1)); - } - return map; - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/job/MetricTypeEndpointStatusJob.java b/nz-admin/src/main/java/com/nis/modules/endpoint/job/MetricTypeEndpointStatusJob.java new file mode 100644 index 00000000..9cd56105 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/job/MetricTypeEndpointStatusJob.java @@ -0,0 +1,382 @@ +package com.nis.modules.endpoint.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.JSONPath; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.nis.common.utils.*; +import com.nis.common.utils.Constant.AgentType; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; +import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.endpoint.entity.MonitorEndpointConfig; +import com.nis.modules.endpoint.entity.MonitorEndpointState; +import com.nis.modules.endpoint.service.MonitorEndpointConfigService; +import com.nis.modules.endpoint.service.MonitorEndpointStateService; +import com.nis.modules.sys.service.SysConfService; +import org.apache.commons.lang3.time.StopWatch; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@DisallowConcurrentExecution +public class MetricTypeEndpointStatusJob extends QuartzJobBean { + + private static final Log log = Log.get(); + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private PromApiService promApiService; + + @Autowired + private AgentService agentService; + + @Autowired + private SysConfService sysConfService; + + @Autowired + private MonitorEndpointStateService endpointStateService; + + @Autowired + private MonitorEndpointConfigService endpointConfigService; + + /** + * 计数器,每 forceSync 个周期 执行一次强制执行 + */ + private volatile static Integer counter = 1; + + @Value("${endpoint.state.force.sync:8}") + private Integer forceSync; + + private static ExecutorService threadPool = Executors.newCachedThreadPool(); + + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + Thread.currentThread().setName("EndpointStateJob"); + + // 检查 haMode + String serverId = (String) redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); + log.info("[EndpointStateJob] [Get ha lock from redis] [server id: {}]", serverId); + if (!StrUtil.equals(serverId, Constant.SERVER_ID)) { + log.warn("[EndpointStateJob] [did not get the ha lock, not run job] [redis server id: {}] [system server id: {}]", serverId, Constant.SERVER_ID); + return; + } + + log.info("[EndpointStateJob] [Begin]"); + StopWatch sw = new StopWatch(); + sw.start(); + try { + // agents For Scrape Endpoints + List<Agent> agentsForScrapeEndpoints = this.getAgentsForScrapeEndpointsByConfig(); + + if (Tool.CollUtil.isEmpty(agentsForScrapeEndpoints)) { + log.warn("[MetricTypeEndpointStatusJob] [no agent available. update all metrics type endpoint to down]"); + this.updateAllMetricTypeEndpointsToDown(); + } else { + // update Endpoint Status + this.updateEndpointStatus(agentsForScrapeEndpoints); + } + } catch (Exception e) { + log.error(e, "[EndpointStateJob Error]"); + } finally { + sw.stop(); + } + log.info("[EndpointStateJob] [Finshed] [Run Time: {}]", sw.toString()); + } + + /** + * get Agents For Scrape Endpoints By Config + * sys_config.prometheus_federation_enabled + * + * @return + */ + private List<Agent> getAgentsForScrapeEndpointsByConfig() { + // federation enable + String federationEnabled = sysConfService.getValueOrDefault(Constant.SYSCONFIG_KEY_PROM_FEDER_ENABLED, "1"); + log.info("[getAgentsForScrapeEndpointsByConfig] [prometheus_federation_enabled] [value: {}]", federationEnabled); + + List<Agent> allAgentsForScrapeEndpoints = Tool.ListUtil.list(true); + + if (StrUtil.equals("0", federationEnabled)) { + // 关闭 federation ,Global scrape endpoint jobs + log.info("[getAgentsForScrapeEndpointsByConfig] [federation is not enabled. get global agents]"); + allAgentsForScrapeEndpoints = agentService.list(new LambdaQueryWrapper<Agent>().eq(Agent::getType, AgentType.GLOBAL.getValue())); + } else if (StrUtil.equals("1", federationEnabled)) { + // 开启 federation ,Per-datacenter scrape endpoint jobs + log.info("[getAgentsForScrapeEndpointsByConfig] [federation is enabled. get per-datacenter agents]"); + allAgentsForScrapeEndpoints = agentService.list(new LambdaQueryWrapper<Agent>().eq(Agent::getType, AgentType.PER_DATACENTER.getValue())); + } + + List<Agent> healthyAgents = allAgentsForScrapeEndpoints.stream().filter(agent -> Tool.ObjectUtil.equal(agent.getStatus(), 1)).collect(Collectors.toList()); + + if (Tool.ObjectUtil.notEqual(allAgentsForScrapeEndpoints.size(), healthyAgents.size())) { + log.warn("[getAgentsForScrapeEndpointsByConfig] [has error status agent] [total size: {}] [error size: {}]", allAgentsForScrapeEndpoints.size(), allAgentsForScrapeEndpoints.size() - healthyAgents.size()); + if (log.isDebugEnabled()) { + List<Agent> errorAgents = allAgentsForScrapeEndpoints.stream().filter(agent -> Tool.ObjectUtil.notEqual(agent.getStatus(), 1)).collect(Collectors.toList()); + log.debug("[getAgentsForScrapeEndpointsByConfig] [has error status agent] [error agents: {}]", Tool.JSONUtil.toJsonStr(errorAgents)); + } + } + + log.info("[getAgentsForScrapeEndpointsByConfig] [agents size: {}]", healthyAgents.size()); + return healthyAgents; + } + + @SuppressWarnings("unlikely-arg-type") + @Transactional(rollbackFor = Exception.class) + public void updateEndpointStatus(List<Agent> agentsForScrapeEndpoints) { + + List<MonitorEndpointState> updateMetricsEndpointStateList = this.getCurrentMetricsEndpointStatusList(agentsForScrapeEndpoints); + log.info("[updateEndpointStatus] [update metrics endpoints] [total size: {}]", updateMetricsEndpointStateList.size()); + + // 判断查询数据与缓存中变化的信息 + Map endpointStates = redisTemplate.opsForHash().entries(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY); + if (ToolUtil.isNotEmpty(endpointStates) && counter % forceSync != 0) { + log.info("[updateEndpointStatus] [incrementally update the metrics endpoint state in redis]"); + for (int i = updateMetricsEndpointStateList.size() - 1; i >= 0; i--) { + MonitorEndpointState endpointState = updateMetricsEndpointStateList.get(i); + if (endpointStates.containsKey(endpointState.getEndpointId().toString())) { + MonitorEndpointState cacheEndpointState = JSON.parseObject((String) endpointStates.get(endpointState.getEndpointId().toString()), MonitorEndpointState.class); + redisTemplate.opsForHash().put(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, endpointState.getEndpointId().toString(), JSON.toJSONString(endpointState)); + if (cacheEndpointState.getState().equals(endpointState.getState())) { + // 如果状态相同则只更新缓存中的数据信息 + updateMetricsEndpointStateList.remove(i); + } + } else { + // 数据库存在 缓存中不存在 + redisTemplate.opsForHash().put(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, endpointState.getEndpointId().toString(), JSON.toJSONString(endpointState)); + } + } + } else { + log.info("[updateEndpointStatus] [Full update cache]"); + Map<String, String> updateMetricsEndpointsInRedis = updateMetricsEndpointStateList.stream().collect(Collectors.toMap(state -> StrUtil.toString(state.getEndpointId()), state -> JSONUtil.toJsonStr(state))); + redisTemplate.opsForHash().putAll(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, updateMetricsEndpointsInRedis); + } + // 超时周期设置为两个 endpointState 周期 + redisTemplate.expire(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, 2, TimeUnit.MINUTES); + + // 保存 根据类型以及endpointId进行新增或者修改 + if (ToolUtil.isNotEmpty(updateMetricsEndpointStateList)) { + // 将数据分为新增或者修改 + List<Integer> endpointIds = updateMetricsEndpointStateList.stream().map(MonitorEndpointState::getEndpointId).collect(Collectors.toList()); + List<MonitorEndpointState> existStates = endpointStateService.list(new LambdaQueryWrapper<MonitorEndpointState>() + .in(MonitorEndpointState::getEndpointId, endpointIds).eq(MonitorEndpointState::getType, Constant.MonitorConfType.METRICS.getValue())); + List<Integer> existIds = existStates.stream().map(MonitorEndpointState::getEndpointId).collect(Collectors.toList()); + List<MonitorEndpointState> batchUpdateStates = updateMetricsEndpointStateList.stream().filter(s -> existIds.contains(s.getEndpointId())).collect(Collectors.toList()); + List<MonitorEndpointState> batchAddStates = updateMetricsEndpointStateList.stream().filter(s -> !existIds.contains(s.getEndpointId())).collect(Collectors.toList()); + if (ToolUtil.isNotEmpty(batchAddStates)) { + if (log.isDebugEnabled()) { + log.debug("[updateEndpointStatus] [add endpoint status] [values: {}]", JSON.toJSON(batchAddStates)); + } + endpointStateService.saveBatch(batchAddStates); + } + if (ToolUtil.isNotEmpty(batchUpdateStates)) { + if (log.isDebugEnabled()) { + log.debug("[updateEndpointStatus] [update endpoint status] [values: {}]", JSON.toJSON(batchAddStates)); + } + endpointStateService.modifyBatchEndpointState(batchUpdateStates, Constant.MonitorConfType.METRICS.getValue()); + } + } + if (counter % forceSync == 0) { + counter = 1; + } else { + counter++; + } + log.info("[updateEndpointStatus] [update state finshed] [counter: {}] [forceSync: {}]", counter, forceSync); + } + + /** + * get Current Metrics Endpoint Status List + * 通过查询 prometheus /api/v1/targets 获得 endpoint 状态信息,结合 数据库 中 Endpoint 相关逻辑内容,返回当前所有 Metrics Endpoint State 实体 + * + * @param agentsForScrapeEndpoints + * @return + */ + private List<MonitorEndpointState> getCurrentMetricsEndpointStatusList(List<Agent> agentsForScrapeEndpoints) { + // metric Type Endpoint Config List + List<MonitorEndpointConfig> metricTypeEndpointConfigList = endpointConfigService.getEndpointConfigInfoListByType(Constant.MonitorConfType.METRICS.getValue()); + Map<Integer, MonitorEndpointConfig> endpointIdAndConfigMapping = metricTypeEndpointConfigList.stream().collect(Collectors.toMap(MonitorEndpointConfig::getEndpointId, Function.identity())); + + // everything but up is down + Map<Integer, MonitorEndpointConfig> downMetricsEndpointIdAndConfigMapping = ObjectUtil.cloneByStream(endpointIdAndConfigMapping); + + // active Target List + List<JSONObject> activeTargetList = this.queryTargetsApiToGetEndpointStatus(agentsForScrapeEndpoints); + log.info("[getCurrentMetricsEndpointStatusList] [query active Target] [szie: {}]", activeTargetList.size()); + + // up + List<MonitorEndpointState> upMetricsEndpointStateList = Tool.ListUtil.list(true); + activeTargetList.stream() + .filter(jsonObject -> StrUtil.equalsIgnoreCase("up", JSONPath.read(jsonObject.toJSONString(), "health").toString())) + .map(jsonObject -> JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id").toString()) + .forEach(endpointIdStr -> { + Integer endpointId = Integer.valueOf(endpointIdStr); + MonitorEndpointConfig confObj = endpointIdAndConfigMapping.get(endpointId); + if (ObjectUtil.isNull(confObj)) { + log.warn("[getCurrentMetricsEndpointStatusList] [Can't get endpoint config by activeTarget's endpoint_id value] [activeTarget's endpoint_id: {}]", endpointId); + return; + } + // up endpoint state + upMetricsEndpointStateList.add(new MonitorEndpointState(endpointId, confObj.getId(), Constant.MonitorConfType.METRICS.getValue(), 1, confObj.getVersion(), StrUtil.EMPTY, DateTime.now())); + + // remove up endpoint + downMetricsEndpointIdAndConfigMapping.remove(endpointId); + }); + + // down & suspended + Map<Integer, String> downMetricsEndpointErrorMsgMapping = activeTargetList.stream() + .filter(jsonObject -> StrUtil.equalsIgnoreCase("down", JSONPath.read(jsonObject.toJSONString(), "health").toString())) + .collect(Collectors.toMap( + jsonObject -> Integer.valueOf(JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id").toString()), + jsonObject -> JSONPath.read(jsonObject.toJSONString(), "lastError").toString() + )); + List<MonitorEndpointState> downMetricsEndpointStateList = Tool.ListUtil.list(true); + List<MonitorEndpointState> suspendedMetricsEndpointStateList = Tool.ListUtil.list(true); + for (MonitorEndpointConfig conf : downMetricsEndpointIdAndConfigMapping.values()) { + Integer state = 0; + // 0:关闭 1:开启 + Integer monitor = conf.getStateConf().getMonitor(); + // 0:停用 1:启用 + Integer enabled = conf.getEnable(); + // 开启:ON, 关闭:OFF + String dcStateStr = conf.getDc().getState(); + boolean dcState = StrUtil.equals("ON", dcStateStr) ? true : false; + if (!dcState && monitor.equals(0) && enabled.equals(1)) { + state = 2; + } else if (!dcState && monitor.equals(1) && enabled.equals(0)) { + state = 4; + } else if (dcState && monitor.equals(0) && enabled.equals(0)) { + state = 8; + } else if (!dcState && monitor.equals(1) && enabled.equals(1)) { + state = 6; + } else if (dcState && monitor.equals(0) && enabled.equals(1)) { + state = 10; + } else if (dcState && monitor.equals(1) && enabled.equals(0)) { + state = 12; + } + + // lastError msg in prometheus target api return data + String lastError = downMetricsEndpointErrorMsgMapping.get(conf.getEndpointId()); + MonitorEndpointState endpointState = new MonitorEndpointState(conf.getEndpointId(), conf.getId(), conf.getType(), state, conf.getVersion(), StrUtil.emptyToDefault(lastError, StrUtil.EMPTY), DateTime.now()); + if (ObjectUtil.equal(0, state)) { + downMetricsEndpointStateList.add(endpointState); + } else { + suspendedMetricsEndpointStateList.add(endpointState); + } + } + + List<MonitorEndpointState> updateEndpointStateList = Tool.ListUtil.list(true); + updateEndpointStateList.addAll(upMetricsEndpointStateList); + updateEndpointStateList.addAll(downMetricsEndpointStateList); + updateEndpointStateList.addAll(suspendedMetricsEndpointStateList); + log.info("[getCurrentMetricsEndpointStatusList] [metrics endpoint state size] [total: {}] [up: {}] [down: {}] [suspended: {}]", updateEndpointStateList.size(), upMetricsEndpointStateList.size(), downMetricsEndpointStateList.size(), suspendedMetricsEndpointStateList.size()); + return updateEndpointStateList; + } + + /** + * query Targets Api To Get Endpoint Status + * + * @param agentsForScrapeEndpoints + * @return prometheus targets API result data + */ + private List<JSONObject> queryTargetsApiToGetEndpointStatus(List<Agent> agentsForScrapeEndpoints) { + log.info("[queryTargetsApiToGetEndpointStatus] [begin] [query agent size: {}]", agentsForScrapeEndpoints.size()); + + StopWatch sw = new StopWatch(); + sw.start(); + + // all Active Target List + List<JSONObject> allActiveTargetList = Tool.ListUtil.list(true); + + try { + List<Callable<JSONObject>> tasks = Tool.ListUtil.list(true); + for (Agent agent : agentsForScrapeEndpoints) { + tasks.add(() -> { + JSONObject targets = new JSONObject(); + try { + targets = promApiService.targets(null, StrUtil.toString(agent.getId()), null, null, Tool.ListUtil.empty(), null); + } catch (Exception e) { + log.error(e, "[queryTargetsApiToGetEndpointStatus] [query /targets error] [agent: {}]", JSONUtil.toJsonStr(agent)); + } + return targets; + }); + } + + List<Future<JSONObject>> futures = threadPool.invokeAll(tasks); + for (Future<JSONObject> future : futures) { + if (!future.isCancelled()) { + JSONObject jsonObject = future.get(); + // activeTargets + Object activeTargets = JSONPath.read(jsonObject.toJSONString(), "data.activeTargets"); + List list = (List) Tool.ObjectUtil.defaultIfNull(activeTargets, Tool.ListUtil.empty()); + allActiveTargetList.addAll(list); + } + } + + } catch (Exception e) { + log.error(e, "[queryTargetsApiToGetEndpointStatus] [get result error]"); + } finally { + sw.stop(); + } + + allActiveTargetList = allActiveTargetList.stream() + .filter(Objects::nonNull) + .filter(jsonObject -> ObjectUtil.isNotNull(JSONPath.read(jsonObject.toJSONString(), "labels.endpoint_id"))) + .collect(Collectors.toList()); + log.info("[queryTargetsApiToGetEndpointStatus] [finshed] [Active Target List: {}] [RunTime: {}]", allActiveTargetList.size(), sw.toString()); + return allActiveTargetList; + } + + + /** + * update All Metric Type Endpoints To Down + * db & redis + */ + private void updateAllMetricTypeEndpointsToDown() { + log.info("[updateAllMetricTypeEndpointsToDown] [begin]"); + + List<MonitorEndpointConfig> metricsEndpointConfigList = endpointConfigService.list(new LambdaQueryWrapper<MonitorEndpointConfig>().eq(MonitorEndpointConfig::getType, Constant.MonitorConfType.METRICS.getValue())); + log.info("[updateAllMetricTypeEndpointsToDown] [metrics endpoint size: {}]", metricsEndpointConfigList.size()); + if (Tool.CollUtil.isNotEmpty(metricsEndpointConfigList)) { + // db + // remove + endpointStateService.remove(new LambdaQueryWrapper<MonitorEndpointState>().eq(MonitorEndpointState::getType, Constant.MonitorConfType.METRICS.getValue())); + // insert + List<MonitorEndpointState> saveBatchEndpointStatusList = Tool.ListUtil.list(true); + for (MonitorEndpointConfig endpointConfig : metricsEndpointConfigList) { + MonitorEndpointState endpointState = new MonitorEndpointState(); + endpointState.setEndpointId(endpointConfig.getEndpointId()); + endpointState.setConfigId(endpointConfig.getId()); + endpointState.setType(endpointConfig.getType()); + endpointState.setVer(endpointConfig.getVersion()); + endpointState.setState(0); + endpointState.setMsg(RCode.AGENT_UNAVAILABLE.getMsg()); + saveBatchEndpointStatusList.add(endpointState); + } + endpointStateService.saveBatch(saveBatchEndpointStatusList); + + // redis + Map<String, String> updateMetricsEndpointsInRedis = saveBatchEndpointStatusList.stream().collect(Collectors.toMap(state -> StrUtil.toString(state.getEndpointId()), state -> JSONUtil.toJsonStr(state))); + redisTemplate.opsForHash().putAll(Constant.ENDPOINT_METRICS_STATE_CACHE_KEY, updateMetricsEndpointsInRedis); + } + log.info("[updateAllMetricTypeEndpointsToDown] [finshed]"); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java index 44180a97..2d038713 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointService.java @@ -31,9 +31,6 @@ public interface MonitorEndpointService extends IService<MonitorEndpoint> { List<Integer> getSuspendedEndpointIdList(Integer assetId); - // endpoint 列表,包含 asset dc 数据 - List<MonitorEndpoint> endpointDetailList(); - Integer saveEndpoint(MonitorEndpoint endpoint); Integer updateEndpoint(MonitorEndpoint endpoint); diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointStateService.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointStateService.java index 3340f8e8..5180e8cc 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointStateService.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/MonitorEndpointStateService.java @@ -1,10 +1,10 @@ package com.nis.modules.endpoint.service; -import java.util.List; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.endpoint.entity.MonitorEndpointState; +import java.util.List; + public interface MonitorEndpointStateService extends IService<MonitorEndpointState> { void modifyBatchEndpointState(List<MonitorEndpointState> datas,String type); diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java index a0b5348a..ccb71268 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceImpl.java @@ -11,6 +11,7 @@ import cn.hutool.log.Log; import com.alibaba.fastjson.*; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -28,6 +29,12 @@ import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.AssetTalonStatus; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.asset.service.AssetTalonStatusService; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; import com.nis.modules.endpoint.dao.MonitorEndpointDao; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.entity.MonitorEndpointConfig; @@ -38,12 +45,6 @@ import com.nis.modules.endpoint.service.MonitorEndpointService; import com.nis.modules.endpoint.service.MonitorEndpointStateService; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualChartElement; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualChartElementService; -import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; import com.nis.modules.project.entity.MonitorProject; import com.nis.modules.project.service.MonitorProjectService; import com.nis.modules.stat.service.StatService; @@ -52,6 +53,7 @@ import com.nis.modules.sys.entity.SysUserStarredEntity; import com.nis.modules.sys.service.*; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.shiro.ShiroException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; @@ -78,13 +80,13 @@ import java.util.stream.Collectors; @Service public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, MonitorEndpoint> implements MonitorEndpointService { - private static Log log = Log.get(); + private static final Log log = Log.get(); @Autowired private AssetAssetService assetService; @Autowired - private MonitorEndpointDao monitorEndpointDao; + private AssetTalonStatusService assetTalonService; @Autowired private MonitorModuleService monitorModuleService; @@ -96,18 +98,9 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, private MonitorEndpointStateService endpointStateService; @Autowired - private VisualPanelService visualPanelService; - - @Autowired - private VisualChartService visualChartService; - - @Autowired private AlertMessageService alertMessageService; @Autowired - private VisualChartElementService visualChartElementService; - - @Autowired private MonitorEndpointConfigService endpointConfigService; @Autowired @@ -132,9 +125,6 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, private AgentService agentService; @Autowired - private AssetTalonStatusService assetTalonService; - - @Autowired private SysI18nService i18nService; @Autowired @@ -142,6 +132,15 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, @Autowired private SysConfService sysConfService; + + @Autowired + private VisualService visualService; + + @Autowired + private VisualDashboardService dashboardService; + + @Autowired + private VisualChartService visualChartService; @Override public MonitorEndpoint queryEndpointEntity(Integer id) { @@ -234,7 +233,7 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, params.put("uid",ShiroUtils.getUserId().intValue()); IPage page = new Query(MonitorEndpoint.class).getPage(params); - List<MonitorEndpoint> datas = monitorEndpointDao.queryPage(page, params); + List<MonitorEndpoint> datas = this.getBaseMapper().queryPage(page, params); // 查询结果不为空时处理返回结果 if (CollectionUtils.isNotEmpty(datas)) { @@ -813,70 +812,6 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, return projectList; } - /** - * 通过 module chart tepmlate 新增 endpoint charts - * @param endpoint - */ - public void saveEndpointChartsViaModuleChartTmpl(MonitorEndpoint endpoint) { - MonitorModule module = monitorModuleService.getById(endpoint.getModuleId()); - if (ToolUtil.isNotEmpty(module) && StrUtil.isNotBlank(module.getChartIds())) { - List<String> list = Arrays.asList(module.getChartIds().split(",")); - List<Integer> chartIdList = list.stream().map(Integer::parseInt).collect(Collectors.toList()); - // 补充 group 下的 chart id - List<VisualChart> childCharts = visualChartService.list(new LambdaQueryWrapper<VisualChart>().in(VisualChart::getGroupId, chartIdList)); - List<Integer> childChartIdList = childCharts.stream().map(VisualChart::getId).distinct().collect(Collectors.toList()); - chartIdList.addAll(childChartIdList); - chartIdList = chartIdList.stream().distinct().collect(Collectors.toList()); - List<VisualChart> chartList = visualChartService.queryChartWithElementByIds(chartIdList); - - MonitorEndpoint endpointInfo = this.queryEndpointEntity(endpoint.getId()); - VisualPanel endpointPanel = visualPanelService.getOne(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ENDPOINT.getValue()).eq(VisualPanel::getLink, endpoint.getId())); - - // model chart 组 和 asset 新增 chart 组关联关系,用来做 asset 新增 chart 组关系映射 - Map<Integer, Integer> groupIdMapping = new HashMap<>(); - - // 按照 group 升序,先添加组 - chartList = chartList.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); - - // 渲染新增 - for (VisualChart chart : chartList) { - VisualChart saveChart = new VisualChart(); - Tool.BeanUtil.copyProperties(chart, saveChart); - saveChart.setId(null); - saveChart.setPanelId(endpointPanel.getId()); - saveChart.setUpdateAt(new Date()); - saveChart.setUpdateBy(ShiroUtils.getUserId().intValue()); - saveChart.setPid(chart.getId()); - - saveChart.setVarType(Constant.ChartVariableType.ENDPOINT.getValue()); - saveChart.setVarId(endpoint.getId()); - - Integer newGroupId = groupIdMapping.get(saveChart.getGroupId()); - saveChart.setGroupId(newGroupId == null ? 0 : newGroupId); - - saveChart.setName(Tool.NzExpressionUtil.renderExpression(chart.getName(), endpointInfo)); - saveChart.setParam(ToolUtil.isNotEmpty(chart.getParam()) ? Tool.NzExpressionUtil.renderExpression(chart.getParam().toString(), endpoint) : null); - - saveChart.setSeq(endpoint.getSeq()); - visualChartService.save(saveChart); - - if (Constant.CHART_GROUP_TYPE.equalsIgnoreCase(chart.getType())) { - groupIdMapping.put(chart.getId(), saveChart.getId()); - } - - if (CollectionUtils.isNotEmpty(saveChart.getElements())) { - for (VisualChartElement chartElement : saveChart.getElements()) { - chartElement.setId(null); - chartElement.setChartId(saveChart.getId()); - chartElement.setExpression(ToolUtil.isNotEmpty(chartElement.getExpression()) ? Tool.NzExpressionUtil.renderExpression(chartElement.getExpression(), endpoint) : null); - chartElement.setSeq(endpoint.getSeq()); - } - visualChartElementService.saveBatch(saveChart.getElements()); - } - } - } - } - @Override @Transactional(rollbackFor = Exception.class) public void deleteEndpointByIds(List<Integer> ids) { @@ -898,11 +833,11 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, // 删除 alert alertMessageService.removeByEndpointIds(ids); - // 删除关联的 panel chart chartElement信息 - List<VisualPanel> panels = visualPanelService.list(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ENDPOINT.getValue()).in(VisualPanel::getLink, ids)); - if (CollectionUtils.isNotEmpty(panels)) { - Set<Integer> panelIds = panels.stream().map(VisualPanel::getId).collect(Collectors.toSet()); - visualPanelService.delPanelsAndChartInfoByPanelIds(panelIds); + // 删除关联的 dashboard chart chartElement信息 + List<VisualDashboard> dashboards = dashboardService.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue()).in(VisualDashboard::getLink, ids)); + if (CollectionUtils.isNotEmpty(dashboards)) { + Set<Integer> dashboardIds = dashboards.stream().map(VisualDashboard::getId).collect(Collectors.toSet()); + dashboardService.delDashboardsAndChartInfoByDashboardIds(dashboardIds); } // 删除 关联通过 chart temp 创建的 charts @@ -928,11 +863,11 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, // 撤销导入 this.remove(new LambdaQueryWrapper<MonitorEndpoint>().eq(MonitorEndpoint::getSeq, seq)); - // 删除关联的 panel chart chartElement信息 - List<VisualPanel> panels = visualPanelService.list(new LambdaQueryWrapper<VisualPanel>().eq(VisualPanel::getType, Constant.PanelType.ENDPOINT.getValue()).in(VisualPanel::getLink, endpointIds)); - if (CollectionUtils.isNotEmpty(panels)) { - Set<Integer> panelIds = panels.stream().map(VisualPanel::getId).collect(Collectors.toSet()); - visualPanelService.delPanelsAndChartInfoByPanelIds(panelIds); + // 删除关联的 dashboard chart chartElement信息 + List<VisualDashboard> dashboards = dashboardService.list(new LambdaQueryWrapper<VisualDashboard>().eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue()).in(VisualDashboard::getLink, endpointIds)); + if (CollectionUtils.isNotEmpty(dashboards)) { + Set<Integer> dashboardIds = dashboards.stream().map(VisualDashboard::getId).collect(Collectors.toSet()); + dashboardService.delDashboardsAndChartInfoByDashboardIds(dashboardIds); } // configs @@ -949,6 +884,9 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveEndpointsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -1028,12 +966,12 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, @Override public List<Integer> getSuspendedEndpointIdList(Integer assetId) { - return monitorEndpointDao.getSuspendedEndpointIdList(assetId); + return this.getBaseMapper().getSuspendedEndpointIdList(assetId); } @Override public List<MonitorEndpoint> getEnableMetricsEndpointInfoListForAgent() { - List<MonitorEndpoint> enableEndpointInfoList = monitorEndpointDao.getEnableMetricsEndpointInfoListForAgent(); + List<MonitorEndpoint> enableEndpointInfoList = this.getBaseMapper().getEnableMetricsEndpointInfoListForAgent(); // 如 asset 存在 parent , 则 set parent List<AssetAsset> assetList = assetService.list(); Map<Integer, AssetAsset> assetIdAndEntityMap = assetList.stream().collect(Collectors.toMap(AssetAsset::getId, Function.identity())); @@ -1046,7 +984,7 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, @Override public List<MonitorEndpoint> getEnableLogsEndpointInfoListForAgent(Integer version) { - List<MonitorEndpoint> enableEndpointInfoList = monitorEndpointDao.getEnableLogsEndpointInfoListForAgent(version); + List<MonitorEndpoint> enableEndpointInfoList = this.getBaseMapper().getEnableLogsEndpointInfoListForAgent(version); // 如 asset 存在 parent , 则 set parent List<AssetAsset> assetList = assetService.list(); Map<Integer, AssetAsset> assetIdAndEntityMap = assetList.stream().collect(Collectors.toMap(AssetAsset::getId, Function.identity())); @@ -1262,7 +1200,7 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, } } String sysHeaderJsonStr = sysConfService.getValue(Constant.SYSCONFIG_KEY_MONITORENDPOINT_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) @@ -1299,23 +1237,20 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, // 是否同步更新关联的dashboard,可选值: 0:不同步 1:同步 默认值:1 String syncDashboard = Tool.ObjectUtil.defaultIfEmpty((String) params.get("syncDashboard"), "1"); if (StrUtil.equals("1", syncDashboard)) { - // endpoint info charts && dashboard charts - List<VisualChart> endpointChartList = visualChartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getVarType, Constant.ChartVariableType.ENDPOINT.getValue()).eq(VisualChart::getVarId, endpoint.getId())); - if (Tool.CollUtil.isNotEmpty(endpointChartList)) { - List<Integer> endpointChartIdList = endpointChartList.stream().map(VisualChart::getId).collect(Collectors.toList()); - Map<String, Object> map = Tool.MapUtil.newHashMap(2); - map.put("ids", endpointChartIdList); - visualChartService.syncTmpl(map); - } + // sync dashboard + VisualDashboard endpointDashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue()) + .eq(VisualDashboard::getLink, endpoint.getId())); + visualService.syncTemplateDashboard(endpointDashboard.getId(), null, null, null); } } else { params.put("save", true); // endpoint this.save(endpoint); - // endpoint panel & info chart - this.saveEndpointInfoPanel(endpoint); - // 通过 module chart tepmlate 新增 endpoint charts - this.saveEndpointChartsViaModuleChartTmpl(endpoint); + // endpoint dashboard & info chart + this.saveEndpointInfoDashboard(endpoint); + // sync Endpoint Dashboard Via Module + this.syncEndpointDashboardViaModule(endpoint.getId(), endpoint.getModuleId()); } // endpoint config @@ -1342,17 +1277,17 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, * * @param endpoint */ - private void saveEndpointInfoPanel(MonitorEndpoint endpoint) { - // endpoint config - String sysEndpointChartTplStr = sysConfService.getValue(Constant.SYSCONFIG_KEY_ENDPOINT_CHART_TPL); - VisualChart chartTemplate = JSONObject.parseObject(sysEndpointChartTplStr, VisualChart.class); - // insert panel chart - visualChartService.saveRelPanelAndChart(Constant.PanelType.ENDPOINT.getValue(), endpoint.getId(), endpoint.getSeq(), chartTemplate); - } + private void saveEndpointInfoDashboard(MonitorEndpoint endpoint) { + // get module template id + MonitorModule module = monitorModuleService.getById(endpoint.getModuleId()); + Integer templateId = module.getDashboardId(); - @Override - public List<MonitorEndpoint> endpointDetailList() { - return monitorEndpointDao.endpointDetailList(); + Integer linkId = endpoint.getId(); + String name = endpoint.getName(); + String seq = endpoint.getSeq(); + + // save Rel Dashboard And Chart + visualChartService.saveRelDashboardAndChart(DashboardConstant.Type.ENDPOINT.getValue(), linkId, name, templateId, seq); } private void validateEndpointInfo(MonitorEndpoint endpoint) { @@ -1547,14 +1482,37 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, // 保存配置信息 this.saveOrUpdateEndpointConfigs(endpoint, module); - // endpoint panel & info chart - this.saveEndpointInfoPanel(endpoint); + // endpoint Dashboard & info chart + this.saveEndpointInfoDashboard(endpoint); - // 通过 module chart tepmlate 新增 endpoint charts - this.saveEndpointChartsViaModuleChartTmpl(endpoint); + // sync Endpoint Dashboard Via Module + this.syncEndpointDashboardViaModule(endpoint.getId(), endpoint.getModuleId()); return endpoint.getId(); } + /** + * sync Endpoint Dashboard Via Module + * + * @param endpointId + * @param moduleId + */ + private void syncEndpointDashboardViaModule(Integer endpointId, Integer moduleId) { + MonitorModule module = monitorModuleService.getById(moduleId); + Integer moduleDashboardTmplId = module.getDashboardId(); + if (ObjectUtil.isNull(moduleDashboardTmplId)) { + log.warn("[syncEndpointDashboardViaModule] [module not config dashboard template. no sync endpoint dashboard] [endpointId: {}] [moduleId: {}]", endpointId, moduleId); + return; + } + + log.info("[syncEndpointDashboardViaModule] [sync endpoint dashboard begin.] [endpointId: {}] [moduleId: {}]", endpointId, moduleId); + // sync dashboard + VisualDashboard endpointDashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue()) + .eq(VisualDashboard::getLink, endpointId)); + visualService.syncTemplateDashboard(endpointDashboard.getId(), null, null, null); + log.info("[syncEndpointDashboardViaModule] [sync endpoint dashboard finshed.] [endpointId: {}] [moduleId: {}]", endpointId, moduleId); + } + private void saveOrUpdateEndpointConfigs(MonitorEndpoint endpoint, MonitorModule module) { List<MonitorEndpointConfig> configList = endpointConfigService.list(new LambdaQueryWrapper<MonitorEndpointConfig>().eq(MonitorEndpointConfig::getEndpointId, endpoint.getId())); AssetAsset asset = endpoint.getAsset() != null ? endpoint.getAsset() : assetService.getById(endpoint.getAssetId()); @@ -1663,9 +1621,20 @@ public class MonitorEndpointServiceImpl extends ServiceImpl<MonitorEndpointDao, throw new NZException(RCode.ENDPOINT_NAME_DUPLICATE); } + // 留作对比是否更改属性 + MonitorEndpoint oldEndpoint = this.getById(endpoint.getId()); + // 保存 this.updateById(endpoint); + // If the endpoint name is modified, the endpoint Dashboard name is also modified + if (ObjectUtil.notEqual(oldEndpoint.getName(), endpoint.getName())) { + dashboardService.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getName, endpoint.getName()) + .eq(VisualDashboard::getLink, endpoint.getId()) + .eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue())); + } + // 保存配置信息 this.saveOrUpdateEndpointConfigs(endpoint, module); diff --git a/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceStateImpl.java b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceStateImpl.java index 76b2a706..f87f7765 100644 --- a/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceStateImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/endpoint/service/impl/MonitorEndpointServiceStateImpl.java @@ -4,11 +4,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.modules.endpoint.dao.MonitorEndpointStateDao; import com.nis.modules.endpoint.entity.MonitorEndpointState; import com.nis.modules.endpoint.service.MonitorEndpointStateService; +import org.springframework.stereotype.Service; import java.util.List; -import org.springframework.stereotype.Service; - @Service public class MonitorEndpointServiceStateImpl extends ServiceImpl<MonitorEndpointStateDao, MonitorEndpointState> implements MonitorEndpointStateService { diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/controller/IpamIpController.java b/nz-admin/src/main/java/com/nis/modules/ipam/controller/IpamIpController.java index ba62044e..7cf3f820 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/controller/IpamIpController.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/controller/IpamIpController.java @@ -6,7 +6,6 @@ import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; import com.nis.modules.ipam.entity.IpamIp; import com.nis.modules.ipam.service.IpamIpService; -import inet.ipaddr.AddressStringException; import inet.ipaddr.IncompatibleAddressException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/dao/IpamSubnetDao.java b/nz-admin/src/main/java/com/nis/modules/ipam/dao/IpamSubnetDao.java index 02c04562..0556b7d7 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/dao/IpamSubnetDao.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/dao/IpamSubnetDao.java @@ -1,15 +1,14 @@ package com.nis.modules.ipam.dao; -import java.util.List; -import java.util.Map; - +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.ipam.entity.IpamSubnet; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.nis.modules.ipam.entity.IpamSubnet; +import java.util.List; +import java.util.Map; @Mapper @Repository diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/entity/IpamSubnet.java b/nz-admin/src/main/java/com/nis/modules/ipam/entity/IpamSubnet.java index 7db80bcb..7b0c5d67 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/entity/IpamSubnet.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/entity/IpamSubnet.java @@ -1,16 +1,14 @@ package com.nis.modules.ipam.entity; -import java.io.Serializable; -import java.math.BigInteger; - import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.nis.modules.asset.entity.Dc; - import lombok.Data; +import java.io.Serializable; + @Data @TableName("ipam_subnet") public class IpamSubnet implements Serializable { diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/service/IpamIpService.java b/nz-admin/src/main/java/com/nis/modules/ipam/service/IpamIpService.java index 2d8dda12..a96b06e1 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/service/IpamIpService.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/service/IpamIpService.java @@ -3,7 +3,6 @@ package com.nis.modules.ipam.service; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.ipam.entity.IpamIp; -import inet.ipaddr.AddressStringException; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamIpServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamIpServiceImpl.java index 50062c54..634cd255 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamIpServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamIpServiceImpl.java @@ -25,6 +25,7 @@ import com.nis.modules.ipam.service.IpamIpService; import com.nis.modules.ipam.service.IpamSubnetService; import com.nis.modules.sys.service.BasicImportAndExportServices; import com.nis.modules.sys.service.SysConfigService; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -34,7 +35,6 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.UnknownHostException; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; @Service @@ -132,7 +132,7 @@ public class IpamIpServiceImpl extends ServiceImpl<IpamIpDao, IpamIp> implements } } if (!inRange){ - throw new NZException(RCode.IPAM_IP_SUBNET_ISNULL); + throw new NZException(RCode.IPAM_IP_SUBNET_NOT_EXISTS); } if (Tool.ObjectUtil.isEmpty(ipamIp.getState())){ ipamIp.setState(1); @@ -165,6 +165,9 @@ public class IpamIpServiceImpl extends ServiceImpl<IpamIpDao, IpamIp> implements // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(excelFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveIpamIpsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -207,7 +210,7 @@ public class IpamIpServiceImpl extends ServiceImpl<IpamIpDao, IpamIp> implements validateUtil.validateRequired(addr, lineNum, IpamIpEum.ADDR.getIndex()); validateUtil.validateIp(addr, lineNum , IpamIpEum.ADDR.getIndex(), ""); if (ipamSubnet == null){ - validateUtil.recordImportAttrErr(lineNum, RCode.IPAM_IP_SUBNET_ISNULL); + validateUtil.recordImportAttrErr(lineNum, RCode.IPAM_IP_SUBNET_NOT_EXISTS); }else { validateUtil.validateIpInScope(addr, ipamSubnet.getAddr(),ipamSubnet.getMask().toString(), lineNum, IpamIpEum.ADDR.getIndex()); } @@ -276,7 +279,7 @@ public class IpamIpServiceImpl extends ServiceImpl<IpamIpDao, IpamIp> implements } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_IPAMIP_IMPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamSubnetServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamSubnetServiceImpl.java index 447d7dfe..5079a50b 100644 --- a/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamSubnetServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/ipam/service/impl/IpamSubnetServiceImpl.java @@ -32,6 +32,7 @@ import inet.ipaddr.AddressStringException; import inet.ipaddr.IPAddress; import inet.ipaddr.IPAddressString; import inet.ipaddr.IncompatibleAddressException; +import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -274,6 +275,9 @@ public class IpamSubnetServiceImpl extends ServiceImpl<IpamSubnetDao, IpamSubnet // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveIpamSubnetsFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -382,7 +386,7 @@ public class IpamSubnetServiceImpl extends ServiceImpl<IpamSubnetDao, IpamSubnet } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_IPAMSUBNET_IMPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) diff --git a/nz-admin/src/main/java/com/nis/modules/metric/controller/MetricsController.java b/nz-admin/src/main/java/com/nis/modules/metric/controller/MetricsController.java index 5b671155..2238ccd5 100644 --- a/nz-admin/src/main/java/com/nis/modules/metric/controller/MetricsController.java +++ b/nz-admin/src/main/java/com/nis/modules/metric/controller/MetricsController.java @@ -1,13 +1,7 @@ package com.nis.modules.metric.controller;
-import com.nis.modules.metric.dto.NezhaMetrics;
import com.nis.modules.sys.controller.AbstractController;
-import io.micrometer.core.instrument.MeterRegistry;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.servlet.ModelAndView;
@RestController
public class MetricsController extends AbstractController {
diff --git a/nz-admin/src/main/java/com/nis/modules/metric/dto/NezhaMetrics.java b/nz-admin/src/main/java/com/nis/modules/metric/dto/NezhaMetrics.java index 7d57e65c..24637c2a 100644 --- a/nz-admin/src/main/java/com/nis/modules/metric/dto/NezhaMetrics.java +++ b/nz-admin/src/main/java/com/nis/modules/metric/dto/NezhaMetrics.java @@ -4,14 +4,14 @@ import com.alibaba.fastjson.JSONObject; import com.nis.common.utils.Constant; import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.alert.dao.AlertHandlerDao; import com.nis.modules.alert.dao.AlertRuleDao; import com.nis.modules.asset.dao.AssetModelDao; import com.nis.modules.asset.dao.DcDao; import com.nis.modules.asset.entity.Dc; import com.nis.modules.module.dao.MonitorModuleDao; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.AgentService; import com.nis.modules.sys.service.SysConfService; import io.micrometer.core.instrument.*; import io.micrometer.core.instrument.binder.MeterBinder; diff --git a/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java index 258ba21d..c9cd8f0a 100644 --- a/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java +++ b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModule.java @@ -1,11 +1,9 @@ package com.nis.modules.module.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; +import com.nis.modules.dashboard.entity.VisualChart; +import com.nis.modules.dashboard.entity.VisualDashboard; import com.nis.modules.endpoint.entity.MonitorEndpoint; -import com.nis.modules.panel.entity.VisualChart; import com.nis.modules.project.entity.MonitorProject; import lombok.Data; @@ -102,6 +100,15 @@ public class MonitorModule implements Serializable { @TableField(exist = false) private List<VisualChart> charts; + /** + * template id + */ + @TableField(strategy = FieldStrategy.IGNORED) + private Integer dashboardId; + + @TableField(exist = false) + private VisualDashboard dashboard; + @TableField(exist = false) private List alert; diff --git a/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModuleImportEnum.java b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModuleImportEnum.java index 3fe6a0f0..4e5c2683 100644 --- a/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModuleImportEnum.java +++ b/nz-admin/src/main/java/com/nis/modules/module/entity/MonitorModuleImportEnum.java @@ -10,7 +10,7 @@ public enum MonitorModuleImportEnum { PROJECT("project name", 1), ENDPOINT_NAME_TEMPLATE("endpoint name template", 2), CONFIGURATIONS("endpoint config json array", 3), - CHART_TEMPLATES("chart templates", 4), + DASHBOARD_TEMPLATE("dashboard template", 4), REMARK("remark", 5); private String name; diff --git a/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java index e594d223..e7ea90c2 100644 --- a/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/module/service/impl/MonitorModuleServiceImpl.java @@ -1,5 +1,6 @@ package com.nis.modules.module.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.BooleanUtil; @@ -11,6 +12,7 @@ import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -21,15 +23,18 @@ import com.nis.common.utils.*; import com.nis.modules.alert.entity.AlertMessageEntity; import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetModelImportEnum; import com.nis.modules.asset.entity.Dc; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; +import com.nis.modules.dashboard.service.VisualService; +import com.nis.modules.dashboard.utils.DashboardConstant; import com.nis.modules.endpoint.entity.MonitorEndpoint; import com.nis.modules.endpoint.service.MonitorEndpointService; import com.nis.modules.module.dao.MonitorModuleDao; import com.nis.modules.module.entity.MonitorModule; import com.nis.modules.module.entity.MonitorModuleImportEnum; import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.service.VisualChartService; import com.nis.modules.project.entity.MonitorProject; import com.nis.modules.project.service.MonitorProjectService; import com.nis.modules.project.service.TopoService; @@ -43,6 +48,7 @@ import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserStarredService; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @@ -87,7 +93,10 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni private SnmpCredentialService snmpCredentialService; @Autowired - private VisualChartService visualChartService; + private VisualDashboardService dashboardService; + + @Autowired + private VisualService visualService; @Autowired private StatService statService; @@ -124,10 +133,10 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni List<Map<String, Object>> alert = statService.getSeverityStatByRuleMsgCount(Tool.MapUtil.empty(), ruleIdAndAlertCountMap); module.setAlert(alert); - String chartIds = module.getChartIds(); - if (StrUtil.isNotBlank(chartIds)) { - List<VisualChart> charts = (List<VisualChart>) visualChartService.listByIds(Arrays.asList(chartIds.split(","))); - module.setCharts(charts); + Integer dashboardId = module.getDashboardId(); + if(ToolUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = dashboardService.getById(dashboardId); + module.setDashboard(dashboard); } // 当前用户收藏状态 1:收藏 0:未收藏 @@ -215,6 +224,16 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni throw new NZException(RCode.MODULE_NAME_DUPLICATE); } + // module dashboard template, type = template & varType = endpoint + Integer dashboardId = module.getDashboardId(); + if (ToolUtil.isNotEmpty(dashboardId)) { + VisualDashboard dashboard = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getId, dashboardId) + .eq(VisualDashboard::getType, DashboardConstant.Type.TEMPLATE.getValue()) + .eq(VisualDashboard::getVarType, DashboardConstant.VariableType.ENDPOINT.getValue())); + ValidateUtils.is(dashboard).notNull(RCode.DASHBOARD_NOT_EXIST); + } + // config 格式校验 List<Map> configMapList; try { @@ -419,12 +438,24 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni } // 4. 修改了 project , 修改 topo config - if (!oldModule.getProjectId().equals(moduleEntity.getProjectId())) { + if (ObjectUtil.notEqual(oldModule.getProjectId(), moduleEntity.getProjectId())) { List<MonitorModule> modules = new ArrayList(); modules.add(oldModule); topoService.removeTopoConfigNodeAndLineByModules(modules); } + // If the dashboard template is modified, the endpoint dashboard template ID will also be modified + if (ObjectUtil.notEqual(oldModule.getDashboardId(), moduleEntity.getDashboardId())) { + List<MonitorEndpoint> endpointList = monitorEndpointService.list(new LambdaQueryWrapper<MonitorEndpoint>().eq(MonitorEndpoint::getModuleId, moduleEntity.getId())); + if (CollUtil.isNotEmpty(endpointList)) { + List<Integer> endpointIdList = endpointList.stream().map(MonitorEndpoint::getId).collect(Collectors.toList()); + dashboardService.update(new LambdaUpdateWrapper<VisualDashboard>() + .set(VisualDashboard::getTmplId, ObjectUtil.defaultIfNull(moduleEntity.getDashboardId(), -1)) + .in(VisualDashboard::getLink, endpointIdList) + .eq(VisualDashboard::getType, DashboardConstant.Type.ENDPOINT.getValue())); + } + } + // 保存 this.updateById(moduleEntity); return moduleEntity.getId(); @@ -673,6 +704,9 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni // 表头信息 国际化之后的 List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + String fileExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); + params.put("fileExtension", fileExtension); + // 返回统计信息 Map statMap = this.saveModulesFromImportDataList(importDataList, headerInfos, params); return statMap; @@ -805,26 +839,19 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni } } - String chartNames = dataMap.get(MonitorModuleImportEnum.CHART_TEMPLATES.getIndex()); - StringBuilder relChartTemplateIds = new StringBuilder(); - if (StringUtils.isNotEmpty(chartNames)) { - // module 只能选择 endpoint 类型且 groupId = 0 的图表 - List<VisualChart> endpointChartTemplateList = visualChartService.list(new LambdaQueryWrapper<VisualChart>() - .eq(VisualChart::getPanelId, 0).eq(VisualChart::getGroupId, 0) - .eq(VisualChart::getVarType, Constant.ChartVariableType.ENDPOINT.getValue())); - - StrUtil.split(chartNames, StrUtil.C_COMMA).stream().forEach(chartName -> { - List<Integer> chartIdList = endpointChartTemplateList.stream() - .filter(visualChart -> StrUtil.equals(visualChart.getName(), chartName)) - .map(VisualChart::getId).collect(Collectors.toList()); - if (Tool.CollUtil.isEmpty(chartIdList)) { - validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_RELATED_OBJ_NOT_EXIST.setParam(MonitorModuleImportEnum.CHART_TEMPLATES.getIndex())); - } else if (chartIdList.size() > 1) { - validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_FIELD_DUPLICATE.setParam(MonitorModuleImportEnum.CHART_TEMPLATES.getIndex())); - } else if (chartIdList.size() == 1) { - relChartTemplateIds.append(StrUtil.concat(true, chartIdList.get(0).toString(), ",")); - } - }); + String dashboardTemplateName = dataMap.get(MonitorModuleImportEnum.DASHBOARD_TEMPLATE.getIndex()); + Integer dashboardTemplateId = null; + if (StrUtil.isNotEmpty(dashboardTemplateName)) { + // dashboard template, type = template varType = endpoint + VisualDashboard dashboardTemplate = dashboardService.getOne(new LambdaQueryWrapper<VisualDashboard>() + .eq(VisualDashboard::getName, dashboardTemplateName) + .eq(VisualDashboard::getType, DashboardConstant.Type.TEMPLATE.getValue()) + .eq(VisualDashboard::getVarType, DashboardConstant.VariableType.ENDPOINT.getValue())); + if (ObjectUtil.isNull(dashboardTemplate)) { + validateUtil.recordImportAttrErr(lineNum, RCode.IMPORT_RELATED_OBJ_NOT_EXIST.setParam(AssetModelImportEnum.DASHBOARD_TEMPLATE.getIndex())); + } else { + dashboardTemplateId = dashboardTemplate.getId(); + } } List<Map<String, String>> errMsgForThisLine = validateUtil.getImportErrMsgForThisLine(lineNum); @@ -851,7 +878,7 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni module.setName(moduleName); module.setEndpointNameTmpl(endpointNameTmpl); module.setRemark(remark); - module.setChartIds(StrUtil.isNotEmpty(relChartTemplateIds) ? relChartTemplateIds.substring(0, relChartTemplateIds.length() - 1) : ""); + module.setDashboardId(dashboardTemplateId); module.setConfigs(configStr); List<Map> configMapList = JSONObject.parseArray(configStr, Map.class); Map metricsConfigMap = configMapList.stream().filter(map -> { @@ -901,7 +928,7 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni } } String sysHeaderJsonStr = sysConfigService.getValue(Constant.SYSCONFIG_KEY_MODULE_EXPORT_HEADER); - String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, Constant.ImportFileType.EXCEL.getValue()); + String failedContentFileBase64Str = basicImportAndExportServices.getFailedContentFileBase64Str(failContentList, sysHeaderJsonStr, MapUtil.getStr(params, "fileExtension")); // 返回统计信息 Map<Object, Object> statMap = Tool.MapUtil.builder() .put("seq", seq) @@ -957,6 +984,12 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni monitorEndpointService.syncTmpl(ListUtil.of(module.getId()), Collections.emptyList(), Collections.emptyList()); } } + + // 是否同步更新关联的 dashboard,可选值: 0:不同步 1:同步 默认值:1 + String syncDashboard = Tool.ObjectUtil.defaultIfEmpty((String) params.get("syncDashboard"), "1"); + if (StrUtil.equals("1", syncDashboard) && ObjectUtil.isNotNull(module.getDashboardId())) { + visualService.syncTemplateDashboard(null, null, null, module.getId()); + } } else { params.put("save", true); // insert @@ -1014,16 +1047,8 @@ public class MonitorModuleServiceImpl extends ServiceImpl<MonitorModuleDao, Moni tempList.add(module.getProject().getName()); tempList.add(ObjectUtil.defaultIfNull(module.getEndpointNameTmpl(), "")); tempList.add(ObjectUtil.defaultIfNull(module.getConfigs(), "")); - String chartIds = module.getChartIds(); - String chartNames = ""; - if (StrUtil.isNotEmpty(chartIds)) { - List<VisualChart> chartList = visualChartService.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getPanelId, 0).in(VisualChart::getId, Arrays.asList(chartIds.split(",")))); - for (VisualChart chart : chartList) { - chartNames += chart.getName() + ","; - } - chartNames = StrUtil.isNotEmpty(chartNames) ? chartNames.substring(0, chartNames.length() - 1) : chartNames; - } - tempList.add(ObjectUtil.defaultIfNull(chartNames, "").toString()); + VisualDashboard dashboard = module.getDashboard(); + tempList.add(ObjectUtil.isNotNull(dashboard) ? dashboard.getName() : StrUtil.EMPTY); tempList.add(ObjectUtil.defaultIfNull(module.getRemark(), "").toString()); exportDataList.add(tempList); } diff --git a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualController.java b/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualController.java deleted file mode 100644 index 5683cfc3..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualController.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.nis.modules.panel.controller; - -import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.RCode; -import com.nis.modules.panel.service.VisualService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -@RestController -@RequestMapping("/visual") -public class VisualController { - - @Autowired - private VisualService visualService; - - /** - * explore 快照 - */ - @GetMapping("/explore/snapshot") - public void exploreSnapshot(HttpServletResponse response, HttpServletRequest request, String format, Integer type, Long start, - Long end, Integer unit, String limit, String direction, @RequestParam(value="expressions[]")String[] expressions) throws IOException { - ValidateUtils.is(type).notNull(RCode.AGENT_TYPE_ISNULL) - .and(start).notNull(RCode.AGENT_PARAM_START_ISNULL) - .and(end).notNull(RCode.AGENT_PARAM_END_ISNULL) - .and(expressions).notNull(RCode.AGENT_PARAM_QUERY_ISNULL); - String language = request.getHeader(Constant.LANGUAGE); - visualService.exploreSnapshot(response, format, type, start, end, language, unit, limit, direction, expressions); - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualPanelController.java b/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualPanelController.java deleted file mode 100644 index 611c9fac..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/controller/VisualPanelController.java +++ /dev/null @@ -1,181 +0,0 @@ -package com.nis.modules.panel.controller; - -import com.nis.common.annotation.SysLog; -import com.nis.common.exception.NZException; -import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.*; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualPanel; -//import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -@RestController -@RequestMapping("/visual/panel") -public class VisualPanelController { - - @Autowired - private VisualPanelService visualPanelService; - - @GetMapping("/{id}") - @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.VISUALPANEL) - public R panel(@PathVariable Integer id) { - VisualPanel panel = visualPanelService.queryInfo(id); - return R.ok(panel); - } - - @GetMapping - @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.VISUALPANEL) - public R panelList(@RequestParam Map<String, Object> params) { - List<VisualPanel> panels = visualPanelService.queryList(params); - return R.ok().putData("list",panels); - } - - @RequestMapping(method = { RequestMethod.POST }) - @SysLog(operation = OperationEnum.ADD, type = TypeEnum.VISUALPANEL) - @RequiresPermissions({ "visual:panel:save" }) - public R panelSave(@RequestBody VisualPanel panel) { - ValidateUtils.is(panel.getName()).maxLength(64); - visualPanelService.saveVisualPanel(panel); - return R.ok().putData("panel", panel); - } - - @RequestMapping(method = { RequestMethod.PUT }) - @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.VISUALPANEL) - @RequiresPermissions({ "visual:panel:update" }) - public R panelUpdate(@RequestBody VisualPanel panel) { - ValidateUtils.is(panel.getId()).notNull(RCode.PANEL_ID_ISNULL) - .and(panel.getName()).maxLength(64); - - visualPanelService.updateVisualPanel(panel); - return R.ok().putData("panel", panel); - } - - @DeleteMapping - @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.VISUALPANEL) - @RequiresPermissions({ "visual:panel:delete" }) - public R panleDelete(@RequestParam Integer... ids) { - ValidateUtils.is(ids).notNull(RCode.PANEL_ID_ISNULL); - - visualPanelService.delPanels(ids); - return R.ok(); - } - - /** - * 排序 - * - * @param panelList - * @return - */ - @PutMapping("/tree") - @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.VISUALPANEL) - public R modify(@RequestBody List<VisualPanel> panelList) { - visualPanelService.modify(panelList); - return R.ok(); - } - - @GetMapping("/template") - public void getTemplateByLanguage(HttpServletResponse response, - @RequestParam(required = false, defaultValue = "dashboard") String type, - @RequestParam(required = false, defaultValue = "en") String language, - @RequestParam(required = false, defaultValue = "1") String format) throws IOException { - - // 校验 LANGUAGE - if (!Arrays.asList(Constant.LANGUAGE_VALUES).contains(language)) { - throw new NZException(RCode.EXCELFILE_HEADER_LANGUAGE_ERROR); - } - // 校验 FORMAT - List<String> supportImportingFileTypes = Arrays.asList(Constant.ImportFileType.values()).stream().map(Constant.ImportFileType::getValue).collect(Collectors.toList()); - if (!supportImportingFileTypes.contains(format)) { - throw new NZException(RCode.EXCELFILE_TYPE_ERROR); - } - - visualPanelService.getTemplateByLanguage(response, format, type); - } - - @PostMapping("/import") - @SysLog(operation = OperationEnum.IMPORT, type = TypeEnum.CHART) - @RequiresPermissions({ "visual:panel:save"}) - public R importChartData(@RequestParam(value = "file") MultipartFile excelFile, String type, Integer linkId, HttpServletRequest request) throws IOException { - - String language = request.getHeader(Constant.LANGUAGE); - ValidateUtils.is(excelFile).notNull(RCode.EXCELFILE_IMPORT_FILE_ISNULL) - .and(type).notNull(RCode.PANEL_CHART_TEMPLATE_TYPE_ISNULL); - // 校验 LANGUAGE - if (!Arrays.asList(Constant.LANGUAGE_VALUES).contains(language)) { - throw new NZException(RCode.EXCELFILE_HEADER_LANGUAGE_ERROR); - } - - Map info = visualPanelService.importChartData(excelFile, type, linkId, language); - return R.ok(info); - } - - @GetMapping("/export") - @SysLog(operation = OperationEnum.EXPORT, type = TypeEnum.CHART) - public void export(HttpServletResponse response, @RequestParam Map<String, Object> params) throws IOException { - Object format = params.get("format"); - String formatStr = format == null ? "1" : format.toString(); - // 校验 FORMAT - List<String> supportImportingFileTypes = Arrays.asList(Constant.ImportFileType.values()).stream().map(Constant.ImportFileType::getValue).collect(Collectors.toList()); - if (!supportImportingFileTypes.contains(formatStr)) { - throw new NZException(RCode.EXCELFILE_TYPE_ERROR); - } - params.put("format", formatStr); - - visualPanelService.export(response, params); - } - - @DeleteMapping("/cancelImport") - @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.CHART) - public R cancelImport(String seq) { - ValidateUtils.is(seq).notNull(RCode.UNDO_IMPORT_SEQ_ISNULL); - - visualPanelService.cancelImport(seq); - return R.ok(); - } - - /** - * 复制panel配置 - * @param id - * @return - */ - @PostMapping("/duplicate/{id}") - @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.VISUALPANEL) - public R duplicate(@PathVariable Integer id) { - ValidateUtils.is(id).notNull(RCode.PANEL_ID_ISNULL); - visualPanelService.duplicate(id); - return R.ok(); - } - - /** - * panel 快照 - * @param response - * @param request - * @param format - * @param panelId - * @param start - * @param end - * @param vars - */ - @GetMapping("/snapshot") - public void snapshot(HttpServletResponse response, HttpServletRequest request, String format, Integer panelId, Long start, Long end, String vars) throws IOException { - ValidateUtils.is(panelId).notNull(RCode.PANEL_ID_ISNULL) - .and(start).notNull(RCode.AGENT_PARAM_START_ISNULL) - .and(end).notNull(RCode.AGENT_PARAM_END_ISNULL); - String language = request.getHeader(Constant.LANGUAGE); - visualPanelService.snapshot(response, format, panelId, start, end, language, vars); - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualPanelDao.java b/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualPanelDao.java deleted file mode 100644 index 70f06839..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/dao/VisualPanelDao.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.nis.modules.panel.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.nis.modules.panel.entity.VisualPanel; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; - -@Mapper -public interface VisualPanelDao extends BaseMapper<VisualPanel> { - List<VisualPanel> queryList(@Param("params")Map<String, Object> params); - - List<VisualPanel> queryListByType(@Param("type")String type); - - void updateWeightBatch(@Param("panels") List<VisualPanel> updatePanels); - - VisualPanel queryInfo(Integer id); - - void delReceivers(List<String> idList); - - List<VisualPanel> queryReportOfEmptyReceivers(); -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualChartService.java b/nz-admin/src/main/java/com/nis/modules/panel/service/VisualChartService.java deleted file mode 100644 index d4178a7d..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualChartService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.nis.modules.panel.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.nis.common.utils.PageUtils; -import com.nis.modules.panel.entity.VisualChart; - -import java.util.List; -import java.util.Map; - -public interface VisualChartService extends IService<VisualChart> { - - PageUtils queryPage(Map<String,Object> params); - - VisualChart queryInfo(Integer id); - - void validateChart(VisualChart visualChart); - - Integer saveChart(VisualChart chart); - - Integer updateChart(VisualChart chart); - - void delCharts(Integer[] ids, Integer sync); - - void modify(VisualChart chart); - - void weights(Integer panelId,List<VisualChart> chartList); - - void delVisualChartsByPanelId(Integer... panelId); - - Map<Integer,Integer> queryChartNum(); - - Integer fromTmpl(Map<String,Object> params); - - Integer syncTmpl(Map<String,Object> params); - - void saveRelPanelAndChart(String typeStr, Integer linkId, String seq, VisualChart chartTemplate); - - List<VisualChart> queryChartWithElementByIds(List<Integer> chartIdList); -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualPanelService.java b/nz-admin/src/main/java/com/nis/modules/panel/service/VisualPanelService.java deleted file mode 100644 index 958f624c..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualPanelService.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.nis.modules.panel.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.nis.modules.panel.entity.VisualPanel; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public interface VisualPanelService extends IService<VisualPanel> { - VisualPanel queryInfo(Integer id); - - void delPanels(Integer... ids); - - void modify(List<VisualPanel> visualPanelList); - - List<VisualPanel> queryList(Map<String, Object> params); - - void delPanelsAndChartInfoByPanelIds(Set<Integer> visualPanelIds); - - void saveVisualPanel(VisualPanel visualPanel); - - void updateVisualPanel(VisualPanel visualPanel); - - void getTemplateByLanguage(HttpServletResponse response, String format, String type) throws IOException; - - void cancelImport(String seq); - - void export(HttpServletResponse response, Map<String, Object> params) throws IOException; - - Map importChartData(MultipartFile excelFile, String type, Integer linkId, String language) throws IOException; - - void duplicate(Integer id); - - void snapshot(HttpServletResponse response, String format, Integer panelId, Long start, Long end, String language, String vars) throws IOException; - - String genSnapshotByTemplate(Integer panelId, Long start, Long end, String lang, String vars); -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualService.java b/nz-admin/src/main/java/com/nis/modules/panel/service/VisualService.java deleted file mode 100644 index 6b77ec94..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/VisualService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.nis.modules.panel.service; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Map; - -public interface VisualService { - - String getTimeStep(Long start, Long end); - - void exploreSnapshot(HttpServletResponse response, String format, Integer type, Long start, Long end, String language, Integer unit, String limit, String direction, String[] expressions) throws IOException; - - Map<String, Object> snapshotResultMap(Long start, Long end, String language); - - String replaceSnapshotTemplate(Map<String, Object> resultMap); -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualChartServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualChartServiceImpl.java deleted file mode 100644 index 426682e2..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualChartServiceImpl.java +++ /dev/null @@ -1,1049 +0,0 @@ -package com.nis.modules.panel.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.nis.common.exception.NZException; -import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.*; -import com.nis.common.utils.Constant.ChartDatasourceType; -import com.nis.common.utils.Tool.NzExpressionUtil; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.asset.entity.AssetModel; -import com.nis.modules.asset.service.AssetAssetService; -import com.nis.modules.asset.service.AssetModelService; -import com.nis.modules.endpoint.entity.MonitorEndpoint; -import com.nis.modules.endpoint.service.MonitorEndpointService; -import com.nis.modules.module.entity.MonitorModule; -import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.dao.VisualChartDao; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualChartElement; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualChartElementService; -import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; -import com.nis.modules.sys.service.SysDictService; -import com.nis.modules.sys.shiro.ShiroUtils; -import org.apache.commons.collections.CollectionUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.ObjectUtils; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Service("visualChartService") -public class VisualChartServiceImpl extends ServiceImpl<VisualChartDao, VisualChart> implements VisualChartService { - - private Log log = Log.get(); - - @Autowired - private VisualPanelService visualPanelService; - - @Autowired - private SysDictService sysDictService; - - @Autowired - private VisualChartElementService chartElementService; - - @Autowired - private AssetAssetService assetAssetService; - - @Autowired - private MonitorEndpointService monitorEndpointService; - - @Autowired - private AssetModelService assetModelService; - - @Autowired - private MonitorModuleService monitorModuleService; - - @Override - public PageUtils queryPage(Map<String, Object> params) { - String ids = (String) params.get("ids"); - if(StrUtil.isNotBlank(ids)) { - List<String> listIds = Arrays.asList(ids.split(",")); - params.put("ids",listIds); - } - String pid = (String) params.get("pids"); - if(StrUtil.isNotBlank(pid)) { - List<String> listIds = Arrays.asList(pid.split(",")); - params.put("pids",listIds); - } - IPage page = new Query(VisualChart.class).getPage(params); - // 查询出chart信息 - List<VisualChart> result = this.baseMapper.queryPage(page,params); - //查询elements - List<Integer> chartIds = result.stream().map(VisualChart::getId).collect(Collectors.toList()); - List<VisualChartElement> chartElements = chartElementService.list(new QueryWrapper<VisualChartElement>().lambda().in(VisualChartElement::getChartId, chartIds)); - Map<Integer, List<VisualChartElement>> chartIdAndElement = chartElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); - - String param; - for (VisualChart chart : result) { - // param 格式处理 - param = (String) chart.getParam(); - if (StringUtils.isNotEmpty(param)) { - chart.setParam(JSONObject.parseObject(param, Map.class)); - } - chart.setElements(chartIdAndElement.get(chart.getId())); - } - - String returnChildren = (String) params.get("returnChildren"); - if(ToolUtil.isEmpty(returnChildren)) { - returnChildren = "1" ; - } - if(StrUtil.equals(returnChildren, "1")) { - List<Integer> fatherIds = result.stream().filter(chart->chart.getGroupId()==0).map(VisualChart::getId).collect(Collectors.toList()); - if(ToolUtil.isNotEmpty(fatherIds)) { - Map<String, Object> queryChildren =new HashMap<String,Object>(); - queryChildren.put(Constant.LIMIT, "-1"); - IPage childrenpage = new Query(VisualChart.class).getPage(queryChildren); - queryChildren.put("groupIds", fatherIds); - List<VisualChart> childrens = this.baseMapper.queryPage(childrenpage,queryChildren); - // 查询chart相关的element - if(ToolUtil.isNotEmpty(childrens)) { - List<Integer> childIds = childrens.stream().map(VisualChart::getId).collect(Collectors.toList()); - List<VisualChartElement> childElements = chartElementService.list(new QueryWrapper<VisualChartElement>().lambda().in(VisualChartElement::getChartId, childIds)); - Map<Integer, List<VisualChartElement>> childIdAndElement = childElements.stream().collect(Collectors.groupingBy(VisualChartElement::getChartId)); - for (VisualChart chart : childrens) { - // param 格式处理 - param = (String) chart.getParam(); - if (StringUtils.isNotEmpty(param)) { - chart.setParam(JSONObject.parseObject(param, Map.class)); - } - chart.setElements(childIdAndElement.get(chart.getId())); - } - result.addAll(childrens); - result = this.getChartTreeList(result,0); - } - } - } - page.setRecords(result); - return new PageUtils(page); - } - - /** - * 递归获取树结构 - * - * @param chartList - * @param parentId - * @return - */ - private List<VisualChart> getChartTreeList(List<VisualChart> chartList, Integer parentId) { - List<VisualChart> resultList = new ArrayList<>(); - for (VisualChart chart : chartList) { - Integer id = chart.getId(); - Integer groupId = chart.getGroupId(); - if(parentId.equals(groupId)) { - chart.setChildren(this.getChartTreeList(chartList, id)); - resultList.add(chart); - } - } - return resultList; - } - - - @Override - public VisualChart queryInfo(Integer id) { - - return this.baseMapper.queryInfo(id); - } - - /** - * 校验 chart 信息 - * 1. panel 是否存在 - * 2. tyep 有效性校验 - * 3. param 校验 - * - * @param chart - */ - @Override - public void validateChart(VisualChart chart) { - - Integer panelId = chart.getPanelId(); - ValidateUtils.is(panelId).notNull(RCode.PANEL_ID_ISNULL); - // 1. panel 是否存在 - this.validatePanel(panelId); - - // 校验vartype - if(panelId==0) { - ValidateUtils.is(chart.getVarType()).notNull(RCode.CHART_VARTYPE_ISNULL); - } - - String type = chart.getType(); - ValidateUtils.is(chart.getName()).notNull(RCode.CHART_TITLE_ISNULL).maxLength(64) - .and(chart.getSpan()).notNull(RCode.CHART_SPAN_ISNULL) - .and(chart.getHeight()).notNull(RCode.CHART_HEIGHT_ISNULL) - .and(type).notNull(RCode.CHART_TYPE_ISNULL) - .and(chart.getRemark()).maxLength(256); - - // 2. 验证type是否在枚举范围内 - sysDictService.checkSysDicValue(Constant.DICT_CHART_TYPE, type, RCode.CHART_TYPE_INVALIDE); - - // 3. 根据 type 校验 各项参数 - Map param = (Map) chart.getParam(); - List<VisualChartElement> elements = chart.getElements(); - switch (type) { - // url类型 - case Constant.CHART_URL_TYPE: { - ValidateUtils.is(param).notNull(RCode.CHART_URLPARAM_ISNULL); - Object url = param.get(Constant.CHART_URL_TYPE); - if (ToolUtil.isEmpty(url)) { - throw new NZException(RCode.CHART_URLPARAM_ISNULL); - } - - String urlStr = url.toString(); - // 如果是model panel添加charts url类型支持{{}}替换 - VisualPanel panel = visualPanelService.getById(panelId); - if(ObjectUtil.isNotEmpty(panel) && StrUtil.equals(Constant.PanelType.MODEL.getValue(),panel.getType())) { - // 替换全部变量 替换为 a(任意字符) 不影响原来的数据格式 然后进行校验 - urlStr = urlStr.replaceAll("\\{\\{asset\\..*?\\}\\}", "a"); - - boolean b = CommonUtils.checkUrlInModel(urlStr); - boolean b1 = CommonUtils.checkUrl(urlStr); - - if (!b && !b1) { - throw new NZException(RCode.CHART_PARAMURL_FORMAT); - } - } else { - if (!CommonUtils.checkUrl(urlStr)) { - throw new NZException(RCode.CHART_PARAMURL_FORMAT); - } - } - break; - } - // stat 类型 - case Constant.CHART_SINGLESTAT_TYPE: { - ValidateUtils.is(param).notNull(RCode.CHART_SINGLESTATPARAM_ISNULL); - - Object statistics = param.get(Constant.CHART_SINGLESTAT_PARAMkEY); - if (ToolUtil.isEmpty(statistics)) { - throw new NZException(RCode.CHART_PARAMSINGLESTAT_ISNULL); - } - if (!Constant.CHART_SINGLESTAT_STATISTICS.contains(statistics.toString())) { - throw new NZException(RCode.CHART_PARAMSINGLESTAT_INVALIDE); - } - break; - } - // group 类型不需要校验 elements - case Constant.CHART_GROUP_TYPE:{ - // 当chart为group时 不允许name重复 会影响chart批量导入 - List<VisualChart> charts = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getName, chart.getName()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString()).eq(VisualChart::getPanelId, chart.getPanelId()).ne(ToolUtil.isNotEmpty(chart.getId()), VisualChart::getId,chart.getId()).ne(ToolUtil.isNotEmpty(chart.getVarType()), VisualChart::getVarType,chart.getVarType())); - if(ToolUtil.isNotEmpty(charts)) { - throw new NZException(RCode.CHART_GROUP_NAME_DUPLICATE); - } - chart.setElements(null); - break; - } - case Constant.CHART_TEXT_TYPE: { - ValidateUtils.is(param).notNull(RCode.CHART_TEXTPARAM_ISNULL); - Object text = param.get(Constant.CHART_TEXT_TYPE); - if (ToolUtil.isEmpty(text)) throw new NZException(RCode.CHART_TEXTPARAM_ISNULL); - break; - } - } - - - // 4. 校验 unit 是否合法 - Integer unit = chart.getUnit(); - if (unit != null) { - List<Integer> unitList = new ArrayList(Constant.ALERT_RULE_UNIT_MAP.values()); - if (unit < Collections.min(unitList) || unit > Collections.max(unitList)) { - throw new NZException(RCode.CHART_UNIT_NOTFOUND); - } - } - - // 5. 校验 groupId 是否有值 - Integer groupId = chart.getGroupId(); - if(ObjectUtils.isEmpty(groupId)) { - throw new NZException(RCode.CHART_GROUPID_ISNULL); - } - - // 6. 当前操作人信息赋值 - Long userId = ShiroUtils.getUserId(); - chart.setUpdateBy(userId.intValue()); - - // 7. 校验datasource是否为空 - if(StrUtil.isBlank(chart.getDatasource())) { - throw new NZException(RCode.CHART_DATASOURCE_ISNULL); - }else { - // 校验是否为内置类型 - sysDictService.checkSysDicValue(Constant.DICT_CHART_DATASOURCE, chart.getDatasource(), RCode.CHART_DATASOURCE_INVALIDE); - } - - // 8. 校验element参数 仅datasource类型为 logs metrics需要进行校验 - if (chart.getDatasource().equals(Constant.ChartDatasourceType.METRICS.getValue()) || chart.getDatasource().equals(Constant.ChartDatasourceType.LOGS.getValue())) { - ValidateUtils.is(elements).notNull(RCode.CHART_ELEMENT_ISNULL); - chartElementService.validateElements(elements); - } - } - - /** - * 校验 panel 是否存在 - * - * @param panelId - */ - public void validatePanel(Integer panelId) { - if(panelId.equals(0)) { - return; - } - VisualPanel panel = visualPanelService.getById(panelId); - if (panel == null) { - throw new NZException(RCode.CHART_PANEL_ISNULL); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Integer saveChart(VisualChart chart) { - // 1. 新增 chart 自动追加至末尾 - chart.setUpdateAt(new Date()); - chart.setName(StrUtil.trim(chart.getName())); - Object param = chart.getParam(); - if (param != null && param instanceof HashMap) { - chart.setParam(JSONObject.toJSONString(param)); - } - - // 2. 判断当前 panel 下是否已存在 charts - List<VisualChart> list = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getPanelId, chart.getPanelId())); - if (CollectionUtils.isEmpty(list)) { - // 不存在 charts - this.save(chart); - } else { - VisualChart endChart = this.getOne(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getPanelId, chart.getPanelId()).orderByDesc(VisualChart::getWeight).last("limit 0,1")); - Integer weight = endChart.getWeight(); - chart.setWeight(++weight); - this.save(chart); - } - - // 3. 保存 chart elements信息 - chartElementService.saveOrUpdateElements(chart.getId(), chart.getElements()); - - /*// 4. 同步新增处理 - Integer sync = chart.getSync(); - if (sync != null) { - VisualPanel panel = visualPanelService.getById(chart.getPanelId()); - // 当前 chart 所属 panel 为 model 类型并且 同步标识 为 1 时 ,对已通过对应 model panel 创建的 asset panel 追加新增的 chart - if(StrUtil.equals(Constant.PanelType.MODEL.getValue(),panel.getType()) && sync.equals(1)) { - this.saveAssetChartsSimultaneously(panel, chart); - } - }*/ - - return chart.getId(); - } - - /** - * 新增 model 时对已通过对应 model panel 创建的 asset panel 追加新增的 chart - * - * @param modelPanel - * @param chart - */ - private void saveAssetChartsSimultaneously(VisualPanel modelPanel, VisualChart chart) { - // 1. 通过 panel linke 的 modelId 查找该 model 下是否关联 asset - List<AssetAsset> assets = assetAssetService.list(new LambdaQueryWrapper<AssetAsset>().eq(AssetAsset::getModelId, modelPanel.getLink())); - if (CollectionUtils.isEmpty(assets)) { - return; - } - - // 2. 通过 assets 找到关联的所有 asset panel - List<Integer> assetsIds = assets.stream().map(AssetAsset::getId).collect(Collectors.toList()); - List<VisualPanel> panels = visualPanelService.list(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getType, Constant.PanelType.ASSET.getValue()).in(VisualPanel::getLink, assetsIds)); - - Map<Integer, AssetAsset> assetIdAndEntityMap = new HashMap<>(16); - for (AssetAsset asset : assets) { - assetIdAndEntityMap.put(asset.getId(), asset); - } - - // 3. 得到 panelId 和 关联的 asset 实体 ,准备做 变量替换所需 - Map<Integer, AssetAsset> panelIdAndAsset = new HashMap<>(); - for (VisualPanel entity : panels) { - panelIdAndAsset.put(entity.getId(), assetIdAndEntityMap.get(entity.getLink())); - } - - // 4. 处理属性 - VisualChart targetChart = new VisualChart(); - AssetAsset asset; - for (Map.Entry<Integer, AssetAsset> entry : panelIdAndAsset.entrySet()) { - asset = entry.getValue(); - targetChart = JSONObject.parseObject(JSON.toJSONString(chart), VisualChart.class); - targetChart.setSync(null); - targetChart.setId(null); - targetChart.setPid(chart.getId()); - - // chart : title param chart element : expression 属性需要做 asset 变量替换 - targetChart.setName(Tool.NzExpressionUtil.renderExpression(targetChart.getName(),asset)); - targetChart.setParam(ToolUtil.isNotEmpty(targetChart.getParam()) ? Tool.NzExpressionUtil.renderExpression(targetChart.getParam().toString(), asset) : null); - - if (CollectionUtils.isNotEmpty(targetChart.getElements())) { - for (VisualChartElement element : targetChart.getElements()) { - element.setId(null); - element.setExpression(ToolUtil.isNotEmpty(element.getExpression()) ? Tool.NzExpressionUtil.renderExpression(element.getExpression(), asset) : null); - } - } - - // 5. 调用保存方法进行 新增 - this.saveChart(targetChart); - } - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public Integer updateChart(VisualChart chart) { - // 1. 校验 - chart.setName(StrUtil.trim(chart.getName())); - this.validateChart(chart); - - Object param = chart.getParam(); - if (param != null) { - chart.setParam(JSONObject.toJSONString(param)); - } - - this.updateById(chart); - - // 3. 修改 chart elements - chartElementService.saveOrUpdateElements(chart.getId(), chart.getElements()); - - // 4. 同步修改处理 - Integer sync = chart.getSync(); - if (sync != null) { - VisualPanel panel = visualPanelService.getById(chart.getPanelId()); - // 当前 chart 所属 panel 为 model 类型并且 同步标识 为 1 时 ,对根据 chart pid 查找通过此 chart 创建的 chart 更新 - if(StrUtil.equals(Constant.PanelType.MODEL.getValue(),panel.getType()) && sync.equals(1)) { - this.updateAssetChartsSimultaneously(chart); - } - } - - return chart.getId(); - } - - /** - * 对根据 chart pid 查找通过此 chart 创建的 chart 进行更新 - * - * @param chart - */ - private void updateAssetChartsSimultaneously(VisualChart chart) { - // 1. 查找引用的 charts - List<VisualChart> charts = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getPid, chart.getId())); - if (CollectionUtils.isEmpty(charts)) { - return; - } - - List<Integer> idList = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); - - // 2. 先删除之前的 elements 使用当前 chart element 进行更新 - chartElementService.delElementByChartIds(idList); - - // 3. 返回引用 chartId 和 对应的 asset 信息 ,准备做 变量替换所需 - List<VisualChart> chartIdWithAssetEntity = assetAssetService.getAssetsWithTagByChartIds(idList); - Map<Integer, AssetAsset> chartIdAndAssetEntityMap = chartIdWithAssetEntity.stream().collect(Collectors.toMap(VisualChart::getId, VisualChart::getAsset)); - - // 4. 处理更新 - List<VisualChartElement> elements = chart.getElements(); - List<VisualChartElement> saveElements = new ArrayList<>(); - VisualChartElement tempElement; - AssetAsset asset; - for (VisualChart entity : charts) { - asset = chartIdAndAssetEntityMap.get(entity.getId()); - entity.setName(Tool.NzExpressionUtil.renderExpression(chart.getName(), asset)); - entity.setSpan(chart.getSpan()); - entity.setHeight(chart.getHeight()); - entity.setType(chart.getType()); - entity.setUnit(chart.getUnit()); - entity.setParam(ToolUtil.isNotEmpty(chart.getParam()) ? Tool.NzExpressionUtil.renderExpression(chart.getParam().toString(), asset) : null); - if (CollectionUtils.isNotEmpty(elements)) { - for (VisualChartElement chartElement : elements) { - tempElement = new VisualChartElement(); - BeanUtils.copyProperties(chartElement, tempElement); - tempElement.setChartId(entity.getId()); - tempElement.setId(null); - tempElement.setExpression(ToolUtil.isNotEmpty(chartElement.getExpression()) ? Tool.NzExpressionUtil.renderExpression(chartElement.getExpression(), asset) : null); - saveElements.add(tempElement); - } - } - } - - this.saveOrUpdateBatch(charts); - chartElementService.saveBatch(saveElements); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delCharts(Integer[] ids, Integer sync) { - - // 内置chart不能删除 - this.validateBuildInCharts(Arrays.asList(ids)); - - List<VisualChart> deleteCharts = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getId, Arrays.asList(ids))); - - List<Integer> deleteIds =new ArrayList<Integer>(); - for(VisualChart deleteChart : deleteCharts) { - if(deleteChart.getPanelId().equals(0)) { - deleteIds.add(deleteChart.getId()); - } - } - - if (CollectionUtils.isNotEmpty(deleteIds)) { - if (sync != null) { - // 同步删除 - if(sync.equals(1)) { - this.syncDeleteAssetsCharts(deleteIds); - } - } - } - - List<Integer> idList = new ArrayList<>(Arrays.asList(ids)); - - // 删除 Endpoint modules 引用的 chart templates - List<MonitorModule> monitorModuleList = monitorModuleService.list(new QueryWrapper<MonitorModule>().lambda().isNotNull(MonitorModule::getChartIds).ne(MonitorModule::getChartIds, "")); - for (MonitorModule monitorModule : monitorModuleList) { - monitorModule.setChartIds(this.delIds(monitorModule.getChartIds(), idList)); - } - if(Tool.CollUtil.isNotEmpty(monitorModuleList)) - monitorModuleService.saveOrUpdateBatch(monitorModuleList); - // 删除 Asset models 引用的 chart templates - List<AssetModel> assetModelList = assetModelService.list(new QueryWrapper<AssetModel>().lambda().isNotNull(AssetModel::getChartIds).ne(AssetModel::getChartIds, "")); - for (AssetModel assetModel : assetModelList) { - assetModel.setChartIds(this.delIds(assetModel.getChartIds(), idList)); - } - if(Tool.CollUtil.isNotEmpty(assetModelList)) - assetModelService.saveOrUpdateBatch(assetModelList); - - // 如果删除 ids 中 type 为 group ,则补充 group 包含的 chart ids - List<VisualChart> childrenCharts = this.list(new LambdaQueryWrapper<VisualChart>().in(VisualChart::getGroupId, Arrays.asList(ids))); - if(CollectionUtils.isNotEmpty(childrenCharts)){ - Set<Integer> idSet = childrenCharts.stream().map(VisualChart::getId).collect(Collectors.toSet()); - idList.addAll(idSet); - } - - // 删除自身 - this.baseMapper.deleteBatchIds(idList); - - // 删除char element - chartElementService.delElementByChartIds(idList); - } - - private String delIds(String chartIds, List<Integer> chartIdList){ - String str = ""; - for (String chartId : chartIds.split(",")) { - if(!chartIdList.contains(Integer.valueOf(chartId))){ - str += "," + chartId; - } - } - return StrUtil.isBlank(str) ? str : str.substring(1); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delVisualChartsByPanelId(Integer... panelIds) { - if (ToolUtil.isEmpty(panelIds)) { - return; - } - - // 1. 再次通过 panelid 查询 是为了只删除当前 panel 下的 charts - List<VisualChart> charts = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getPanelId, panelIds)); - List<Integer> chartIds = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); - - // 2. 内置chart不能删除 - this.validateBuildInCharts(chartIds); - - // 3. 不为空 则删除自身 同时删除关联的 element - if (CollectionUtils.isNotEmpty(chartIds)) { - this.removeByIds(chartIds); - chartElementService.delElementByChartIds(chartIds); - } - } - - /** - * 校验是否是内置chart - * - * @param chartIds - */ - private void validateBuildInCharts(List<Integer> chartIds) { - // 内置charts - List<VisualChart> buildInCharts = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getBuildIn, 1)); - Map<Integer, String> buildInChartIdAndTitleMap = buildInCharts.stream().collect(Collectors.toMap(VisualChart::getId, VisualChart::getName)); - - chartIds.forEach(id -> { - if (ToolUtil.isNotEmpty(buildInChartIdAndTitleMap.get(id))) { - throw new NZException(buildInChartIdAndTitleMap.get(id) + " chart is built-in and cannot be deleted", RCode.CHART_BUILDIN_CAN_NOT_REMOVE.getCode()); - } - }); - } - - /** - * 根据 chart.pid 查找引用自此chart,同步删除 - * - * @param deleteIds - */ - private void syncDeleteAssetsCharts(List<Integer> deleteIds) { - // 关联 charts - List<VisualChart> list = this.list(new QueryWrapper<VisualChart>().lambda().in(VisualChart::getPid, deleteIds)); - if (CollectionUtils.isEmpty(list)) { - return; - } - Map<Integer, List<VisualChart>> listMap = list.stream().collect(Collectors.groupingBy(VisualChart::getPanelId)); - - List<Integer> allDeleteChartIds = listMap.values().stream().flatMap(Collection::stream).map(VisualChart::getId).collect(Collectors.toList()); - // 删除自身 - this.removeByIds(allDeleteChartIds); - // 删除关联的 chart Elements - chartElementService.delElementByChartIds(allDeleteChartIds); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void modify(VisualChart chart) { - - // 调整大小 - this.baseMapper.updateSizeById(chart); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void weights(Integer panelId,List<VisualChart> chartList) { - - if (CollectionUtils.isEmpty(chartList)) throw new NZException(RCode.CHART_WEIGHT_ISNULL); - for (VisualChart chart : chartList) { - if (chart.getId() == null) throw new NZException(RCode.CHART_ID_ISNULL); - if (chart.getWeight() == null) throw new NZException(RCode.CHART_WEIGHT_ISNULL); - } - - this.baseMapper.updateWeightBatch(panelId,chartList); - } - - @Override - public Map<Integer,Integer> queryChartNum() { - Map<Integer, Integer> collect = new HashMap<Integer, Integer>(); - List<VisualChart> result = this.baseMapper.selectChartNum(); - if(!ObjectUtils.isEmpty(result)) { - collect = result.stream().collect(Collectors.toMap(VisualChart::getId, VisualChart::getChartNums)); - } - return collect; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Integer fromTmpl(Map<String, Object> params) { - // 校验参数合法 - Integer pid = (Integer) params.get("pid"); - List<Integer> varIds = (List<Integer>) params.get("varIds"); - ValidateUtils.is(pid).notNull(RCode.CHART_PID_ISNULL).and(varIds).notNull(RCode.CHART_VARID_ISNULL); - /* - * 当panelId 不为空时,是向一个panel添加多个 chart - * 当panelId 为空时,则向多个panel (varIds) 添加一个chart - */ - Integer panelId = (Integer) params.get("panelId"); - - List<VisualChart> chartList = new ArrayList<>(); - // 查询模板添加的chart信息 - VisualChart chartInfo = this.baseMapper.queryInfo(pid); - chartList.add(chartInfo); - if (Constant.CHART_GROUP_TYPE.equalsIgnoreCase(chartInfo.getType())) { - // 如果类型为 group 则添加组下所有 charts - List<VisualChart> childrenChartList = this.list(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getGroupId, chartInfo.getId()).eq(VisualChart::getPanelId, 0)); - List<Integer> childrenChartIdList = childrenChartList.stream().map(VisualChart::getId).distinct().collect(Collectors.toList()); - - if(ObjectUtil.isNotEmpty(childrenChartIdList)) { - List<VisualChart> visualCharts = this.baseMapper.queryList(childrenChartIdList); - chartList.addAll(visualCharts); - } - } - - // 按照 group 升序,先添加组 - chartList = chartList.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); - - List<VisualPanel> panelList = visualPanelService.list(); - - if (ObjectUtil.isNotEmpty(panelId)) { - VisualPanel panel = panelList.stream().filter(visualPanel -> visualPanel.getId().equals(panelId)).findAny().orElse(null); - ValidateUtils.is(panel).notNull(RCode.PANEL_NOT_EXIST); - } - - Integer total = 0; - for (Integer entityId : varIds) { - Map<Integer, Integer> groupIdMapping = new HashMap<>(); - - List<VisualChart> tempChartList = JSONObject.parseArray(JSONObject.toJSONString(chartList), VisualChart.class); - for (VisualChart chart : tempChartList) { - Map<Integer, Object> objs = new HashMap<>(); - // 查询所有 varId 对应数据信息 - if (chart.getVarType().equals(Constant.ChartVariableType.ASSET.getValue())) { - AssetAsset asset = assetAssetService.queryAssetInfo(entityId); - objs.put(entityId, asset); - } else if (chart.getVarType().equals(Constant.ChartVariableType.ENDPOINT.getValue())) { - MonitorEndpoint endpoint = monitorEndpointService.queryEndpointEntity(entityId); - objs.put(entityId, endpoint); - } - - if (ToolUtil.isEmpty(objs.get(entityId))) { - throw new NZException(RCode.CHART_VARID_ERROR); - } - - VisualChart visualChart = new VisualChart(); - BeanUtil.copyProperties(chart, visualChart); - - visualChart.setId(null); - visualChart.setPid(chart.getId()); - visualChart.setVarId(entityId); - visualChart.setUpdateAt(new Date()); - visualChart.setUpdateBy(ShiroUtils.getUserId().intValue()); - - if (ObjectUtil.isNotEmpty(panelId)) { - visualChart.setPanelId(panelId); - } else { - String type = chart.getVarType().equals(Constant.ChartVariableType.ASSET.getValue()) ? Constant.PanelType.ASSET.getValue() : Constant.PanelType.ENDPOINT.getValue(); - VisualPanel linkPanel = panelList.stream().filter(panel -> type.equalsIgnoreCase(panel.getType()) && entityId.equals(panel.getLink())).findAny().orElse(null); - visualChart.setPanelId(linkPanel.getId()); - } - - visualChart.setName(NzExpressionUtil.renderExpression(visualChart.getName(), objs.get(entityId))); - visualChart.setParam(ToolUtil.isNotEmpty(visualChart.getParam()) ? Tool.NzExpressionUtil.renderExpression(visualChart.getParam().toString(), objs.get(entityId)) : null); - - Integer newGroupId = groupIdMapping.get(visualChart.getGroupId()); - visualChart.setGroupId(newGroupId == null ? 0 : newGroupId); - - // 因为 组名不能重复问题 如果添加组则校验组名唯一 - if (Constant.CHART_GROUP_TYPE.equalsIgnoreCase(chart.getType())) { - List<VisualChart> charts = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getName, visualChart.getName()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString()).eq(VisualChart::getPanelId, visualChart.getPanelId())); - if (ToolUtil.isNotEmpty(charts)) { - throw new NZException(RCode.CHART_GROUP_NAME_DUPLICATE); - } - } - - // 保存 - this.save(visualChart); - total++; - - // 添加之后 group 类型保存 id mapping - if (Constant.CHART_GROUP_TYPE.equalsIgnoreCase(chart.getType())) { - groupIdMapping.put(chart.getId(), visualChart.getId()); - } - - if (CollectionUtils.isNotEmpty(visualChart.getElements())) { - for (VisualChartElement element : visualChart.getElements()) { - element.setId(null); - element.setExpression(NzExpressionUtil.renderExpression(element.getExpression(), objs.get(entityId))); - element.setChartId(visualChart.getId()); - } - chartElementService.saveBatch(visualChart.getElements()); - } - } - } - return total; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Integer syncTmpl(Map<String, Object> params) { - // 校验参数合法 - Integer pid = (Integer) params.get("pid"); - List<Integer> ids = (List<Integer>) params.get("ids"); - Integer panelId = (Integer) params.get("panelId"); - List<Integer> models = (List<Integer>) params.get("models"); - Integer modules = (Integer) params.get("modules"); - // 五个参数不能同时为空 - if (ObjectUtil.isAllEmpty(pid, ids, panelId, models, modules)) { - throw new NZException(RCode.CHART_SYNCTMPL_ERROR); - } - List<VisualChart> analysis = new ArrayList<VisualChart>(); - if(ToolUtil.isNotEmpty(pid) || ToolUtil.isNotEmpty(ids) || ToolUtil.isNotEmpty(panelId)) { - // 查询 - List<VisualChart> charts = this.baseMapper.selectTmplCharts(params); - if(ToolUtil.isEmpty(charts)) { - return 0; - } - // 记录同步的chartId统一删除 - List<Integer> removeIds = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); - // 获取所有父类模板的id信息 - List<Integer> pids = charts.stream().map(VisualChart::getPid).collect(Collectors.toList()); - // 获取所有模板数据 - List<VisualChart> templateCharts = this.baseMapper.queryList(pids); - List<VisualChart> chartResult = this.handlerSyncChart(charts,templateCharts,null); - if(ToolUtil.isNotEmpty(chartResult)) { - // 批量删除chart 重新同步chart - this.delCharts(removeIds.toArray(new Integer[] {removeIds.size()}), 1); - } - analysis.addAll(chartResult); - } - if(ToolUtil.isNotEmpty(models) || ToolUtil.isNotEmpty(modules)) { - if(ToolUtil.isNotEmpty(models)) { - List<AssetModel> assetModels = (List<AssetModel>) assetModelService.listByIds(models); - for(AssetModel assetModel : assetModels) { - if(StrUtil.isNotBlank(assetModel.getChartIds())) { - List<String> assetModelChartIds = Arrays.asList(assetModel.getChartIds().split(",")); - List<Integer> chartIdList = assetModelChartIds.stream().map(Integer::parseInt).collect(Collectors.toList()); - // 获取所有模板数据 - List<VisualChart> templateCharts = this.baseMapper.queryList(chartIdList); - // 获取所有实例化图表数据信息 用于删除操作 - List<VisualChart> charts = this.baseMapper.selectInstanceChart(1, assetModel.getId()); - // 记录同步的chartId统一删除 - List<Integer> removeIds = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); - Map<String,Object> assetMap =new HashMap<String,Object>(); - assetMap.put("modelIds", assetModel.getId()+""); - assetMap.put("pageSize", "-1"); - PageUtils assetPage = assetAssetService.queryAssetPage(assetMap); - List<AssetAsset> assetAssets = (List<AssetAsset>) assetPage.getList(); - if(ToolUtil.isEmpty(assetAssets)) { - continue; - } - List<VisualChart> chartResult = this.handlerSyncChart(null,templateCharts,assetAssets); - if(ToolUtil.isNotEmpty(chartResult)) { - // 批量删除chart 重新同步chart - this.delCharts(removeIds.toArray(new Integer[] {removeIds.size()}), 1); - } - analysis.addAll(chartResult); - } - } - } - - if(ToolUtil.isNotEmpty(modules)) { - MonitorModule monitorModule = monitorModuleService.getById(modules); - if(StrUtil.isNotBlank(monitorModule.getChartIds())) { - List<String> moduleChartIds = Arrays.asList(monitorModule.getChartIds().split(",")); - List<Integer> chartIdList = moduleChartIds.stream().map(Integer::parseInt).collect(Collectors.toList()); - // 获取所有模板数据 - List<VisualChart> templateCharts = this.baseMapper.queryList(chartIdList); - // 获取所有实例化图表数据信息 用于删除操作 - List<VisualChart> charts = this.baseMapper.selectInstanceChart(2, monitorModule.getId()); - // 记录同步的chartId统一删除 - List<Integer> removeIds = charts.stream().map(VisualChart::getId).collect(Collectors.toList()); - Map<String,Object> endpointMap =new HashMap<String,Object>(); - endpointMap.put("moduleIds", monitorModule.getId()+""); - endpointMap.put("pageSize", "-1"); - PageUtils endpointPage = (PageUtils) monitorEndpointService.queryPage(endpointMap).get("page"); - List<MonitorEndpoint> monitorEndpoints = (List<MonitorEndpoint>) endpointPage.getList(); - if(ToolUtil.isEmpty(monitorEndpoints)) { - return 0; - } - List<VisualChart> chartResult = this.handlerSyncChart(null,templateCharts,monitorEndpoints); - if(ToolUtil.isNotEmpty(chartResult)) { - // 批量删除chart 重新同步chart - this.delCharts(removeIds.toArray(new Integer[] {removeIds.size()}), 1); - } - analysis.addAll(chartResult); - } - } - } - return analysis.size(); - } - - /** - * 传入已经通过模板生成的图表 用于获取绑定关联关系 - * 传入模板图表 进行sync操作 - * - * @param instanceCharts - * @param tmpCharts - * @return - */ - public List<VisualChart> handlerSyncChart(List<VisualChart> instanceCharts,List<VisualChart> tmpCharts,Object obj) { - List<VisualChart> resultCharts = new ArrayList<VisualChart>(); - // 处理模板图表 主要处理当前模板图表中有group组新增图表情况的可能 将图表类型是组下的图表先剔除 后添加 避免重复添加 - List<VisualChart> groupTmpCharts = new ArrayList<VisualChart>(); - - Map<Integer,List<VisualChart>> groupIdAndChildren = new HashMap<Integer,List<VisualChart>>(); - // 根据组进行排序 - tmpCharts=tmpCharts.stream().sorted(Comparator.comparing(VisualChart::getGroupId).reversed()).collect(Collectors.toList()); - for(int i =tmpCharts.size()-1;i>=0;i--) { - VisualChart tmpChart = tmpCharts.get(i); - if(tmpChart.getType().equals(Constant.CHART_GROUP_TYPE)) { - // 如果类型为组 查询组下所有模板信息 - List<VisualChart> list = this.list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getGroupId, tmpChart.getId())); - List<Integer> childIds = list.stream().map(VisualChart::getId).collect(Collectors.toList()); - if(ToolUtil.isNotEmpty(childIds)) { - List<VisualChart> groupChildrens = this.baseMapper.queryList(childIds); - groupTmpCharts.addAll(groupChildrens); - groupIdAndChildren.put(tmpChart.getId(),groupChildrens); - } - } - if(tmpChart.getGroupId()!=0 && ToolUtil.isNotEmpty(groupIdAndChildren.get(tmpChart.getGroupId()))) { - tmpCharts.remove(i); - } - } - // 组装所有模板图表包含新增图表 - tmpCharts.addAll(groupTmpCharts); - // 根据后两项参数进行逻辑区分 - if (ToolUtil.isEmpty(obj) && instanceCharts!=null) { - Map<Integer, VisualChart> map = tmpCharts.stream().collect(Collectors.toMap(VisualChart::getId, Function.identity())); - instanceCharts = instanceCharts.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); - for(VisualChart instanceChart : instanceCharts) { - VisualChart temp = map.get(instanceChart.getPid()); - if(ToolUtil.isEmpty(temp) || (temp.getGroupId()!=0 && ToolUtil.isNotEmpty(groupIdAndChildren.get(temp.getGroupId())))) { - continue; - } - Integer groupChartId = handlerSyncGroupChart(temp,instanceChart,resultCharts); - if(temp.getType().equals(Constant.CHART_GROUP_TYPE)) { - instanceChart.setGroupId(groupChartId); - List<VisualChart> children = groupIdAndChildren.get(temp.getId()); - if(ToolUtil.isNotEmpty(children)) { - for(VisualChart child : children) { - handlerSyncGroupChart(child,instanceChart,resultCharts); - } - } - - } - } - }else if(ToolUtil.isNotEmpty(obj) && instanceCharts==null){ - Map<String,Integer> tmpGroupIdAndInstanceGroupId = new HashMap<String,Integer>(); - for(VisualChart tmpChart : tmpCharts) { - for(Object data : (List<Object>)obj) { - Integer varId =0; - String type=""; - if(data instanceof MonitorEndpoint) { - data = (MonitorEndpoint) data; - varId = ((MonitorEndpoint) data).getId(); - type = Constant.PanelType.ENDPOINT.getValue(); - }else if(data instanceof AssetAsset){ - data = (AssetAsset) data; - varId = ((AssetAsset) data).getId(); - type = Constant.PanelType.ASSET.getValue(); - } - VisualChart syncChart =new VisualChart(); - BeanUtils.copyProperties(tmpChart, syncChart); - Integer instantceId = tmpGroupIdAndInstanceGroupId.get(tmpChart.getGroupId()+":"+varId); - syncChart.setGroupId(ToolUtil.isEmpty(instantceId)? 0:instantceId); - syncChart.setPid(tmpChart.getId()); - syncChart.setVarId(varId); - syncChart.setUpdateAt(new Date()); - syncChart.setUpdateBy(ShiroUtils.getUserId().intValue()); - syncChart.setName(NzExpressionUtil.renderExpression(tmpChart.getName(),data)); - syncChart.setRemark(NzExpressionUtil.renderExpression(tmpChart.getRemark(),data)); - syncChart.setParam(ToolUtil.isNotEmpty(tmpChart.getParam()) ? Tool.NzExpressionUtil.renderExpression(tmpChart.getParam().toString(), data) : null); - // 获取各自的panelId信息 - VisualPanel panel = visualPanelService.getOne(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getType, type).eq(VisualPanel::getLink, varId)); - syncChart.setPanelId(panel.getId()); - List<VisualChartElement> elements = tmpChart.getElements(); - List<VisualChartElement> copyElements = new ArrayList<VisualChartElement>(); - //将表达式进行替换 - for(VisualChartElement element : elements) { - VisualChartElement vce = new VisualChartElement(); - BeanUtil.copyProperties(element, vce); - String renderExpression = NzExpressionUtil.renderExpression(vce.getExpression(), data); - vce.setExpression(renderExpression); - copyElements.add(vce); - } - syncChart.setElements(copyElements); - resultCharts.add(syncChart); - - if(syncChart.getType().equals(Constant.CHART_GROUP_TYPE)) { - // 当chart为group时 不允许name重复 会影响chart批量导入 - VisualChart chart = this.getOne(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getName, syncChart.getName()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString()).eq(VisualChart::getPanelId, syncChart.getPanelId()).ne(ToolUtil.isNotEmpty(syncChart.getId()), VisualChart::getId,syncChart.getId())); - if(ToolUtil.isNotEmpty(chart)) { - // group chart不能重复 先将group删除 防止不能创建组 - this.removeById(chart.getId()); - } - } - this.save(syncChart); - List<VisualChartElement> tmplChartElements = new ArrayList<VisualChartElement>(); - List<VisualChartElement> instanceElements = syncChart.getElements(); - for(VisualChartElement element : instanceElements) { - element.setChartId(syncChart.getId()); - tmplChartElements.add(element); - } - chartElementService.saveBatch(tmplChartElements); - if(tmpChart.getType().equals(Constant.CHART_GROUP_TYPE)) { - tmpGroupIdAndInstanceGroupId.put(tmpChart.getId()+":"+varId, syncChart.getId()); - } - } - } - } - return resultCharts; - } - - public Integer handlerSyncGroupChart(VisualChart temp,VisualChart instance,List<VisualChart> result) { - VisualChart syncChart =new VisualChart(); - BeanUtils.copyProperties(temp, syncChart); - syncChart.setPid(temp.getId()); - syncChart.setVarId(instance.getVarId()); - syncChart.setUpdateAt(new Date()); - syncChart.setUpdateBy(ShiroUtils.getUserId().intValue()); - - Object obj = null; - if (instance.getVarType().equals(Constant.ChartVariableType.ENDPOINT.getValue())) { - obj = monitorEndpointService.queryEndpointEntity(instance.getVarId()); - } else if (instance.getVarType().equals(Constant.ChartVariableType.ASSET.getValue())) { - obj = assetAssetService.queryAssetInfo(instance.getVarId()); - } - - syncChart.setName(NzExpressionUtil.renderExpression(temp.getName(),obj)); - syncChart.setRemark(NzExpressionUtil.renderExpression(temp.getRemark(),obj)); - syncChart.setParam(ToolUtil.isNotEmpty(temp.getParam()) ? Tool.NzExpressionUtil.renderExpression(temp.getParam().toString(), obj) : null); - syncChart.setPanelId(instance.getPanelId()); - syncChart.setGroupId(instance.getGroupId()); - List<VisualChartElement> elements = temp.getElements(); - List<VisualChartElement> copyElements = new ArrayList<VisualChartElement>(); - //将表达式进行替换 - for(VisualChartElement element : elements) { - VisualChartElement vce = new VisualChartElement(); - BeanUtil.copyProperties(element, vce); - String renderExpression = NzExpressionUtil.renderExpression(vce.getExpression(), obj); - vce.setExpression(renderExpression); - copyElements.add(vce); - } - syncChart.setElements(copyElements); - result.add(syncChart); - if(syncChart.getType().equals(Constant.CHART_GROUP_TYPE)) { - // 当chart为group时 不允许name重复 - VisualChart chart = this.getOne(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getName, syncChart.getName()).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString()).eq(VisualChart::getPanelId, syncChart.getPanelId()).ne(ToolUtil.isNotEmpty(syncChart.getId()), VisualChart::getId,syncChart.getId())); - if(ToolUtil.isNotEmpty(chart)) { - // group chart不能重复 先将group删除 防止不能创建组 - this.removeById(chart.getId()); - } - } - this.save(syncChart); - List<VisualChartElement> tmplChartElements = new ArrayList<VisualChartElement>(); - List<VisualChartElement> instanceElements = syncChart.getElements(); - for(VisualChartElement element : instanceElements) { - element.setChartId(syncChart.getId()); - tmplChartElements.add(element); - } - chartElementService.saveBatch(tmplChartElements); - return syncChart.getId(); - } - - @Override - public void saveRelPanelAndChart(String typeStr, Integer linkId, String seq, VisualChart chartTemplate) { - VisualPanel panel = new VisualPanel(); - panel.setName(typeStr + "_panel_" + linkId); - panel.setType(typeStr); - panel.setPid(0); - panel.setLink(linkId); - panel.setWeight(0); - panel.setCreateBy(ShiroUtils.getUserId().intValue()); - panel.setUts(new Date().getTime()); - if(StringUtils.isNotEmpty(seq)){ - panel.setSeq(seq); - } - visualPanelService.save(panel); - - VisualChart target = new VisualChart(); - BeanUtils.copyProperties(chartTemplate, target); - target.setParam(ToolUtil.isNotEmpty(target.getParam()) ? JSONObject.toJSONString(target.getParam()) : null); - target.setPanelId(panel.getId()); - target.setGroupId(0); - target.setUpdateBy(ShiroUtils.getUserId().intValue()); - target.setDatasource(ChartDatasourceType.SYSTEM.getValue()); - target.setUpdateAt(new Date()); - if(StringUtils.isNotEmpty(seq)){ - target.setSeq(seq); - } - this.save(target); - } - - @Override - public List<VisualChart> queryChartWithElementByIds(List<Integer> chartIdList) { - List<VisualChart> visualCharts = this.baseMapper.queryChartWithElementByIds(chartIdList); - return CollectionUtils.isEmpty(visualCharts) ? new ArrayList<>() : visualCharts; - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualPanelServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualPanelServiceImpl.java deleted file mode 100644 index d96e11c4..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualPanelServiceImpl.java +++ /dev/null @@ -1,2007 +0,0 @@ -package com.nis.modules.panel.service.impl; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import javax.servlet.http.HttpServletResponse; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.map.MapUtil; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.endpoint.entity.MonitorEndpoint; -import org.apache.commons.collections.CollectionUtils; -import org.quartz.SchedulerException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.stereotype.Service; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.JSONPath; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.nis.common.exception.NZException; -import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.CommonUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.JSONUtil; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.ResponseUtil; -import com.nis.common.utils.StringUtils; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; -import com.nis.modules.agent.service.LokiApiService; -import com.nis.modules.agent.service.PromApiService; -import com.nis.modules.asset.service.AssetAssetService; -import com.nis.modules.endpoint.service.MonitorEndpointService; -import com.nis.modules.panel.dao.VisualPanelDao; -import com.nis.modules.panel.entity.VisualChart; -import com.nis.modules.panel.entity.VisualChartElement; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualChartElementService; -import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; -import com.nis.modules.panel.service.VisualService; -import com.nis.modules.report.job.ReportJobManager; -import com.nis.modules.stat.service.impl.StatServiceImpl; -import com.nis.modules.sys.entity.SysDictEntity; -import com.nis.modules.sys.entity.SysUserStarredEntity; -import com.nis.modules.sys.service.BasicImportAndExportServices; -import com.nis.modules.sys.service.SysConfigService; -import com.nis.modules.sys.service.SysDictService; -import com.nis.modules.sys.service.SysI18nService; -import com.nis.modules.sys.service.SysUserStarredService; -import com.nis.modules.sys.shiro.ShiroUtils; - -import cn.hutool.core.thread.NamedThreadFactory; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; - -@Service("visualPanelService") -public class VisualPanelServiceImpl extends ServiceImpl<VisualPanelDao, VisualPanel> implements VisualPanelService { - - private Log log = Log.get(); - /** - * dashboard snapshot 查询超时时间,单位:ms - */ - @Value("${dashboard.snapshot.timeout:300000}") - private Integer timeout; - - @Autowired - private VisualChartService visualChartService; - - @Autowired - private SysConfigService sysConfigService; - - @Autowired - private VisualChartElementService chartElementService; - - @Autowired - private DataSourceTransactionManager dataSourceTransactionManager; - - @Autowired - private TransactionDefinition transactionDefinition; - - @Autowired - private SysDictService sysDictService; - - @Autowired - private BasicImportAndExportServices basicImportAndExportServices; - - @Autowired - private StatServiceImpl statServiceImpl; - - @Autowired - private PromApiService promApiService; - - @Autowired - private LokiApiService lokiApiService; - - @Autowired - private SysUserStarredService starredService; - - @Autowired - private AssetAssetService assetAssetService; - - @Autowired - private MonitorEndpointService monitorEndpointService; - - @Autowired - private RedisTemplate redisTemplate; - - @Autowired - private ReportJobManager reportJobManager; - - @Autowired - private SysI18nService sysI18nService; - - @Autowired - private VisualService visualService; - - @Value("${snapshot.concurrency:10}") - private Integer snapshotConcurrency; - - @Value("${snapshot.corePoolSize:5}") - private Integer snapshotCorePoolSize; - - @Value("${snapshot.keepAliveTime:30}") - private Long snapshotKeepAliveTime; - - @Value("${snapshot.capacity:10000}") - private Integer snapshotCapacity; - // snapshot 执行线程池,避免大量请求访问 prometheus 服务 - private ExecutorService snapshotThreadPool; - - @Override - public VisualPanel queryInfo(Integer id) { - VisualPanel visualPanel = this.baseMapper.queryInfo(id); - if (ToolUtil.isNotEmpty(visualPanel.getParam())) - visualPanel.setParam(JSONObject.parseObject(String.valueOf(visualPanel.getParam()), Map.class)); - - // 当前用户收藏状态 1:收藏 0:未收藏 - int count = starredService.count(new LambdaQueryWrapper<SysUserStarredEntity>() - .eq(SysUserStarredEntity::getTid, visualPanel.getId()).eq(SysUserStarredEntity::getType, "panel") - .eq(SysUserStarredEntity::getUid, ShiroUtils.getUserId().intValue())); - - visualPanel.setStarred(count == 0 ? 0 : 1); - return visualPanel; - } - - @Override - public List<VisualPanel> queryList(Map<String, Object> params) { - String ids = (String) params.get("ids"); - if (StrUtil.isNotBlank(ids)) { - List<String> listIds = Arrays.asList(ids.split(",")); - params.put("ids", listIds); - } - // 获取当前登录用户的id - Long currentLoginUserID = ShiroUtils.getUserId(); - params.put("currentLoginUserID", currentLoginUserID); - // 1. 查询时 type 为空则默认 dashboard 类型 - String type = (String) params.get("type"); - if (StringUtils.isEmpty(type)) { - type = Constant.PanelType.DASHBOARD.getValue(); - params.put("type", type); - } - // 2. dashboard 类型 需要进行排序返回 - List<VisualPanel> panelList = new ArrayList<>(); - if (StrUtil.equals(Constant.PanelType.DASHBOARD.getValue(), type)) { - panelList = this.baseMapper.queryList(params); - if (CollectionUtils.isNotEmpty(panelList) && panelList.size() != 1) { - panelList = this.getVisualPanelTreeList(panelList, 0); - } - } else { - // 3. 其他类型不进行排序 - panelList = this.baseMapper.queryList(params); - for (VisualPanel visualPanel : panelList) { - if (ToolUtil.isNotEmpty(visualPanel.getParam())) - visualPanel.setParam(JSONObject.parseObject(String.valueOf(visualPanel.getParam()), Map.class)); - } - } - - // 查询当前panel下的chart数量并且进行赋值 -// Map<Integer, Integer> chartNums = visualChartService.queryChartNum(); -// for(VisualPanel visualPanel : panelList) { -// Integer chartNum = ObjectUtil.isEmpty(chartNums.get(visualPanel.getId()))?0:chartNums.get(visualPanel.getId()); -// visualPanel.setChartNum(chartNum); -// } - return panelList; - } - - /** - * 递归获取树结构 - * - * @param panelList - * @param parentId - * @return - */ - private List<VisualPanel> getVisualPanelTreeList(List<VisualPanel> panelList, Integer parentId) { - List<VisualPanel> resultList = new ArrayList<>(); - for (VisualPanel panel : panelList) { - if (ToolUtil.isNotEmpty(panel.getParam()) && panel.getParam() instanceof String) - panel.setParam(JSONObject.parseObject(String.valueOf(panel.getParam()), Map.class)); - Integer id = panel.getId(); - Integer pid = panel.getPid(); - if (parentId.equals(pid)) { - panel.setChildren(this.getVisualPanelTreeList(panelList, id)); - resultList.add(panel); - } - } - return resultList; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delPanelsAndChartInfoByPanelIds(Set<Integer> panelIds) { - if (CollectionUtils.isNotEmpty(panelIds)) { - // 删除 panel - this.removeByIds(panelIds); - - // 删除 chart info - Integer[] removePanelIds = panelIds.stream().toArray(n -> new Integer[n]); - visualChartService.delVisualChartsByPanelId(removePanelIds); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delPanels(Integer... ids) { - if (ToolUtil.isEmpty(ids)) { - return; - } - - List<VisualPanel> panels = this.list(); - - // 1. 校验内置panel不能被删除 - this.validateBuildInPanels(panels, ids); - - // 获取这些节点的所有子节点 - List<Integer> idList = Arrays.stream(ids).collect(Collectors.toList()); - List<VisualPanel> panelList = this.list(); - Set<Integer> allPanelIds = new HashSet<>(); - for (Integer id : idList) { - allPanelIds.add(id); - allPanelIds.addAll(this.getChildrenIds(panelList, id)); - } - - // 2. 删除 panel ,如果包含子节点,也一并删除 - this.removeByIds(allPanelIds); - - // 删除对应的收藏记录 - starredService.remove(new LambdaQueryWrapper<SysUserStarredEntity>().eq(SysUserStarredEntity::getType, "panel") - .in(SysUserStarredEntity::getTid, allPanelIds)); - - // 3. 删除关联的 chart chartElement - Integer[] removePanelIds = allPanelIds.stream().toArray(n -> new Integer[n]); - visualChartService.delVisualChartsByPanelId(removePanelIds); - - try { - // 删除 Report job - for (Integer panelId : allPanelIds) { - reportJobManager.delJobByName(panelId.toString()); - } - } catch (SchedulerException e) { - log.error("Delete dashboard report job error", e); - } - } - - /** - * 查询所有子节点 ID - * - * @param panelList - * @param parentId - * @return - */ - private List<Integer> getChildrenIds(List<VisualPanel> panelList, Integer parentId) { - List<Integer> resultList = new ArrayList<>(); - for (VisualPanel panel : panelList) { - Integer id = panel.getId(); - Integer pid = panel.getPid(); - if (parentId.equals(pid)) { - resultList.add(id); - resultList.addAll(this.getChildrenIds(panelList, id)); - } - } - return resultList; - } - - /** - * 校验内置 panel 不可删除 - * - * @param panels - * @param removeIds - */ - private void validateBuildInPanels(List<VisualPanel> panels, Integer... removeIds) { - // 内置 panel 不能删除 - List<Integer> buildInPanels = panels.stream().filter(panel -> panel.getBuildIn() == 1).map(VisualPanel::getId) - .collect(Collectors.toList()); - List<Integer> removeIdList = Arrays.stream(removeIds).collect(Collectors.toList()); - removeIdList.retainAll(buildInPanels); - if (CollectionUtils.isNotEmpty(removeIdList)) { - List<String> panelNames = this.listByIds(removeIdList).stream().map(VisualPanel::getName) - .collect(Collectors.toList()); - throw new NZException( - "These panel is built-in and cannot be deleted, panels info: " + panelNames.toString(), - RCode.PANEL_BUILDIN_CAN_NOT_REMOVE.getCode()); - } - } - - /** - * 校验 panel 相关参数是否正确 - * - * @param panel - */ - public void validatePanel(VisualPanel panel) { - String name = panel.getName(); - ValidateUtils.is(name).notNull(RCode.PANEL_NAME_ISNULL); - - if (name.contains("/")) { - throw new NZException(RCode.PANEL_NAME_FORMAT_ERROR); - } - - Integer pid = panel.getPid(); - pid = (pid == null) ? 0 : pid; - // 校验name是否重复 - List<VisualPanel> list = this.list(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getPid, pid) - .eq(VisualPanel::getName, panel.getName())); - boolean flag = false; - // 当只有一个结果并且这个结果是自身时,或没有结果时,说明名称不重复 - if ((list == null || list.size() == 0) - || (list != null && list.size() == 1 && list.get(0).getId().equals(panel.getId()))) { - flag = true; - } - - if (!flag) { - throw new NZException(RCode.PANEL_NAME_DUPLICATE); - } - - // link 不为空时 - if (ToolUtil.isNotEmpty(panel.getLink())) { - // 校验 type - String type = panel.getType(); - ValidateUtils.is(type).notNull(RCode.PANEL_TYPE_ISNULL); - List<Constant.PanelType> panelTypes = Arrays.asList(Constant.PanelType.values()); - List<String> types = panelTypes.stream().map(Constant.PanelType::getValue).collect(Collectors.toList()); - if (!types.contains(type)) { - throw new NZException(RCode.PANEL_TYPE_INVALIDE); - } - } - - // pid 是否存在 - if (panel.getPid() != null && panel.getPid() != 0) { - VisualPanel entity = this.getById(panel.getPid()); - if (entity == null) { - throw new NZException(RCode.PANEL_NOT_EXIST); - } - } - - // panel param 校验 - if (ToolUtil.isNotEmpty(panel.getParam())) { - Map param = JSONObject.parseObject(JSONObject.toJSONString(panel.getParam()), Map.class); - if (ToolUtil.isNotEmpty(param.get("report"))) { - Map report = JSONObject.parseObject(JSONObject.toJSONString(param.get("report")), Map.class); - // enable 为 true 时 - if (ToolUtil.isNotEmpty(report.get("enable")) - && ToolUtil.equals("true", report.get("enable").toString())) { - ValidateUtils.is(report.get("range")).notNull(RCode.PANEL_PARAM_REPORTRANGE_ISNULL) - .and(report.get("schedule")).notNull(RCode.PANEL_PARAM_REPORTSCHEDULE_ISNULL) - .and(report.get("receivers")).notNull(RCode.PANEL_PARAM_REPORTRECEIVERS_ISNULL); - Map range = JSONObject.parseObject(JSONObject.toJSONString(report.get("range")), Map.class); - ValidateUtils.is(range.get("type")).notNull(RCode.PANEL_PARAM_RANGETYPE_ISNULL) - .and(range.get("interval")).notNull(RCode.PANEL_PARAM_RANGEINTERVAL_ISNULL) - .and(range.get("unit")).notNull(RCode.PANEL_PARAM_RANGEUNIT_ISNULL); - if (!Arrays.asList(new String[] { "previous", "last" }).contains(range.get("type"))) { - throw new NZException(RCode.PANEL_PARAM_RANGETYPE_INVALIDE); - } else if (!Arrays.asList(new String[] { "hour", "day", "week", "month" }) - .contains(range.get("unit"))) { - throw new NZException(RCode.PANEL_PARAM_RANGEUNIT_INVALIDE); - } - Map schedule = JSONObject.parseObject(JSONObject.toJSONString(report.get("schedule")), Map.class); - ValidateUtils.is(schedule.get("type")).notNull(RCode.PANEL_PARAM_SCHEDULETYPE_ISNULL) - .and(schedule.get("stime")).notNull(RCode.PANEL_PARAM_SCHEDULESTIME_ISNULL); - if (!Arrays.asList(new Integer[] { 1, 2, 3, 4 }).contains(schedule.get("type"))) { - throw new NZException(RCode.PANEL_PARAM_SCHEDULETYPE_INVALIDE); - } - if (ToolUtil.equals(schedule.get("type").toString(), "2")) { - ValidateUtils.is(schedule.get("repeat")).notNull(RCode.PANEL_PARAM_SCHEDULEREPEAT_ISNULL); - } else if (ToolUtil.equals(schedule.get("type").toString(), "3")) { - ValidateUtils.is(schedule.get("repeat")).notNull(RCode.PANEL_PARAM_SCHEDULEREPEAT_ISNULL) - .and(schedule.get("nums")).notNull(RCode.PANEL_PARAM_SCHEDULENUMS_ISNULL); - if (!Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7 }).containsAll( - JSONArray.parseObject(JSONObject.toJSONString(schedule.get("nums")), List.class))) { - throw new NZException(RCode.PANEL_PARAM_SCHEDULENUMS_INVALIDE); - } - } else if (ToolUtil.equals(schedule.get("type").toString(), "4")) { - ValidateUtils.is(schedule.get("nums")).notNull(RCode.PANEL_PARAM_SCHEDULENUMS_ISNULL); - List<Integer> monthlyList = new ArrayList<>(); - for (int i = 1; i < 32; i++) { - monthlyList.add(i); - } - monthlyList.add(-1); - if (!monthlyList.containsAll( - JSONArray.parseObject(JSONObject.toJSONString(schedule.get("nums")), List.class))) { - throw new NZException(RCode.PANEL_PARAM_SCHEDULENUMS_INVALIDE); - } - } - } else { - if (ToolUtil.isEmpty(report.get("enable"))) { - report.put("enable", false); - param.put("report", report); - } - } - } - if (ToolUtil.isNotEmpty(param.get("chartShare"))) { - if (!Arrays.asList(new String[] { "none", "crosshair", "tooltip" }).contains(param.get("chartShare"))) { - throw new NZException(RCode.PANEL_PARAM_REPORTCHARTSHARE_INVALIDE); - } - } else { - param.put("chartShare", "none"); - } - panel.setParam(JSONObject.toJSONString(param)); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void saveVisualPanel(VisualPanel panel) { - panel.setName(StrUtil.trim(panel.getName())); - this.validatePanel(panel); - - Long userId = ShiroUtils.getUserId(); - panel.setCreateBy(userId.intValue()); - - if (ToolUtil.isEmpty(panel.getLink())) { - panel.setType(Constant.PanelType.DASHBOARD.getValue()); - } - panel.setUts(System.currentTimeMillis()); - String reportEnable = null; - if (ToolUtil.isNotEmpty(panel.getParam())) { - reportEnable = JSONPath.read(panel.getParam().toString(), "report.enable").toString(); - panel.setParam(String.valueOf(panel.getParam())); - } - - Integer pid = panel.getPid(); - pid = (pid == null) ? 0 : pid; - // 查询该父级节点下是否存在 Panel 节点 - List<VisualPanel> list = this.list(new QueryWrapper<VisualPanel>().lambda() - .eq(VisualPanel::getType, panel.getType()).eq(VisualPanel::getPid, pid)); - if (CollectionUtils.isEmpty(list)) { - // 父级节点下暂无其他节点,直接保存 - this.save(panel); - } else { - // 找到当前末尾的 panel , 加到其后 - VisualPanel endPanel = list.stream().max(Comparator.comparingInt(VisualPanel::getWeight)).get(); - Integer weight = endPanel.getWeight(); - panel.setWeight(++weight); - this.save(panel); - } - - // publish report config when reportEnable is true - if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { - Map publishMap = new HashMap(4); - publishMap.put("panelId", panel.getId()); - publishMap.putAll(JSONObject.parseObject(panel.getParam().toString(), Map.class)); - - redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateVisualPanel(VisualPanel panel) { - panel.setName(StrUtil.trim(panel.getName())); - this.validatePanel(panel); - - VisualPanel oldPanel = this.getById(panel.getId()); - - if (oldPanel == null) { - throw new NZException(RCode.PANEL_NOT_EXIST); - } - panel.setUts(System.currentTimeMillis()); - if (ToolUtil.isNotEmpty(panel.getParam())) - panel.setParam(String.valueOf(panel.getParam())); - - // 改变 pid 父级节点时,将该 panel 加入到该 pid 下末尾位置 - if (!oldPanel.getPid().equals(panel.getPid())) { - VisualPanel endPanel = this.getOne(new LambdaQueryWrapper<VisualPanel>() - .eq(VisualPanel::getPid, panel.getPid()).orderByDesc(VisualPanel::getWeight).last("limit 0,1")); - // 该 pid 下存在节点 - if (endPanel != null) { - Integer weight = endPanel.getWeight(); - panel.setWeight(++weight); - } else { - panel.setWeight(0); - } - } - - // 修改 - this.updateById(panel); - - // report - String oldParamStr = ToolUtil.isEmpty(oldPanel.getParam()) ? JSONObject.toJSONString(Tool.MapUtil.empty()) - : oldPanel.getParam().toString(); - Map oldParamMap = JSONObject.parseObject(oldParamStr, LinkedHashMap.class); - String newParamStr = ToolUtil.isEmpty(panel.getParam()) ? JSONObject.toJSONString(Tool.MapUtil.empty()) - : panel.getParam().toString(); - Map newParamMap = JSONObject.parseObject(newParamStr, LinkedHashMap.class); - if (!oldParamMap.equals(newParamMap)) { - Map publishMap = new HashMap(4); - publishMap.put("panelId", panel.getId()); - publishMap.putAll(newParamMap); - - redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void modify(List<VisualPanel> panelList) { - if (CollectionUtils.isEmpty(panelList)) - throw new NZException(RCode.PANEL_ID_ISNULL); - for (VisualPanel panel : panelList) { - if (panel.getId() == null) - throw new NZException(RCode.PANEL_ID_ISNULL); - if (panel.getPid() == null) - throw new NZException(RCode.PANEL_PID_ISNULL); - if (panel.getWeight() == null) - throw new NZException(RCode.PANEL_WEIGHT_ISNULL); - } - - this.getBaseMapper().updateWeightBatch(panelList); - } - - @Override - public void getTemplateByLanguage(HttpServletResponse response, String format, String type) throws IOException { - // 按类型获取表头模板信息 - String configKey = this.getChartTemplateConfigKeyByType(type); - String sysHeaderJsonStr = sysConfigService.getValue(configKey); - String fileName = "PanelChartTemplate"; - basicImportAndExportServices.getTemplate(sysHeaderJsonStr, format, fileName, response); - } - - @Override - public Map importChartData(MultipartFile multipartFile, String type, Integer linkId, String language) - throws IOException { - String configKey = this.getChartTemplateConfigKeyByType(type); - String sysHeaderJsonStr = sysConfigService.getValue(configKey); - Map<String, String> exportHeaderMap = basicImportAndExportServices.getI18nHeaderMap(sysHeaderJsonStr); - List<Map<Integer, String>> importDataList = basicImportAndExportServices - .getImportDataFromMultipartFile(multipartFile, sysHeaderJsonStr); - - List<Map> failDetails = new ArrayList<>(); - String seqUUID = UUID.randomUUID().toString(); - type = StringUtils.isEmpty(type) ? Constant.PanelType.DASHBOARD.getValue() : type; - - ArrayList<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); - int successNum = 0; - List<Map<Integer, String>> handleImportData = null; - if (StrUtil.equals(Constant.PanelType.DASHBOARD.getValue(), type)) { - // 处理excel表数据 将group chart相关排在前列 - handleImportData = this.groupChartRowHandle(importDataList, 1); - successNum = this.saveDashboardChartData(handleImportData, failDetails, headerInfos, seqUUID); - } else { - handleImportData = this.groupChartRowHandle(importDataList, 0); - successNum = this.saveAssetEndpointChartData(handleImportData, failDetails, seqUUID, type, linkId, - headerInfos); - } - int totalNum = ToolUtil.isNotEmpty(handleImportData) ? handleImportData.size() : 0; - - Map resultMap = new HashMap(8); - resultMap.put("seq", seqUUID); - resultMap.put("totalNum", totalNum); - resultMap.put("successNum", successNum); - resultMap.put("failNum", totalNum - successNum); - resultMap.put("failDetail", CommonUtils.handleImportFailDetails(failDetails)); - - return resultMap; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void duplicate(Integer id) { - VisualPanel panel = this.getById(id); - if (panel == null) { - throw new NZException(RCode.CHART_PANEL_ISNULL); - } - - panel.setName("copy from " + panel.getName()); - if (panel.getName().length() > 64) { - throw new NZException(RCode.PANEL_NAME_TOO_LONG); - } - Long userId = ShiroUtils.getUserId(); - panel.setCreateBy(userId.intValue()); - panel.setId(null); - panel.setUts(System.currentTimeMillis()); - String reportEnable = null; - if (ToolUtil.isNotEmpty(panel.getParam()) && ToolUtil.contains(panel.getParam(), "enable")) { - reportEnable = JSONPath.read(panel.getParam().toString(), "report.enable").toString(); - panel.setParam(String.valueOf(panel.getParam())); - } - - Integer pid = panel.getPid(); - // 查询该父级节点下是否存在 Panel 节点 - List<VisualPanel> list = this.list(new QueryWrapper<VisualPanel>().lambda() - .eq(VisualPanel::getType, panel.getType()).eq(VisualPanel::getPid, pid == null ? 0 : pid)); - // 找到当前末尾的 panel , 加到其后 - VisualPanel endPanel = list.stream().max(Comparator.comparingInt(VisualPanel::getWeight)).get(); - Integer weight = endPanel.getWeight(); - panel.setWeight(++weight); - this.save(panel); - - // publish report config when reportEnable is true - if (Tool.StrUtil.equalsIgnoreCase("true", StrUtil.nullToDefault(reportEnable, "false"))) { - Map publishMap = new HashMap(4); - publishMap.put("panelId", panel.getId()); - publishMap.putAll(JSONObject.parseObject(panel.getParam().toString(), Map.class)); - - redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); - } - - // 复制panel 下的 charts - List<VisualChart> chartsGroupList = visualChartService.list(new QueryWrapper<VisualChart>().lambda() - .eq(VisualChart::getPanelId, id).orderByAsc(VisualChart::getGroupId)); - Map<Integer, Integer> chartsGroupMap = new HashMap<>(); - Integer chartId; - if (!CollectionUtils.isEmpty(chartsGroupList)) { - for (VisualChart chart : chartsGroupList) { - chartId = chart.getId(); - chart.setId(null); - chart.setUpdateAt(new Date()); - chart.setUpdateBy(userId.intValue()); - chart.setPanelId(panel.getId()); - if (ToolUtil.equals(chart.getType(), "group")) { - visualChartService.save(chart); - chartsGroupMap.put(chartId, chart.getId()); - } else { - if (!ToolUtil.equals(chart.getGroupId(), 0)) - chart.setGroupId(chartsGroupMap.get(chart.getGroupId())); - visualChartService.save(chart); - } - // 查询当前chart下的chartElement - List<VisualChartElement> elementList = chartElementService.list( - new QueryWrapper<VisualChartElement>().lambda().eq(VisualChartElement::getChartId, chartId)); - if (!CollectionUtils.isEmpty(elementList)) { - for (VisualChartElement element : elementList) { - element.setId(null); - element.setChartId(chart.getId()); - } - chartElementService.saveOrUpdateElements(chart.getId(), elementList); - } - } - } - } - - @Override - public void snapshot(HttpServletResponse response, String format, Integer panelId, Long start, Long end, - String language, String vars) throws IOException { - // 生成模板 - String snapshotStr = this.genSnapshotByTemplate(panelId, start, end, language, vars); - // 目前下载名称由前端控制 - // String downFileName = String.format("%s-%s.%s", "panel", panel.getName(), - // StrUtil.emptyToDefault(format, "html")); - ResponseUtil.downloadFile(response, "panel.html", snapshotStr.getBytes()); - } - - @Override - public String genSnapshotByTemplate(Integer panelId, Long start, Long end, String language, String vars) { - VisualPanel panel = this.getById(panelId); - if (panel == null) { - throw new NZException(RCode.CHART_PANEL_ISNULL); - } - // 计算步长 - String step = visualService.getTimeStep(start, end); - // 封装返回结果 - Map<String, Object> resultMap = visualService.snapshotResultMap(start, end, language); - resultMap.put("step", step); - // charts 查询 - Map param = new HashMap<>(); - param.put("pageSize", "-1"); - param.put("panelId", panel.getId()); - param.put("groupId", 0); - PageUtils chartPageUtils = visualChartService.queryPage(param); - List<VisualChart> chartsList = (List<VisualChart>) chartPageUtils.getList(); - if (Tool.CollUtil.isEmpty(chartsList)) { - throw new NZException(RCode.CHART_NOTEXSITS); - } else { - List<Map> varList = StrUtil.isNotEmpty(vars) ? JSONObject.parseArray(vars, Map.class) - : Tool.ListUtil.empty(); - - // 将chartsData获取任务装入futureList - List<CompletableFuture<Map>> futureList = this.recursionChartsData(chartsList, resultMap, varList); - Map chartsDataMap = new HashMap(); - try { - CompletableFuture completableFuture = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])); - completableFuture.get(timeout,TimeUnit.MILLISECONDS); - } catch (Exception e) { - log.error(e, "snapshot query timeout"); - } - futureList.forEach(future -> { - Map<String, Object> result = future.getNow(null); - if (Tool.MapUtil.isNotEmpty(result)) { - chartsDataMap.put(StrUtil.concat(true, StrUtil.toString(result.get("chartId")), "_", - StrUtil.toString(result.get("eleIndex"))), result); - } - }); - resultMap.put("chartsData", chartsDataMap); - resultMap.remove("step"); - resultMap.put("panel", R.ok(panel)); - resultMap.put("charts", R.ok(chartPageUtils)); - } - return visualService.replaceSnapshotTemplate(resultMap); - } - - /** - * 根据 vars 渲染 element 表达式 - * - * @param expr - * @param varList - */ - private String replaceExprByVars(String expr, List<Map> varList) { - if (Tool.CollectionUtil.isEmpty(varList)) - return expr; - // 将 expr $xxx 变量渲染 - for (Map<String, String> map : varList) { - String name = map.get("name"); - String value = map.get("value"); - expr = expr.replaceAll("\\$" + name, value); - } - return expr; - } - - private List<CompletableFuture<Map>> recursionChartsData(List<VisualChart> chartsList, - Map<String, Object> basicQueryParam, List<Map> varList) { - String start = StrUtil.toString(basicQueryParam.get("start")); - String end = StrUtil.toString(basicQueryParam.get("end")); - String step = StrUtil.toString(basicQueryParam.get("step")); - List<CompletableFuture<Map>> futureList = new ArrayList<>(); - - for (VisualChart chart : chartsList) { - String datasource = chart.getDatasource(); - if (StrUtil.equals("misc", datasource)) { - if (Tool.CollUtil.isNotEmpty(chart.getChildren())) { - List<CompletableFuture<Map>> callables = this.recursionChartsData(chart.getChildren(), - basicQueryParam, varList); - if (Tool.CollUtil.isNotEmpty(callables)) - futureList.addAll(callables); - } - continue; - } - Map<String, Object> chartParam = (HashMap) chart.getParam(); - if (StrUtil.equals("system", datasource)) { - futureList.add(CompletableFuture.supplyAsync(() -> { - VisualPanel visualPanel = this.getById(chart.getPanelId()); - R ok = R.ok(); - Map<String, Object> queryParams = MapUtil.newHashMap(); - queryParams.put("type", "total"); - queryParams.put("dimension", "priority"); - queryParams.put("step", "d"); - if (StrUtil.equals("assetInfo", chart.getType())) { - queryParams.put("assetId", visualPanel.getLink()); - Map<String, Object> alertMessageTrend = statServiceImpl.queryAlertMessageTrend(queryParams); - AssetAsset asset = assetAssetService.queryAssetInfo(visualPanel.getLink()); - Map<String, Object> assetDataMap = BeanUtil.beanToMap(asset); - assetDataMap.put("alertMessageTrend", alertMessageTrend); - ok.put("data", assetDataMap); - } else if (StrUtil.equals("endpointInfo", chart.getType())) { - queryParams.put("endpointId", visualPanel.getLink()); - Map<String, Object> alertMessageTrend = statServiceImpl.queryAlertMessageTrend(queryParams); - MonitorEndpoint endpoint = monitorEndpointService.queryEndpointEntity(visualPanel.getLink()); - Map<String, Object> endpointDataMap = BeanUtil.beanToMap(endpoint); - endpointDataMap.put("alertMessageTrend", alertMessageTrend); - ok.put("data", endpointDataMap); - } else { - cn.hutool.json.JSONObject dataSource = JSONUtil.parseArray(chartParam.get("datasource")) - .getJSONObject(0); - dataSource.set("select", JSONUtil.createArray().put(dataSource.get("select"))); - ok.putAllData(statServiceImpl.queryAnalyse( - JSONUtil.toBean(JSONUtil.createObj().set("q", dataSource.toString()), Map.class))); - } - ok.put("eleIndex", "0"); - ok.put("chartId", chart.getId()); - return ok; - }, this.getSnapshotThreadPool())); - } else { - if (Tool.CollUtil.isNotEmpty(chart.getElements())) { - Integer eleIndex = 0; - String limit = chartParam.get("limit") == null ? "100" : chartParam.get("limit").toString(); - for (VisualChartElement element : chart.getElements()) { - String indexStr = StrUtil.toString(eleIndex++); - // 将表达式进行变量渲染 - String expr = this.replaceExprByVars(element.getExpression(), varList); - futureList.add(CompletableFuture.supplyAsync(() -> { - JSONObject jsonObject = null; - try { - if (StrUtil.equals("metrics", datasource)) { - jsonObject = promApiService.query_range(expr, start, end, step, - ToolUtil.toStr(chartParam.get("nullType"), null), null); - } else if (StrUtil.equals("logs", datasource)) { - jsonObject = lokiApiService.query_range(expr, start, end, limit, step, null, - "backward", "1", null); - } - jsonObject.put("eleIndex", indexStr); - jsonObject.put("chartId", chart.getId()); - } catch (NZException e) { - log.error(e); - } - return jsonObject; - }, this.getSnapshotThreadPool())); - } - } else { - futureList.add(CompletableFuture.supplyAsync(() -> JSONUtil - .toBean(JSONUtil.createObj().set("eleIndex", 0).set("chartId", chart.getId()), Map.class), - this.getSnapshotThreadPool())); - } - } - } - return futureList; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void cancelImport(String seq) { - List<VisualPanel> panelList = this.list(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getType, - Constant.PanelType.DASHBOARD.getValue())); - List<Integer> delPanelIds = panelList.stream().filter(panel -> seq.equals(panel.getSeq())) - .map(VisualPanel::getId).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(delPanelIds)) { - // 删除 panel - this.remove(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getSeq, seq)); - } - - List<VisualChart> delCharts = visualChartService - .list(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getSeq, seq)); - if (CollectionUtils.isNotEmpty(delCharts)) { - // 删除 charts - visualChartService.remove(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getSeq, seq)); - } - chartElementService.remove(new QueryWrapper<VisualChartElement>().lambda().eq(VisualChartElement::getSeq, seq)); - } - - @Override - public void export(HttpServletResponse response, Map<String, Object> params) throws IOException { - String maxLine = sysConfigService.getValue(Constant.SYSCONFIG_KEY_EXPORT_MAX_LINE); - long exportMaxLine = Integer.parseInt(StrUtil.emptyToDefault(maxLine, "10000")); - // 导出最大条数限制 - Object limit = params.get(Constant.LIMIT) == null ? Constant.PAGESIZE : params.get(Constant.LIMIT); - Long pageSize = Long.parseLong(limit.toString()); - if (pageSize == -1) { - // 导出所有直接限制 pageSize - params.put(Constant.PAGE, "1"); - params.put(Constant.LIMIT, Long.toString(exportMaxLine)); - } else if (pageSize > exportMaxLine) { - // 分页超过最大限制 则设置最大限制为 系统配置值,和 pageSize == -1 判断区别在于 pageNo - params.put(Constant.LIMIT, Long.toString(exportMaxLine)); - } - // 导出查询与列表查询一致 - List<VisualChart> charts = this.exportDataByParams(params); - String type = Constant.PanelType.DASHBOARD.getValue(); - if (CollectionUtils.isNotEmpty(charts)) { - VisualChart chart = charts.stream().findFirst().get(); - VisualPanel panel = this.getById(chart.getPanelId()); - if (panel == null || !StrUtil.equals(Constant.PanelType.DASHBOARD.getValue(), panel.getType())) { - type = Constant.PanelType.ASSET.getValue(); - } - } - // 获取导出配置 key 名称 - String configKey = this.getChartTemplateConfigKeyByType(type); - String sysHeaderJsonStr = sysConfigService.getValue(configKey); - - charts = charts.stream().sorted(Comparator.comparing(VisualChart::getGroupId)).collect(Collectors.toList()); - String fileName = "Charts"; - String formatStr = params.get("format").toString(); - - if (StrUtil.equals(Constant.PanelType.DASHBOARD.getValue(), type)) { - List<List<String>> exportDataList = this.handleDashboardChartExportDataList(charts); - basicImportAndExportServices.exportDataByFormat(response, exportDataList, sysHeaderJsonStr, formatStr, - fileName); - } else { - List<List<String>> exportDataList = this.handleAssetEndpointChartExportDataList(charts); - basicImportAndExportServices.exportDataByFormat(response, exportDataList, sysHeaderJsonStr, formatStr, - fileName); - } - } - - private String getChartTemplateConfigKeyByType(String type) { - // 默认 dashboard 类型 - type = StringUtils.isEmpty(type) ? Constant.PanelType.DASHBOARD.getValue() : type; - String chartTemplateTyep; - switch (type) { - case "dashboard": { - chartTemplateTyep = Constant.SYSCONFIG_KEY_CHART_EXPORT_HEADER; - break; - } - /* - * case "model": { chartTemplateTyep = - * Constant.SYSCONFIG_KEY_MODEL_CHART_EXPORT_HEADER; break; } - */ - case "asset": - case "template": - case "endpoint": { - chartTemplateTyep = Constant.SYSCONFIG_KEY_ASSET_CHART_EXPORT_HEADER; - break; - } - default: - throw new NZException(RCode.PANEL_CHART_TEMPLATE_TYPE_INCORRECT); - } - return chartTemplateTyep; - } - - private List<List<String>> handleAssetEndpointChartExportDataList(List<VisualChart> charts) { - Map<Integer, String> varTypeIdAndNameMap = new HashMap<>(4); - varTypeIdAndNameMap.put(1, "Asset"); - varTypeIdAndNameMap.put(2, "Endpoint"); - - // type 导出转换为 国际化之后的名称 - List<SysDictEntity> chartTypeList = sysDictService - .list(new LambdaQueryWrapper<SysDictEntity>().eq(SysDictEntity::getType, Constant.DICT_CHART_TYPE)); - Map<String, String> chartTypeAndI18nMap = chartTypeList.stream() - .collect(Collectors.toMap(SysDictEntity::getValue, SysDictEntity::getI18nCode)); - - List<List<String>> exportDataList = new ArrayList<>(); - for (VisualChart chart : charts) { - if (chart == null || Constant.CHART_ASSETINFO_TYPE.equalsIgnoreCase(chart.getType()) - || Constant.CHART_ENDPOINTINFO_TYPE.equalsIgnoreCase(chart.getType())) - continue; - List<String> tempList = new ArrayList<>(); - String type = chart.getType(); - tempList.add(chart.getGroup().getName()); - tempList.add(chart.getName()); - String typeI18nCode = chartTypeAndI18nMap.get(type); - tempList.add(sysI18nService.queryValue(typeI18nCode)); - tempList.add(ToolUtil.isEmpty(varTypeIdAndNameMap.get(chart.getVarType())) ? "" - : varTypeIdAndNameMap.get(chart.getVarType())); - tempList.add(ObjectUtil.defaultIfNull(chart.getSpan(), "").toString()); - tempList.add(ObjectUtil.defaultIfNull(chart.getHeight(), "").toString()); - if (StrUtil.equals(Constant.CHART_TEXT_TYPE, type)) { - tempList.add(""); - } else { - tempList.add(this.getUnitDescrByVal(chart.getUnit())); - } - tempList.add(this.handleChartParam(chart.getParam())); - tempList.add(this.handleChartElementForExport(chart.getElements())); - tempList.add(chart.getRemark()); - tempList.add(chart.getDatasource()); - tempList.add(ObjectUtil.defaultIfNull(chart.getX(), "").toString()); - tempList.add(ObjectUtil.defaultIfNull(chart.getY(), "").toString()); - exportDataList.add(tempList); - } - return exportDataList; - } - - private String handleChartElementForExport(List<VisualChartElement> chartElements) { - if (CollectionUtils.isEmpty(chartElements)) { - return ""; - } - List<Map> handleMaps = new ArrayList<>(); - Map tempMap; - for (VisualChartElement element : chartElements) { - tempMap = new LinkedHashMap(4); - tempMap.put("expression", element.getExpression()); - tempMap.put("state", element.getState()); - if (ToolUtil.isNotEmpty(element.getLegend())) { - tempMap.put("legend", element.getLegend()); - } - if (ToolUtil.isNotEmpty(element.getName())) { - tempMap.put("name", element.getName()); - } - handleMaps.add(tempMap); - } - return JSONArray.toJSONString(handleMaps); - } - - private String getUnitDescrByVal(Integer unitVal) { - String unitDescr = null; - for (Map.Entry<String, Integer> entry : Constant.ALERT_RULE_UNIT_MAP.entrySet()) { - if (entry.getValue().equals(unitVal)) { - unitDescr = entry.getKey(); - break; - } - } - return unitDescr; - } - - private String handleChartParam(Object param) { - if (ToolUtil.isEmpty(param)) { - return ""; - } - Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(param), Map.class); - map.entrySet().removeIf(entry -> ToolUtil.isEmpty(entry.getValue())); - return ToolUtil.isEmpty(map) ? "" : JSONObject.toJSONString(map); - } - - public void getPanelNamePathAndIdMapFromTree(VisualPanel panel, String path, - Map<String, Integer> nodeNamePathAndIdMap) { - if (CollectionUtils.isEmpty(panel.getChildren())) { - return; - } - for (VisualPanel cPanel : panel.getChildren()) { - String cPath = ""; - cPath += path + "/" + cPanel.getName(); - nodeNamePathAndIdMap.put(cPath, cPanel.getId()); - this.getPanelNamePathAndIdMapFromTree(cPanel, cPath, nodeNamePathAndIdMap); - } - } - - private int saveDashboardChartData(List<Map<Integer, String>> importDataList, List<Map> failDetails, - List<String> headerInfos, String seqUUID) { - List<VisualPanel> panelTreeList = this.queryList(new HashMap()); - Map<String, Integer> nodeNamePathAndIdMap = new HashMap<>(); - for (VisualPanel panel : panelTreeList) { - nodeNamePathAndIdMap.put(panel.getName(), panel.getId()); - this.getPanelNamePathAndIdMapFromTree(panel, panel.getName(), nodeNamePathAndIdMap); - } - - List<VisualPanel> dashboardTypePanelList = this.list(new LambdaQueryWrapper<VisualPanel>() - .eq(VisualPanel::getType, Constant.PanelType.DASHBOARD.getValue())); - Integer panelMaxWeight; - if (CollectionUtils.isEmpty(dashboardTypePanelList)) { - panelMaxWeight = 0; - } else { - VisualPanel endPanel = dashboardTypePanelList.stream().max(Comparator.comparingInt(VisualPanel::getWeight)) - .get(); - panelMaxWeight = endPanel.getWeight(); - } - - // 查询 chart datasource类型防止频繁查库 - List<SysDictEntity> chartDatasources = sysDictService.list( - new QueryWrapper<SysDictEntity>().lambda().eq(SysDictEntity::getType, Constant.DICT_CHART_DATASOURCE)); - List<String> datasources = chartDatasources.stream().map(SysDictEntity::getValue).collect(Collectors.toList()); - - // chart 导入 Type 是国际化后的,这里统一获取 chart type 可读名称 & 真实 type 值 - Map<String, String> typeReadableNameMap = this.getChartTypeReadableNameMap(); - - int successNum = 0; - for (int i = 0; i < importDataList.size(); i++) { - int dataFromExcelRowNum = i + 1; - Map<Integer, String> dataMap = importDataList.get(i); - - boolean saveFlag = true; - boolean typeFlag = true; - String panelName = dataMap.get(0); - if (StringUtils.isEmpty(panelName)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(0), - RCode.PANEL_NAME_ISNULL.getMsg()); - } - Integer panelId = this.handlePanelNameForCellVal(nodeNamePathAndIdMap, panelName, seqUUID, - ++panelMaxWeight); - Integer groupId = 0; - String groupName = dataMap.get(1); - if (StrUtil.isNotBlank(groupName) && saveFlag) { - VisualChart groupChart = visualChartService.getOne(new QueryWrapper<VisualChart>().lambda() - .eq(VisualChart::getName, groupName).eq(VisualChart::getPanelId, panelId) - .eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString())); - if (ToolUtil.isEmpty(groupChart)) { - groupChart = new VisualChart(); - groupChart.setPanelId(panelId); - groupChart.setName(groupName); - groupChart.setGroupId(0); - groupChart.setSpan(12d); - groupChart.setHeight(-1d); - groupChart.setUpdateBy((ShiroUtils.getUserId()).intValue()); - groupChart.setUpdateAt(new Date()); - groupChart.setType(Constant.CHART_GROUP_TYPE.toString()); - groupChart.setUnit(2); - groupChart.setBuildIn(0); - groupChart.setRemark(""); - groupChart.setSeq(seqUUID); - // group 默认 datasource misc - groupChart.setDatasource(Constant.ChartDatasourceType.MISC.getValue()); - visualChartService.save(groupChart); - } - groupId = groupChart.getId(); - } - - String name = dataMap.get(2); - if (StringUtils.isEmpty(name)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_TITLE_ISNULL.getMsg()); - } else if (name.length() > 64) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_NAME_TOO_LONG.getMsg()); - } - String type = dataMap.get(3); - - if (StringUtils.isEmpty(type)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), - RCode.CHART_TYPE_ISNULL.getMsg()); - } else { - // 根据可读名称,获取 chart type - type = typeReadableNameMap.get(type); - if (StringUtils.isEmpty(type)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), - RCode.CHART_TYPE_INVALIDE.getMsg()); - } - } - - VisualChart groupChart = visualChartService - .getOne(new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getName, name) - .eq(VisualChart::getPanelId, panelId).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE)); - if (StrUtil.equals(type, Constant.CHART_GROUP_TYPE) && ToolUtil.isNotEmpty(groupChart)) { - // chart group 不允许重复 - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), - RCode.CHART_GROUP_NAME_DUPLICATE.getMsg()); - } - - String span = dataMap.get(4); - if (StringUtils.isEmpty(span)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_SPAN_ISNULL.getMsg()); - } else { - Integer width = null; - try { - width = Double.valueOf(span).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_WIDTH_FORMAT.getMsg()); - } - if (width != null && (width < 1 || width > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_WIDTH_INVALIDE.getMsg()); - } - } - String height = dataMap.get(5); - if (StringUtils.isEmpty(height)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_ISNULL.getMsg()); - } else { - Integer heightIntVal = null; - try { - heightIntVal = Double.valueOf(height).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_FORMAT.getMsg()); - } - if (heightIntVal != null && (heightIntVal < 1 || heightIntVal > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_INVALIDE.getMsg()); - } - } - String unit = dataMap.get(6); - if (StringUtils.isNotEmpty(unit)) { - if (ToolUtil.isEmpty(Constant.ALERT_RULE_UNIT_MAP.get(unit))) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(6), - RCode.CHART_UNIT_NOTFOUND.getMsg()); - } - } - String param = dataMap.get(7); - if (typeFlag) { - String msg = this.validateChartParamForImport(type, param, "dashboard"); - if (StringUtils.isNotEmpty(msg)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(7), msg); - } - } - - String datasource = dataMap.get(10); - if (StringUtils.isEmpty(datasource)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(10), - RCode.CHART_DATASOURCE_ISNULL.getMsg()); - } else { - if (!datasources.contains(datasource)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(10), - RCode.CHART_DATASOURCE_INVALIDE.getMsg()); - } - } - - String elements = dataMap.get(8); - if (typeFlag) { - String msg = this.validateChartElementForImport(datasource, elements); - if (StringUtils.isNotEmpty(msg)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(8), msg); - } - } - String description = dataMap.get(9); - - String x = dataMap.get(11); - if (StringUtils.isEmpty(x)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_ISNULL.getMsg()); - } else { - Integer xIntVal = null; - try { - xIntVal = Double.valueOf(x).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_FORMAT.getMsg()); - } - if (xIntVal != null && (xIntVal < 0 || xIntVal > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_INVALIDE.getMsg()); - } - } - - // x和width之和不能大于12 - if (StringUtils.isNotEmpty(x) && StringUtils.isNotEmpty(span)) { - Double xVal = Double.valueOf(x); - Double widthVal = Double.valueOf(span); - if (xVal + widthVal > 12) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_WIDTH_INVALIDE.getMsg()); - } - } - - String y = dataMap.get(12); - if (StringUtils.isEmpty(y)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(12), - RCode.CHART_Y_ISNULL.getMsg()); - } else { - Integer yIntVal = null; - try { - yIntVal = Double.valueOf(y).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(12), - RCode.CHART_Y_FORMAT.getMsg()); - } - } - - if (saveFlag) { - TransactionStatus transactionStatus = dataSourceTransactionManager - .getTransaction(transactionDefinition); - try { - VisualChart chart = new VisualChart(); - chart.setSeq(seqUUID); - chart.setPanelId(panelId); - chart.setName(name); - chart.setType(type); - chart.setSpan(Double.valueOf(span)); - chart.setHeight(Double.valueOf(height)); - // unit 为空 设置默认值为 short - unit = StringUtils.isEmpty(unit) ? "short" : unit; - chart.setUnit(Constant.ALERT_RULE_UNIT_MAP.get(unit)); - chart.setParam(param.toString()); - chart.setUpdateAt(new Date()); - chart.setUpdateBy((ShiroUtils.getUserId()).intValue()); - chart.setGroupId(groupId); - chart.setRemark(description); - chart.setDatasource(datasource); - chart.setX(Double.valueOf(x)); - chart.setY(Double.valueOf(y)); - // 查询当前 panel 下的 charts - List<VisualChart> chartList = visualChartService.list( - new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getPanelId, chart.getPanelId())); - if (CollectionUtils.isEmpty(chartList)) { - visualChartService.save(chart); - } else { - VisualChart endChart = visualChartService.getOne( - new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getPanelId, chart.getPanelId()) - .orderByDesc(VisualChart::getWeight).last("limit 0,1")); - Integer weight = endChart.getWeight(); - chart.setWeight(++weight); - visualChartService.save(chart); - } - List<VisualChartElement> chartElements = JSONArray.parseArray(elements, VisualChartElement.class); - if (CollectionUtils.isNotEmpty(chartElements)) { - chartElements.forEach(chartElement -> { - chartElement.setChartId(chart.getId()); - chartElement.setSeq(seqUUID); - chartElement.setType(Constant.CHART_ELEMENT_EXPERT_TYPE); - }); - chartElementService.saveBatch(chartElements); - } - dataSourceTransactionManager.commit(transactionStatus); - successNum++; - } catch (RuntimeException e) { - dataSourceTransactionManager.rollback(transactionStatus); - this.addFailDetail(dataFromExcelRowNum, failDetails, "System", e.getMessage() + ""); - log.error(String.format("保存 panel chart chartelement失败,回滚事务,错误信息:%s", e)); - } - } - } - return successNum; - } - - /** - * chart 导入 Type 是国际化后的,这里统一获取 chart type 可读名称 & 真实 type 值 - * - * @return - */ - private Map<String, String> getChartTypeReadableNameMap() { - List<SysDictEntity> chartTypeList = sysDictService - .list(new LambdaQueryWrapper<SysDictEntity>().eq(SysDictEntity::getType, Constant.DICT_CHART_TYPE)); - Map<String, String> chartTypeI18nCodeAndValueMap = chartTypeList.stream() - .filter(sysDict -> StrUtil.isNotEmpty(sysDict.getI18nCode())) - .collect(Collectors.toMap(SysDictEntity::getI18nCode, SysDictEntity::getValue)); - - Map<String, String> map = Tool.MapUtil.newHashMap(); - - for (Map.Entry<String, String> entry : chartTypeI18nCodeAndValueMap.entrySet()) { - // chart type i18n code - String i18nCode = entry.getKey(); - // chart type real - String type = entry.getValue(); - - String chartReadableName = sysI18nService.queryValue(i18nCode); - map.put(chartReadableName, type); - } - return map; - } - - private String validateChartElementForImport(String datasource, String elements) { - // datasource类型为metrics logs的需要校验elements - if (datasource.equals(Constant.ChartDatasourceType.METRICS.getValue()) - || datasource.equals(Constant.ChartDatasourceType.LOGS.getValue())) { - if (StringUtils.isEmpty(elements)) { - return RCode.CHART_ELEMENT_ISNULL.getMsg(); - } - List<VisualChartElement> elementsList = null; - try { - elementsList = JSONArray.parseArray(elements, VisualChartElement.class); - } catch (JSONException e) { - return RCode.CHART_ELEMENTS_FORMAT.getMsg(); - } - - if (CollectionUtils.isEmpty(elementsList)) { - return RCode.CHART_ELEMENT_ISNULL.getMsg(); - } - - for (VisualChartElement element : elementsList) { - if (ToolUtil.isEmpty(element.getExpression())) { - return RCode.CHARTELEMENT_EXPRESSION_ISNULL.getMsg(); - } - if (ToolUtil.isEmpty(element.getName())) { - return RCode.CHARTELEMENT_NAME_ISNULL.getMsg(); - } - } - } - return ""; - } - - /** - * @param panelName 格式: 使用 / 作为字符分隔,表示 父子节点关系 - * @param seqUUID 导入序列号 - */ - private Integer handlePanelNameForCellVal(Map<String, Integer> nodeNamePathAndIdMap, String panelName, - String seqUUID, Integer panelWeight) { - String savePanelNames = panelName; - Integer panelId; - while (true) { - panelId = nodeNamePathAndIdMap.get(panelName); - if (panelId != null) { - break; - } - // 仍然包含 ‘/’ 证明还是有父子关系 - if (panelName.lastIndexOf("/") != -1) { - panelName = panelName.substring(0, panelName.lastIndexOf("/")); - } else { - // 最后的 panel 也不存在,赋值 为空 ,下面会进行过滤添加 - panelName = ""; - break; - } - } - savePanelNames = savePanelNames.replace(panelName, ""); - - // 如果存在需要保存的 panel - if (StringUtils.isNotEmpty(savePanelNames)) { - if (savePanelNames.startsWith("/")) { - savePanelNames = savePanelNames.substring(savePanelNames.indexOf("/") + 1); - } - - VisualPanel panel = new VisualPanel(); - panel.setType(Constant.PanelType.DASHBOARD.getValue()); - panel.setCreateBy(ShiroUtils.getUserId().intValue()); - panel.setSeq(seqUUID); - panel.setWeight(panelWeight); - panel.setUts(System.currentTimeMillis()); - - List<String> saveList = Arrays.asList(savePanelNames.split("/")); - int size = saveList.size(); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < size; i++) { - String name = saveList.get(i); - panel.setName(name); - if (panel.getId() == null) { - panel.setPid(panelId); - } else { - panel.setPid(panel.getId()); - } - this.save(panel); - sb.append(name + "/"); - String temp = panelName + "/" + sb.substring(0, sb.lastIndexOf("/")); - // 因为用户输入根节点没有 ‘/’,所以不保存根节点 '/' 路径作为对比 - if (temp.startsWith("/")) { - temp = temp.substring(temp.indexOf("/") + 1); - } - nodeNamePathAndIdMap.put(temp, panel.getId()); - } - return panel.getId(); - } - return panelId; - } - - private String validateChartParamForImport(String type, String param, String panelType) { - switch (type) { - // url - case Constant.CHART_URL_TYPE: { - if (StringUtils.isEmpty(param)) { - return RCode.CHART_URLPARAM_ISNULL.getMsg(); - } - Map map = null; - try { - map = JSONObject.parseObject(param, Map.class); - } catch (JSONException e) { - return RCode.CHART_PARAM_FORMAT.getMsg(); - } - Object url = map.get(Constant.CHART_URL_TYPE); - if (ToolUtil.isEmpty(url)) { - return RCode.CHART_URLPARAM_ISNULL.getMsg(); - } - - if (StrUtil.equals(Constant.PanelType.MODEL.getValue(), panelType)) { - // 替换全部变量 替换为 a(任意字符) 不影响原来的数据格式 然后进行校验 - String urlStr = url.toString(); - urlStr = urlStr.replaceAll("\\{\\{asset\\..*?\\}\\}", "a"); - - boolean b = CommonUtils.checkUrlInModel(urlStr); - boolean b1 = CommonUtils.checkUrl(urlStr); - - if (!b && !b1) { - return RCode.CHART_PARAMURL_FORMAT.getMsg(); - } - } else { - if (!CommonUtils.checkUrl(url.toString())) { - return RCode.CHART_PARAMURL_FORMAT.getMsg(); - } - } - break; - } - // singleStat - case Constant.CHART_SINGLESTAT_TYPE: { - if (StringUtils.isEmpty(param)) { - return RCode.CHART_SINGLESTATPARAM_ISNULL.getMsg(); - } - Map map = null; - try { - map = JSONObject.parseObject(param, Map.class); - } catch (JSONException e) { - return RCode.CHART_PARAM_FORMAT.getMsg(); - } - Object statistics = map.get(Constant.CHART_SINGLESTAT_PARAMkEY); - if (ToolUtil.isEmpty(statistics)) { - return RCode.CHART_PARAMSINGLESTAT_ISNULL.getMsg(); - } - if (!Constant.CHART_SINGLESTAT_STATISTICS.contains(statistics.toString())) { - return RCode.CHART_PARAMSINGLESTAT_INVALIDE.getMsg(); - } - break; - } - case Constant.CHART_TEXT_TYPE: { - if (StringUtils.isEmpty(param)) { - return RCode.CHART_TEXTPARAM_ISNULL.getMsg(); - } - Map map = null; - try { - map = JSONObject.parseObject(param, Map.class); - } catch (JSONException e) { - return RCode.CHART_PARAM_FORMAT.getMsg(); - } - Object text = map.get(Constant.CHART_TEXT_TYPE); - if (ToolUtil.isEmpty(text)) { - return RCode.CHART_TEXTPARAM_ISNULL.getMsg(); - } - break; - } - default: { - if (StringUtils.isNotEmpty(param)) { - try { - JSONObject.parseObject(param, Map.class); - } catch (JSONException e) { - return RCode.CHART_PARAM_FORMAT.getMsg(); - } - } - } - } - return ""; - } - - private void addFailDetail(int i, List<Map> failDetails, String headerInfo, String msg) { - Map failDetail = new HashMap(4); - failDetail.put("lineNo", i); - failDetail.put("errorMsg", headerInfo + ": " + msg); - failDetails.add(failDetail); - } - - private int saveAssetEndpointChartData(List<Map<Integer, String>> importDataList, List<Map> failDetails, - String seqUUID, String panelType, Integer linkId, List<String> headerInfos) { - // 导入类型 template 标识 - Boolean templateFlag = Constant.PanelType.TEMPLATE.getValue().equalsIgnoreCase(panelType); - // chart template 导入导出 varType map - Map<String, Integer> varTypeAndValMap = new HashMap<>(4); - varTypeAndValMap.put("Asset", 1); - varTypeAndValMap.put("Endpoint", 2); - - if (linkId == null && !templateFlag) - throw new NZException(RCode.PANEL_CHART_IMPORT_LINKID_ISNULL); - - VisualPanel panel = this.getOne(new QueryWrapper<VisualPanel>().lambda().eq(VisualPanel::getType, panelType) - .eq(VisualPanel::getLink, linkId)); - if (panel == null && !templateFlag) - throw new NZException(RCode.PANEL_NOT_EXIST); - - // 查询 chart datasource类型防止频繁查库 - List<SysDictEntity> chartDatasources = sysDictService.list( - new QueryWrapper<SysDictEntity>().lambda().eq(SysDictEntity::getType, Constant.DICT_CHART_DATASOURCE)); - List<String> datasources = chartDatasources.stream().map(SysDictEntity::getValue).collect(Collectors.toList()); - - // chart 导入 Type 是国际化后的,这里统一获取 chart type 可读名称 & 真实 type 值 - Map<String, String> typeReadableNameMap = this.getChartTypeReadableNameMap(); - - int successNum = 0; - for (int i = 0; i < importDataList.size(); i++) { - int dataFromExcelRowNum = i + 1; - Map<Integer, String> dataMap = importDataList.get(i); - boolean saveFlag = true; - boolean typeFlag = true; - - Integer groupId = 0; - String groupName = dataMap.get(0); - String varType = dataMap.get(3); - if (StrUtil.isNotBlank(groupName)) { - VisualChart groupChart; - if (templateFlag) { - // template 类型,panel = 0 为 template - groupChart = visualChartService - .getOne(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getName, groupName) - .eq(VisualChart::getPanelId, 0).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE) - .eq(VisualChart::getVarType, varTypeAndValMap.get(varType.trim()))); - } else { - // asset endpoint 类型,通过指定 panel group name 查找 group - groupChart = visualChartService.getOne(new QueryWrapper<VisualChart>().lambda() - .eq(VisualChart::getName, groupName).eq(VisualChart::getPanelId, panel.getId()) - .eq(VisualChart::getType, Constant.CHART_GROUP_TYPE.toString())); - } - if (ToolUtil.isEmpty(groupChart)) { - groupChart = new VisualChart(); - // panel 为 null,即为 template type, panel_id = 0 - groupChart.setPanelId(ToolUtil.isEmpty(panel) ? 0 : panel.getId()); - groupChart.setName(groupName); - groupChart.setGroupId(0); - groupChart.setSpan(12d); - groupChart.setHeight(-1d); - groupChart.setUpdateBy((ShiroUtils.getUserId()).intValue()); - groupChart.setUpdateAt(new Date()); - groupChart.setType(Constant.CHART_GROUP_TYPE.toString()); - groupChart.setUnit(2); - groupChart.setBuildIn(0); - groupChart.setRemark(""); - if (templateFlag) { - groupChart.setVarType(varTypeAndValMap.get(varType.trim())); - } - // group 默认 datasource misc - groupChart.setDatasource(Constant.ChartDatasourceType.MISC.getValue()); - groupChart.setSeq(seqUUID); - visualChartService.save(groupChart); - } - groupId = groupChart.getId(); - } - - String name = dataMap.get(1); - if (StringUtils.isEmpty(name)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(0), - RCode.CHART_TITLE_ISNULL.getMsg()); - } else if (name.length() > 64) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_NAME_TOO_LONG.getMsg()); - } - - String type = dataMap.get(2); - if (StringUtils.isEmpty(type)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_TYPE_ISNULL.getMsg()); - } else { - // 根据可读名称,获取 chart type - type = typeReadableNameMap.get(type); - if (StringUtils.isEmpty(type)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_TYPE_INVALIDE.getMsg()); - } - } - - VisualChart groupChart = null; - if (templateFlag) { - groupChart = visualChartService - .getOne(new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getName, name) - .eq(VisualChart::getPanelId, 0).eq(VisualChart::getType, Constant.CHART_GROUP_TYPE) - .eq(VisualChart::getVarType, varTypeAndValMap.get(varType.trim()))); - } else { - groupChart = visualChartService.getOne(new QueryWrapper<VisualChart>().lambda() - .eq(VisualChart::getName, name).eq(VisualChart::getPanelId, panel.getId()) - .eq(VisualChart::getType, Constant.CHART_GROUP_TYPE)); - } - if (StrUtil.equals(type, Constant.CHART_GROUP_TYPE) && ToolUtil.isNotEmpty(groupChart)) { - // chart group 不允许重复 - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(2), - RCode.CHART_GROUP_NAME_DUPLICATE.getMsg()); - } - - // varType, type = template required - - if (templateFlag) { - if (StringUtils.isEmpty(varType)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), - RCode.CHART_VARTYPE_ISNULL.getMsg()); - } else if (ToolUtil.isEmpty(varTypeAndValMap.get(varType.trim()))) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(3), - RCode.CHART_VARTYPE_ERROR.getMsg()); - } - } - - String span = dataMap.get(4); - if (StringUtils.isEmpty(span)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_SPAN_ISNULL.getMsg()); - } else { - Integer width = null; - try { - width = Double.valueOf(span).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_WIDTH_FORMAT.getMsg()); - } - if (width != null && (width < 1 || width > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(4), - RCode.CHART_WIDTH_INVALIDE.getMsg()); - } - } - String height = dataMap.get(5); - if (StringUtils.isEmpty(height)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_ISNULL.getMsg()); - } else { - Integer heightIntVal = null; - try { - heightIntVal = Double.valueOf(height).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_FORMAT.getMsg()); - } - if (heightIntVal != null && (heightIntVal < 1 || heightIntVal > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(5), - RCode.CHART_HEIGHT_INVALIDE.getMsg()); - } - } - String unit = dataMap.get(6); - if (StringUtils.isNotEmpty(unit)) { - if (ToolUtil.isEmpty(Constant.ALERT_RULE_UNIT_MAP.get(unit))) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(6), - RCode.CHART_UNIT_NOTFOUND.getMsg()); - } - } - String param = dataMap.get(7); - if (typeFlag) { - String msg = this.validateChartParamForImport(type, param, type); - if (StringUtils.isNotEmpty(msg)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(7), msg); - } - } - - String datasource = dataMap.get(10); - if (StringUtils.isEmpty(datasource)) { - saveFlag = typeFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(10), - RCode.CHART_DATASOURCE_ISNULL.getMsg()); - } else { - if (!datasources.contains(datasource)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(10), - RCode.CHART_DATASOURCE_INVALIDE.getMsg()); - } - } - - String elements = dataMap.get(8); - if (typeFlag) { - String msg = this.validateChartElementForImport(datasource, elements); - if (StringUtils.isNotEmpty(msg)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(8), msg); - } - } - String description = dataMap.get(9); - - String x = dataMap.get(11); - if (StringUtils.isEmpty(x)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_ISNULL.getMsg()); - } else { - Integer xIntVal = null; - try { - xIntVal = Double.valueOf(x).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_FORMAT.getMsg()); - } - if (xIntVal != null && (xIntVal < 0 || xIntVal > 12)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_INVALIDE.getMsg()); - } - } - - // x和width之和不能大于12 - if (StringUtils.isNotEmpty(x) && StringUtils.isNotEmpty(span)) { - Double xVal = Double.valueOf(x); - Double widthVal = Double.valueOf(span); - if (xVal + widthVal > 12) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(11), - RCode.CHART_X_WIDTH_INVALIDE.getMsg()); - } - } - - String y = dataMap.get(12); - if (StringUtils.isEmpty(y)) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(12), - RCode.CHART_Y_ISNULL.getMsg()); - } else { - Integer yIntVal = null; - try { - yIntVal = Double.valueOf(y).intValue(); - } catch (NumberFormatException e) { - saveFlag = false; - this.addFailDetail(dataFromExcelRowNum, failDetails, headerInfos.get(12), - RCode.CHART_Y_FORMAT.getMsg()); - } - } - - if (saveFlag) { - TransactionStatus transactionStatus = dataSourceTransactionManager - .getTransaction(transactionDefinition); - try { - VisualChart chart = new VisualChart(); - chart.setSeq(seqUUID); - // panel 为 null,即为 template type, panel_id = 0 - chart.setPanelId(ToolUtil.isEmpty(panel) ? 0 : panel.getId()); - chart.setName(name); - chart.setType(type); - chart.setSpan(Double.valueOf(span)); - chart.setHeight(Double.valueOf(height)); - // unit 为空 设置默认值为 short - unit = StringUtils.isEmpty(unit) ? "short" : unit; - chart.setUnit(Constant.ALERT_RULE_UNIT_MAP.get(unit)); - chart.setParam(param.toString()); - chart.setUpdateAt(new Date()); - chart.setUpdateBy((ShiroUtils.getUserId()).intValue()); - chart.setGroupId(groupId); - chart.setVarType(varTypeAndValMap.get(varType)); - chart.setVarId(linkId); - chart.setRemark(description); - chart.setDatasource(datasource); - chart.setX(Double.valueOf(x)); - chart.setY(Double.valueOf(y)); - // 查询当前 panel 下的 charts - List<VisualChart> chartList = visualChartService.list( - new QueryWrapper<VisualChart>().lambda().eq(VisualChart::getPanelId, chart.getPanelId())); - if (CollectionUtils.isEmpty(chartList)) { - visualChartService.save(chart); - } else { - VisualChart endChart = visualChartService.getOne( - new LambdaQueryWrapper<VisualChart>().eq(VisualChart::getPanelId, chart.getPanelId()) - .orderByDesc(VisualChart::getWeight).last("limit 0,1")); - Integer weight = endChart.getWeight(); - chart.setWeight(++weight); - visualChartService.save(chart); - } - List<VisualChartElement> chartElements = JSONArray.parseArray(elements, VisualChartElement.class); - if (CollectionUtils.isNotEmpty(chartElements)) { - chartElements.forEach(chartElement -> { - chartElement.setChartId(chart.getId()); - chartElement.setSeq(seqUUID); - chartElement.setType(Constant.CHART_ELEMENT_EXPERT_TYPE); - }); - chartElementService.saveBatch(chartElements); - } - dataSourceTransactionManager.commit(transactionStatus); - successNum++; - } catch (RuntimeException e) { - dataSourceTransactionManager.rollback(transactionStatus); - this.addFailDetail(dataFromExcelRowNum, failDetails, "System", e.getMessage() + ""); - log.error(String.format("保存 panel chart chartelement失败,回滚事务,错误信息:%s", e)); - } - } - } - return successNum; - } - - private List<VisualChart> exportDataByParams(Map<String, Object> params) { - String panelId = null; - if (ToolUtil.isNotEmpty(params.get("panelId"))) { - panelId = params.get("panelId").toString(); - } - String chartId = null; - if (ToolUtil.isNotEmpty(params.get("chartId"))) { - chartId = params.get("chartId").toString(); - } - String panelType = null; - if (ToolUtil.isNotEmpty(params.get("type"))) { - panelType = params.get("type").toString(); - if (!Constant.PanelType.TEMPLATE.getValue().equals(panelType)) { - params.put("panelType", panelType); - } else { - panelId = "0"; - } - params.remove("type"); - } - List<VisualChart> chartList = new ArrayList<VisualChart>(); - if (chartId != null) { - // 只导出当前 chart - chartList.addAll(this.queryChartsByPanelId(panelId, chartId, params)); - } else if (ToolUtil.isEmpty(panelId)) { - // 导出所有 dashboard panel - List<VisualPanel> panelList = this.list(new LambdaQueryWrapper<VisualPanel>() - .eq(VisualPanel::getType, Constant.PanelType.DASHBOARD.getValue()) - .orderByAsc(VisualPanel::getWeight, VisualPanel::getId)); - for (VisualPanel panel : panelList) { - Map<String, Object> param = new HashMap<String, Object>(); - param.put("panelType", panelType); - param.put("pageSize", (String) params.get("pageSize")); - chartList.addAll(this.queryChartsByPanelId(panel.getId().toString(), null, param)); - } - } else if (ToolUtil.isNotEmpty(panelId)) { - // 导出 panel 下所有chart - chartList.addAll(this.queryChartsByPanelId(panelId, null, params)); - } - return chartList; - } - - private List<List<String>> handleDashboardChartExportDataList(List<VisualChart> charts) { - List<VisualPanel> panelTreeList = this.queryList(new HashMap()); - Map<Integer, String> nodeIdAndNamePathMap = new HashMap<>(); - for (VisualPanel panel : panelTreeList) { - nodeIdAndNamePathMap.put(panel.getId(), panel.getName()); - this.getPanelIdAndNamePathMapFromTree(panel, panel.getName(), nodeIdAndNamePathMap); - } - // type 导出转换为 国际化之后的名称 - List<SysDictEntity> chartTypeList = sysDictService - .list(new LambdaQueryWrapper<SysDictEntity>().eq(SysDictEntity::getType, Constant.DICT_CHART_TYPE)); - Map<String, String> chartTypeAndI18nMap = chartTypeList.stream() - .collect(Collectors.toMap(SysDictEntity::getValue, SysDictEntity::getI18nCode)); - - List<List<String>> exportDataList = new ArrayList<>(); - for (VisualChart chart : charts) { - if (chart == null) - continue; - List<String> tempList = new ArrayList<>(); - String type = chart.getType(); - tempList.add(nodeIdAndNamePathMap.get(chart.getPanelId())); - tempList.add(chart.getGroup().getName()); - tempList.add(chart.getName()); - String typeI18nCode = chartTypeAndI18nMap.get(type); - tempList.add(sysI18nService.queryValue(typeI18nCode)); - tempList.add(ObjectUtil.defaultIfNull(chart.getSpan(), "").toString()); - tempList.add(ObjectUtil.defaultIfNull(chart.getHeight(), "").toString()); - if (StrUtil.equals(Constant.CHART_TEXT_TYPE, type)) { - tempList.add(""); - } else { - tempList.add(this.getUnitDescrByVal(chart.getUnit())); - } - tempList.add(this.handleChartParam(chart.getParam())); - tempList.add(this.handleChartElementForExport(chart.getElements())); - tempList.add(chart.getRemark()); - tempList.add(chart.getDatasource()); - tempList.add(ObjectUtil.defaultIfNull(chart.getX(), "").toString()); - tempList.add(ObjectUtil.defaultIfNull(chart.getY(), "").toString()); - exportDataList.add(tempList); - } - return exportDataList; - } - - public void getPanelIdAndNamePathMapFromTree(VisualPanel panel, String path, - Map<Integer, String> nodeIdAndNamePathMap) { - if (CollectionUtils.isEmpty(panel.getChildren())) { - return; - } - for (VisualPanel cPanel : panel.getChildren()) { - String cPath = ""; - cPath += path + "/" + cPanel.getName(); - nodeIdAndNamePathMap.put(cPanel.getId(), cPath); - this.getPanelIdAndNamePathMapFromTree(cPanel, cPath, nodeIdAndNamePathMap); - } - } - - public List<VisualChart> queryChartsByPanelId(String panelId, String chartId, Map<String, Object> params) { - params.put("panelId", panelId); - // 加上原有 ids - String ids = (String) params.get("ids"); - if (StrUtil.isNotEmpty(ids)) { - chartId = StrUtil.emptyToDefault(chartId, ""); - chartId += chartId.endsWith(",") ? ids : "," + ids; - } - params.put("ids", chartId); - params.put("returnChildren", "1"); - params.put("groupId", 0); - PageUtils queryPage = visualChartService.queryPage(params); - List<VisualChart> result = (List<VisualChart>) queryPage.getList(); - - // 递归展开节点信息 - List<VisualChart> allChartList = new ArrayList<>(); - for (VisualChart entity : result) { - getAllChildrenChartList(entity, allChartList); - } - return allChartList; - } - - /** - * 平铺 获取所有 chart 节点 - * - * @param chart - * @param chartList - */ - public void getAllChildrenChartList(VisualChart chart, List<VisualChart> chartList) { - chartList.add(chart); - if (CollectionUtils.isNotEmpty(chart.getChildren())) { - for (VisualChart pojo : chart.getChildren()) { - getAllChildrenChartList(pojo, chartList); - } - } - } - - public List<Map<Integer, String>> groupChartRowHandle(List<Map<Integer, String>> importDataList, Integer index) { - // type标识dashboard还是asset 区别去第几列查找group chart信息 - List<Map<Integer, String>> list = importDataList.stream().filter(dataMap -> { - String groupName = dataMap.get(index); - if (StringUtils.isEmpty(groupName)) { - return true; - } - return false; - }).collect(Collectors.toList()); - importDataList.removeAll(list); - list.addAll(importDataList); - return list; - } - - private synchronized ExecutorService getSnapshotThreadPool() { - if (snapshotThreadPool == null) { - snapshotThreadPool = new ThreadPoolExecutor(snapshotCorePoolSize, snapshotConcurrency, - snapshotKeepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(snapshotCapacity), - new NamedThreadFactory("SNAPSHOT-", true)); - } - return snapshotThreadPool; - } - -} diff --git a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualServiceImpl.java deleted file mode 100644 index b19aff3f..00000000 --- a/nz-admin/src/main/java/com/nis/modules/panel/service/impl/VisualServiceImpl.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.nis.modules.panel.service.impl; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.hutool.log.Log; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.nis.common.utils.JSONUtil; -import com.nis.common.utils.ResponseUtil; -import com.nis.common.utils.Tool; -import com.nis.modules.agent.service.LokiApiService; -import com.nis.modules.agent.service.PromApiService; -import com.nis.modules.panel.service.VisualService; -import com.nis.modules.sys.entity.Timezone; -import com.nis.modules.sys.service.SysConfigService; -import com.nis.modules.sys.service.TimezoneService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - - -@Service("visualService") -public class VisualServiceImpl implements VisualService { - - private Log log = Log.get(); - @Value("${connect.timeout:30000}") - private Integer connectTimeout; - - @Autowired - private SysConfigService sysConfigService; - - @Autowired - private PromApiService promApiService; - - @Autowired - private LokiApiService lokiApiService; - - @Autowired - private TimezoneService timezoneService; - - @Override - public void exploreSnapshot(HttpServletResponse response, String format, Integer type, Long start, Long end, String language, Integer unit, String limit, String direction, String[] expressions) throws IOException { - // 计算步长 - String step = this.getTimeStep(start, end); - if(!StrUtil.equals(direction, "forward")){ - direction = "backward"; - } - - List<CompletableFuture<JSONObject>> futureList = new ArrayList<>(); - for (int i = 0; i < expressions.length; i++) { - String expression = URLUtil.decode(expressions[i]); - String finalDirection = direction; - futureList.add(CompletableFuture.supplyAsync(() -> { - JSONObject queryData = null; - if(type == 1){ - queryData = promApiService.query_range(expression, StrUtil.toString(start), StrUtil.toString(end), step, "null", null); - } else if (type == 2) { - queryData = lokiApiService.query_range(expression, StrUtil.toString(start), StrUtil.toString(end), StrUtil.emptyToDefault(limit, "100"), null, null, finalDirection, "1", null); - } - queryData.put("expression", expression); - return queryData; - })); - } - List<JSONObject> dataList = new ArrayList(); - try{ - CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).get(connectTimeout, TimeUnit.MILLISECONDS); - futureList.forEach(future -> { - JSONObject result = future.getNow(null); - if (Tool.MapUtil.isNotEmpty(result)) { - dataList.add(result); - } - }); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - log.error(e); - } - // 封装返回结果 - Map<String, Object> resultMap = this.snapshotResultMap(start, end, language); - resultMap.put("type", type); - resultMap.put("unit", unit); - resultMap.put("direction", direction); - resultMap.put("limit", limit); - resultMap.put("data", dataList); - - String snapshotTemplate = this.replaceSnapshotTemplate(resultMap); - // 目前下载名称由前端控制 - // String downFileName = String.format("%s-%s.%s", "explore", System.currentTimeMillis(), StrUtil.emptyToDefault(format, "html")); - ResponseUtil.downloadFile(response, "exploreSnapshot.html", snapshotTemplate.getBytes()); - } - - /** - * 模板基本返回参数 - */ - @Override - public Map<String, Object> snapshotResultMap(Long start, Long end, String language){ - Map<String, Object> resultMap = Tool.MapUtil.newHashMap(); - resultMap.put("language", language); - resultMap.put("start", start); - resultMap.put("end", end); - // 查询系统时区信息 - String timezone = sysConfigService.getValue("timezone"); - Timezone timezoneEntity = timezoneService.getOne(new LambdaUpdateWrapper<Timezone>().eq(Timezone::getName, timezone)); - resultMap.put("offset", timezoneEntity.getOffset()); - resultMap.put("timezone", timezone); - return resultMap; - } - - /** - * 读取快照模板,替换数据 - */ - @Override - public String replaceSnapshotTemplate(Map<String, Object> resultMap){ - BufferedReader reader = null; - StringBuffer sbf = new StringBuffer(); - try { - String path = sysConfigService.getValue("snapshot_template_path"); - reader = new BufferedReader(new FileReader(Tool.StrUtil.concat(true, path, File.separator, "snapshot_template.html"))); - String line; - while ((line = reader.readLine()) != null) { - if (Tool.StrUtil.startWith(line, "<script>window.dataJson")) - line = "<script>window.dataJson=" + JSONUtil.toJsonStr(resultMap) + "</script>"; - sbf.append(line + "\n"); - } - } catch (IOException e) { - log.error(e); - } finally { - if (reader != null) IoUtil.close(reader); - } - return sbf.toString(); - } - - /** - * 计算Dashboards step - */ - @Override - public String getTimeStep(Long start, Long end){ - Long timeDiff = (end - start) / (24 * 60 * 60); - if(timeDiff < 1){ - return "15s"; - }else if(timeDiff < 7){ - return "5m"; - }else if(timeDiff < 30){ - return "10m"; - }else{ - return "30m"; - } - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java index 9c8a8a71..e3107fcd 100644 --- a/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/project/service/impl/TopoIconServiceImpl.java @@ -1,37 +1,34 @@ package com.nis.modules.project.service.impl; -import java.awt.image.BufferedImage; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletResponse; - -import com.nis.common.utils.Tool; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.TransientDataAccessResourceException; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; - +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; import com.nis.modules.project.dao.TopoIconDao; import com.nis.modules.project.entity.TopoIcon; import com.nis.modules.project.service.TopoIconService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.TransientDataAccessResourceException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service("topoIconService") public class TopoIconServiceImpl extends ServiceImpl<TopoIconDao, TopoIcon> implements TopoIconService { diff --git a/nz-admin/src/main/java/com/nis/modules/report/job/ReportJob.java b/nz-admin/src/main/java/com/nis/modules/report/job/ReportJob.java index 30a9229d..4c865e41 100644 --- a/nz-admin/src/main/java/com/nis/modules/report/job/ReportJob.java +++ b/nz-admin/src/main/java/com/nis/modules/report/job/ReportJob.java @@ -10,9 +10,9 @@ import com.nis.common.utils.Constant; import com.nis.common.utils.MailUtil; import com.nis.common.utils.TemplateUtil; import com.nis.common.utils.Tool; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualPanelService; import com.nis.modules.agent.service.PromApiService; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.service.SysConfService; import com.nis.modules.sys.service.SysUserService; @@ -68,7 +68,7 @@ public class ReportJob extends QuartzJobBean { private SysConfService sysConfService; @Autowired - private VisualPanelService visualPanelService; + private VisualDashboardService dashboardService; @Autowired private PromApiService promApiService; @@ -82,15 +82,15 @@ public class ReportJob extends QuartzJobBean { JobKey key = context.getJobDetail().getKey(); log.info(String.format("Job name: %s, Job group: %s", key.getName(), key.getGroup())); - String panelId = key.getName(); - VisualPanel visualPanel = visualPanelService.getById(panelId); - if (visualPanel == null) { - log.error("dashboard report panel not found, panelId:{}", panelId); + String dashboardId = key.getName(); + VisualDashboard visualDashboard = dashboardService.getById(dashboardId); + if (visualDashboard == null) { + log.error("dashboard report dashboard not found, dashboardId:{}", dashboardId); return; } // JOB 每天都执行,根据匹配规则,检查本次是否执行 - String configJsonStr = visualPanel.getParam().toString(); + String configJsonStr = visualDashboard.getParam().toString(); String scheduleType = JSONPath.read(configJsonStr, "report.schedule.type").toString(); String stime = JSONPath.read(configJsonStr, "report.schedule.stime").toString(); String repeatStr = JSONPath.read(configJsonStr, "report.schedule.repeat").toString(); @@ -98,62 +98,64 @@ public class ReportJob extends QuartzJobBean { Boolean isRun = ReportJobManager.checkJobIsRun(scheduleType, stime, repeatStr, nums); if (isRun) { - log.info("dashboard report notific begin ..."); - String receiversStr = JSONPath.read(configJsonStr, "report.receivers").toString(); - if (StrUtil.isEmpty(receiversStr)) { - log.error("dashboard report receiver user is empty, panelId:{}", panelId); - return; - } + Tool.ThreadUtil.execAsync(() -> { + log.info("dashboard report notific begin ..."); + String receiversStr = JSONPath.read(configJsonStr, "report.receivers").toString(); + if (StrUtil.isEmpty(receiversStr)) { + log.error("dashboard report receiver user is empty, dashboardId:{}", dashboardId); + return; + } - List<String> receiverIds = JSONObject.parseArray(receiversStr, String.class); - List<SysUserEntity> userList = sysUserService.list(new LambdaQueryWrapper<SysUserEntity>().in(SysUserEntity::getId, receiverIds)); - if (receiverIds.size() != userList.size()) { - log.error("dashboard report receiver user not found, panelId:{}", panelId); - return; - } + List<String> receiverIds = JSONObject.parseArray(receiversStr, String.class); + List<SysUserEntity> userList = sysUserService.list(new LambdaQueryWrapper<SysUserEntity>().in(SysUserEntity::getId, receiverIds)); + if (receiverIds.size() != userList.size()) { + log.error("dashboard report receiver user not found, dashboardId:{}", dashboardId); + return; + } - // 计算 query_range start&end - String timezone = sysConfService.getValue("timezone"); - timezone = StrUtil.emptyToDefault(timezone, TimeZone.getDefault().getID()); - Map<String, Long> queryRangeStartAndEndTime = getQueryRangeStartAndEndTime(configJsonStr, timezone.trim()); - log.info("dashboard report range data, panelId:{}, query_range start&end {}", panelId, JSONObject.toJSONString(queryRangeStartAndEndTime)); - - try { - Template template = getEmailTemplate(); - String content = this.genMailContent(visualPanel, template); - - String format = "html"; - String fileName = String.format("%s.%s", visualPanel.getName(), format); - - Long start = queryRangeStartAndEndTime.get("start"); - Long end = queryRangeStartAndEndTime.get("end"); - - // 模拟前端实现 组织快照接口 vars 参数 - List<Map<String, String>> snapshotVars = this.getSnapshotVars(configJsonStr, start, end); - log.info("dashboard report snapshot vars: {}", JSONObject.toJSONString(snapshotVars)); - - for (SysUserEntity user : userList) { - // 以用户默认语言生成 快照文件 - String lang = user.getLang(); - String snapshotStr = visualPanelService.genSnapshotByTemplate(Integer.valueOf(panelId), start, end, lang, JSONObject.toJSONString(snapshotVars)); - - File file = null; - try { - // 写到临时目录下,通知用户之后,此文件删除 - file = Tool.FileUtil.newFile(Constant.TEMP_PATH + File.separator + fileName); - Tool.FileUtil.writeUtf8String(snapshotStr, file); - - // 发送邮件通知 - mailUtil.sendHTMLAndAppendFile(Tool.ListUtil.toList(user.getEmail()), "Dashboard report", content, file.getAbsolutePath()); - log.info("dashboard report notific success ,user {}", user.getUsername()); - } finally { - if (file != null && file.exists()) file.delete(); + // 计算 query_range start&end + String timezone = sysConfService.getValue("timezone"); + timezone = StrUtil.emptyToDefault(timezone, TimeZone.getDefault().getID()); + Map<String, Long> queryRangeStartAndEndTime = this.getQueryRangeStartAndEndTime(configJsonStr, timezone.trim()); + log.info("dashboard report range data, dashboardId:{}, query_range start&end {}", dashboardId, JSONObject.toJSONString(queryRangeStartAndEndTime)); + + try { + Template template = getEmailTemplate(); + String content = this.genMailContent(visualDashboard, template); + + String format = "html"; + String fileName = String.format("%s.%s", visualDashboard.getName(), format); + + Long start = queryRangeStartAndEndTime.get("start"); + Long end = queryRangeStartAndEndTime.get("end"); + + // 模拟前端实现 组织快照接口 vars 参数 + List<Map<String, String>> snapshotVars = this.getSnapshotVars(configJsonStr, start, end); + log.info("dashboard report snapshot vars: {}", JSONObject.toJSONString(snapshotVars)); + + for (SysUserEntity user : userList) { + // 以用户默认语言生成 快照文件 + String lang = user.getLang(); + String snapshotStr = dashboardService.genSnapshotByTemplate(Integer.valueOf(dashboardId), start, end, lang, JSONObject.toJSONString(snapshotVars)); + + File file = null; + try { + // 写到临时目录下,通知用户之后,此文件删除 + file = Tool.FileUtil.newFile(Constant.TEMP_PATH + File.separator + fileName); + Tool.FileUtil.writeUtf8String(snapshotStr, file); + + // 发送邮件通知 + mailUtil.sendHTMLAndAppendFile(Tool.ListUtil.toList(user.getEmail()), "Dashboard report", content, file.getAbsolutePath()); + log.info("dashboard report notific success ,user {}", user.getUsername()); + } finally { + if (file != null && file.exists()) file.delete(); + } } + } catch (IOException | TemplateException | MessagingException e) { + log.error("dashboard report notific error.", e); } - } catch (IOException | TemplateException | MessagingException e) { - log.error("dashboard report notific error.", e); - } - log.info("dashboard report notific finished."); + log.info("dashboard report notific finished."); + }); } else { log.info("dashboard report is not executed, this time does't match the report schedule"); } @@ -162,15 +164,15 @@ public class ReportJob extends QuartzJobBean { /** * mail content * - * @param visualPanel + * @param visualDashboard * @param template * @return * @throws IOException * @throws TemplateException */ - private String genMailContent(VisualPanel visualPanel, Template template) throws IOException, TemplateException { + private String genMailContent(VisualDashboard visualDashboard, Template template) throws IOException, TemplateException { Map<String, Object> modelMap = new HashMap<>(); - modelMap.put("panel", visualPanel); + modelMap.put("dashboard", visualDashboard); String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, modelMap); return content; } @@ -439,16 +441,19 @@ public class ReportJob extends QuartzJobBean { m.put("name", name); // 根据 allOption 确定最终值 - String allOptionStr = JSONPath.read(varJsonStr, "allOption").toString(); - allOptionStr = Tool.StrUtil.emptyToDefault(allOptionStr, "false"); - - if (Tool.StrUtil.equals(allOptionStr, "true")) { - // allOption = true 时,变量值 为 .* - m.put("value", ".*"); - } else { - // 否则 取第一个值 - m.put("value", Tool.CollectionUtil.isEmpty(valueList) ? "" : valueList.get(0)); - } +// String allOptionStr = JSONPath.read(varJsonStr, "allOption").toString(); +// allOptionStr = Tool.StrUtil.emptyToDefault(allOptionStr, "false"); +// +// if (Tool.StrUtil.equals(allOptionStr, "true")) { +// // allOption = true 时,变量值 为 .* +// m.put("value", ".*"); +// } else { +// // 否则 取第一个值 +// m.put("value", Tool.CollectionUtil.isEmpty(valueList) ? "" : valueList.get(0)); +// } + // 与前端保持一致 + // allOption 默认也取第一个值 + m.put("value", Tool.CollectionUtil.isEmpty(valueList) ? "" : valueList.get(0)); snapshotVars.add(m); } return snapshotVars; @@ -466,7 +471,7 @@ public class ReportJob extends QuartzJobBean { List<String> promiseList = new ArrayList<>(); boolean isLabelNames = Tool.ReUtil.isMatch(SPECIAL_KEY_MAP.get("label_names"), expression); if (isLabelNames) { - JSONObject resultMap = promApiService.labels("/api/v1/labels", String.valueOf(start), String.valueOf(end), null); + JSONObject resultMap = promApiService.labels("/api/v1/labels", String.valueOf(start), String.valueOf(end), Tool.ListUtil.empty()); List<String> labelList = (List<String>) resultMap.get("data"); promiseList = Tool.CollectionUtil.isEmpty(labelList) ? new ArrayList<>() : labelList; diff --git a/nz-admin/src/main/java/com/nis/modules/report/job/ReportJobManager.java b/nz-admin/src/main/java/com/nis/modules/report/job/ReportJobManager.java index 5fdd597c..32d3f75e 100644 --- a/nz-admin/src/main/java/com/nis/modules/report/job/ReportJobManager.java +++ b/nz-admin/src/main/java/com/nis/modules/report/job/ReportJobManager.java @@ -48,7 +48,7 @@ public class ReportJobManager { // job 已结束,不再创建 Date now = new Date(); if (endAt != null && !now.before(endAt)) { - log.info("Report endtime is before current time,job is over. panelId:{}", jobName); + log.info("Report endtime is before current time,job is over. dashboardId:{}", jobName); return; } @@ -83,11 +83,11 @@ public class ReportJobManager { /** * 根据 jobkey 查询 JOB 是否存在,存在则删除 - * @param panelId + * @param dashboardId * @throws SchedulerException */ - public void delJobByName(String panelId) throws SchedulerException { - JobKey jobKey = this.getJobKey(panelId, Constant.REPORT_JOB_GROUP); + public void delJobByName(String dashboardId) throws SchedulerException { + JobKey jobKey = this.getJobKey(dashboardId, Constant.REPORT_JOB_GROUP); boolean b = scheduler.checkExists(jobKey); if (b) scheduler.deleteJob(jobKey); } diff --git a/nz-admin/src/main/java/com/nis/modules/stat/dao/StatDao.java b/nz-admin/src/main/java/com/nis/modules/stat/dao/StatDao.java index d55b02a4..1d253881 100644 --- a/nz-admin/src/main/java/com/nis/modules/stat/dao/StatDao.java +++ b/nz-admin/src/main/java/com/nis/modules/stat/dao/StatDao.java @@ -1,13 +1,12 @@ package com.nis.modules.stat.dao; -import java.util.List; -import java.util.Map; - +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.nis.modules.stat.entity.StatAnalysis; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.nis.modules.stat.entity.StatAnalysis; +import java.util.List; +import java.util.Map; @Mapper public interface StatDao { diff --git a/nz-admin/src/main/java/com/nis/modules/stat/entity/StatAnalysis.java b/nz-admin/src/main/java/com/nis/modules/stat/entity/StatAnalysis.java index a6cc9ef0..f07c9cc5 100644 --- a/nz-admin/src/main/java/com/nis/modules/stat/entity/StatAnalysis.java +++ b/nz-admin/src/main/java/com/nis/modules/stat/entity/StatAnalysis.java @@ -1,7 +1,6 @@ package com.nis.modules.stat.entity; import com.fasterxml.jackson.annotation.JsonInclude; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/stat/service/StatService.java b/nz-admin/src/main/java/com/nis/modules/stat/service/StatService.java index a0f0ed30..91f0773c 100644 --- a/nz-admin/src/main/java/com/nis/modules/stat/service/StatService.java +++ b/nz-admin/src/main/java/com/nis/modules/stat/service/StatService.java @@ -1,11 +1,11 @@ package com.nis.modules.stat.service; -import java.util.List; -import java.util.Map; - import com.nis.common.utils.PageUtils; import com.nis.modules.stat.entity.StatAnalysis; +import java.util.List; +import java.util.Map; + public interface StatService{ StatAnalysis queryUserTotal(); diff --git a/nz-admin/src/main/java/com/nis/modules/stat/service/impl/StatServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/stat/service/impl/StatServiceImpl.java index ed4112d5..7b76b68b 100644 --- a/nz-admin/src/main/java/com/nis/modules/stat/service/impl/StatServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/stat/service/impl/StatServiceImpl.java @@ -1,33 +1,24 @@ package com.nis.modules.stat.service.impl; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - +import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Pair; -import com.nis.modules.alert.dao.AlertMessageDao; -import com.nis.modules.alert.entity.AlertMessageEntity; -import com.nis.modules.alert.service.AlertRuleService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.ObjectUtils; - +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.nis.common.exception.NZException; -import com.nis.common.utils.Constant; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.Query; -import com.nis.common.utils.RCode; -import com.nis.common.utils.StringUtils; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; +import com.nis.common.utils.*; +import com.nis.modules.alert.dao.AlertMessageDao; +import com.nis.modules.alert.entity.AlertMessageEntity; import com.nis.modules.alert.entity.AlertSeverityConf; import com.nis.modules.alert.service.AlertMessageService; +import com.nis.modules.alert.service.AlertRuleService; import com.nis.modules.alert.service.AlertSeverityService; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.entity.AssetPing; @@ -51,12 +42,13 @@ import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.service.TimezoneService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.core.util.URLUtil; -import cn.hutool.log.Log; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; @Service diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/CtlController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/CtlController.java index 3f60fb56..a874cddd 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/CtlController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/CtlController.java @@ -1,22 +1,19 @@ package com.nis.modules.sys.controller; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - +import cn.hutool.core.util.StrUtil; import com.nis.common.annotation.SysLog; import com.nis.common.utils.IPUtils; import com.nis.common.utils.OperationEnum; import com.nis.common.utils.R; import com.nis.common.utils.TypeEnum; import com.nis.modules.sys.service.CtlService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import cn.hutool.core.util.StrUtil; +import javax.servlet.http.HttpServletRequest; +import java.util.Map; @RestController @RequestMapping("/ctl") diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/MfaController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/MfaController.java index 138f73be..62e23baa 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/MfaController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/MfaController.java @@ -1,32 +1,11 @@ package com.nis.modules.sys.controller;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
+import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.nis.common.annotation.SysLog;
import com.nis.common.smartvalidate.ValidateUtils;
-import com.nis.common.utils.HttpContextUtils;
-import com.nis.common.utils.IPUtils;
-import com.nis.common.utils.MfaUtils;
-import com.nis.common.utils.OperationEnum;
-import com.nis.common.utils.R;
-import com.nis.common.utils.RCode;
-import com.nis.common.utils.Tool;
-import com.nis.common.utils.ToolUtil;
-import com.nis.common.utils.TypeEnum;
+import com.nis.common.utils.*;
import com.nis.modules.sys.entity.AuthTokenEntity;
import com.nis.modules.sys.entity.SysConfigEntity;
import com.nis.modules.sys.entity.SysUserEntity;
@@ -36,8 +15,18 @@ import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserService;
import com.nis.modules.sys.service.TimezoneService;
import com.nis.modules.sys.shiro.ShiroUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
-import cn.hutool.core.util.StrUtil;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
@RestController
@RequestMapping("/mfa")
diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SnmpCredentialController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SnmpCredentialController.java index 108ee8e3..d0c5a7bb 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SnmpCredentialController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SnmpCredentialController.java @@ -1,33 +1,16 @@ package com.nis.modules.sys.controller; -import java.util.Arrays; -import java.util.Map; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import com.alibaba.fastjson.JSON; import com.nis.common.annotation.SysLog; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.SnmpUtil; -import com.nis.common.utils.ToolUtil; -import com.nis.common.utils.TypeEnum; -import com.nis.modules.asset.entity.AssetFieldGroup; +import com.nis.common.utils.*; import com.nis.modules.sys.entity.SnmpCredential; import com.nis.modules.sys.service.SnmpCredentialService; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; @RestController @RequestMapping("/snmp/credential") diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysBackupController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysBackupController.java index 651b3b62..30701522 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysBackupController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysBackupController.java @@ -6,9 +6,12 @@ import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; import com.nis.modules.sys.service.SysBackupService; +import org.apache.commons.lang3.time.StopWatch; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -25,6 +28,9 @@ public class SysBackupController { @Autowired private SysBackupService sysBackupService; + @Autowired + private RedisLock redisLock; + /** * 查询列表 */ @@ -49,16 +55,33 @@ public class SysBackupController { List<Object> result = sysBackupService.queryBackupList(); return R.ok(result); } - + @PostMapping public R backupData() { + // get lock + String uuid = Tool.StrUtil.uuid(); try { - sysBackupService.backupData(); + if (redisLock.lock(Constant.SYS_BACKUP_LOCK, uuid, 5L)) { + log.info("[backupData] [Get lock and start system data backup]"); + + StopWatch sw = new StopWatch(); + sw.start(); + + sysBackupService.backupData(); + sw.stop(); + log.info("[backupData] [System data backup finished] [Run time: {}]", sw.toString()); + + return R.ok(); + } else { + log.warn("[backupData] [System data backup is in progress please try again later]"); + return R.error(RCode.SYS_BACKUP_IN_PROGRESS); + } } catch (Exception e) { - log.error("data backup error", e); + log.error(e, "[backupData] [backup error]"); throw new NZException(RCode.SYS_BACKUP_ERROR); + } finally { + redisLock.unlock(Constant.SYS_BACKUP_LOCK, uuid); } - return R.ok(); } @@ -94,4 +117,14 @@ public class SysBackupController { return R.ok(); } + /** + * 系统备份下载接口 + * @param filename + */ + @GetMapping("/download") + public void download(HttpServletResponse response, String filename) throws IOException { + if (Tool.StrUtil.isEmpty(filename)) throw new NZException(RCode.SYS_BACKUP_FILENAME_ISNULL); + sysBackupService.downloadBackFileByFilename(response, filename); + } + } diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysI18nController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysI18nController.java index ffd21b32..a45052fc 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysI18nController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysI18nController.java @@ -1,19 +1,5 @@ package com.nis.modules.sys.controller; -import java.util.Arrays; -import java.util.Map; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - import com.nis.common.annotation.SysLog; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.OperationEnum; @@ -22,8 +8,12 @@ import com.nis.common.utils.R; import com.nis.common.utils.TypeEnum; import com.nis.modules.sys.entity.SysI18nEntity; import com.nis.modules.sys.service.SysI18nService; - import io.swagger.annotations.ApiParam; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; /** diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLicenseController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLicenseController.java index c6249c98..24e95cfe 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLicenseController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLicenseController.java @@ -1,54 +1,39 @@ package com.nis.modules.sys.controller; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import javax.servlet.http.HttpServletResponse; - -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.multipart.MultipartFile; - +import Aladdin.HaspStatus; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.LicenseUtil; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.ResponseUtil; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.sys.entity.LicenseEntity; import com.nis.modules.sys.entity.Signature; import com.nis.modules.sys.entity.SysComponent; import com.nis.modules.sys.service.LicenseService; import com.nis.modules.sys.service.SysComponentService; import com.nis.modules.sys.service.SysConfigService; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.multipart.MultipartFile; -import Aladdin.HaspStatus; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; @RestController @RequestMapping("/sys/license") diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLogController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLogController.java index 76510937..1b8bccf1 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLogController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLogController.java @@ -10,9 +10,7 @@ package com.nis.modules.sys.controller; import com.nis.common.utils.PageUtils; import com.nis.common.utils.R; -import com.nis.common.xss.XssUtil; import com.nis.modules.sys.service.SysLogService; -import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLoginController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLoginController.java index b3808c87..b5bbbbf3 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLoginController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysLoginController.java @@ -1,38 +1,7 @@ package com.nis.modules.sys.controller; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.imageio.ImageIO; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import cn.hutool.core.util.ObjectUtil; -import org.apache.commons.lang.time.DateUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.IncorrectCredentialsException; -import org.apache.shiro.authc.LockedAccountException; -import org.apache.shiro.authc.UnknownAccountException; -import org.apache.shiro.authc.UsernamePasswordToken; -import org.apache.shiro.subject.Subject; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.ListOperations; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; - +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -41,17 +10,7 @@ import com.google.code.kaptcha.Constants; import com.google.code.kaptcha.Producer; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; -import com.nis.common.utils.CommonUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.HttpContextUtils; -import com.nis.common.utils.IPUtils; -import com.nis.common.utils.MfaUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.sys.entity.AuthTokenEntity; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.entity.SysUserEntity; @@ -61,8 +20,28 @@ import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.service.TimezoneService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.lang.time.DateUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.subject.Subject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; -import cn.hutool.core.util.StrUtil; +import javax.imageio.ImageIO; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * 登录相关 diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserController.java index 9fa5b0c5..649a9ea6 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserController.java @@ -1,37 +1,21 @@ package com.nis.modules.sys.controller; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.nis.common.annotation.SysLog; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.OperationEnum; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.Tool; -import com.nis.common.utils.TypeEnum; +import com.nis.common.utils.*; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.service.SysConfigService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; @RestController diff --git a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserStarredController.java b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserStarredController.java index 949649a9..02e7e53c 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserStarredController.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/controller/SysUserStarredController.java @@ -8,7 +8,6 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/dao/SnmpCredentialDao.java b/nz-admin/src/main/java/com/nis/modules/sys/dao/SnmpCredentialDao.java index f8891497..a665beb0 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/dao/SnmpCredentialDao.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/dao/SnmpCredentialDao.java @@ -2,7 +2,6 @@ package com.nis.modules.sys.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.sys.entity.SnmpCredential; - import org.apache.ibatis.annotations.Mapper; @Mapper diff --git a/nz-admin/src/main/java/com/nis/modules/sys/dao/SysComponentDao.java b/nz-admin/src/main/java/com/nis/modules/sys/dao/SysComponentDao.java index deacd18a..b3f35058 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/dao/SysComponentDao.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/dao/SysComponentDao.java @@ -1,9 +1,8 @@ package com.nis.modules.sys.dao; -import org.apache.ibatis.annotations.Mapper; - import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.sys.entity.SysComponent; +import org.apache.ibatis.annotations.Mapper; @Mapper public interface SysComponentDao extends BaseMapper<SysComponent>{ diff --git a/nz-admin/src/main/java/com/nis/modules/sys/dao/SysConfDao.java b/nz-admin/src/main/java/com/nis/modules/sys/dao/SysConfDao.java index fcf48dbf..2f935eaf 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/dao/SysConfDao.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/dao/SysConfDao.java @@ -4,9 +4,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.nis.modules.sys.entity.SysConfigEntity; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; @Mapper public interface SysConfDao extends BaseMapper<SysConfigEntity> { void clearData(@Param("sql") String sql); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/LicenseEntity.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/LicenseEntity.java index d839eb9c..f28b7910 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/LicenseEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/LicenseEntity.java @@ -1,23 +1,14 @@ package com.nis.modules.sys.entity; -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; - -import com.alibaba.fastjson.annotation.JSONField; -import com.nis.common.utils.Tool; - import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.crypto.SecureUtil; +import com.alibaba.fastjson.annotation.JSONField; +import com.nis.common.utils.Tool; import lombok.Data; -import lombok.Setter; + +import javax.xml.bind.annotation.*; +import java.io.Serializable; +import java.util.Map; /** * license证书实体 * @author fang diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/Signature.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/Signature.java index db9478e8..a6ec24f9 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/Signature.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/Signature.java @@ -1,11 +1,10 @@ package com.nis.modules.sys.entity; -import java.io.Serializable; +import lombok.Data; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlTransient; - -import lombok.Data; +import java.io.Serializable; @Data public class Signature implements Serializable{ diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/SnmpCredential.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/SnmpCredential.java index fc8d8fa3..8e883e81 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/SnmpCredential.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/SnmpCredential.java @@ -1,7 +1,6 @@ package com.nis.modules.sys.entity; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysComponent.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysComponent.java index e00ae9e5..bbe826fb 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysComponent.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysComponent.java @@ -3,7 +3,6 @@ package com.nis.modules.sys.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; - import lombok.Data; @Data diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysI18nEntity.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysI18nEntity.java index 4c8b6cc2..92a7e99d 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysI18nEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysI18nEntity.java @@ -1,7 +1,9 @@ package com.nis.modules.sys.entity; -import com.baomidou.mybatisplus.annotation.*; -import com.fasterxml.jackson.annotation.JsonIgnore; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysUserStarredEntity.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysUserStarredEntity.java index f9a894ec..24bbf518 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/SysUserStarredEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/SysUserStarredEntity.java @@ -18,7 +18,7 @@ public class SysUserStarredEntity implements Serializable { private Integer uid; /** - * 支持类型:datacenter,project,module,endpoint,alertRule,asset,panel,chart,cabinet,ipamSubnet,issueRecord,recordRule + * 支持类型:datacenter,project,module,endpoint,alertRule,asset,dashboard,chart,cabinet,ipamSubnet,issueRecord,recordRule */ private String type; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/entity/Timezone.java b/nz-admin/src/main/java/com/nis/modules/sys/entity/Timezone.java index c1536105..f3fc8e82 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/entity/Timezone.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/entity/Timezone.java @@ -1,5 +1,6 @@ package com.nis.modules.sys.entity; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @@ -7,9 +8,13 @@ import lombok.Data; @Data @TableName("sys_timezone") public class Timezone { + @TableId private Integer id; + private String name; + + @TableField(value = "`offset`") private Integer offset; } diff --git a/nz-admin/src/main/java/com/nis/modules/sys/job/CleanJob.java b/nz-admin/src/main/java/com/nis/modules/sys/job/CleanJob.java index c9a55cf8..bf3d88bb 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/job/CleanJob.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/job/CleanJob.java @@ -12,11 +12,9 @@ import com.nis.modules.alert.dao.AlertMessageHistoryPartitionManagementDao; import com.nis.modules.alert.entity.AlertRuleEvalLog; import com.nis.modules.alert.entity.AlertRuleSchedLog; import com.nis.modules.alert.job.AlertMessageHistoryPartitionManagementJob; -import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.alert.service.AlertRuleEvalLogService; import com.nis.modules.alert.service.AlertRuleSchedLogService; import com.nis.modules.sys.service.SysConfigService; -import com.nis.modules.terminal.service.TerminalSessionService; import org.apache.commons.lang3.time.StopWatch; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; @@ -29,8 +27,10 @@ import java.util.List; import java.util.stream.Collectors; /** - * 系统清理任务 1. terminal log,默认保留 365天. 2. alert_rule_eval_log,默认保留 30天 3. - * alert_rule_sched_log,默认保留 30天 4. alert_message_history ,默认不清理 + * 系统清理任务 + * 1. alert_rule_eval_log,默认保留 30天 + * 2. alert_rule_sched_log,默认保留 30天 + * 3. alert_message_history ,默认不清理 */ @DisallowConcurrentExecution public class CleanJob extends QuartzJobBean { @@ -38,18 +38,12 @@ public class CleanJob extends QuartzJobBean { private Log log = Log.get(); @Autowired - private TerminalSessionService terminalSessionService; - - @Autowired private AlertRuleEvalLogService alertRuleEvalLogService; @Autowired private AlertRuleSchedLogService alertRuleSchedLogService; @Autowired - private AlertMessageService alertMessageService; - - @Autowired private SysConfigService sysConfigService; @Autowired @@ -71,19 +65,19 @@ public class CleanJob extends QuartzJobBean { StopWatch sw = new StopWatch(); // terminal_* - String terminalRecordLocalRetention = sysConfigService.getValue("terminal_record_local_retention"); - terminalRecordLocalRetention = Tool.StrUtil.emptyToDefault(terminalRecordLocalRetention, "365"); - DateTime startCleanTerminalTime = Tool.DateUtil.offsetDay(now, -Integer.valueOf(terminalRecordLocalRetention)); - sw.start(); - try { - log.info("start clean terminal data"); - terminalSessionService.cleanExpiredDataByTime(startCleanTerminalTime); - } catch (Exception e) { - log.error("clean terminal data error", e); - } finally { - sw.stop(); - } - log.info("clean terminal data Run Time: {}", sw.toString()); +// String terminalRecordLocalRetention = sysConfigService.getValue("terminal_record_local_retention"); +// terminalRecordLocalRetention = Tool.StrUtil.emptyToDefault(terminalRecordLocalRetention, "365"); +// DateTime startCleanTerminalTime = Tool.DateUtil.offsetDay(now, -Integer.valueOf(terminalRecordLocalRetention)); +// sw.start(); +// try { +// log.info("start clean terminal data"); +// terminalSessionService.cleanExpiredDataByTime(startCleanTerminalTime); +// } catch (Exception e) { +// log.error("clean terminal data error", e); +// } finally { +// sw.stop(); +// } +// log.info("clean terminal data Run Time: {}", sw.toString()); // alert_rule_eval_log String ruleEvalLogLocalRetention = sysConfigService.getValue("alert_rule_eval_log_local_retention"); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/job/SessionTimeOutJob.java b/nz-admin/src/main/java/com/nis/modules/sys/job/SessionTimeOutJob.java index c40a87d5..2e1dc01f 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/job/SessionTimeOutJob.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/job/SessionTimeOutJob.java @@ -1,33 +1,30 @@ package com.nis.modules.sys.job; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.quartz.QuartzJobBean; -import org.springframework.web.socket.WebSocketSession; - +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.nis.common.utils.Constant; import com.nis.common.utils.ToolUtil; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.shiro.ShiroUtils; -import com.nis.modules.terminal.config.Constants; -import com.nis.modules.terminal.config.TerminalHandler; -import com.nis.modules.terminal.config.TerminalSession; +import com.nis.modules.terminal.backend.TerminalHandler; +import com.nis.modules.terminal.backend.TerminalSession; import com.nis.modules.terminal.entity.TerminalSessionEntity; -import com.nis.modules.terminal.service.TerminalRecordService; import com.nis.modules.terminal.service.TerminalSessionService; +import com.nis.modules.terminal.utils.TerminalConstant; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.web.socket.WebSocketSession; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @DisallowConcurrentExecution public class SessionTimeOutJob extends QuartzJobBean { @@ -35,9 +32,6 @@ public class SessionTimeOutJob extends QuartzJobBean { private Log log = Log.get(); @Autowired - private TerminalRecordService terminalRecordService; - - @Autowired private TerminalSessionService terminalSessionService; @Autowired @@ -72,7 +66,7 @@ public class SessionTimeOutJob extends QuartzJobBean { List<TerminalSessionEntity> userTerminals = userIdAndTerminal.get(userId); for(TerminalSessionEntity userTerminal : userTerminals) { userTerminal.setEndTime(new Date()); - userTerminal.setStatus(Constants.SessionStatus.FORCE_QUIT.getValue()); + userTerminal.setStatus(TerminalConstant.SessionStatus.FORCE_QUIT.getValue()); updateDatas.add(userTerminal); WebSocketSession session = TerminalSession.findSession(userTerminal.getUuid()); try { @@ -83,7 +77,7 @@ public class SessionTimeOutJob extends QuartzJobBean { log.error(String.format("terminal session kill failed,uuid = %s,错误信息 = %s", userTerminal.getUuid(), e.getMessage()), e); } // kill 之后,将剩余文件写到数据库中 - TerminalHandler.handleRecodeAfterClientClose(userTerminal.getUuid(), terminalRecordService); + TerminalHandler.saveRecordContentAfterClientClosed(userTerminal.getUuid()); } } if(ToolUtil.isNotEmpty(updateDatas)) { diff --git a/nz-admin/src/main/java/com/nis/modules/sys/job/SysComponentJob.java b/nz-admin/src/main/java/com/nis/modules/sys/job/SysComponentJob.java index 1b9c271e..a427436e 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/job/SysComponentJob.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/job/SysComponentJob.java @@ -1,5 +1,13 @@ package com.nis.modules.sys.job; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.sys.entity.SysComponent; +import com.nis.modules.sys.service.SysComponentService; +import com.nis.modules.sys.service.SysConfigService; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -8,16 +16,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.quartz.QuartzJobBean; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.nis.common.utils.Constant; -import com.nis.common.utils.Tool; -import com.nis.modules.sys.entity.SysComponent; -import com.nis.modules.sys.service.SysComponentService; -import com.nis.modules.sys.service.SysConfigService; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; - /** * 系统组件 状态检查线程 1、更新当前组件的状态 a、当设置了host时,直接使用 host b、没有设置host时,通过socket 连接 数据库 * 获取local address 2、主进程 a、清除超过两个周期没有更新的记录 b、检查 sys_config 表 alert_api diff --git a/nz-admin/src/main/java/com/nis/modules/sys/redis/SysLoginRedis.java b/nz-admin/src/main/java/com/nis/modules/sys/redis/SysLoginRedis.java index 364fe77c..3bfe330c 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/redis/SysLoginRedis.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/redis/SysLoginRedis.java @@ -4,14 +4,13 @@ package com.nis.modules.sys.redis; import com.alibaba.fastjson.JSON; import com.nis.common.utils.RedisKeys; import com.nis.modules.sys.entity.AuthTokenEntity; - -import java.util.concurrent.TimeUnit; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; +import java.util.concurrent.TimeUnit; + /** * authToken Redis * diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/BasicImportAndExportServices.java b/nz-admin/src/main/java/com/nis/modules/sys/service/BasicImportAndExportServices.java index 47e8bc0a..17f323dc 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/BasicImportAndExportServices.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/BasicImportAndExportServices.java @@ -17,7 +17,7 @@ public interface BasicImportAndExportServices { void exportDataByFormat(HttpServletResponse response, List<List<String>> exportDataList, String sysHeaderJsonStr, String format, String fileName) throws IOException; - String getFailedContentFileBase64Str(List<Map<Integer, String>> failContentList, String sysHeaderJsonStr, String format); + String getFailedContentFileBase64Str(List<Map<Integer, String>> failContentList, String sysHeaderJsonStr, String fileExtension); /** * 根据表名、列名、value值查询列表,导入判定对象是否存在时使用 diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/SnmpCredentialService.java b/nz-admin/src/main/java/com/nis/modules/sys/service/SnmpCredentialService.java index 7889cbdc..18c163f2 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/SnmpCredentialService.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/SnmpCredentialService.java @@ -1,12 +1,12 @@ package com.nis.modules.sys.service; -import java.util.List; -import java.util.Map; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.sys.entity.SnmpCredential; +import java.util.List; +import java.util.Map; + public interface SnmpCredentialService extends IService<SnmpCredential>{ PageUtils queryPage(Map<String,Object> params); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/SysBackupService.java b/nz-admin/src/main/java/com/nis/modules/sys/service/SysBackupService.java index d0582990..d791c186 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/SysBackupService.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/SysBackupService.java @@ -1,5 +1,7 @@ package com.nis.modules.sys.service; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -15,4 +17,5 @@ public interface SysBackupService { void removeBackFileByFilename(String filename); + void downloadBackFileByFilename(HttpServletResponse response, String filename) throws IOException; } diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/SysConfService.java b/nz-admin/src/main/java/com/nis/modules/sys/service/SysConfService.java index db94123a..efadc02c 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/SysConfService.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/SysConfService.java @@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.sys.entity.SysConfigEntity; import java.io.IOException; -import java.util.List; import java.util.Map; public interface SysConfService extends IService<SysConfigEntity> { diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/SysI18nService.java b/nz-admin/src/main/java/com/nis/modules/sys/service/SysI18nService.java index 7a5d3625..bf810631 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/SysI18nService.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/SysI18nService.java @@ -1,13 +1,13 @@ package com.nis.modules.sys.service; -import java.util.List; -import java.util.Locale; -import java.util.Map; - import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; import com.nis.modules.sys.entity.SysI18nEntity; +import java.util.List; +import java.util.Locale; +import java.util.Map; + /** * i18n信息表 * diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/SysUserService.java b/nz-admin/src/main/java/com/nis/modules/sys/service/SysUserService.java index 72f1998f..850d30c9 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/SysUserService.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/SysUserService.java @@ -13,8 +13,6 @@ import com.nis.common.utils.PageUtils; import com.nis.modules.sys.entity.SysUserEntity; import javax.servlet.http.HttpServletRequest; - -import java.util.Date; import java.util.List; import java.util.Map; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/BasicImportAndExportServicesImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/BasicImportAndExportServicesImpl.java index 972b9517..68ee7eeb 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/BasicImportAndExportServicesImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/BasicImportAndExportServicesImpl.java @@ -16,9 +16,11 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.nis.common.exception.NZException; import com.nis.common.utils.*; +import com.nis.common.utils.Constant.ImportFileType; import com.nis.modules.sys.dao.BasicMapper; import com.nis.modules.sys.service.BasicImportAndExportServices; import com.nis.modules.sys.service.SysI18nService; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Row; @@ -68,8 +70,9 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer @Override public void getTemplate(String sysHeaderJsonStr, String format, String fileName, HttpServletResponse response) throws IOException { Map<String, String> exportHeaderMap = this.getI18nHeaderMap(sysHeaderJsonStr); - switch (format) { - case "1": { // XLSX + switch (ImportFileType.getInstanceByValue(format)) { + case XLS: + case XLSX: { SXSSFWorkbook workbook = null; try { workbook = ExcelUtils.createExcel07(exportHeaderMap, "Datasheet", true); @@ -82,11 +85,11 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer } break; } - case "2": {// CSV + case CSV: { fileName += ".csv"; File file = FileUtil.file(Constant.TMP_ROOT_PATH + fileName); FileOutputStream fos = new FileOutputStream(file); - fos.write(new byte[] { (byte) 0xEF, (byte) 0xBB,(byte) 0xBF}); + fos.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}); try { CsvWriter writer = CsvUtil.getWriter(file, CharsetUtil.CHARSET_UTF_8, true); writer.write( @@ -99,7 +102,7 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer } break; } - case "3": {// JSON + case JSON: { for (Map.Entry<String, String> entry : exportHeaderMap.entrySet()) { entry.setValue(StrUtil.EMPTY); } @@ -122,17 +125,15 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer @Override public List<Map<Integer, String>> getImportDataFromMultipartFile(MultipartFile multipartFile, String sysHeaderJsonStr) throws IOException { - String originalFilename = multipartFile.getOriginalFilename(); - String fileType = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); - fileType = fileType.toLowerCase(); + String fileType = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); Map<String, String> exportHeaderMap = this.getI18nHeaderMap(sysHeaderJsonStr); - List<String> headerInfos = new ArrayList<>(exportHeaderMap.keySet()); + List<Map<Integer, String>> importDataList = new ArrayList<>(); - switch (fileType) { - case "xlsx": - case "xls": { + switch (ImportFileType.getInstanceByType(fileType)) { + case XLS: + case XLSX: { Workbook work = ExcelUtils.getWorkBookFromMultipartFile(multipartFile); Sheet sheet = work.getSheetAt(0); // 表头校验 @@ -151,7 +152,7 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer } break; } - case "csv": { + case CSV: { CsvData csvData = CSVUtils.getCsvDataFromMultipartFile(multipartFile); List<CsvRow> rows = csvData.getRows(); CsvRow headers = rows.get(0); @@ -164,8 +165,8 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer Map<Integer, String> tmpMap = Tool.MapUtil.newHashMap(); for (int j = 0; j < headerInfos.size(); j++) { String cellStr = StrUtil.trim(csvRow.get(j)); - if((StrUtil.startWith(cellStr, "[") && StrUtil.endWith(cellStr, "]")) || - (StrUtil.startWith(cellStr, "{") && StrUtil.endWith(cellStr, "}"))){ // csv文件中json格式双引号会变成两个 + if ((StrUtil.startWith(cellStr, "[") && StrUtil.endWith(cellStr, "]")) || + (StrUtil.startWith(cellStr, "{") && StrUtil.endWith(cellStr, "}"))) { // csv文件中json格式双引号会变成两个 cellStr = StrUtil.replace(cellStr, "\"\"", "\""); } tmpMap.put(j, cellStr); @@ -174,7 +175,7 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer } break; } - case "json": { + case JSON: { String str = IoUtil.read(multipartFile.getInputStream(), CharsetUtil.charset("UTF-8")); List<LinkedHashMap> mapList = JSONObject.parseArray(str, LinkedHashMap.class); LinkedHashMap map = mapList.get(0); @@ -207,9 +208,9 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer @Override public void exportDataByFormat(HttpServletResponse response, List<List<String>> exportDataList, String sysHeaderJsonStr, String format, String fileName) throws IOException { Map<String, String> exportHeaderMap = this.getI18nHeaderMap(sysHeaderJsonStr); - Constant.ImportFileType fileType = Constant.ImportFileType.getType(format); - switch (fileType) { - case EXCEL: { + switch (ImportFileType.getInstanceByValue(format)) { + case XLS: + case XLSX: { SXSSFWorkbook workbook = null; try { String sheetName = "Datasheet"; @@ -283,7 +284,7 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer } @Override - public String getFailedContentFileBase64Str(List<Map<Integer, String>> failContentList, String sysHeaderJsonStr, String format) { + public String getFailedContentFileBase64Str(List<Map<Integer, String>> failContentList, String sysHeaderJsonStr, String fileExtension) { if (CollUtil.isEmpty(failContentList)) return StrUtil.EMPTY; List<List<String>> list = ListUtil.list(true); @@ -293,11 +294,10 @@ public class BasicImportAndExportServicesImpl implements BasicImportAndExportSer }); Map<String, String> exportHeaderMap = this.getI18nHeaderMap(sysHeaderJsonStr); - format = StrUtil.emptyToDefault(format, Constant.ImportFileType.EXCEL.getValue()); - Constant.ImportFileType fileType = Constant.ImportFileType.getType(format); try { - switch (fileType) { - case EXCEL: { + switch (ImportFileType.getInstanceByType(fileExtension)) { + case XLS: + case XLSX: { String sheetName = "Datasheet"; SXSSFWorkbook workbook = ExcelUtils.createExcel07(exportHeaderMap, sheetName, true); SXSSFSheet sheet = workbook.getSheet(sheetName); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/CtlServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/CtlServiceImpl.java index ec478f78..cf359d7f 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/CtlServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/CtlServiceImpl.java @@ -1,24 +1,21 @@ package com.nis.modules.sys.service.impl; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang.RandomStringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - +import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.nis.common.utils.Constant; import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.service.CtlService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; -import cn.hutool.log.Log; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; @Service public class CtlServiceImpl implements CtlService { diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SnmpCredentialServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SnmpCredentialServiceImpl.java index bec2196e..d34f7c83 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SnmpCredentialServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SnmpCredentialServiceImpl.java @@ -1,28 +1,26 @@ package com.nis.modules.sys.service.impl; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import com.nis.common.utils.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - +import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; import com.nis.modules.asset.entity.AssetAsset; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.sys.dao.SnmpCredentialDao; import com.nis.modules.sys.entity.SnmpCredential; import com.nis.modules.sys.service.SnmpCredentialService; - -import cn.hutool.core.util.ObjectUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + @Service public class SnmpCredentialServiceImpl extends ServiceImpl<SnmpCredentialDao,SnmpCredential> implements SnmpCredentialService{ diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysBackupServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysBackupServiceImpl.java index 61441e2f..d010cbd3 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysBackupServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysBackupServiceImpl.java @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; +import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource; import java.io.BufferedWriter; import java.io.File; @@ -244,6 +245,29 @@ public class SysBackupServiceImpl implements SysBackupService { } } + @Override + public void downloadBackFileByFilename(HttpServletResponse response, String filename) throws IOException { + SysConfigEntity config = sysConfigDao.queryByKey("backup_file_path"); + String path = Constant.BACKUP_ROOT_PATH; + + if (Optional.ofNullable(config).map(SysConfigEntity::getParamValue).isPresent()) { + path = config.getParamValue(); + } + + String sqlFilePath = Tool.StrUtil.concat(true, path, File.separator, filename); + boolean exist = FileUtil.exist(sqlFilePath); + if (exist) { + exist = FileUtil.isFile(sqlFilePath); + if (exist) { + ResponseUtil.downloadFile(response, FileUtil.file(sqlFilePath)); + } + } + if(!exist){ + // 文件不存在 + throw new NZException(RCode.SYS_BACKUP_FILENAME_NOTEXIST); + } + } + /** * 根据数据库配置 判断保存文件数量是否超标 */ diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysComponentServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysComponentServiceImpl.java index 61d5ff78..5f6702e4 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysComponentServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysComponentServiceImpl.java @@ -1,11 +1,5 @@ package com.nis.modules.sys.service.impl; -import java.util.regex.Pattern; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.utils.Constant; @@ -13,6 +7,11 @@ import com.nis.common.utils.Tool; import com.nis.modules.sys.dao.SysComponentDao; import com.nis.modules.sys.entity.SysComponent; import com.nis.modules.sys.service.SysComponentService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.regex.Pattern; @Service public class SysComponentServiceImpl extends ServiceImpl<SysComponentDao, SysComponent> implements SysComponentService { diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfServiceImpl.java index 1d03224f..7f8eebe7 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfServiceImpl.java @@ -10,12 +10,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.agent.service.MonitorEventLogService; import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.alert.entity.AlertMessageEntity; import com.nis.modules.alert.service.AlertMessageService; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.AgentService; import com.nis.modules.sys.dao.SysConfDao; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.entity.SysUserEntity; @@ -56,7 +56,7 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> public static final String[][] BASIC_DEPEND={}; - public static final String[] MONITOR_KEYS = {"alert_api", "prometheus_federation_enabled", "default_scrape_interval", "default_scrape_timeout", "asset_ping_interval", "asset_ping_from", "metrics_storage_retention", "metrics_storage_type", "metrics_storage_s3_endpoint", "metrics_storage_s3_bucket", "metrics_storage_s3_access_key", "metrics_storage_s3_secret_access_key", "metrics_query_max_series", "logs_storage_retention", "logs_storage_type", "logs_storage_s3_endpoint", "logs_storage_s3_bucket", "logs_storage_s3_access_key", "logs_storage_s3_secret_access_key", "logs_query_range_default_limit"}; + public static final String[] MONITOR_KEYS = {"alert_api", "prometheus_federation_enabled", "default_scrape_interval", "default_scrape_timeout", "asset_ping_interval", "asset_ping_from", "metrics_storage_retention", "metrics_storage_type", "metrics_storage_s3_endpoint", "metrics_storage_s3_bucket", "metrics_storage_s3_access_key", "metrics_storage_s3_secret_access_key", "metrics_query_max_series", "logs_storage_retention", "logs_storage_type", "logs_storage_s3_endpoint", "logs_storage_s3_bucket", "logs_storage_s3_access_key", "logs_storage_s3_secret_access_key", "logs_query_range_default_limit", "interface_name"}; public static final String[] MONITOR_REQUIRED = {"prometheus_federation_enabled", "default_scrape_interval", "default_scrape_timeout", "asset_ping_interval", "asset_ping_from", "metrics_storage_retention", "metrics_storage_type", "metrics_query_max_series", "logs_storage_retention", "logs_storage_type", "logs_query_range_default_limit"}; @@ -85,17 +85,19 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> public static final String[] SWITCH_TYPES={"on","off"}; - public static final String[] TERMINAL_KEYS={"terminal_timeout","terminal_telnet_user_tip","terminal_telnet_pin_tip","terminal_record_local_retention"}; + public static final String[] TERMINAL_KEYS={"terminal_timeout","terminal_telnet_user_tip","terminal_telnet_pin_tip","terminal_record_local_retention","terminal_storage_type","terminal_storage_s3_endpoint","terminal_storage_s3_bucket","terminal_storage_s3_access_key","terminal_storage_s3_secret_access_key"}; + + public static final String[] TERMINAL_REQUIRED={"terminal_telnet_user_tip","terminal_telnet_pin_tip","terminal_record_local_retention","terminal_storage_type"}; - public static final String[] TERMINAL_REQUIRED={"terminal_telnet_user_tip","terminal_telnet_pin_tip","terminal_record_local_retention"}; + public static final String[] TERMINAL_S3_REQUIRED={"terminal_storage_s3_endpoint","terminal_storage_s3_bucket","terminal_storage_s3_access_key","terminal_storage_s3_secret_access_key"}; - public static final String[] TERMINAL_INTEGER={"terminal_timeout","terminal_record_local_retention"}; + public static final String[] TERMINAL_INTEGER={"terminal_timeout","terminal_record_local_retention","terminal_storage_type"}; public static final String[] LDAP_KEYS={"ldap_address","ldap_dn","ldap_password","ldap_ou","ldap_user_filter","ldap_mapping","ldap_timeout","ldap_enable"}; public static final String[] LDAP_REQUIRED={"ldap_address","ldap_dn","ldap_user_filter","ldap_mapping","ldap_enable","ldap_timeout"}; - private static Log logger = Log.get(); + private static final Log logger = Log.get(); @Autowired private SysConfigRedis sysConfigRedis; @@ -149,6 +151,10 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> this.validateRequired(result,TERMINAL_REQUIRED,null); //校验integer类型 this.validateInteger(TERMINAL_INTEGER,result); + //校验S3存储参数 + if(StrUtil.equals(String.valueOf(params.get("terminal_storage_type")), "2")){ + this.validateRequired(result,TERMINAL_S3_REQUIRED,null); + } this.saveOrUpdateConfsBatch(result); } @@ -382,26 +388,26 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> for (String key : keyList){ if(Tool.StrUtil.isEmpty(params.get(key))){ - throw new NZException(String.format("%s can not be null",Tool.StrUtil.replace(key,"_"," ")),573011); + throw new NZException(String.format("%s can not be null",Tool.StrUtil.replace(key,"_"," ")),99999); } } if(dependKeys!=null && dependKeys.length>0){ for (String[] depend : dependKeys){ String key = depend[0]; - String[] dependKey = Tool.StrUtil.split(depend[1],","); //多个依赖用逗号隔开 - String[] values = Tool.StrUtil.split(depend[2],",");//多个value用逗号隔开 + List<String> dependKey = Tool.StrUtil.split(depend[1],","); //多个依赖用逗号隔开 + List<String> values = Tool.StrUtil.split(depend[2],",");//多个value用逗号隔开 boolean isDepend = true; - for (int i = 0; i < dependKey.length; i++) { - String dk = dependKey[i]; // - String value = values[i]; + for (int i = 0; i < dependKey.size(); i++) { + String dk = dependKey.get(i); + String value = values.get(i); if(!(params.containsKey(dk) && Tool.StrUtil.equals(params.get(dk),value))){ //如果不存在依赖的key 或者依赖的key对应的value 不符合,说明不需要依赖 isDepend = false; break; } } if(isDepend&& Tool.StrUtil.isEmpty(params.get(key))){ - throw new NZException(String.format("%s can not be null", Tool.StrUtil.replace(key,"_"," ")),573011); + throw new NZException(String.format("%s can not be null", Tool.StrUtil.replace(key,"_"," ")),99999); } } } @@ -576,6 +582,11 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> if (logsStorageTypeIntValue != 1 && logsStorageTypeIntValue != 2) { throw new NZException(RCode.SYS_CONFIGI_LOGSSTORAGETYPE_NCORRECT); } + + // interface_name + String interfaceName = result.get("interface_name"); + result.put("interface_name", StrUtil.emptyToDefault(interfaceName, "eth0,en0,bond0,ens2f0,enp0s31f6")); + // 处理 monitor_event_log 数据变动 this.handleMoniotEventLog(result); //保存 @@ -615,7 +626,7 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> updateKeys.add(key); } } - + logger.info("[handleMoniotEventLog] [Updated monitor config] [key size: {}] [value: {}]", updateKeys.size(), JSONUtil.toJsonStr(updateKeys)); // 根据 key 更新不同 event_log 值 if (Tool.CollectionUtil.isNotEmpty(updateKeys)) { Set<String> incrementKeys = new HashSet<>(); @@ -655,6 +666,12 @@ public class SysConfServiceImpl extends ServiceImpl<SysConfDao, SysConfigEntity> // incrementKeys.add("rule"); incrementKeys.add("cortex"); } + // interface_name + if (updateKeys.contains("interface_name")) { + logger.info("[handleMoniotEventLog] [Updated interface_name]"); + incrementKeys.add("cortex"); + incrementKeys.add("loki"); + } eventLogService.increment(ArrayUtil.toArray(incrementKeys, String.class)); } } diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfigServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfigServiceImpl.java index c91898e5..fb05e21a 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfigServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysConfigServiceImpl.java @@ -21,10 +21,10 @@ import com.google.gson.Gson; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.utils.*; -import com.nis.modules.agent.util.AgentUtil; -import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.agent.entity.Agent; import com.nis.modules.agent.service.AgentService; +import com.nis.modules.agent.util.AgentUtil; +import com.nis.modules.alert.service.AlertMessageService; import com.nis.modules.sys.dao.SysConfigDao; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.entity.SysUserEntity; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysDictServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysDictServiceImpl.java index 3d4aec7d..3cc8d3c7 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysDictServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysDictServiceImpl.java @@ -26,7 +26,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; -import java.util.stream.Collectors; @Service("sysDictService") diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysI18nServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysI18nServiceImpl.java index ab6135c6..49e1bd30 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysI18nServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysI18nServiceImpl.java @@ -1,25 +1,8 @@ package com.nis.modules.sys.service.impl; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.stream.Collectors; - -import javax.servlet.http.HttpServletRequest; - +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.nis.common.utils.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Service; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.servlet.i18n.SessionLocaleResolver; -import org.springframework.web.util.WebUtils; - import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -27,6 +10,7 @@ import com.nis.common.config.I18nConfig; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; import com.nis.common.smartvalidate.utils.CommonUtil; +import com.nis.common.utils.*; import com.nis.modules.sys.dao.SysI18nDao; import com.nis.modules.sys.entity.SysDictEntity; import com.nis.modules.sys.entity.SysI18nEntity; @@ -34,9 +18,17 @@ import com.nis.modules.sys.service.SysDictService; import com.nis.modules.sys.service.SysI18nService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.shiro.ShiroUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; +import org.springframework.web.util.WebUtils; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; +import javax.servlet.http.HttpServletRequest; +import java.util.*; +import java.util.stream.Collectors; @Service("sysI18nService") public class SysI18nServiceImpl extends ServiceImpl<SysI18nDao, SysI18nEntity> implements SysI18nService { diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysInfoServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysInfoServiceImpl.java index 784fde1e..47045d0a 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysInfoServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysInfoServiceImpl.java @@ -6,9 +6,9 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.nis.common.utils.*; -import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.agent.dao.AgentDao; import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.sys.dao.SysConfigDao; import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.service.SysInfoService; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysLogServiceImpl.java index d40b7491..9d82519c 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysLogServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysLogServiceImpl.java @@ -8,6 +8,7 @@ package com.nis.modules.sys.service.impl; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -20,8 +21,6 @@ import com.nis.modules.sys.entity.SysLogEntity; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.service.SysLogService; import com.nis.modules.sys.service.SysUserService; - -import cn.hutool.core.util.StrUtil; import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java index 375a81be..cc549b4f 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java @@ -1,5 +1,6 @@ package com.nis.modules.sys.service.impl; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -53,25 +54,21 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRoleEntity> i new Query(SysRoleEntity.class).getPage(params), new LambdaUpdateWrapper<SysRoleEntity>() .eq(ToolUtil.isNotEmpty(params.get("id")), SysRoleEntity::getId, params.get("id")) - .like(ToolUtil.isNotEmpty(params.get("name")), SysRoleEntity::getName, Tool.StrUtil.likeEscape(Tool.MapUtil.getStr(params,"name"))) + .like(ToolUtil.isNotEmpty(params.get("name")), SysRoleEntity::getName, Tool.StrUtil.likeEscape(Tool.MapUtil.getStr(params, "name"))) ); + List<SysRoleEntity> records = page.getRecords(); + for (SysRoleEntity role : records) { + Integer buildIn = role.getBuildIn(); + // 非内置角色不返回 i18n_code + if (ObjectUtil.equal(0, buildIn)) { + role.setI18n(null); + } + } return new PageUtils(page); } /** - * 校验 role 是否存在 - * - * @param roleId - */ - private void validateRoleExist(Integer roleId) { - SysRoleEntity role = this.getById(roleId); - - if (role == null) - throw new NZException(RCode.SYS_ROLE_ISNULL); - } - - /** * 校验 角色 相关信息 * * @param role @@ -120,20 +117,21 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRoleEntity> i @Override @Transactional(rollbackFor = Exception.class) public void update(SysRoleEntity role) { - // 校验 角色 相关信息 - role.setName(StrUtil.trim(role.getName())); - this.validateRoleInfo(role); - SysRoleEntity oldRole = this.getById(role.getId()); - if (oldRole == null) - throw new NZException(RCode.SYS_ROLE_ISNULL); + ValidateUtils.is(oldRole).notNull(RCode.SYS_ROLE_ISNULL); - // 内置角色 name 不允许修改 - if (oldRole.getBuildIn() == 1) { - if(!StrUtil.equals(oldRole.getName(),role.getName())) - throw new NZException(RCode.SYS_ROLE_NAME_CANNOT_MODIFY); + // 内置角色不允许修改 + Integer buildIn = oldRole.getBuildIn(); + buildIn = ObjectUtil.defaultIfNull(buildIn, 0); + if (ObjectUtil.equal(buildIn, 1)) { + throw new NZException(RCode.SYS_ROLE_NOT_SUPPORT_MODIFY); } + // 校验 角色 相关信息 + role.setName(StrUtil.trim(role.getName())); + this.validateRoleInfo(role); + + // update this.updateById(role); // 处理角色菜单关系 @@ -187,15 +185,12 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRoleEntity> i @Override public Map getMenuListByRoleId(Integer roleId) { // 校验 role 是否存在 - this.validateRoleExist(roleId); + SysRoleEntity role = this.getById(roleId); + ValidateUtils.is(role).notNull(RCode.SYS_ROLE_ISNULL); Map resultData = new HashMap(4); List<SysMenuEntity> menuList = sysMenuService.getMenuList(null); - /* List<SysMenuEntity> roleMenuList = sysMenuService.getRoleMenuList(roleId); - List<Integer> selectedIds = Collections.emptyList(); - if(CollectionUtils.isNotEmpty(roleMenuList)) - selectedIds = sysMenuService.getSelectedMenuIds(roleMenuList);*/ List<SysMenuEntity> roleMenuList = sysMenuDao.getRoleMenuList(roleId); Set<Integer> selectedIds = roleMenuList.stream().filter(Objects::nonNull).map(SysMenuEntity::getId).collect(Collectors.toSet()); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java index 85615ad1..1144f83f 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java @@ -18,9 +18,9 @@ import com.nis.modules.alert.entity.AlertRuleEntity; import com.nis.modules.alert.service.AlertRuleService; import com.nis.modules.asset.entity.Dc; import com.nis.modules.asset.service.DcService; -import com.nis.modules.panel.dao.VisualPanelDao; -import com.nis.modules.panel.entity.VisualPanel; -import com.nis.modules.panel.service.VisualPanelService; +import com.nis.modules.dashboard.dao.VisualDashboardDao; +import com.nis.modules.dashboard.entity.VisualDashboard; +import com.nis.modules.dashboard.service.VisualDashboardService; import com.nis.modules.sys.dao.SysRoleDao; import com.nis.modules.sys.dao.SysUserDao; import com.nis.modules.sys.entity.SysApiKey; @@ -84,10 +84,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i private AlertRuleDao alertRuleDao; @Autowired - private VisualPanelDao visualPanelDao; + private VisualDashboardDao dashboardDao; @Autowired - private VisualPanelService visualPanelService; + private VisualDashboardService dashboardService; @Autowired private DcService dcService; @@ -351,19 +351,19 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i dcService.update(new LambdaUpdateWrapper<Dc>().in(Dc::getPrincipal, idList).set(Dc::getPrincipal, null)); // 删除相关 sys_api_key sysApiKeyService.remove(new LambdaUpdateWrapper<SysApiKey>().in(SysApiKey::getCreateBy, idList)); - // 删除 panel 引用 - visualPanelDao.delReceivers(idList); - // 关闭 panel 接收人为空的报表 - List<VisualPanel> visualPanelList = visualPanelDao.queryReportOfEmptyReceivers(); - for (VisualPanel panel : visualPanelList) { - Map newParamMap = JSONObject.parseObject(panel.getParam().toString(), LinkedHashMap.class); + // 删除 dashboard 引用 + dashboardDao.delReceivers(idList); + // 关闭 dashboard 接收人为空的报表 + List<VisualDashboard> visualDashboardList = dashboardDao.queryReportOfEmptyReceivers(); + for (VisualDashboard dashboard : visualDashboardList) { + Map newParamMap = JSONObject.parseObject(dashboard.getParam().toString(), LinkedHashMap.class); Map publishMap = new HashMap(4); - publishMap.put("panelId", panel.getId()); + publishMap.put("dashboardId", dashboard.getId()); publishMap.putAll(newParamMap); redisTemplate.convertAndSend(Constant.REPORT_TOPIC_NAME, JSONObject.toJSONString(publishMap)); } - if(Tool.CollUtil.isNotEmpty(visualPanelList)) visualPanelService.updateBatchById(visualPanelList); + if(Tool.CollUtil.isNotEmpty(visualDashboardList)) dashboardService.updateBatchById(visualDashboardList); // 删除 redis 中 用户token 信息 List<String> removeKeys = new ArrayList<>(); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserStarredImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserStarredImpl.java index ad6554d7..0030512e 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserStarredImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserStarredImpl.java @@ -8,15 +8,15 @@ import com.nis.common.utils.RCode; import com.nis.common.utils.StringUtils; import com.nis.common.utils.Tool; import com.nis.modules.alert.service.AlertRuleService; +import com.nis.modules.alert.service.RecordRuleService; import com.nis.modules.asset.service.AssetAssetService; import com.nis.modules.asset.service.DcService; import com.nis.modules.asset.service.IssueRecordService; +import com.nis.modules.dashboard.service.VisualChartService; +import com.nis.modules.dashboard.service.VisualDashboardService; import com.nis.modules.endpoint.service.MonitorEndpointService; import com.nis.modules.module.service.MonitorModuleService; -import com.nis.modules.panel.service.VisualChartService; -import com.nis.modules.panel.service.VisualPanelService; import com.nis.modules.project.service.MonitorProjectService; -import com.nis.modules.alert.service.RecordRuleService; import com.nis.modules.sys.dao.SysUserStarredDao; import com.nis.modules.sys.entity.SysUserStarredEntity; import com.nis.modules.sys.service.SysUserStarredService; @@ -54,7 +54,7 @@ public class SysUserStarredImpl extends ServiceImpl<SysUserStarredDao, SysUserSt private AssetAssetService assetAssetService; @Autowired - private VisualPanelService visualPanelService; + private VisualDashboardService dashboardService; @Autowired private VisualChartService visualChartService; @@ -133,8 +133,8 @@ public class SysUserStarredImpl extends ServiceImpl<SysUserStarredDao, SysUserSt case "asset": sysUserStarredEntity.setName(assetAssetService.getById(tid).getName()); break; - case "panel": - sysUserStarredEntity.setName(visualPanelService.getById(tid).getName()); + case "dashboard": + sysUserStarredEntity.setName(dashboardService.getById(tid).getName()); break; case "chart": sysUserStarredEntity.setName(visualChartService.getById(tid).getName()); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java index c02050d4..40a564a8 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java @@ -1,12 +1,9 @@ package com.nis.modules.sys.shiro; -import com.alibaba.fastjson.JSON; +import cn.hutool.log.Log; import com.nis.common.utils.SpringContextUtils; import com.nis.common.utils.ToolUtil; import com.nis.modules.sys.entity.SysUserEntity; - -import cn.hutool.log.Log; - import org.apache.shiro.SecurityUtils; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.session.Session; diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/UserRealm.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/UserRealm.java index fae2025a..e1b89e7c 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/shiro/UserRealm.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/shiro/UserRealm.java @@ -266,49 +266,51 @@ public class UserRealm extends AuthorizingRealm { queryFilter.append(new HardcodedFilter(ldapUserFilter)); } // 支持配置多个 ou 搜索用户 - List<String> baseList = StrUtil.splitTrim(ldapOu, "|"); SysUserEntity entity = null; - for (String base : baseList) { - LdapQuery query = LdapQueryBuilder.query().base(base).timeLimit(20000).countLimit(1000).filter(queryFilter); - try { - // 开始认证 - entity = ldapTemplate.authenticate(query, pin,new AuthenticatedLdapEntryContextMapper<SysUserEntity>() { - @Override - public SysUserEntity mapWithContext(DirContext ctx,LdapEntryIdentification ldapEntryIdentification) { - LdapName ldapName = ldapEntryIdentification.getAbsoluteName(); - Attributes attributes; - SysUserEntity user = null; - try { - attributes = ctx.getAttributes(ldapName); - Map<String, String> attrMap = new HashMap<String, String>(); - // 获取用户属性导入 系统 - for (Entry<String, String> entry : defaultMapping.entrySet()) { - String key = entry.getKey(); - String attrKey = StrUtil.isNotBlank(configMapping.get(key)) ? configMapping.get(key) : entry.getValue(); - List<String> attrKeyList = StrUtil.splitTrim(attrKey, "|"); - for (String ak : attrKeyList) { - Object obj = attributes.get(ak) != null ? attributes.get(ak).get() : null; - if (obj != null) { - attrMap.put(key, obj.toString()); - break; - } + if(StrUtil.isNotEmpty(ldapOu)){ + List<String> baseList = StrUtil.splitTrim(ldapOu, "|"); + for (String base : baseList) { + LdapQuery query = LdapQueryBuilder.query().base(base).timeLimit(20000).countLimit(1000).filter(queryFilter); + try { + // 开始认证 + entity = ldapTemplate.authenticate(query, pin,new AuthenticatedLdapEntryContextMapper<SysUserEntity>() { + @Override + public SysUserEntity mapWithContext(DirContext ctx,LdapEntryIdentification ldapEntryIdentification) { + LdapName ldapName = ldapEntryIdentification.getAbsoluteName(); + Attributes attributes; + SysUserEntity user = null; + try { + attributes = ctx.getAttributes(ldapName); + Map<String, String> attrMap = new HashMap<String, String>(); + // 获取用户属性导入 系统 + for (Entry<String, String> entry : defaultMapping.entrySet()) { + String key = entry.getKey(); + String attrKey = StrUtil.isNotBlank(configMapping.get(key)) ? configMapping.get(key) : entry.getValue(); + List<String> attrKeyList = StrUtil.splitTrim(attrKey, "|"); + for (String ak : attrKeyList) { + Object obj = attributes.get(ak) != null ? attributes.get(ak).get() : null; + if (obj != null) { + attrMap.put(key, obj.toString()); + break; } } - // 赋值 sysuser - user = new SysUserEntity(); - BeanUtil.fillBeanWithMap(attrMap, user, true); - } catch (NamingException e) { - log.debug(e); } - LdapUtils.closeContext(ctx); - return user; + // 赋值 sysuser + user = new SysUserEntity(); + BeanUtil.fillBeanWithMap(attrMap, user, true); + } catch (NamingException e) { + log.debug(e); } - }); - } catch (RuntimeException e) { - log.warn(e,"ldap Authentication failed,base: {}",base); - } - if (entity != null) { - break; + LdapUtils.closeContext(ctx); + return user; + } + }); + } catch (RuntimeException e) { + log.warn(e,"ldap Authentication failed,base: {}",base); + } + if (entity != null) { + break; + } } } return entity; diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalClient.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalClient.java new file mode 100644 index 00000000..d46a3317 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalClient.java @@ -0,0 +1,518 @@ +/** + * Copyright (c) 2015 The Nezha Project + * <p> + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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 com.nis.modules.terminal.backend; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.jcraft.jsch.ChannelShell; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.nis.common.utils.JSONUtil; +import com.nis.common.utils.Tool; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.terminal.entity.TerminalCmd; +import com.nis.modules.terminal.entity.TerminalRecord; +import com.nis.modules.terminal.service.TerminalCmdService; +import com.nis.modules.terminal.service.TerminalRecordService; +import com.nis.modules.terminal.utils.TerminalConstant; +import lombok.Data; +import org.apache.commons.net.telnet.InvalidTelnetOptionException; +import org.apache.commons.net.telnet.TelnetClient; +import org.apache.commons.net.telnet.TelnetOption; +import org.apache.commons.net.telnet.WindowSizeOptionHandler; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.*; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Data +public class TerminalClient { + + private static final Log log = Log.get(); + + /** + * uuid token + */ + private String clientId; + + /** + * User Authorization Token + */ + private String token; + + private AssetAsset asset; + + /** + * conn object + */ + private Session session; + private ChannelShell shellChannel; + private TelnetClient telnetClient; + private WebSocketSession webSocketSession; + + /** + * stream + */ + private InputStream inputStream; + private OutputStream outputStream; + private BufferedWriter writer; + + public TerminalClient(WebSocketSession webSocketSession, AssetAsset asset, String clientId, String token) { + log.info("[TerminalClient] [init] [clientId: {}] [connection info: {}] [websocket uri: {}] [token: {}]", clientId, JSONUtil.toJsonStr(asset), webSocketSession.getUri(), token); + this.webSocketSession = webSocketSession; + this.asset = asset; + this.clientId = clientId; + this.token = token; + } + + /** + * Ssh Terminal + * + * @param jschSession + * @param cols + * @param rows + * @param width + * @param height + * @throws JSchException + * @throws IOException + */ + public void openSshTerminal(Session jschSession, final int cols, int rows, int width, int height) throws JSchException, IOException { + this.session = jschSession; + this.shellChannel = (ChannelShell) session.openChannel("shell"); + this.shellChannel.setPtyType("xterm", cols, rows, width, height); + this.inputStream = this.shellChannel.getInputStream(); + this.outputStream = this.shellChannel.getOutputStream(); + this.writer = new BufferedWriter(new OutputStreamWriter(this.outputStream, "UTF-8")); + this.shellChannel.connect(); + + // send login Success Prompt + String loginSuccessPromptStr = StrUtil.concat(true, + "\r\nConnecting to " + asset.getManageIp() + ":" + asset.getAuthProtocolPort() + "\r\n", + "Connection established. \r\n", + "Login success,use user " + asset.getAuthUsername() + " \r\n"); + webSocketSession.sendMessage(new TextMessage(loginSuccessPromptStr)); + + // run ssh terminal runable + Tool.ThreadUtil.execute( + new TerminalInteractionRunnable(this) + ); + } + + /** + * TELNET Terminal + * + * @param telnetClient + * @param width + * @param height + * @throws IOException + */ + public void openTelnetTerminal(TelnetClient telnetClient, Integer width, Integer height) throws IOException, InvalidTelnetOptionException { + this.telnetClient = telnetClient; + this.telnetClient.addOptionHandler(new WindowSizeOptionHandler(width, height, true, true, true, true)); + this.inputStream = this.telnetClient.getInputStream(); + this.outputStream = this.telnetClient.getOutputStream(); + this.writer = new BufferedWriter(new OutputStreamWriter(this.outputStream, "UTF-8")); + + // send login Success Prompt + String loginSuccessPromptStr = StrUtil.concat(true, + "\r\nConnecting to " + asset.getManageIp() + ":" + asset.getAuthProtocolPort() + "\r\n", + "Connection established. \r\n", + "Login success,use user " + asset.getAuthUsername() + " \r\n"); + webSocketSession.sendMessage(new TextMessage(loginSuccessPromptStr)); + + // run telnet terminal runable + Tool.ThreadUtil.execute( + new TerminalInteractionRunnable(this) + ); + } + + /** + * send Message To Monitor Terminal + * + * @param clientId + * @param message + */ + public void sendMessageToMonitorTerminal(String clientId, String message) { + try { + // monitor terminal session + List<WebSocketSession> webSocketSessions = TerminalSession.TERMINAL_MONITORS_MAPPING.get(clientId); + if (Tool.CollUtil.isNotEmpty(webSocketSessions)) { + List<String> webSocketSessionIdList = webSocketSessions.stream().map(WebSocketSession::getId).collect(Collectors.toList()); + log.info("send Message To Monitor Terminal. clientId: {}, monitor terminal info: {}", clientId, Tool.JSONUtil.toJsonStr(webSocketSessionIdList)); + for (WebSocketSession socketSession : webSocketSessions) { + socketSession.sendMessage(new TextMessage(message)); + } + } + } catch (IOException e) { + log.error(e, "send Message To Monitor Terminal error. clientId: {}, terminal_monitors_mapping: {}", clientId, Tool.JSONUtil.toJsonStr(TerminalSession.TERMINAL_MONITORS_MAPPING.get(clientId))); + } + } + + /** + * save Or Append Terminal Record Message + * + * @param tempFile + * @param message + * @throws IOException + */ + public void saveOrAppendTerminalRecordMessage(File tempFile, String message) { + // save Terminal Record Message + // record file is larger than the system config size,save db. + if (BooleanUtil.and( + tempFile.exists(), + tempFile.length() > TerminalConstant.RECORD_TEMPFILE_MAX_LENGTH)) { + try { + log.info("Save terminal record content. clientid: {}, file length: {}, File info: {}", clientId, tempFile.length(), tempFile.toString()); + TerminalRecordService terminalRecordService = (TerminalRecordService) TerminalSession.CLIENT_ATTRIBUTE_INFO.get("terminalRecordService"); + List<TerminalRecord> list = terminalRecordService.list(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, clientId).orderByAsc(TerminalRecord::getId)); + TerminalRecord terminalRecord = new TerminalRecord(); + terminalRecord.setUuid(clientId); + // first time, start time = 0 + if (Tool.CollUtil.isEmpty(list)) { + terminalRecord.setStartTime(0); + } else { + // start time == end of the last time + terminalRecord.setStartTime(list.get(list.size() - 1).getEndTime()); + } + long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); + terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); + terminalRecord.setContent(Files.readAllBytes(tempFile.toPath())); + terminalRecordService.saveTerminalRecordContent(terminalRecord); + } catch (Exception e) { + log.error(e, "Save terminal record content error. clientid: {}, file length: {}, File info: {}", clientId, tempFile.length(), tempFile.toString()); + } finally { + FileUtil.del(tempFile); + } + } + + // Append Terminal Record Message + try { + long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("t", (int) (System.currentTimeMillis() - terminalSessionStartTime)); + jsonObject.put("c", message); + String str = StrUtil.concat(true, JSONUtil.toJsonStr(jsonObject), ","); + FileUtil.writeBytes(str.getBytes(), tempFile, 0, str.getBytes().length, true); + } catch (Exception e) { + log.error(e, "failed to append terminal record file content. clientid: {}, File info: {}", clientId, tempFile != null && tempFile.exists() ? tempFile.toString() : "file does not exist"); + } + } + + /** + * 处理服务器方向键以及tab操作返回的指令信息 便于做日志记录 + * + * @param serverResponse 服务器响应内容 + */ + public void processCommand(String serverResponse) { + Map terminalAttributeInfo = TerminalSession.getTerminalAttributeInfo(clientId); + Integer cmdCharPos = (Integer) terminalAttributeInfo.get("cmdCharPos"); + + // cmd info + List<Character> list = Tool.CollUtil.defaultIfEmpty(TerminalSession.TERMINAL_CMD_INFO.get(clientId), Tool.ListUtil.list(true)); + + char[] charArray = serverResponse.toCharArray(); + + // 转义字符 + boolean esc_mode = false; + int esc_arg = 0; + + boolean maybeCmd = false; + if (charArray.length >= 2) { + // 0x0d 13 \r 0x0a 10 \n + maybeCmd = (charArray[0] == 13 && charArray[1] == 10); + } + + boolean client_single_char = false; + if (charArray.length == 1) { + int c = charArray[0]; + if (TerminalConstant.INVISIBLE_CHAR.contains(c)) { + client_single_char = true; + } + } + + int offset = 0; + int len = charArray.length; + for (; offset < charArray.length; ) { + char ch = charArray[offset]; + if (esc_mode) { + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + // 字符转数字 + esc_arg = esc_arg * 10 + (ch - '0'); + break; + } + case 63: + case ';': + case '>': { + TerminalSession.TERMINAL_CMD_INFO.put(clientId, Tool.ListUtil.list(true)); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); + return; + } + case 75: { // K + if (0 == esc_arg) { + list = list.subList(0, cmdCharPos); + cmdCharPos = list.size(); + } else if (1 == esc_arg) { + list = list.subList(cmdCharPos, list.size()); + cmdCharPos = list.size(); + } else if (2 == esc_arg) { + list = new ArrayList<>(); + cmdCharPos = 0; + } + TerminalSession.TERMINAL_CMD_INFO.put(clientId, list); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + esc_mode = false; + break; + } + case 67: { // ^[C + // 光标右移 + if (esc_arg == 0) { + esc_arg = 1; + } + + for (int j = 0; j < esc_arg; ++j) { + if (cmdCharPos != list.size()) { + cmdCharPos++; + } + } + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + esc_mode = false; + break; + } + case 68: { // ^[D + // 光标左移 + if (esc_arg == 0) { + esc_arg = 1; + } + for (int j = 0; j < esc_arg; ++j) { + if (cmdCharPos != 0) { + cmdCharPos--; + } + } + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + esc_mode = false; + break; + } + case 80: { // 'P' 删除指定数量的字符 + if (esc_arg == 0) { + esc_arg = 1; + } + + for (int j = 0; j < esc_arg; ++j) { + // 不是最后一个 + if (cmdCharPos != list.size()) { + int index = cmdCharPos; + list.remove(index); + } + } + TerminalSession.TERMINAL_CMD_INFO.put(clientId, list); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + esc_mode = false; + break; + } + case 64: { + if (esc_arg == 0) { + esc_arg = 1; + } + for (int j = 0; j < esc_arg; ++j) { + list.add(cmdCharPos, ' '); + cmdCharPos++; + } + TerminalSession.TERMINAL_CMD_INFO.put(clientId, list); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + esc_mode = false; + break; + } + default: + esc_mode = false; + break; + } + + offset++; + continue; + } + + switch (ch) { + case 7: + // 响铃 + break; + case 8: { + // 光标左移 + if (cmdCharPos != 0 && CollectionUtils.isNotEmpty(list)) { + cmdCharPos--; + TerminalSession.TERMINAL_CMD_INFO.put(clientId, list); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + } + break; + } + case 27: { // 0x1b esc + if (offset + 1 < len) { + if (charArray[offset + 1] == 91 || charArray[offset + 1] == 93) { + if (offset == 0 && client_single_char) { + TerminalSession.removeTerminalCmd(clientId); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); + maybeCmd = false; + client_single_char = false; + return; + } + } + + if (charArray[offset + 1] == 91 || charArray[offset + 1] == 93) { + esc_mode = true; + + esc_arg = 0; + offset += 1; + } + } + break; + } + // 0x0d 13 \r 0x0a 10 \n + case 13: { + if (offset + 1 < len && charArray[offset + 1] == 10) { + if (maybeCmd) { + if (Tool.CollUtil.isNotEmpty(list)) { + TerminalCmdService terminalCmdService = (TerminalCmdService) TerminalSession.CLIENT_ATTRIBUTE_INFO.get("terminalCmdService"); + TerminalCmd terminalCmd = new TerminalCmd(); + terminalCmd.setCmd(StrUtil.join(StrUtil.EMPTY, list)); + terminalCmd.setUuid(clientId); + long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); + terminalCmd.setTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); + terminalCmdService.save(terminalCmd); + } + TerminalSession.removeTerminalCmd(clientId); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); + maybeCmd = false; + } + } + TerminalSession.removeTerminalCmd(clientId); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); + return; + } + default: { + if (cmdCharPos != list.size()) { + int index = cmdCharPos; + list.remove(index); + list.add(cmdCharPos, ch); + cmdCharPos++; + } else { + list.add(ch); + cmdCharPos = list.size(); + } + TerminalSession.TERMINAL_CMD_INFO.put(clientId, list); + TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); + } + } + offset++; + } + } + + /** + * 向终端输入内容 + * + * @param message + * @throws IOException + */ + public void writeContentToTerminal(String message) { + // write + if (Tool.ObjectUtil.isNotNull(outputStream)) { + IoUtil.write(outputStream, false, message.getBytes()); + IoUtil.flush(outputStream); + } + } + + /** + * resize + * + * @param cols + * @param rows + * @param width + * @param height + */ + public void resize(Integer cols, Integer rows, Integer width, Integer height) { + log.info("terminal re window size. col: {}, rows: {}, width: {}, height: {}", cols, rows, width, height); + try { + if (this.shellChannel != null) { + this.shellChannel.setPtySize(cols, rows, width, height); + } + // RFC 1073 + if (this.telnetClient != null) { + this.telnetClient.deleteOptionHandler(TelnetOption.WINDOW_SIZE); + this.telnetClient.addOptionHandler(new WindowSizeOptionHandler(width, height, true, true, true, true)); + } + } catch (Exception e) { + log.error(e, "terminal re window size error. col: {}, rows: {}, width: {}, height: {}", cols, rows, width, height); + } + } + + /** + * disconnect + * + * @throws IOException + */ + public void disconnect() { + log.info("[disconnect] [begin] [client id: {}]", clientId); + + IoUtil.close(writer); + IoUtil.close(inputStream); + IoUtil.close(outputStream); + + if (shellChannel != null) { + shellChannel.disconnect(); + } + + if (session != null) { + session.disconnect(); + session = null; + // remove cache + TerminalSession.TERMINAL_CONNECTED_CACHE.remove(clientId); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.remove(clientId); + } + + if (webSocketSession != null) { + IoUtil.close(webSocketSession); + TerminalSession.remove(webSocketSession); + } + + log.info("[disconnect] [finshed] [client id: {}]", clientId); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java new file mode 100644 index 00000000..5d7ca0cb --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java @@ -0,0 +1,440 @@ +/** + * Copyright (c) 2015 The Nezha Project + * <p> + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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 com.nis.modules.terminal.backend; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.jcraft.jsch.Session; +import com.nis.common.utils.*; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.sys.entity.SysUserEntity; +import com.nis.modules.sys.service.SysConfService; +import com.nis.modules.sys.shiro.ShiroUtils; +import com.nis.modules.terminal.entity.TerminalCmd; +import com.nis.modules.terminal.entity.TerminalRecord; +import com.nis.modules.terminal.entity.TerminalSessionEntity; +import com.nis.modules.terminal.service.TerminalCmdService; +import com.nis.modules.terminal.service.TerminalRecordService; +import com.nis.modules.terminal.service.TerminalSessionService; +import com.nis.modules.terminal.utils.TerminalConstant; +import org.apache.commons.net.telnet.TelnetClient; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.File; +import java.nio.file.Files; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static com.nis.common.utils.CommonUtils.toInt; + +@Component +public class TerminalHandler extends TextWebSocketHandler { + + private static final Log log = Log.get(); + + /** + * nz login system token + */ + private String token; + + /** + * uuid token + * connection information key (get SSH | TELNET session) + */ + private String uuid; + + /** + * windows fields + */ + private Integer cols; + private Integer rows; + private Integer width; + private Integer height; + + private Long userId; + + private SysConfService sysConfService; + + private AssetAssetService assetAssetService; + + private TerminalCmdService terminalCmdService; + + private TerminalRecordService terminalRecordService; + + private TerminalSessionService terminalSessionService; + + /** + * init Field Val + * + * @param session + */ + private void initFieldVal(WebSocketSession session) { + this.uuid = (String) session.getAttributes().get("uuid"); + this.token = (String) session.getAttributes().get("terminalToken"); + + cols = toInt(session.getAttributes().get("cols").toString()); + rows = toInt(session.getAttributes().get("rows").toString()); + width = toInt(session.getAttributes().get("width").toString()); + height = toInt(session.getAttributes().get("height").toString()); + + // 创建登录服务器日志记录相关内容 + terminalSessionService = (TerminalSessionService) SpringContextUtils.getBean("terminalSessionService"); + terminalCmdService = (TerminalCmdService) SpringContextUtils.getBean("terminalCmdService"); + terminalRecordService = (TerminalRecordService) SpringContextUtils.getBean("terminalRecordService"); + assetAssetService = SpringContextUtils.getBean(AssetAssetService.class); + sysConfService = SpringContextUtils.getBean(SysConfService.class); + + TerminalSession.CLIENT_ATTRIBUTE_INFO.put("terminalSessionService", terminalSessionService); + TerminalSession.CLIENT_ATTRIBUTE_INFO.put("terminalCmdService", terminalCmdService); + TerminalSession.CLIENT_ATTRIBUTE_INFO.put("terminalRecordService", terminalRecordService); + TerminalSession.CLIENT_ATTRIBUTE_INFO.put("assetAssetService", assetAssetService); + TerminalSession.CLIENT_ATTRIBUTE_INFO.put("sysConfService", sysConfService); + } + + /** + * inti Terminal Client + * + * @param session + * @param asset + * @return + */ + private TerminalClient initTerminalClient(WebSocketSession session, AssetAsset asset, String token) { + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(session); + if (Tool.ObjectUtil.isNotNull(terminalClient)) { + return terminalClient; + } + + // init + terminalClient = new TerminalClient(session, asset, uuid, token); + TerminalSession.TERMINAL_SESSION.put(session, terminalClient); + return terminalClient; + } + + + @Override + public synchronized void afterConnectionEstablished(WebSocketSession session) throws Exception { + super.afterConnectionEstablished(session); + + // init Field Val + this.initFieldVal(session); + log.info("WebSocket connectioned. after connection established open terminal begin... uuid: {}", uuid); + + SysUserEntity userEntity = Tool.MapUtil.get(ShiroUtils.getShiroSessionInfoMap(), StrUtil.concat(true, ShiroUtils.REDIS_KEYPREFIX, token), SysUserEntity.class); + if (ObjectUtil.isNull(userEntity)) { + log.warn("open terminal error. system login token exception. uuid: {}, token: {}", uuid, token); + session.sendMessage(new TextMessage("Token error, Please log in to the system first")); + session.close(); + return; + } + // user id + userId = userEntity.getId(); + + // get connected obj + Map<Object, Object> connObjMap = TerminalSession.TERMINAL_CONNECTED_CACHE.get(uuid); + if (ObjectUtil.isNull(connObjMap)) { + log.warn("open terminal error. Connection information not found, expired or does not exist, please login again. uuid: {}", uuid); + session.sendMessage(new TextMessage("Connection information not found, expired or does not exist, please login again.")); + session.close(); + return; + } + + // terminal Connection Info + AssetAsset terminalConnInfo = (AssetAsset) connObjMap.get(TerminalSession.CONNECTION_ASSET_KEY); + + // terminal session + TerminalSessionEntity sessionEntity = new TerminalSessionEntity(); + sessionEntity.setUuid(uuid); + sessionEntity.setUserId(userId); + sessionEntity.setHost(terminalConnInfo.getManageIp()); + sessionEntity.setPort(terminalConnInfo.getAuthProtocolPort()); + sessionEntity.setAssetId(terminalConnInfo.getId()); + + TerminalConstant.ProtocolType protocolType = TerminalConstant.ProtocolType.getEntityByValue(terminalConnInfo.getAuthProtocol()); + sessionEntity.setProtocol(protocolType.toString()); + + TerminalConstant.SshAuthType sshAuthType = TerminalConstant.SshAuthType.getEntityByType(terminalConnInfo.getAuthType()); + sessionEntity.setAuthType(sshAuthType.getType()); + + sessionEntity.setLoginUser(terminalConnInfo.getAuthUsername()); + sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); + sessionEntity.setStartTime(new Date()); + sessionEntity.setStatus(TerminalConstant.SessionStatus.CONNECTING.getValue()); + + TerminalClient terminalClient = null; + try { + String token = (String) connObjMap.get(Constant.AUTH_TOKEN_CODE); + // init client + terminalClient = this.initTerminalClient(session, terminalConnInfo, token); + + // asset info + terminalClient.setAsset(terminalConnInfo); + + TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionEntity", sessionEntity); + TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionStartTime", System.currentTimeMillis()); + + // terminal cmd 信息 + TerminalCmd terminalCmd = new TerminalCmd(); + terminalCmd.setUuid(uuid); + terminalCmd.setTime(0); + terminalCmd.setCmd("Login"); + terminalCmdService.save(terminalCmd); + + Integer authProtocol = terminalConnInfo.getAuthProtocol(); + // SSH + if (TerminalConstant.ProtocolType.SSH.getValue().equals(authProtocol)) { + log.info("open ssh terminal,uuid: {},terminal Connection Info: {}", uuid, JSONUtil.toJsonStr(terminalConnInfo)); + Session jschSession = (Session) connObjMap.get(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY); + terminalClient.openSshTerminal(jschSession, cols, rows, width, height); + } + // TELNET + if (TerminalConstant.ProtocolType.TELNET.getValue().equals(authProtocol)) { + log.info("open telnet terminal,uuid: {},terminal Connection Info: {}", uuid, JSONUtil.toJsonStr(terminalConnInfo)); + TelnetClient telnetClient = (TelnetClient) connObjMap.get(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY); + terminalClient.openTelnetTerminal(telnetClient, width, height); + } + terminalSessionService.save(sessionEntity); + log.info("WebSocket connectioned. after connection established open terminal finished. uuid: {}", uuid); + } catch (Exception e) { + log.error(e, "WebSocket connectioned. after connection established open terminal error. uuid: {}", uuid); + // 连接异常,关闭session 记录,更改状态为 连接失败 + sessionEntity.setEndTime(new Date()); + sessionEntity.setLoginUser(StrUtil.emptyToDefault(terminalConnInfo.getAuthUsername(), StrUtil.EMPTY)); + sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); + sessionEntity.setEndTime(new Date()); + sessionEntity.setStatus(TerminalConstant.SessionStatus.CONNECTION_FAILED.getValue()); + terminalSessionService.save(sessionEntity); + + // disconnect + if (ObjectUtil.isNotNull(terminalClient)) { + terminalClient.disconnect(); + } + TerminalSession.remove(session); + } + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 每次请求获取对应的 uuid 信息 + Map<String, Object> attributes = session.getAttributes(); + String uuid = (String) attributes.get("uuid"); + super.handleTextMessage(session, message); + log.info("handleTextMessage meesage info : {}", message.getPayload()); + + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(session); + try { + if (terminalClient != null) { + // 保存当前输入字符信息 以便 client 端获取对应的操作字符 + terminalClient.writeContentToTerminal(message.getPayload()); + } + } catch (Exception e) { + // 出现异常将光标信息重置防止下一次无法正常执行命令 + log.error(e, "terminal handle Text Message error."); + + // cmd 信息保存 + TerminalCmd terminalCmd = new TerminalCmd(); + terminalCmd.setCmd("Terminal due to abnormal disconnection"); + terminalCmd.setUuid(uuid); + long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionStartTime"); + terminalCmd.setTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); + terminalCmdService.save(terminalCmd); + + // terminal sesssion 信息保存 + TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); + sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); + sessionEntity.setUuid(uuid); + sessionEntity.setUserId(userId); + sessionEntity.setStatus(TerminalConstant.SessionStatus.CONNECTION_FAILED.getValue()); + sessionEntity.setStartTime(new Date()); + sessionEntity.setEndTime(new Date()); + terminalSessionService.save(sessionEntity); + + TerminalSession.removeTerminalAttributeInfo(uuid); + session.sendMessage(new TextMessage(e.getMessage() + "\r\n")); + session.sendMessage(new TextMessage("Sorry! Nz Terminal was closed, please try again. \r\n")); + if (ToolUtil.isNotEmpty(terminalClient)) { + terminalClient.disconnect(); + } + TerminalSession.remove(session); + } + } + + @Override + public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { + log.error(exception, "WebSocket handle Transport Error"); + super.handleTransportError(session, exception); + TerminalHandler.closeTerminalRescourse(session); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + try { + log.info("[afterConnectionClosed] [WebSocket connection closed] [websocket uri: {}]", session.getUri()); + super.afterConnectionClosed(session, status); + + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(session); + log.info("[afterConnectionClosed] [Close terminal client connection] [clientId: {}]", ObjectUtil.isNull(terminalClient) ? null : terminalClient.getClientId()); + if (ObjectUtil.isNull(terminalClient)) { + log.warn("[afterConnectionClosed] [failed to get terminal client through websocket connection.] [websocket uri: {}]", session.getUri()); + return; + } + + // close terminal + TerminalHandler.closeTerminalRescourse(session); + + // client id + String clientId = terminalClient.getClientId(); + + // update Session Status After Client Closed + TerminalHandler.updateSessionStatusAfterClientClosed(clientId); + + // save Record Content After Client Closed + TerminalHandler.saveRecordContentAfterClientClosed(clientId); + + // remove Terminal Attribute Info + TerminalSession.removeTerminalAttributeInfo(clientId); + + // monitor terminal session + List<WebSocketSession> monitorWebSocketSessions = TerminalSession.TERMINAL_MONITORS_MAPPING.get(clientId); + if (Tool.CollUtil.isNotEmpty(monitorWebSocketSessions)) { + log.info("[afterConnectionClosed] [close monitor windows] [size: {}]", monitorWebSocketSessions.size()); + for (WebSocketSession socketSession : monitorWebSocketSessions) { + socketSession.sendMessage(new TextMessage("\u001B[01;31m\u001B[KConnection closed \u001B[m\u001B[K")); + } + TerminalSession.TERMINAL_MONITORS_MAPPING.remove(clientId); + } + log.info("[afterConnectionClosed] [close resource finshed.] [clientId: {}]", clientId); + } catch (Exception e) { + log.error(e, "[afterConnectionClosed] [error] [session: {}] [status: {}]", JSONUtil.toJsonStr(session), JSONUtil.toJsonStr(status)); + throw e; + } + } + + /** + * close Terminal + * + * @param session + */ + public static synchronized void closeTerminalRescourse(WebSocketSession session) { + log.info("[closeTerminalRescourse] [begin] [websocket uri: {}]", session.getUri()); + TerminalClient terminalClient = TerminalSession.remove(session); + log.info("[closeTerminalRescourse] [find terminal client] [exist: {}]", Tool.ObjectUtil.isNotNull(terminalClient)); + + if (Tool.ObjectUtil.isNotNull(terminalClient)) { + log.info("[closeTerminalRescourse] [terminal client exist. close rescourse] [client id: {}]", terminalClient.getClientId()); + + // disconnect + terminalClient.disconnect(); + + // remove cache + TerminalSession.TERMINAL_CONNECTED_CACHE.remove(terminalClient.getClientId()); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.remove(terminalClient.getClientId()); + } else { + log.warn("[closeTerminalRescourse] [terminal client not exist] [websocket uri: {}]", session.getUri()); + } + + log.info("[closeTerminalRescourse] [finshed] [websocket uri: {}]", session.getUri()); + } + + /** + * update Session Status After Client Closed + * + * @param clientId + */ + public static synchronized void updateSessionStatusAfterClientClosed(String clientId) { + log.info("[updateSessionStatusAfterClientClosed] [begin] [clientId: {}]", clientId); + TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionEntity"); + log.info("[updateSessionStatusAfterClientClosed] [update session entity] [clientId: {}] [exist: {}]", clientId, Tool.ObjectUtil.isNotNull(sessionEntity)); + + if (Tool.ObjectUtil.isNotNull(sessionEntity)) { + log.info("[updateSessionStatusAfterClientClosed] [udpate session status] [session id: {}] [status: {}]", sessionEntity.getUuid(), sessionEntity.getStatus()); + if (sessionEntity.getStartTime() == null) { + sessionEntity.setStartTime(new Date()); + } + + // 正常连接状态 关闭窗口,将状态改为 已结束,其他不做处理 + if (TerminalConstant.SessionStatus.CONNECTING.getValue() == sessionEntity.getStatus()) { + sessionEntity.setStatus(TerminalConstant.SessionStatus.OVER.getValue()); + } + + sessionEntity.setEndTime(new Date()); + TerminalSessionService terminalSessionService = (TerminalSessionService) TerminalSession.CLIENT_ATTRIBUTE_INFO.get("terminalSessionService"); + terminalSessionService.saveOrUpdate(sessionEntity); + } else { + log.warn("[updateSessionStatusAfterClientClosed] [not found TerminalSessionEntity through client id.] [clientId: {}]", clientId); + } + log.info("[updateSessionStatusAfterClientClosed] [finshed] [clientId: {}]", clientId); + } + + /** + * save Record Content After Client Closed + * + * @param uuid + */ + public static synchronized void saveRecordContentAfterClientClosed(String uuid) { + log.info("[saveRecordContentAfterClientClosed] [begin] [uuid: {}]", uuid); + File tempFile = Tool.FileUtil.file(Tool.StrUtil.concat(true, Constant.TEMP_PATH, File.separator, uuid, ".log")); + log.info("[saveRecordContentAfterClientClosed] [save ending file] [uuid: {}] [exist: {}]", uuid, Tool.FileUtil.exist(tempFile)); + + // exist + if (Tool.FileUtil.exist(tempFile)) { + try { + log.info("[saveRecordContentAfterClientClosed] [Terminal is closed. save Record content] [clientid: {}] [file length: {}] [File info: {}]", uuid, tempFile.length(), tempFile.toString()); + TerminalRecordService terminalRecordService = (TerminalRecordService) TerminalSession.CLIENT_ATTRIBUTE_INFO.get("terminalRecordService"); + // 将本次内容保存至数据库 + List<TerminalRecord> list = terminalRecordService.list(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, uuid).orderByAsc(TerminalRecord::getId)); + TerminalRecord terminalRecord = new TerminalRecord(); + terminalRecord.setUuid(uuid); + // first time, start time = 0 + if (Tool.CollUtil.isEmpty(list)) { + terminalRecord.setStartTime(0); + } else { + // start time == end of the last time + terminalRecord.setStartTime(list.get(list.size() - 1).getEndTime()); + } + long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionStartTime"); + terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); + terminalRecord.setContent(Files.readAllBytes(tempFile.toPath())); + terminalRecordService.saveTerminalRecordContent(terminalRecord); + } catch (Exception e) { + log.error(e, "[saveRecordContentAfterClientClosed] [Save terminal record content error] [clientid: {}] [file length: {}] [File info: {}]", uuid, tempFile.length(), tempFile.toString()); + } finally { + // del file + FileUtil.del(tempFile); + } + + // not exsit. + } else { + log.info("[saveRecordContentAfterClientClosed] [Terminal is closed. No save record file exsit] [clientId: {}]", uuid); + } + + log.info("[saveRecordContentAfterClientClosed] [finshed] [uuid: {}]", uuid); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalInteractionRunnable.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalInteractionRunnable.java new file mode 100644 index 00000000..ae41750c --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalInteractionRunnable.java @@ -0,0 +1,83 @@ +package com.nis.modules.terminal.backend; + +import cn.hutool.log.Log; +import com.nis.common.utils.Constant; +import com.nis.common.utils.DigestUtils; +import com.nis.common.utils.Tool; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.File; + +public class TerminalInteractionRunnable extends Thread { + + private static final Log log = Log.get(); + + private TerminalClient client; + + public TerminalInteractionRunnable(TerminalClient client) { + this.client = client; + } + + @Override + public void run() { + byte[] buffer = new byte[1024 * 4]; + String clientId = client.getClientId(); + WebSocketSession webSocketSession = client.getWebSocketSession(); + try { + while (webSocketSession != null && webSocketSession.isOpen()) { + int size = client.getInputStream().read(buffer); + // logout + if (size == Tool.StrUtil.INDEX_NOT_FOUND) { + log.warn("[TerminalInteractionRunnable] [no more data because the end of the stream has been reached] [clientid: {}]", clientId); + + // Try sending an exit prompt statement + if (webSocketSession.isOpen()) { + webSocketSession.sendMessage(new TextMessage("Connection closed \r\n")); + } + + // close terminal + TerminalHandler.closeTerminalRescourse(webSocketSession); + + // update Session Status After Client Closed + TerminalHandler.updateSessionStatusAfterClientClosed(clientId); + + // save Record Content After Client Closed + TerminalHandler.saveRecordContentAfterClientClosed(clientId); + + // remove Terminal Attribute Info + TerminalSession.removeTerminalAttributeInfo(clientId); + return; + } + // update last active time + // connected last active time + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(clientId, Tool.DateUtil.currentSeconds()); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + char chr = (char) (buffer[i] & 0xff); + sb.append(chr); + } + // 取到 linux 远程机器输出的信息发送给前端 + String message = sb.toString(); + message = Tool.StrUtil.str(message.getBytes(DigestUtils.getEncoding(message)), "UTF-8"); + + // send Message To Monitor Terminal + client.sendMessageToMonitorTerminal(clientId, message); + + // save Or Append Terminal Record Message + File tempFile = Tool.FileUtil.file(Tool.StrUtil.concat(true, Constant.TEMP_PATH, File.separator, clientId, ".log")); + client.saveOrAppendTerminalRecordMessage(tempFile, message); + + // 处理服务器方向键以及 tab 操作返回的指令信息 便于做日志记录 + client.processCommand(message); + + // send message to terminal + webSocketSession.sendMessage(new TextMessage(message)); + } + } catch (Exception e) { + log.error(e, "[TerminalInteractionRunnable] [Terminal error.]"); + TerminalSession.remove(webSocketSession); + } + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalMonitorHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java index 517a7af1..ed6f38b4 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalMonitorHandler.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java @@ -1,23 +1,17 @@ -package com.nis.modules.terminal.config; - +package com.nis.modules.terminal.backend; import cn.hutool.log.Log; -import com.nis.common.utils.SpringContextUtils; +import com.nis.common.utils.Tool; import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.shiro.ShiroUtils; import org.apache.commons.collections.CollectionUtils; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Component; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; -import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -25,7 +19,7 @@ import java.util.Map; @Component public class TerminalMonitorHandler extends TextWebSocketHandler { - private static final Log logger = Log.get(); + private static final Log log = Log.get(); @Override public synchronized void afterConnectionEstablished(WebSocketSession session) throws Exception { @@ -34,40 +28,33 @@ public class TerminalMonitorHandler extends TextWebSocketHandler { Map<String, Object> attributes = session.getAttributes(); String token = (String) attributes.get("terminalToken"); - RedisConnectionFactory factory = SpringContextUtils.getBean(RedisConnectionFactory.class); - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - redisTemplate.afterPropertiesSet(); - - ValueOperations ops = redisTemplate.opsForValue(); - Object obj = ops.get(ShiroUtils.REDIS_KEYPREFIX + token); - if (obj == null) { + Map<String, SysUserEntity> shiroSessionInfoMap = ShiroUtils.getShiroSessionInfoMap(); + SysUserEntity user = shiroSessionInfoMap.get(Tool.StrUtil.concat(true, ShiroUtils.REDIS_KEYPREFIX, token)); + if (user == null) { session.sendMessage(new TextMessage("Token error,Please log in to the system first")); session.close(); - logger.error("terminal error user token Incorrect token info is : {}", token); + log.warn("terminal error user token Incorrect token info is : {}", token); return; } String uuid = (String) attributes.get("uuid"); WebSocketSession webSocketSession = TerminalSession.findSession(uuid); - TerminalClient terminalClient = TerminalSession.terminalSession.get(webSocketSession); + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(webSocketSession); if (terminalClient == null) { session.sendMessage(new TextMessage("Connection closed \r\n")); session.close(); - logger.error("被监控的 terminal 连接已经关闭 sessionId : {}", uuid); + log.warn("The monitored terminal connection has been closed. sessionId : {}", uuid); return; } - List<WebSocketSession> webSocketSessions = TerminalSession.terminalMonitorsMap.get(uuid); - webSocketSessions = (CollectionUtils.isEmpty(webSocketSessions)) ? new ArrayList<>() : webSocketSessions; + List<WebSocketSession> webSocketSessions = TerminalSession.TERMINAL_MONITORS_MAPPING.get(uuid); + webSocketSessions = Tool.CollUtil.defaultIfEmpty(webSocketSessions, Tool.ListUtil.list(true)); webSocketSessions.add(session); - TerminalSession.terminalMonitorsMap.put(uuid, webSocketSessions); + TerminalSession.TERMINAL_MONITORS_MAPPING.put(uuid, webSocketSessions); // 打开 monitor 返回的第一条消息 - AssetAsset terminal = terminalClient.getTerminal(); - String firstMessage = String.format("Connection established, Start monitoring. %s@%s \r\n", terminal.getAuthUsername(), terminal.getManageIp()); + AssetAsset asset = terminalClient.getAsset(); + String firstMessage = String.format("Connection established, Start monitoring. %s@%s \r\n", asset.getAuthUsername(), asset.getManageIp()); session.sendMessage(new TextMessage(firstMessage)); } @@ -75,7 +62,7 @@ public class TerminalMonitorHandler extends TextWebSocketHandler { public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { super.afterConnectionClosed(session, status); - for (Map.Entry<String, List<WebSocketSession>> entry : TerminalSession.terminalMonitorsMap.entrySet()) { + for (Map.Entry<String, List<WebSocketSession>> entry : TerminalSession.TERMINAL_MONITORS_MAPPING.entrySet()) { List<WebSocketSession> value = entry.getValue(); if (CollectionUtils.isEmpty(value)) { continue; diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalSession.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalSession.java new file mode 100644 index 00000000..779e3358 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalSession.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2015 The Nezha Project + * <p> + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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 com.nis.modules.terminal.backend; + +import cn.hutool.core.util.StrUtil; +import com.nis.common.utils.Tool; +import org.springframework.util.ObjectUtils; +import org.springframework.web.socket.WebSocketSession; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +public class TerminalSession implements Serializable { + + /** + * 连接建立后,记录 connectionAsset、sftp、connectionEntity(jsch.session | telnet client) + */ + public static final String CONNECTION_ASSET_KEY = "connectionAsset"; + public static final String CONNECTION_CONNECTION_ENTITY_KEY = "connectionEntity"; + + /** + * terminal login cache + * key = uuid + * value = { + * connectionAsset: 连接实体信息 + * connectionEntity: SSH SESSION | TELNET CLIENT + * } + */ + public static final Map<String, Map<Object, Object>> TERMINAL_CONNECTED_CACHE = Tool.MapUtil.newHashMap(); + + /** + * terminal connnection last active time map + * key = uuid + * value = last active timestamp + * 记录连接最后数据交互的时间,用以判断是否长期未实际使用,关闭连接 + * 窗口数据交互 & sftp 命令执行 都需要记录 + */ + public static final Map<String, Long> TERMINAL_CONNECTED_LAST_ACTIVE_MAP = Tool.MapUtil.newHashMap(); + + /** + * 当前websockt连接信息对应的服务器信息 将来可以实现远程连接列表 用以进行主动断开服务器连接功能 + */ + public static final Map<WebSocketSession, TerminalClient> TERMINAL_SESSION = Tool.MapUtil.newHashMap(); + + /** + * client terminal monitor list mapping + */ + public static final Map<String, List<WebSocketSession>> TERMINAL_MONITORS_MAPPING = Tool.MapUtil.newConcurrentHashMap(); + + /** + * terminal service, Include terminal session & record & cmd 。。。 mybatis service object + */ + public static final Map<String, Object> CLIENT_ATTRIBUTE_INFO = Tool.MapUtil.newHashMap(); + + /** + * 保存用户连接当前websocket的一些配置信息 包括光标位置、未登录时的一些状态信息 + * 每个连接功能会公用一个terminalHandler类 将各自属性根据uuid以及相应的状态信息进行保存 + */ + public static final Map<String, Map> TERMINAL_ATTRIBUTE_INFO = Tool.MapUtil.newHashMap(); + + /** + * terminal cmd info + */ + public static final Map<String, List<Character>> TERMINAL_CMD_INFO = Tool.MapUtil.newHashMap(); + + /** + * remove Terminal Cmd + * + * @param uuid + */ + public static void removeTerminalCmd(String uuid) { + TERMINAL_CMD_INFO.remove(uuid); + } + + + /** + * set Terminal Attribute Info + * + * @param uuid + * @param key + * @param value + */ + public static void setTerminalAttributeInfo(String uuid, String key, Object value) { + Map map = TERMINAL_ATTRIBUTE_INFO.get(uuid); + if (Tool.MapUtil.isEmpty(map)) { + // init Attribute map + map = getTerminalAttributeInfo(uuid); + } + // put new key + map.put(key, value); + TERMINAL_ATTRIBUTE_INFO.put(uuid, map); + } + + /** + * 终端快捷键标识 + * + * @param uuid + * @return + */ + public static Map getTerminalAttributeInfo(String uuid) { + Map map = TERMINAL_ATTRIBUTE_INFO.get(uuid); + if (ObjectUtils.isEmpty(map)) { + // 第一次获取基础配置的时候 初始化配置信息 + map = Tool.MapUtil.newHashMap(); + // 指令光标位置信息 + map.put("cursorIndex", 0); + // 光标是否移动标识 + map.put("cursorFlag", false); + // 历史记录位置信息 + map.put("historyIndex", 0); + // ssh连接登录标识 + map.put("sshLogin", false); + // tab键标识 + map.put("tabFlag", false); + + // 光标位置 + map.put("cmdCharPos", 0); + TERMINAL_ATTRIBUTE_INFO.put(uuid, map); + } + return map; + } + + public static void removeTerminalAttributeInfo(String uuid) { + TERMINAL_ATTRIBUTE_INFO.remove(uuid); + } + + public static TerminalClient remove(WebSocketSession key) { + return TERMINAL_SESSION.remove(key); + } + + + /** + * 通过 uuid 得到 webSocketSession 对象 + * + * @param uuid + * @return + */ + public static WebSocketSession findSession(String uuid) { + Map.Entry<WebSocketSession, TerminalClient> mapEntry = TERMINAL_SESSION.entrySet().stream() + .filter(Objects::nonNull) + .filter(entry -> Tool.ObjectUtil.isNotNull(entry.getValue()) && StrUtil.equalsIgnoreCase(entry.getValue().getClientId(), uuid)) + .findFirst() + .orElse(null); + + return Tool.ObjectUtil.isNotNull(mapEntry) ? mapEntry.getKey() : null; + } + + /** + * get all session client (onLine) by token + * + * @param token + * @return + */ + public static List<TerminalClient> getAllTerminalClient(String token) { + List<TerminalClient> terminalClients = TERMINAL_SESSION.values().stream() + .filter(client -> StrUtil.equals(client.getClientId(), token)) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + return terminalClients; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/Constants.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/Constants.java deleted file mode 100644 index b06da666..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/Constants.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.nis.modules.terminal.config; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -public class Constants { - public static final String PARAM_HTTP_SESSION_ID_KEY = "http_session_id"; - public static final String CHARSET_UTF8 = "UTF-8"; - public static final String NZ_USER_HOME = System.getProperty("user.home") + File.separator + ".nezha"; - public static final String PARAM_TERMINAL_PREFIX_KEY = "nezha_term_"; - - // 不可见字符 - public static final List<Integer> INVISIBLE_CHAR; - - static { - INVISIBLE_CHAR = new ArrayList<>(); - INVISIBLE_CHAR.add(7); - INVISIBLE_CHAR.add(8); - INVISIBLE_CHAR.add(12); - INVISIBLE_CHAR.add(10); - INVISIBLE_CHAR.add(13); - INVISIBLE_CHAR.add(9); - INVISIBLE_CHAR.add(11); - INVISIBLE_CHAR.add(92); - INVISIBLE_CHAR.add(63); - INVISIBLE_CHAR.add(39); - INVISIBLE_CHAR.add(34); - INVISIBLE_CHAR.add(0); - } - - public enum SshType { - ACCOUNT(1, "password"), - SSHKEY(2, "key"); - - private Integer type; - private String value; - - SshType(Integer type, String value) { - this.type = type; - this.value = value; - } - - - public Integer getType() { - return type; - } - - public void setType(Integer type) { - this.type = type; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } - - - public enum SessionStatus { - - /** - * 连接中 - */ - CONNECTING(0), - - /** - * 连接失败 - */ - CONNECTION_FAILED(1), - - /** - * 已结束 - */ - OVER(2), - - /** - * 强制退出 - */ - FORCE_QUIT(3), - - /** - * 未知错误 - */ - UNKNOWN_ERROR(4); - - - private int value; - - SessionStatus(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - // 单位为 byte , 10485760 byte = 10Mb - public static final Integer RECORD_TEMPFILE_MAX_LENGTH = 10485760; -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/SFTPConnectionPool.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/SFTPConnectionPool.java new file mode 100644 index 00000000..3c1bf3b7 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/config/SFTPConnectionPool.java @@ -0,0 +1,205 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * 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 com.nis.modules.terminal.config; + +import cn.hutool.log.Log; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.nis.common.utils.Tool; +import lombok.Data; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/** + * Concurrent/Multiple Connections. + * SFTPConnectionPool + */ +@Data +public class SFTPConnectionPool { + + private static final Log log = Log.get(); + + /** + * Maximum number of allowed live connections. This doesn't mean we cannot + * have more live connections. It means that when we have more + * live connections than this threshold, any unused connection will be + * closed. + */ + private Session session; + private Integer maxConnection; + private Integer liveConnectionCount = 0; + private HashMap<String, HashSet<ChannelSftp>> idleConnections = Tool.MapUtil.newHashMap(); + private HashMap<ChannelSftp, String> con2infoMap = Tool.MapUtil.newHashMap(); + + public SFTPConnectionPool(Session session, int maxConnection) { + this.session = session; + this.maxConnection = maxConnection; + } + + /** + * getIdleChannel + * + * @param uuid + * @return + * @throws IOException + */ + public ChannelSftp getIdleChannel(String uuid) throws IOException { + try { + ChannelSftp channel = getChannelFromPool(uuid); + if (channel != null) { + return channel; + } + + channel = (ChannelSftp) session.openChannel("sftp"); + channel.connect(); + synchronized (this) { + con2infoMap.put(channel, uuid); + liveConnectionCount++; + } + return channel; + } catch (JSchException e) { + throw new IOException(stringifyException(e)); + } + } + + private ChannelSftp getChannelFromPool(String uuid) throws IOException { + // get connection from pool + ChannelSftp channel = getFromPool(uuid); + + if (channel != null) { + if (channel.isConnected()) { + return channel; + } else { + channel = null; + synchronized (this) { + --liveConnectionCount; + con2infoMap.remove(channel); + } + } + } + return null; + } + + synchronized ChannelSftp getFromPool(String uuid) throws IOException { + Set<ChannelSftp> cons = idleConnections.get(uuid); + ChannelSftp channel; + if (cons != null && cons.size() > 0) { + Iterator<ChannelSftp> it = cons.iterator(); + if (it.hasNext()) { + channel = it.next(); + idleConnections.remove(uuid); + return channel; + } else { + throw new IOException("Connection pool error."); + } + } + return null; + } + + /** + * Add the channel into pool. + * + * @param channel + */ + synchronized void returnToPool(ChannelSftp channel) { + String uuid = con2infoMap.get(channel); + HashSet<ChannelSftp> cons = idleConnections.get(uuid); + if (cons == null) { + cons = new HashSet<ChannelSftp>(); + } + cons.add(channel); + idleConnections.put(uuid, cons); + } + + /** + * Shutdown the connection pool and close all open connections. + */ + synchronized void shutdown() { + if (this.con2infoMap == null) { + return; // already shutdown in case it is called + } + log.info("Inside shutdown, con2infoMap size=" + con2infoMap.size()); + + this.maxConnection = 0; + Set<ChannelSftp> cons = con2infoMap.keySet(); + if (cons != null && cons.size() > 0) { + // make a copy since we need to modify the underlying Map + Set<ChannelSftp> copy = new HashSet<ChannelSftp>(cons); + // Initiate disconnect from all outstanding connections + for (ChannelSftp con : copy) { + try { + disconnect(con); + } catch (IOException ioe) { + String uuid = con2infoMap.get(con); + log.error(ioe, "Error encountered while closing connection to " + uuid); + } + } + } + // make sure no further connections can be returned. + this.idleConnections = null; + this.con2infoMap = null; + } + + public void disconnect(ChannelSftp channel) throws IOException { + if (channel != null) { + // close connection if too many active connections + boolean closeConnection = false; + synchronized (this) { + if (liveConnectionCount > maxConnection) { + --liveConnectionCount; + con2infoMap.remove(channel); + closeConnection = true; + } + } + if (closeConnection) { + if (channel.isConnected()) { + try { + Session session = channel.getSession(); + channel.disconnect(); + session.disconnect(); + } catch (JSchException e) { + throw new IOException(stringifyException(e)); + } + } + } else { + returnToPool(channel); + } + } + } + + /** + * stringifyException + * + * @param e + * @return + */ + public static String stringifyException(Throwable e) { + StringWriter stm = new StringWriter(); + PrintWriter wrt = new PrintWriter(stm); + e.printStackTrace(wrt); + wrt.close(); + return stm.toString(); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/SftpMonitor.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/SftpMonitor.java deleted file mode 100644 index 2d5ef795..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/SftpMonitor.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - -import cn.hutool.log.Log; -import com.jcraft.jsch.SftpProgressMonitor; - -import java.text.DecimalFormat; -import java.util.Timer; -import java.util.TimerTask; - - -public class SftpMonitor extends TimerTask implements SftpProgressMonitor { - - private static Log logger = Log.get(); - - private long progressInterval = 2000; // 间隔时间 - - private boolean isEnd = false; // 记录传输是否结束 - - private long transfered; // 记录已传输的数据总大小 - - private long fileSize; // 记录文件总大小 - - private Timer timer; // 定时器对象 - - private boolean isScheduled = false; // 记录是否已启动timer记时器 - - public SftpMonitor(long fileSize) { - this.fileSize = fileSize; - } - - @Override - public void run() { - if (!isEnd()) { // 判断传输是否已结束 - long transfered = getTransfered(); - if (transfered != fileSize) { // 判断当前已传输数据大小是否等于文件总大小 - sendProgressMessage(transfered); - } else { - if (logger.isInfoEnabled()) { - logger.info(" Sftp file transfering is done."); - } - setEnd(true); // 如果当前已传输数据大小等于文件总大小,说明已完成,设置end - } - } else { - if (logger.isInfoEnabled()) { - logger.info("Sftp file transfering is done.cancel timer"); - } - stop(); // 如果传输结束,停止timer记时器 - return; - } - } - - public void stop() { - if (logger.isInfoEnabled()) { - logger.info("Sftp progress monitor Stopping..."); - } - if (timer != null) { - timer.cancel(); - timer.purge(); - timer = null; - isScheduled = false; - } - if (logger.isInfoEnabled()) { - logger.info("Sftp progress monitor Stoped."); - } - } - - public void start() { - if (logger.isInfoEnabled()) { - logger.info("Sftp progress monitor Starting..."); - } - if (timer == null) { - timer = new Timer(); - } - timer.schedule(this, 1000, progressInterval); - isScheduled = true; - } - - private void sendProgressMessage(long transfered) { - if (fileSize != 0) { - double d = ((double) transfered * 100) / (double) fileSize; - DecimalFormat df = new DecimalFormat("#.##"); - if (logger.isInfoEnabled()) { - logger.info("Sftp Sending progress message: {} %", df.format(d)); - } - } else { - if (logger.isInfoEnabled()) { - logger.info("Sftp Sending progress message: ", transfered); - } - } - } - - public boolean count(long count) { - if (isEnd()) return false; - if (!isScheduled) { - start(); - } - add(count); - return true; - } - - public void end() { - setEnd(true); - } - - private synchronized void add(long count) { - transfered = transfered + count; - } - - private synchronized long getTransfered() { - return transfered; - } - - - private synchronized void setEnd(boolean isEnd) { - this.isEnd = isEnd; - } - - private synchronized boolean isEnd() { - return isEnd; - } - - public void init(int op, String src, String dest, long max) { - } -}
\ No newline at end of file diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalClient.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalClient.java deleted file mode 100644 index 94ca9e08..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalClient.java +++ /dev/null @@ -1,1036 +0,0 @@ - -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.google.common.primitives.Bytes; -import com.jcraft.jsch.*; -import com.nis.common.utils.CommonUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.DigestUtils; -import com.nis.common.utils.StringUtils; -import com.nis.common.utils.Tool; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.sys.entity.SysConfigEntity; -import com.nis.modules.sys.service.SysConfService; -import com.nis.modules.terminal.entity.TerminalCmd; -import com.nis.modules.terminal.entity.TerminalRecord; -import com.nis.modules.terminal.entity.TerminalSessionEntity; -import com.nis.modules.terminal.service.TerminalCmdService; -import com.nis.modules.terminal.service.TerminalRecordService; -import com.nis.modules.terminal.service.TerminalSessionService; -import org.apache.commons.io.IOUtils; -import org.apache.commons.net.telnet.TelnetClient; -import org.springframework.http.HttpHeaders; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; - -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.net.URLEncoder; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static com.nis.common.utils.CommonUtils.notEmpty; - -public class TerminalClient { - private static final Log logger = Log.get(); - private static final ExecutorService executorService = Executors.newCachedThreadPool(); - private String clientId;//每次生成的唯一值token - private String httpSessionId;//打开该终端的SessionId - private WebSocketSession webSocketSession; - private JSch jSch; - private ChannelShell channelShell; - private Session session; - private AssetAsset terminal; - private InputStream inputStream; - private OutputStream outputStream; - private BufferedWriter writer; - - //获取路径相关变量 - private String pwd; - private boolean sendTempCmd = false; - private String sendTempCmdId; - - //控制命令(exit)终端退出相关变量 - private boolean sendEnter; - private boolean receiveEnd = false; - private StringBuffer sendBuffer = new StringBuffer(); - - //连接时长相关变量 - public static final int SERVER_ALIVE_INTERVAL = 60 * 1000; - public static final int SESSION_TIMEOUT = 60000; - public static final int CHANNEL_TIMEOUT = 60000; - - private boolean closed = false; - // 是否可进行上传下载操作 - private boolean transfer =true; - // telnet连接次数 - private Integer telnetConnectCount=0; - // 标识telnet连接状态 true是正在尝试连接 false为连接成功或失败 - private boolean telnetConnect=false; - private boolean telnetUser=false; - private StringBuilder sb=new StringBuilder(); - public TerminalClient(WebSocketSession webSocketSession, AssetAsset terminal, String clientId) { - this.webSocketSession = webSocketSession; - this.terminal = terminal; - this.clientId = clientId; - - //解决分布式环境下,不同的server为用户打开的终端实例会话不一致问题,导致根据会话Id查找不到另一个server打开的终端实例的问题 - List<String> userAgents = webSocketSession.getHandshakeHeaders().get(HttpHeaders.USER_AGENT); - if (CommonUtils.notEmpty(userAgents)) { - String userAgent = StringUtils.joinString(userAgents); - userAgent = userAgent.replaceAll("\\s+", ""); - this.httpSessionId = DigestUtils.md5Hex(userAgent); - } else { - this.httpSessionId = (String) webSocketSession.getAttributes().get(Constants.PARAM_HTTP_SESSION_ID_KEY); - } - this.sendTempCmdId = Tool.StrUtil.concat(true, this.clientId,this.httpSessionId); - this.jSch = new JSch(); - } - - public void openTerminal(final int cols, int rows, int width, int height) throws JSchException, IOException { - this.session = jSch.getSession(terminal.getAuthUsername(), terminal.getManageIp(), terminal.getAuthProtocolPort()); - - Integer sshType = terminal.getAuthType(); - switch (sshType) { - case 2 : {// key - String keyPassword = terminal.getAuthPin(); - String privateKey = terminal.getAuthPriKey(); - if (notEmpty(privateKey)) { - File keyFile = FileUtil.file(terminal.getPrivateKeyPath()); -// if (!keyFile.exists()) { - //将数据库中的私钥写到用户的机器上 - FileUtil.writeFromStream(new ByteArrayInputStream(privateKey.getBytes()),keyFile); -// } - if (notEmpty(keyPassword)) { - //设置带口令的密钥 - jSch.addIdentity(terminal.getPrivateKeyPath(), StringUtils.str(Base64.getDecoder().decode(keyPassword))); - } else { - //设置不带口令的密钥 - jSch.addIdentity(terminal.getPrivateKeyPath()); - } - UserInfo userInfo = new SshUserInfo(); - session.setUserInfo(userInfo); - } - session.setConfig("StrictHostKeyChecking", "no"); - break; - } - case 1: {// pin - session.setConfig("StrictHostKeyChecking", "no"); - session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password"); - session.setPassword(StringUtils.str(Base64.getDecoder().decode(terminal.getAuthPin()))); - break; - } - default: { - } - } - this.session.setServerAliveInterval(SERVER_ALIVE_INTERVAL); - this.session.connect(SESSION_TIMEOUT); - this.channelShell = (ChannelShell) session.openChannel("shell"); - this.channelShell.setPtyType("xterm", cols, rows, width, height); - this.inputStream = this.channelShell.getInputStream(); - this.outputStream = this.channelShell.getOutputStream(); - this.writer = new BufferedWriter(new OutputStreamWriter(this.outputStream, "UTF-8")); - this.channelShell.connect(); - - StringBuilder sb = new StringBuilder(); - sb.append("\r\nConnecting to " + terminal.getManageIp() + ":" + terminal.getAuthProtocolPort() + "\r\n"); - sb.append("Connection established. \r\n"); - sb.append("Login success,use user " + terminal.getAuthUsername() + " \r\n"); - webSocketSession.sendMessage(new TextMessage(sb.toString())); - - - executorService.execute((new Runnable() { - @Override - public void run() { - TerminalCmdService terminalCmdService = (TerminalCmdService) TerminalSession.clientAttributeInfo.get("terminalCmdService"); - TerminalRecordService terminalRecordService = (TerminalRecordService) TerminalSession.clientAttributeInfo.get("terminalRecordService"); - byte[] buffer = new byte[1024 * 4]; - StringBuilder builder = new StringBuilder(); - try { - while (webSocketSession != null && webSocketSession.isOpen()) { - builder.setLength(0); - int size = inputStream.read(buffer); - if (size == -1) { - return; - } - for (int i = 0; i < size; i++) { - char chr = (char) (buffer[i] & 0xff); - builder.append(chr); - } - //取到linux远程机器输出的信息发送给前端 - String message = builder.toString(); - - logger.info(message); - - // terminal record 信息梳理 - File file = FileUtil.file(Constant.TEMP_PATH, clientId + ".log"); - Path path = file.toPath(); - - message = StrUtil.str(message.getBytes(DigestUtils.getEncoding(message)),"UTF-8"); - - List<WebSocketSession> webSocketSessions = TerminalSession.terminalMonitorsMap.get(clientId); - if(CollectionUtils.isNotEmpty(webSocketSessions)){ - for (WebSocketSession socketSession : webSocketSessions) { - socketSession.sendMessage(new TextMessage(message)); - } - } - - TerminalClient.handleTerminalRecordMessage(file, path, terminalRecordService, clientId, message); - - processCommand(terminalCmdService, message); - //获取pwd的结果输出,不能发送给前台 - if (sendTempCmd) { - if (message.contains(sendTempCmdId)) { - if (pwd != null || message.contains("echo")) { - continue; - } - pwd = message.replace(sendTempCmdId, "").replaceAll("\r\n.*", "") + "/"; - if (logger.isInfoEnabled()) { - logger.info(" Sftp upload file target path:{}", pwd); - } - } - } else { - if((message.replaceAll("\r\n", "")).equals("logout")) { - // 已结束连接 - String unloginInfo = getUnloginInfo(Constants.SessionStatus.OVER.getValue()); - webSocketSession.sendMessage(new TextMessage(unloginInfo)); - - try { - // 将结束信息保存入库 - TerminalRecord terminalRecord = new TerminalRecord(); - terminalRecord.setUuid(clientId); - terminalRecord.setContent(Files.readAllBytes(path)); - TerminalRecord lastRecord = terminalRecordService.getOne(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, clientId).orderByDesc(TerminalRecord::getId).last("limit 0,1")); - // 之前没有文件记录 - if(lastRecord == null){ - terminalRecord.setStartTime(0); - }else{ - terminalRecord.setStartTime(lastRecord.getEndTime()); - } - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); - terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalRecordService.save(terminalRecord); - - boolean delete = file.delete(); - if(delete) { - logger.debug("文件删除成功"); - }else { - logger.debug("文件删除失败"); - } - } catch (IOException e) { - logger.error(String.format("SSH 连接已关闭,terminal record 结尾临时文件入库失,文件路径是: %s,错误信息是: %s", path.toString(), e.getMessage()), e); - } - }else { - webSocketSession.sendMessage(new TextMessage(message)); - } - if (sendEnter) { - String trimMessage = message.replaceAll("\r\n", ""); - if (CommonUtils.isEmpty(trimMessage)) { - receiveEnd = false; - } else { - if (sendBuffer.toString().equals("exit") && trimMessage.equals("logout")) { - channelShell.disconnect(); - webSocketSession.close(); - TerminalSession.remove(webSocketSession); - closed = true; - } - receiveEnd = true; - } - if (receiveEnd) { - sendBuffer.setLength(0); - } - } - } - } - } catch (UnsupportedEncodingException e) { - logger.error("TerminalClient error info :",e); - TerminalSession.remove(webSocketSession); - } catch (IOException e) { - logger.error("TerminalClient error info :",e); - TerminalSession.remove(webSocketSession); - } - - } - })); - - } - - /** - * terminal record 信息入库 - * - * @param file - * @param path - * @param terminalRecordService - * @param clientId - * @param message - */ - public static void handleTerminalRecordMessage(File file, Path path, TerminalRecordService terminalRecordService, String clientId, String message) { - // 文件大于 定义临时文件大小, - if (file.exists() && file.length() > Constants.RECORD_TEMPFILE_MAX_LENGTH) { - logger.info("临时文件大于定义大小,保存 record 文件入库,文件路径 是:" + path.toString()); - // 将本次内容保存至数据库 - try { - List<TerminalRecord> list = terminalRecordService.list(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, clientId).orderByAsc(TerminalRecord::getId)); - TerminalRecord terminalRecord = new TerminalRecord(); - terminalRecord.setUuid(clientId); - // 如果是第一次保存到库的话 , start time 为 0 - if (CollectionUtils.isEmpty(list)) { - terminalRecord.setStartTime(0); - } else { - // 其他的开始时间为上一次的结束时间 - terminalRecord.setStartTime(list.get(list.size() - 1).getEndTime()); - } - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); - terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalRecord.setContent(Files.readAllBytes(path)); - terminalRecordService.save(terminalRecord); - // 清空文件内容 - boolean delete = file.delete(); - if(delete) { - logger.debug("文件删除成功"); - }else { - logger.debug("文件删除失败"); - } - } catch (IOException e) { - logger.error(String.format("terminal record 文件入库失败,文件路径是: %s,错误信息是: %s", path.toString(), e.getMessage()), e); - } - } - // 以追加的方式追加服务器返回内容 - try { - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); - Map<String, Object> map = new HashMap(4); - map.put("t",(int) (System.currentTimeMillis() - terminalSessionStartTime)); - map.put("c",message); - String s = JSONObject.toJSONString(map); - s += ","; - FileUtil.writeBytes(s.getBytes(), file, 0, s.getBytes().length, true); - } catch (IORuntimeException e) { - logger.error(String.format("追加 terminal record 文件失败,文件路径是: %s,错误信息是: %s", path.toString(), e.getMessage()), e); - } - } - - public void openTelnetTerminal(final int cols, int rows, int width, int height) throws IOException { - TelnetClient telnet = new TelnetClient("VT100");// VT100 VT52 VT220 VTNT ANSI - telnet.connect(terminal.getManageIp(), terminal.getAuthProtocolPort()); - // telnet 不允许上传下载操作 - this.transfer=false; - this.inputStream=telnet.getInputStream(); - this.outputStream=telnet.getOutputStream(); - this.writer = new BufferedWriter(new OutputStreamWriter(this.outputStream, "UTF-8")); - //当前正在进行telnet连接 相关日志不记录 - this.telnetConnect=true; - - String pin = StringUtils.str(Base64.getDecoder().decode(terminal.getAuthPin())); - SysConfService sysConfService = (SysConfService) TerminalSession.clientAttributeInfo.get("sysConfService"); - List<SysConfigEntity> configEntities = sysConfService.list(new LambdaQueryWrapper<SysConfigEntity>().in(SysConfigEntity::getParamKey, "terminal_telnet_user_tip", "terminal_telnet_pin_tip")); - - String authUserTip = this.getTelenetLoginTip(terminal.getAuthUserTip(), configEntities, "terminal_telnet_user_tip"); - String authPinTip = this.getTelenetLoginTip(terminal.getAuthPinTip(), configEntities, "terminal_telnet_pin_tip"); - - logger.debug(String.format("telnet ip : %s, userTip : %s , pinTip : %s", terminal.getManageIp(), authUserTip, authPinTip)); - executorService.execute(new Runnable() { - @Override - public void run() { - TerminalSessionService terminalSessionService = (TerminalSessionService) TerminalSession.clientAttributeInfo.get("terminalSessionService"); - TerminalCmdService terminalCmdService = (TerminalCmdService) TerminalSession.clientAttributeInfo.get("terminalCmdService"); - TerminalRecordService terminalRecordService = (TerminalRecordService) TerminalSession.clientAttributeInfo.get("terminalRecordService"); - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionEntity"); - byte[] buffer = new byte[1024 * 4]; - StringBuilder builder = new StringBuilder(); - telnetUser=true; - try { - while (webSocketSession != null && webSocketSession.isOpen()) { - String user = terminal.getAuthUsername(); - - builder.setLength(0); - int size = inputStream.read(buffer); - if (size == -1) { - return; - } - for (int i = 0; i < size; i++) { - char chr = (char) (buffer[i] & 0xff); - builder.append(chr); - } - //取到linux远程机器输出的信息发送给前端 - String message = builder.toString(); - - // terminal record 信息梳理 - String fileName = Constant.TEMP_PATH + File.separator + clientId + ".log"; - File file = new File(fileName); - Path path = file.toPath(); - - message = StrUtil.str(message.getBytes(DigestUtils.getEncoding(message)),"UTF-8"); - - List<WebSocketSession> webSocketSessions = TerminalSession.terminalMonitorsMap.get(clientId); - if(CollectionUtils.isNotEmpty(webSocketSessions)){ - for (WebSocketSession socketSession : webSocketSessions) { - socketSession.sendMessage(new TextMessage(message)); - } - } - - TerminalClient.handleTerminalRecordMessage(file, path, terminalRecordService, clientId, message); - - processCommand(terminalCmdService, message); - //获取pwd的结果输出,不能发送给前台 - if (sendTempCmd) { - if (message.contains(sendTempCmdId)) { - if (pwd != null || message.contains("echo")) { - continue; - } - pwd = message.replace(sendTempCmdId, "").replaceAll("\r\n.*", "") + "/"; - if (logger.isInfoEnabled()) { - logger.info(" Sftp upload file target path:{}", pwd); - } - } - } else { - if((message.replaceAll("\r\n", "")).equals("logout")) { - // 已结束连接 - String unloginInfo = getUnloginInfo(Constants.SessionStatus.OVER.getValue()); - webSocketSession.sendMessage(new TextMessage(unloginInfo)); - - try { - // 将结束信息保存入库 - TerminalRecord terminalRecord = new TerminalRecord(); - terminalRecord.setUuid(clientId); - terminalRecord.setContent(Files.readAllBytes(path)); - TerminalRecord lastRecord = terminalRecordService.getOne(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, clientId).orderByDesc(TerminalRecord::getId).last("limit 0,1")); - // 之前没有文件记录 - if(lastRecord == null){ - terminalRecord.setStartTime(0); - }else{ - terminalRecord.setStartTime(lastRecord.getEndTime()); - } - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); - terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalRecordService.save(terminalRecord); - - boolean delete = file.delete(); - if(delete) { - logger.debug("文件删除成功"); - }else { - logger.debug("文件删除失败"); - } - } catch (IOException e) { - logger.error(String.format("Telnet 连接已关闭,terminal record 结尾临时文件入库失,文件路径是: %s,错误信息是: %s", path.toString(), e.getMessage()), e); - } - }else { - //telnet登录状态修改 - if(message.contains("Last login")) { - // cmd 信息 - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setUuid(clientId); - terminalCmd.setCmd("Login"); - terminalCmd.setTime(0); - terminalCmdService.saveOrUpdate(terminalCmd); - - // session 信息 - sessionEntity.setStatus(Constants.SessionStatus.CONNECTING.getValue()); - sessionEntity.setStartTime(new Date()); - terminalSessionService.saveOrUpdate(sessionEntity); - - telnetConnect=false; - // 登录成功后清空 前端输入字符 防止日志保存空数据 - TerminalSession.clientAttributeInfo.put(clientId+"shell", null); - } - - //判断用户登录telnet连接次数 - if(message.contains("Login incorrect")) { - telnetConnectCount++; - telnetUser=true; - } - logger.error(message); - if (message.trim().matches(authUserTip) && StringUtils.isNotEmpty(user)) { - webSocketSession.sendMessage(new TextMessage(message + user + "\r\n")); - write(user + "\r"); - } else if (message.trim().matches(authPinTip) && StringUtils.isBlank(user)) { - telnetUser = false; - webSocketSession.sendMessage(new TextMessage("\r\n" + message)); - } else if (message.trim().matches(authPinTip) && StringUtils.isNotEmpty(user) && StringUtils.isNotEmpty(pin)) { - telnetUser = false; - webSocketSession.sendMessage(new TextMessage("\r\n" + message)); - write(pin + "\r"); - } else if (message.contains("timed out after 60 seconds")) { - webSocketSession.sendMessage(new TextMessage(message+"\r\nConnection closed by foreign host.\r\n$: ")); - // 连接超时 - TerminalSession.remove(webSocketSession); - closed=true; - telnetConnect=false; - // 连接失败 - String unloginInfo = getUnloginInfo(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - webSocketSession.sendMessage(new TextMessage(unloginInfo)); - } else { - webSocketSession.sendMessage(new TextMessage(message)); - if(telnetConnectCount==3) { - // 连接错误达到限制 关闭连接 连接失败 - // cmd 信息 - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setUuid(clientId); - terminalCmd.setCmd("Login"); - terminalCmd.setTime(0); - terminalCmdService.save(terminalCmd); - - // session 信息 - sessionEntity.setLoginUser(user); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTING.getValue()); - sessionEntity.setStartTime(new Date()); - terminalSessionService.saveOrUpdate(sessionEntity); - - // 强制退出 错误达到限制 - String unloginInfo = getUnloginInfo(Constants.SessionStatus.FORCE_QUIT.getValue()); - webSocketSession.sendMessage(new TextMessage(unloginInfo)); - - webSocketSession.close(); - TerminalSession.remove(webSocketSession); - closed=true; - } - } - } - if (sendEnter) { - String trimMessage = message.replaceAll("\r\n", ""); - if (CommonUtils.isEmpty(trimMessage)) { - receiveEnd = false; - } else { - if (sendBuffer.toString().equals("exit") && trimMessage.equals("logout")) { - webSocketSession.close(); - TerminalSession.remove(webSocketSession); - closed = true; - } - receiveEnd = true; - } - if (receiveEnd) { - sendBuffer.setLength(0); - } - } - } - } - } catch (UnsupportedEncodingException e) { - logger.error("TerminalClient error info :",e); - TerminalSession.remove(webSocketSession); - } catch (IOException e) { - logger.error("TerminalClient error info :",e); - TerminalSession.remove(webSocketSession); - } - - } - }); - } - - /** - * 用户有自定义 tip 则使用用户的,没有则使用系统配置的 - * @param tip - * @param configEntities - * @param key - * @return - */ - private String getTelenetLoginTip(String tip, List<SysConfigEntity> configEntities, String key) { - if(StringUtils.isNotEmpty(tip)){ - return ".*" + tip.trim(); - }else { - SysConfigEntity configEntity = configEntities.stream().filter(entity -> entity.getParamKey().equalsIgnoreCase(key)).findFirst().orElse(null); - return ".*" + configEntity.getParamValue(); - } - } - - /** - * 处理服务器方向键以及tab操作返回的指令信息 便于做日志记录 - * @param serverResponse 服务器响应内容 - */ - public void processCommand(TerminalCmdService terminalCmdService, String serverResponse) { - Map terminalAttributeInfo = TerminalSession.getTerminalAttributeInfo(clientId); - Integer cmdCharPos = (Integer) terminalAttributeInfo.get("cmdCharPos"); - - List<Character> list = TerminalSession.terminalCmdInfo.get(clientId); - list = (list == null) ? new ArrayList<>() : list; - - char[] charArray = serverResponse.toCharArray(); - - // 转义字符 - boolean esc_mode = false; - int esc_arg = 0; - - boolean maybeCmd = false; - if (charArray.length >= 2) { - maybeCmd = (charArray[0] == 13 && charArray[1] == 10); // 0x0d 13 \r 0x0a 10 \n - } - - boolean client_single_char = false; - if (charArray.length == 1) { - int c = charArray[0]; - if (Constants.INVISIBLE_CHAR.contains(c)) { - client_single_char = true; - } - } - - int offset = 0; - int len = charArray.length; - for (; offset < charArray.length; ) { - char ch = charArray[offset]; - if (esc_mode) { - switch (ch) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - // 字符转数字 - esc_arg = esc_arg * 10 + (ch - '0'); - break; - } - case 63: - case ';': - case '>': { - TerminalSession.terminalCmdInfo.put(clientId, new ArrayList<>()); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); - return; - } - case 75: { // K - if (0 == esc_arg) { - list = list.subList(0, cmdCharPos); - cmdCharPos = list.size(); - } else if (1 == esc_arg) { - list = list.subList(cmdCharPos, list.size()); - cmdCharPos = list.size(); - } else if (2 == esc_arg) { - list = new ArrayList<>(); - cmdCharPos = 0; - } - TerminalSession.terminalCmdInfo.put(clientId, list); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - esc_mode = false; - break; - } - case 67: { // ^[C - // 光标右移 - if (esc_arg == 0) { - esc_arg = 1; - } - - for (int j = 0; j < esc_arg; ++j) { - if (cmdCharPos != list.size()) { - cmdCharPos++; - } - } - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - esc_mode = false; - break; - } - case 68: { // ^[D - // 光标左移 - if (esc_arg == 0) { - esc_arg = 1; - } - for (int j = 0; j < esc_arg; ++j) { - if (cmdCharPos != 0) { - cmdCharPos--; - } - } - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - esc_mode = false; - break; - } - case 80: { // 'P' 删除指定数量的字符 - if (esc_arg == 0) { - esc_arg = 1; - } - - for (int j = 0; j < esc_arg; ++j) { - // 不是最后一个 - if (cmdCharPos != list.size()) { - int index = cmdCharPos; - list.remove(index); - } - } - TerminalSession.terminalCmdInfo.put(clientId, list); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - esc_mode = false; - break; - } - case 64:{ - if (esc_arg == 0){ - esc_arg = 1; - } - for (int j = 0; j < esc_arg; ++j){ - list.add(cmdCharPos, ' '); - cmdCharPos++; - } - TerminalSession.terminalCmdInfo.put(clientId, list); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - esc_mode = false; - break; - } - default: - esc_mode = false; - break; - } - - offset++; - continue; - } - - switch (ch) { - case 7: - // 响铃 - break; - case 8: { - // 光标左移 - if (cmdCharPos != 0 && CollectionUtils.isNotEmpty(list)) { - cmdCharPos--; - TerminalSession.terminalCmdInfo.put(clientId, list); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - } - break; - } - case 27: { // 0x1b esc - if (offset + 1 < len) { - if (charArray[offset + 1] == 91 || charArray[offset + 1] == 93) { - if (offset == 0 && client_single_char) { - TerminalSession.removeTerminalCmd(clientId); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); - maybeCmd = false; - client_single_char = false; - return; - } - } - - if (charArray[offset + 1] == 91 || charArray[offset + 1] == 93) { - esc_mode = true; - - esc_arg = 0; - offset += 1; - } - } - break; - } - // 0x0d 13 \r 0x0a 10 \n - case 13: { - if (offset + 1 < len && charArray[offset + 1] == 10) { - if (maybeCmd) { - if (CollectionUtils.isNotEmpty(list) && !telnetConnect) { - String cmd = ""; - for (Character character : list) { - cmd += character; - } - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setCmd(cmd); - terminalCmd.setUuid(clientId); - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionStartTime"); - terminalCmd.setTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalCmdService.save(terminalCmd); - } - TerminalSession.removeTerminalCmd(clientId); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); - maybeCmd = false; - } - } - TerminalSession.removeTerminalCmd(clientId); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", 0); - return; - } - default: { - if (cmdCharPos != list.size()) { - int index = cmdCharPos; - list.remove(index); - list.add(cmdCharPos, ch); - cmdCharPos++; - } else { - list.add(ch); - cmdCharPos = list.size(); - } - TerminalSession.terminalCmdInfo.put(clientId, list); - TerminalSession.setTerminalAttributeInfo(clientId, "cmdCharPos", cmdCharPos); - } - } - offset++; - } - } - - /** - * 处理终端响应信息 - * @param param - * @return - */ - public String terminalResponseHandle(String param) { - byte[] bytes = param.getBytes(); - List<Byte> asList = new ArrayList<>(Bytes.asList(bytes)); - for(int i=asList.size()-1;i>=0;i--) { - if(asList.get(i)==8){ - asList.remove(i); - }else if(asList.get(i)==13) { - asList.remove(i); - }else if(asList.get(i)==10) { - asList.remove(i); - }else if(asList.get(i)==27) { - asList.remove(i); - }else if(asList.get(i)==91) { - asList.remove(i); - }else if(i!=0&&asList.get(i-1)==91) { - asList.remove(i); - }else if(asList.get(i)==7) { - asList.remove(i); - } - } - byte[] array = Bytes.toArray(asList); - return StringUtils.str(array); - } - - /** - * 向ssh终端输入内容 - * - * @param message - * @throws IOException - */ - public void write(String message) throws IOException { - // 获取telnet登录用户名信息 - if (telnetUser && telnetConnect && StringUtils.isEmpty(terminal.getAuthUsername())) { - sb.append(message); - webSocketSession.sendMessage(new TextMessage(message)); - } else if (StringUtils.isNotEmpty(sb.toString())) { - terminal.setAuthUsername(sb.toString()); - } - if (message.equals("\r")) { - if (closed) { - disconnect(); - } else { - sendEnter = true; - } - } else { - // 防止用户输入ctrl+c出现程序异常 以及记录日志异常 - if(ObjectUtils.isNotEmpty(message) && message.getBytes()[0]!=3) { - sendEnter = false; - sendBuffer.append(message); - } - } - - if (outputStream != null) { - IoUtil.write(outputStream, false, message.getBytes()); - outputStream.flush(); - } - } - - public void upload(String src, String dst, long fileSize) throws IOException,SftpException,JSchException,InterruptedException { - FileInputStream file =null; - ChannelSftp channelSftp = null; - try { - file = IoUtil.toStream(FileUtil.file(src)); - channelSftp = (ChannelSftp) this.session.openChannel("sftp"); - channelSftp.connect(CHANNEL_TIMEOUT); - //当前路径下,获取用户终端的当前位置 - if (dst.startsWith("./")) { - //不出绝招不行啊....很神奇 - sendTempCmd = true; - write(String.format("echo %s$(pwd)\r", this.sendTempCmdId)); - //等待获取返回的路径... -// Thread.sleep(100); - sendTempCmd = false; - if (pwd == null) { - throw new RuntimeException("Sftp upload file target path error!"); - } - dst = dst.replaceFirst("\\./", pwd); - pwd = null; - } else if (dst.startsWith("~")) { - dst = dst.replaceAll("~/|~", ""); - } - channelSftp.put(file, dst, new SftpMonitor(fileSize)); - - } catch (JSchException | SftpException | IOException e) { - throw e; - } finally { - //exit - if (channelSftp != null) { - channelSftp.exit(); - } - //disconnect - if (channelSftp != null) { - channelSftp.disconnect(); - } - if(file!=null) { - IOUtils.closeQuietly(file); - } - } - } - - public void download(String path,HttpServletResponse res) throws IOException,SftpException,JSchException,InterruptedException { - ChannelSftp channelSftp=null; - InputStream is =null; - OutputStream outputStream =null; - try { - logger.info("TerminalClient download param is {}",path); - channelSftp = (ChannelSftp) this.session.openChannel("sftp"); - channelSftp.connect(CHANNEL_TIMEOUT); - //当前路径下,获取用户终端的当前位置 - if (path.startsWith("./")) { - //不出绝招不行啊....很神奇 - sendTempCmd = true; - write(String.format("echo %s$(pwd)\r", this.sendTempCmdId)); - //等待获取返回的路径... -// Thread.sleep(100); - sendTempCmd = false; - if (pwd == null) { - throw new RuntimeException("Sftp upload file target path error!"); - } - path = path.replaceFirst("\\./", pwd); - pwd = null; - } else if (path.startsWith("~")) { - path = path.replaceAll("~/|~", ""); - } - //截取路径中的文件名称 - String fileName = path.substring(path.lastIndexOf("/")+1); - String pathExceptFileName = path.substring(0,path.lastIndexOf("/")); - logger.info("TerminalClient download fileName is {}",fileName); - logger.info("TerminalClient download pathExceptFileName is {}",pathExceptFileName); - channelSftp.cd(pathExceptFileName); - is = channelSftp.get(fileName); - res.setCharacterEncoding("utf-8"); - res.setContentType("multipart/form-data"); - res.setHeader("Content-disposition", "attachment;filename=" + fileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8")); - res.setHeader("Access-Control-Expose-Headers","Content-Disposition"); - // 发送给客户端的数据 - outputStream = res.getOutputStream(); - byte[] buff = new byte[1024]; - int i = is.read(buff); - while (i != -1) { - outputStream.write(buff, 0, i); - outputStream.flush(); - i = is.read(buff); - } - } catch (JSchException | SftpException | IOException e) { - throw e; - } finally { - if(outputStream!=null) { - IOUtils.closeQuietly(outputStream); - } - if(is!=null) { - IOUtils.closeQuietly(is); - } - //exit - if (channelSftp != null) { - channelSftp.exit(); - } - //disconnect - if (channelSftp != null) { - channelSftp.disconnect(); - } - } - } - - - - public void disconnect() throws IOException { - if (writer != null) { - writer.close(); - writer = null; - } - if (session != null) { - session.disconnect(); - session = null; - } - if (jSch != null) { - jSch = null; - } - closed = true; - } - - public void resize(Integer cols, Integer rows, Integer width, Integer height) throws IOException { - if (channelShell != null) { - channelShell.setPtySize(cols, rows, width, height); - } - } - - public AssetAsset getTerminal() { - return terminal; - } - - public void setTerminal(AssetAsset terminal) { - this.terminal = terminal; - } - - public boolean isClosed() { - return closed; - } - - public WebSocketSession getWebSocketSession() { - return webSocketSession; - } - - public String getHttpSessionId() { - return httpSessionId; - } - - public String getClientId() { - return clientId; - } - - public boolean isTransfer() { - return transfer; - } - - public void setTransfer(boolean transfer) { - this.transfer = transfer; - } - - public String getUnloginInfo() { - StringBuilder sb=new StringBuilder(); - sb.append("\r\nlogout\r\n"); - sb.append("Welcome to Nezha Terminal! \r\n"); - sb.append("Type `help' to learn how to use Nezha Terminal prompt. \r\n"); - sb.append("$: "); - return sb.toString(); - } - - public String getUnloginInfo(Integer status) { - /** - * session 已经结束,更新状态,设置结束时间 - */ - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(clientId).get("terminalSessionEntity"); - if (sessionEntity.getStartTime() == null) { - sessionEntity.setStartTime(new Date()); - } - sessionEntity.setStatus(status); - sessionEntity.setEndTime(new Date()); - TerminalSessionService terminalSessionService = (TerminalSessionService) TerminalSession.clientAttributeInfo.get("terminalSessionService"); - terminalSessionService.saveOrUpdate(sessionEntity); - - StringBuilder sb = new StringBuilder(); - sb.append("\r\nlogout\r\n"); - sb.append("Connection closed \r\n"); - return sb.toString(); - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalContext.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalContext.java deleted file mode 100644 index 371eae2d..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalContext.java +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - -import com.nis.modules.asset.entity.AssetAsset; -import org.springframework.stereotype.Component; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - - -@Component -public class TerminalContext implements Serializable { - - //key-->uuid value--->Terminal User (账号信息保存在 AssetAsset entity 中) - public static final Map<String, AssetAsset> terminalContext = new HashMap<>(); - - public static final Map<String, Set<String>> terminalUuid = new HashMap<>(); - - private String uuid; - - public AssetAsset get(String key) { - return terminalContext.get(key(key)); - } - - public void put(String key, AssetAsset asset) { - this.uuid = key; - //该终端实例只能被的打开一次,之后就失效 - terminalContext.put(key(key), asset); - /** - * 为复制会话 - */ - String reKey = asset.getId() + "_" + key; - terminalContext.put(key(reKey), asset); - } - - public AssetAsset remove(String key) { - return terminalContext.remove(key(key)); - } - - private String key(String key) { - return Constants.PARAM_TERMINAL_PREFIX_KEY + key; - } - - public String getToken() { - return this.uuid; - } - -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalHandler.java deleted file mode 100644 index 7904371f..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalHandler.java +++ /dev/null @@ -1,1019 +0,0 @@ -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; -import com.jcraft.jsch.JSchException; -import com.mchange.lang.ByteUtils; -import com.nis.common.utils.CommonUtils; -import com.nis.common.utils.Constant; -import com.nis.common.utils.ToolUtil; -import com.nis.modules.asset.entity.AssetAsset; -import com.nis.modules.asset.entity.AssetTypeConf; -import com.nis.modules.asset.service.AssetAssetService; -import com.nis.modules.asset.service.AssetTypeConfService; -import com.nis.modules.sys.entity.SysUserEntity; -import com.nis.modules.sys.service.SysConfService; -import com.nis.modules.sys.shiro.ShiroUtils; -import com.nis.modules.terminal.config.Constants.SshType; -import com.nis.modules.terminal.entity.TerminalCmd; -import com.nis.modules.terminal.entity.TerminalRecord; -import com.nis.modules.terminal.entity.TerminalSessionEntity; -import com.nis.modules.terminal.service.TerminalCmdService; -import com.nis.modules.terminal.service.TerminalRecordService; -import com.nis.modules.terminal.service.TerminalSessionService; -import org.apache.commons.lang3.StringUtils; -import org.apache.shiro.session.mgt.SimpleSession; -import org.apache.shiro.subject.SimplePrincipalCollection; -import org.apache.shiro.subject.support.DefaultSubjectContext; -import org.springframework.context.ApplicationContext; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import org.springframework.stereotype.Component; -import org.springframework.web.socket.CloseStatus; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; -import org.springframework.web.socket.handler.TextWebSocketHandler; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; - -import static com.nis.common.utils.CommonUtils.toInt; - -@Component -public class TerminalHandler extends TextWebSocketHandler { - - private static final Log logger = Log.get(); - - private static String SSH_PROTOCOL = "SSH"; - private static String TELNET_PROTOCOL = "TELNET"; - - private TerminalClient terminalClient; - - private static ApplicationContext applicationContext; - - public static void setApplicationContext(ApplicationContext applicationContext) { - TerminalHandler.applicationContext = applicationContext; - } - - private TerminalContext terminalContext; - - // 当前用户登录认证唯一标识 - private String uuid; - // 当前登录设备信息 - private String assetId; - - private String token; - - // private String accountId; - - private String host; - private String port; - private String authProtocol; - private String authProtocolPort; - private String authType; - private String authUsername; - private String authPin; - private String authPriKey; - private String authUserTip; - private String authPinTip; - - private Long userId; - - private TerminalSessionService terminalSessionService; - - private TerminalCmdService terminalCmdService; - - private TerminalRecordService terminalRecordService; - - private AssetAssetService assetAssetService; - - private AssetTypeConfService assetTypeConfService; - - private SysConfService sysConfService; - - @Override - public synchronized void afterConnectionEstablished(WebSocketSession session) throws Exception { - super.afterConnectionEstablished(session); - if (terminalContext == null) { - terminalContext = (TerminalContext) applicationContext.getBean("terminalContext"); - } - assetId = (String) session.getAttributes().get("assetId"); - // accountId=(String)session.getAttributes().get("accountId"); - authProtocol = (String) session.getAttributes().get("authProtocol"); - host = (String) session.getAttributes().get("host"); - port = (String) session.getAttributes().get("port"); - authProtocolPort = (String) session.getAttributes().get("authProtocolPort"); - authType = (String) session.getAttributes().get("authType"); - authUsername = (String) session.getAttributes().get("authUsername"); - authPin = (String) session.getAttributes().get("authPin"); - authPriKey = (String) session.getAttributes().get("authPriKey"); - authUserTip = (String) session.getAttributes().get("authUserTip"); - authPinTip = (String) session.getAttributes().get("authPinTip"); - - uuid = (String) session.getAttributes().get("uuid"); - token = (String) session.getAttributes().get("terminalToken"); - - RedisConnectionFactory factory = applicationContext.getBean(RedisConnectionFactory.class); - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - - redisTemplate.afterPropertiesSet(); - //判断用户传入的token是否为项目获取的token信息 - ValueOperations ops = redisTemplate.opsForValue(); - Object obj = ops.get(ShiroUtils.REDIS_KEYPREFIX + token); - if (obj == null) { - session.sendMessage(new TextMessage("Token error,Please log in to the system first")); - session.close(); - logger.error("terminal error user token Incorrect token info is : {}", token); - return; - } - - SimpleSession simpleSession = (SimpleSession) obj; - SimplePrincipalCollection primaryPrincipal = (SimplePrincipalCollection) simpleSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); - SysUserEntity userEntity = (SysUserEntity) primaryPrincipal.getPrimaryPrincipal(); - userId = userEntity.getId(); - - // 创建登录服务器日志记录相关内容 - terminalSessionService = (TerminalSessionService) applicationContext.getBean("terminalSessionService"); - terminalCmdService = (TerminalCmdService) applicationContext.getBean("terminalCmdService"); - terminalRecordService = (TerminalRecordService) applicationContext.getBean("terminalRecordService"); - assetAssetService = applicationContext.getBean(AssetAssetService.class); - assetTypeConfService = applicationContext.getBean(AssetTypeConfService.class); - sysConfService = applicationContext.getBean(SysConfService.class); - - TerminalSession.clientAttributeInfo.put("terminalSessionService", terminalSessionService); - TerminalSession.clientAttributeInfo.put("terminalCmdService", terminalCmdService); - TerminalSession.clientAttributeInfo.put("terminalRecordService", terminalRecordService); - TerminalSession.clientAttributeInfo.put("assetAssetService", assetAssetService); - TerminalSession.clientAttributeInfo.put("sysConfService", sysConfService); - - // 初始化服务器连接基本属性配置 - Map terminalAttribute = TerminalSession.getTerminalAttributeInfo(uuid); - terminalAttribute.put("userId", userId); - - // 打开窗口 - TerminalSession.setWindowSize(token); - - AssetAsset terminalInfo = null; - if (StringUtils.isNotEmpty(assetId)) { - // 从缓存中取出之前保存的客户端实例 - terminalInfo = terminalContext.get(uuid); - if (terminalInfo == null) { - // 查询 asset 相关信息 - terminalInfo = assetAssetService.getById(assetId); - if (terminalInfo != null) { - AssetTypeConf typeConf = assetTypeConfService.getById(terminalInfo.getTypeId()); - if (typeConf.getAuthProtocol().equals(1)) { - terminalInfo.setProtocol(SSH_PROTOCOL); - } else if (typeConf.getAuthProtocol().equals(2)) { - terminalInfo.setProtocol(TELNET_PROTOCOL); - } - terminalContext.put(uuid, terminalInfo); - } - } - // 不支持账号协议 并且没有填写账号信息 直接返回 - if (terminalInfo == null || (ToolUtil.isEmpty(terminalInfo.getProtocol()) && ToolUtil.isEmpty(terminalInfo.getAuthType()) && ToolUtil.isEmpty(terminalInfo.getAuthUsername()))) { - //如果用户没有传入asset信息 则友情提示用户 - session.sendMessage(new TextMessage("Login fail! No login account is configured. \r\n")); - unloginUserHandle(session); - session.close(); - return; - } - } else { - terminalInfo = new AssetAsset(); - if (authProtocol.equals("1")) { - terminalInfo.setProtocol(SSH_PROTOCOL); - } else if (authProtocol.equals("2")) { - terminalInfo.setProtocol(TELNET_PROTOCOL); - } - terminalInfo.setAuthProtocolPort(StringUtils.isEmpty(authProtocolPort) ? Integer.valueOf(port) : Integer.valueOf(authProtocolPort)); - terminalInfo.setAuthType(Integer.valueOf(authType)); - terminalInfo.setAuthUsername(authUsername); - authPin = authPin == null ? "" : authPin; - terminalInfo.setAuthPin(authPin); - terminalInfo.setAuthPriKey(authPriKey); - terminalInfo.setAuthUserTip(authUserTip); - terminalInfo.setAuthPinTip(authPinTip); - terminalInfo.setManageIp(host); - terminalInfo.setAuthProtocolPort(Integer.valueOf(port)); - - // 通过 manager ip 获取 asset id - AssetAsset asset = assetAssetService.getOne(new LambdaQueryWrapper<AssetAsset>().eq(AssetAsset::getManageIp, host)); - terminalInfo.setId(asset != null ? asset.getId() : null); - terminalContext.put(uuid, terminalInfo); - } - - final AssetAsset terminal = terminalInfo; - TerminalSessionEntity sessionEntity = new TerminalSessionEntity(); - sessionEntity.setUuid(uuid); - sessionEntity.setHost(terminal.getManageIp()); - sessionEntity.setPort(terminal.getAuthProtocolPort()); - sessionEntity.setProtocol(terminal.getProtocol()); - sessionEntity.setAuthType(SshType.ACCOUNT.getType().equals(terminal.getAuthType()) ? SshType.ACCOUNT.getType() : SshType.SSHKEY.getType()); - sessionEntity.setUserId(userId); - sessionEntity.setAssetId(terminal.getId()); - try { - getClient(session, terminal); - int cols = toInt(session.getAttributes().get("cols").toString()); - int rows = toInt(session.getAttributes().get("rows").toString()); - int width = toInt(session.getAttributes().get("width").toString()); - int height = toInt(session.getAttributes().get("height").toString()); - - // terminal session 信息 - sessionEntity.setLoginUser(terminal.getAuthUsername()); - sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); - sessionEntity.setStartTime(new Date()); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTING.getValue()); - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionEntity", sessionEntity); - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionStartTime", System.currentTimeMillis()); - - // terminal cmd 信息 - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setUuid(uuid); - terminalCmd.setTime(0); - terminalCmd.setCmd("Login"); - terminalCmdService.save(terminalCmd); - - // 根据协议选择打开窗口类型 - String protocol = terminal.getProtocol(); - if (SSH_PROTOCOL.equals(protocol)) { - terminalClient.openTerminal(cols, rows, width, height); - } else if (StrUtil.equals(TELNET_PROTOCOL, protocol)) { - terminalClient.openTelnetTerminal(cols, rows, width, height); - } - - terminalSessionService.save(sessionEntity); - } catch (IOException | JSchException e) { - logger.error("error info :", e); - logger.error(e); - String lowerCase = e.getMessage().toLowerCase(); - if (StrUtil.contains(lowerCase, "auth fail")) { - session.sendMessage(new TextMessage("Login fail, Please check account info is accurate. \r\n")); - } else if (e.getLocalizedMessage().replaceAll("\\s+", "").contentEquals("Operationtimedout")) { - session.sendMessage(new TextMessage("Sorry! Connect timed out, please try again. \r\n")); - } else { - session.sendMessage(new TextMessage("Sorry! Operation error, please try again. \r\n")); - } - - // 连接异常,关闭session 记录,更改状态为 连接失败 - sessionEntity.setEndTime(new Date()); - sessionEntity.setLoginUser(StringUtils.isNotBlank(terminal.getAuthUsername()) ? terminal.getAuthUsername() : ""); - sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); - sessionEntity.setStartTime(new Date()); - sessionEntity.setEndTime(new Date()); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - terminalSessionService.save(sessionEntity); - - terminalClient.disconnect(); - TerminalSession.remove(session); - unloginUserHandle(session); - } - } - - @Override - protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { - // 每次请求获取对应的uuid信息 - Map<String, Object> attributes = session.getAttributes(); - uuid = (String) attributes.get("uuid"); - super.handleTextMessage(session, message); - logger.info("handleTextMessage meesage info : {}",message.getPayload()); - - /** - * 优先处理用户前端输入方向内容保存到session中 以便于执行以及日志记录 - */ - Map terminalAttribute = TerminalSession.getTerminalAttributeInfo(uuid); - boolean sshLogin = (boolean) terminalAttribute.get("sshLogin"); - Integer cursorIndex = (Integer) terminalAttribute.get("cursorIndex"); - boolean cursorFlag = (boolean) terminalAttribute.get("cursorFlag"); - Integer historyIndex = (Integer) terminalAttribute.get("historyIndex"); - - try { - getClient(session, null); - if (this.terminalClient != null) { - // 保存当前输入字符信息 以便client端获取对应的操作字符 - TerminalSession.clientAttributeInfo.put(uuid+"shell", message); - terminalClient.write(message.getPayload()); - - }else { - if(ObjectUtils.isEmpty(message.asBytes())) { - return; - } - //处理用户上下左右方向键操作 - if(message.asBytes()[0]==27) { - // 判断用户是在ssh登录输入密码时操作 则直接返回不进行任何操作 - if(sshLogin) { - return; - } - String operation = ByteUtils.toHexAscii(message.asBytes()); - if(operation.equals("1B5B44")){ - // 左方向操作 - if(cursorIndex!=0) { - // 光标在初始位置不可移动 - // cursorIndex-=message.getPayload().length(); - cursorIndex -= 1; - session.sendMessage(new TextMessage(message.getPayload())); - cursorFlag=true; - }else if(TerminalSession.getTerminalMessage(uuid)==null || cursorIndex==TerminalSession.getTerminalMessage(uuid).length()){ - cursorFlag=false; - } - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorFlag", cursorFlag); - return; - } else if(operation.equals("1B5B43")) { - // 右方向操作 - if((cursorIndex==0 && (TerminalSession.getTerminalMessage(uuid)==null || TerminalSession.getTerminalMessage(uuid).length()==0)) || cursorIndex==TerminalSession.getTerminalMessage(uuid).length()) { - // 光标位置在初始位置 或者已经为当前输入内容最右处 - cursorFlag=false; - }else { - // cursorIndex+=message.getPayload().length(); - cursorIndex += 1; - session.sendMessage(new TextMessage(message.getPayload())); - cursorFlag=true; - } - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorFlag", cursorFlag); - return; - } else if(operation.equals("1B5B41")) { - // 上方向操作 获取用户之前保存的指令信息 - // 获取当前字符串位置 将光标移到开头 同时清空信息 补充历史指令信息 - List<String> list = TerminalSession.userInstructions.get(uuid); - if(ObjectUtils.isEmpty(list)||list.size()==historyIndex) { - // 用户初进入没有任何历史指令 或者历史指令已经到最后一条位置 - return; - } - String historyInstruction = TerminalSession.getHistoryInstruction(uuid, historyIndex+1); - if(historyIndex==0) { - String TerminalMessage = TerminalSession.getTerminalMessage(uuid); - if(StringUtils.isEmpty(TerminalMessage)) { - // 用户并无任何输入情况 - session.sendMessage(new TextMessage(historyInstruction)); - }else { - int positionIndex=0; - positionIndex=TerminalMessage.length(); - if(cursorFlag) { - // 存在光标位置移动情况 将光标位置复原情况 - for(int i=0;i<TerminalMessage.length()-cursorIndex;i++) { - byte[] fromHexAscii = ByteUtils.fromHexAscii("1B5B43"); - session.sendMessage(new TextMessage(fromHexAscii)); - } - }else { - // 光标未移动用户使用回退操作情况 - if(TerminalMessage.length()!=cursorIndex) { - positionIndex=cursorIndex; - } - } - for(int i=0;i<positionIndex-1;i++) { - session.sendMessage(new TextMessage("\b")); - } - byte[] fromHexAscii = ByteUtils.fromHexAscii("081b5b4b"); - session.sendMessage(new TextMessage(fromHexAscii)); - session.sendMessage(new TextMessage(historyInstruction)); - } - }else { - // 无改变--->上一条历史信息 改变---->当前指令信息 - String prefixInstruction = TerminalSession.getTerminalMessage(uuid); - int positionIndex=0; - positionIndex=prefixInstruction.length(); - if(cursorFlag) { - // 存在光标位置移动情况 将光标位置复原情况 - for(int i=0;i<prefixInstruction.length()-cursorIndex;i++) { - byte[] fromHexAscii = ByteUtils.fromHexAscii("1B5B43"); - session.sendMessage(new TextMessage(fromHexAscii)); - } - }else { - // 光标未移动用户使用回退操作情况或者用户新增输入操作 - if(prefixInstruction.length()!=cursorIndex) { - positionIndex=cursorIndex; - } - } - for(int i=0;i<positionIndex-1;i++) { - session.sendMessage(new TextMessage("\b")); - } - byte[] fromHexAscii = ByteUtils.fromHexAscii("081b5b4b"); - session.sendMessage(new TextMessage(fromHexAscii)); - session.sendMessage(new TextMessage(historyInstruction)); - } - historyIndex++; - TerminalSession.removeTerminalMessage(uuid); - TerminalSession.setTerminalMessage(uuid, historyInstruction, null); - cursorIndex=historyInstruction.length(); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - TerminalSession.setTerminalAttributeInfo(uuid, "historyIndex", historyIndex); - return; - } else if(operation.equals("1B5B42")) { - // 下方向操作 - if(historyIndex==0||historyIndex==1) { - return; - } - // 要回溯的历史指令 - String historyInstruction = TerminalSession.getHistoryInstruction(uuid, historyIndex-1); - // 当前指令信息 - String currentInstruction = TerminalSession.getTerminalMessage(uuid); - int positionIndex=0; - positionIndex=currentInstruction.length(); - if(cursorFlag) { - // 存在光标位置移动情况 将光标位置复原情况 - for(int i=0;i<currentInstruction.length()-cursorIndex;i++) { - byte[] fromHexAscii = ByteUtils.fromHexAscii("1B5B43"); - session.sendMessage(new TextMessage(fromHexAscii)); - } - - }else { - if(currentInstruction.length()!=cursorIndex) { - positionIndex=cursorIndex; - } - } - for(int i=0;i<positionIndex-1;i++) { - session.sendMessage(new TextMessage("\b")); - } - byte[] fromHexAscii = ByteUtils.fromHexAscii("081b5b4b"); - session.sendMessage(new TextMessage(fromHexAscii)); - session.sendMessage(new TextMessage(historyInstruction)); - TerminalSession.removeTerminalMessage(uuid); - TerminalSession.setTerminalMessage(uuid, historyInstruction, null); - cursorIndex=historyInstruction.length(); - historyIndex--; - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - TerminalSession.setTerminalAttributeInfo(uuid, "historyIndex", historyIndex); - return; - } - } - /** - * 如果用户未登录 使用uuid为key保存用户发送的指令信息 等到收到回车指令时才执行对应的操作 - */ - if(sshLogin&&message.getPayload().matches("\\r\\n|\\n|\\r|\\n\\r")) { - /** - * 这里进行ssh登录操作 - */ - String sshPwd = TerminalSession.getTerminalMessage(uuid); - //将当前执行指令删除 防止用户保存ssh登录密码 同时将光标等属性重置 - TerminalSession.removeTerminalMessage(uuid); - //将sshlogin登录状态外的其它基础配置恢复默认 - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", 0); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorFlag", false); - TerminalSession.setTerminalAttributeInfo(uuid, "historyIndex", 0); - nezhaMessageHandle(session,sshPwd); - }else if(message.getPayload().matches("\\r\\n|\\n|\\r|\\n\\r")) { - logger.info("user send terminal to start"); - // 处理用户空输入 直接回车操作 - String TerminalMessage = TerminalSession.getTerminalMessage(uuid); - if(historyIndex!=0) { - if(StringUtils.isEmpty(TerminalMessage)) { - TerminalMessage = TerminalSession.getHistoryInstruction(uuid, historyIndex); - } - } - if(StringUtils.isEmpty(TerminalMessage)&&(!sshLogin)) { - session.sendMessage(new TextMessage(message.getPayload()+"\n$: ")); - }else { - // 将用户已经执行的指令存储到历史记录里 - if(!sshLogin) { - TerminalSession.setHistoryInstruction(uuid,TerminalMessage); - } - nezhaMessageHandle(session,TerminalMessage); - //将当前执行指令删除 - TerminalSession.removeTerminalMessage(uuid); - //将sshlogin登录状态外的其它基础配置恢复默认 - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", 0); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorFlag", false); - TerminalSession.setTerminalAttributeInfo(uuid, "historyIndex", 0); - } - }else if(message.asBytes()[0]==127&&sshLogin){ - // ssh登录时处理用户退格键 - TerminalSession.backspaceMessage(uuid,cursorIndex); - cursorIndex--; - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - return; - }else if(message.asBytes()[0]==127) { - String TerminalMessage = TerminalSession.getTerminalMessage(uuid); - if(historyIndex!=0 && cursorIndex != 0) { - if(StringUtils.isEmpty(TerminalMessage)) { - TerminalMessage = TerminalSession.getHistoryInstruction(uuid, historyIndex); - TerminalSession.setTerminalMessage(uuid, TerminalMessage, null); - cursorIndex=TerminalMessage.length(); - } - } - if(StringUtils.isEmpty(TerminalMessage)) { - return; - } - // 处理用户退格键 - byte[] fromHexAscii = ByteUtils.fromHexAscii("081b5b4b"); - boolean backspaceFlag = TerminalSession.backspaceMessage(uuid,cursorIndex); - if(backspaceFlag) { - session.sendMessage(new TextMessage(fromHexAscii)); - if(cursorFlag) { - String substring = TerminalMessage.substring(cursorIndex, TerminalMessage.length()); - session.sendMessage(new TextMessage(substring)); - // 将光标移到对应位置 - for(int i =0;i<Integer.valueOf(TerminalMessage.length())-cursorIndex;i++) { - fromHexAscii = ByteUtils.fromHexAscii("1B5B44"); - session.sendMessage(new TextMessage(fromHexAscii)); - } - } - cursorIndex--; - } - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - return; - }else{ - logger.info("terminal unstart uuid info {}",uuid); - TerminalSession.setTerminalMessage(uuid,message.getPayload(),cursorIndex); - //光标位置 - cursorIndex+=message.getPayload().length(); - // 不返回用户输入的ssh密码信息 - if(!sshLogin) { - session.sendMessage(new TextMessage(message.getPayload())); - if(cursorFlag) { - String TerminalMessage = TerminalSession.getTerminalMessage(uuid); - String substring = TerminalMessage.substring(cursorIndex, TerminalMessage.length()); - session.sendMessage(new TextMessage(substring)); - // 将光标移到对应位置 - for(int i =0;i<Integer.valueOf(TerminalMessage.length())-cursorIndex;i++) { - byte[] fromHexAscii = ByteUtils.fromHexAscii("1B5B44"); - session.sendMessage(new TextMessage(fromHexAscii)); - } - } - } - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", cursorIndex); - } - } - } catch (IOException e) { - // 出现异常将光标信息重置防止下一次无法正常执行命令 - logger.error("error info :",e); - - // cmd 信息保存 - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setCmd("Terminal due to abnormal disconnection"); - terminalCmd.setUuid(uuid); - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionStartTime"); - terminalCmd.setTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalCmdService.save(terminalCmd); - - // terminal sesssion 信息保存 - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); - sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); - sessionEntity.setUuid(uuid); - sessionEntity.setUserId((Long) TerminalSession.getTerminalAttributeInfo(uuid).get("userId")); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - sessionEntity.setStartTime(new Date()); - sessionEntity.setEndTime(new Date()); - terminalSessionService.save(sessionEntity); - - TerminalSession.removeTerminalAttributeInfo(uuid); - TerminalSession.removeTerminalMessage(uuid+"telnetFlag"); - session.sendMessage(new TextMessage(e.getMessage()+"\r\n")); - session.sendMessage(new TextMessage("Sorry! Nezha Terminal was closed, please try again. \r\n")); - if(ToolUtil.isNotEmpty(terminalClient)) { - terminalClient.disconnect(); - } - TerminalSession.remove(session); - // session.close(); - unloginUserHandle(session); - } - } - - @Override - public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { - super.handleTransportError(session, exception); - this.closeTerminal(session); - } - - @Override - public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { - TerminalSession.removeWindowSize(token); - super.afterConnectionClosed(session, status); - this.closeTerminal(session); - - // client 关闭后,处理 session 和 record 信息 - this.handleSessionAfterClientClose(uuid); - TerminalSession.removeTerminalAttributeInfo(uuid); - - - // 处理 monitor 窗口 - String uuid = (String) session.getAttributes().get("uuid"); - List<WebSocketSession> webSocketSessions = TerminalSession.terminalMonitorsMap.get(uuid); - if(CollectionUtils.isNotEmpty(webSocketSessions)){ - for (WebSocketSession socketSession : webSocketSessions) { - socketSession.sendMessage(new TextMessage("\u001B[01;31m\u001B[KConnection closed \u001B[m\u001B[K")); - } - TerminalSession.terminalMonitorsMap.remove(uuid); - } - } - - /** - * 窗口关闭后 - * 1. 处理 session 相关信息 - * 2. 处理 record 剩余文件信息 - * @param uuid - */ - private void handleSessionAfterClientClose(String uuid) { - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); - if (sessionEntity != null) { - sessionEntity.setEndTime(new Date()); - - // 正常连接状态 关闭窗口,将状态改为 已结束,其他不做处理 - if (Constants.SessionStatus.CONNECTING.getValue() == sessionEntity.getStatus()) { - sessionEntity.setStatus(Constants.SessionStatus.OVER.getValue()); - } - terminalSessionService.saveOrUpdate(sessionEntity); - - // 窗口关闭,处理 record 文件 - handleRecodeAfterClientClose(uuid, terminalRecordService); - } - } - - /** - * 窗口关闭后 - * 处理 record 剩余文件信息 - * @param uuid - */ - public static void handleRecodeAfterClientClose(String uuid, TerminalRecordService terminalRecordService) { - String fileName = Constant.TEMP_PATH + File.separator + uuid + ".log"; - File file = new File(fileName); - if(!file.exists()){ - return; - } - - Path path = Paths.get(fileName); - try { - // 将本次内容保存至数据库 - List<TerminalRecord> list = terminalRecordService.list(new LambdaQueryWrapper<TerminalRecord>().eq(TerminalRecord::getUuid, uuid).orderByAsc(TerminalRecord::getId)); - TerminalRecord terminalRecord = new TerminalRecord(); - terminalRecord.setUuid(uuid); - // 如果是第一次保存到库的话 , start time 为 0 - if (CollectionUtils.isEmpty(list)) { - terminalRecord.setStartTime(0); - } else { - // 其他的开始时间为上一次的结束时间 - terminalRecord.setStartTime(list.get(list.size() - 1).getEndTime()); - } - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionStartTime"); - terminalRecord.setEndTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalRecord.setContent(Files.readAllBytes(path)); - terminalRecordService.save(terminalRecord); - boolean delete = file.delete(); - if(delete) { - logger.debug("文件删除成功"); - }else { - logger.debug("文件删除失败"); - } - } catch (IOException e) { - logger.error(String.format("terminal record 文件入库失败,文件路径是: %s,错误信息是: %s", path.toString(), e.getMessage()), e); - } - } - - private TerminalClient getClient(WebSocketSession session, AssetAsset terminal) { - this.terminalClient = TerminalSession.get(session); - if (this.terminalClient == null && terminal != null) { - this.terminalClient = new TerminalClient(session, terminal, uuid); - TerminalSession.put(session, this.terminalClient); - TerminalSession.putTerminalInfo(token,uuid); - } - return this.terminalClient; - } - - private void closeTerminal(WebSocketSession session) throws IOException { - terminalClient = TerminalSession.remove(session); - if (terminalClient != null) { - AssetAsset account = terminalClient.getTerminal(); - if(account!=null){ - String rekey=account.getId() + "_" + terminalClient.getClientId(); - terminalContext.remove(rekey); - } - - terminalClient.disconnect(); - } - //解除实例 -// terminalClusterProcessor.unregistry(terminalToken); - } - - public void nezhaMessageHandle(WebSocketSession session, String message) throws JSchException, IOException { - // cmd 信息保存 - TerminalCmd terminalCmd = new TerminalCmd(); - terminalCmd.setCmd(message); - terminalCmd.setUuid(uuid); - - - // terminal session 信息保存 - TerminalSessionEntity sessionEntity = new TerminalSessionEntity(); - sessionEntity.setUuid(uuid); - sessionEntity.setUserId((Long) TerminalSession.getTerminalAttributeInfo(uuid).get("userId")); - sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); - sessionEntity.setAuthType(1); - sessionEntity.setProtocol(""); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - AssetAsset terminalInfo = terminalContext.get(uuid); - if (terminalInfo != null) { - sessionEntity.setAssetId(terminalInfo.getId()); - } else { - // 直接输入命令登录的,没有asset 信息,通过 host 尝试获取 - String host = TerminalSession.getTerminalMessage(uuid + "ip"); - AssetAsset asset = assetAssetService.getOne(new LambdaQueryWrapper<AssetAsset>().eq(AssetAsset::getManageIp, host)); - sessionEntity.setAssetId((asset != null) ? asset.getId() : null); - } - - logger.info("nezhaMessageHandle message info {}",message); - if(StringUtils.isEmpty(message)) { - message=""; - } - // 处理用户ssh登录问题 - Map terminalAttributeInfo = TerminalSession.getTerminalAttributeInfo(uuid); - boolean sshLogin = (boolean) terminalAttributeInfo.get("sshLogin"); - if(sshLogin) { - // cmd 信息 - terminalCmd.setCmd("Login"); - - // session 信息 - sessionEntity.setProtocol("SSH"); - sessionEntity.setHost(TerminalSession.getTerminalMessage(uuid + "ip")); - sessionEntity.setPort(Integer.valueOf(TerminalSession.getTerminalMessage(uuid + "port"))); - - sshLogin=false; - //获取到用户ssh pwd - AssetAsset terminal = new AssetAsset(); - terminal.setAuthProtocolPort(Integer.valueOf(TerminalSession.getTerminalMessage(uuid + "port"))); - - terminal.setAuthUsername(TerminalSession.getTerminalMessage(uuid + "user")); - terminal.setAuthType(SshType.ACCOUNT.getType()); - terminal.setAuthPin(Base64.getEncoder().encodeToString(message.getBytes())); - - sessionEntity.setLoginUser(TerminalSession.getTerminalMessage(uuid + "user")); - //连接服务 - try { - getClient(session, terminal); - int cols = toInt(session.getAttributes().get("cols").toString()); - int rows = toInt(session.getAttributes().get("rows").toString()); - int width = toInt(session.getAttributes().get("width").toString()); - int height = toInt(session.getAttributes().get("height").toString()); - - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionEntity", sessionEntity); - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionStartTime", System.currentTimeMillis()); - - terminalClient.openTerminal(cols, rows, width, height); - - // 连接之后 session 状态为 connecting - sessionEntity.setStatus(Constants.SessionStatus.CONNECTING.getValue()); - sessionEntity.setStartTime(new Date()); - } catch (IOException | JSchException e) { - // 如果出现异常连接失败 则将session中client信息清空 - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - sessionEntity.setStartTime(new Date()); - sessionEntity.setEndTime(new Date()); - - sshLogin=false; - TerminalSession.remove(session); - session.sendMessage(new TextMessage("Connection failed.")); - } - //连接后(不论成功失败)将基础设置重置 - TerminalSession.setTerminalAttributeInfo(uuid, "cursorIndex", 0); - TerminalSession.setTerminalAttributeInfo(uuid, "cursorFlag", false); - TerminalSession.setTerminalAttributeInfo(uuid,"historyIndex",0); - TerminalSession.setTerminalAttributeInfo(uuid, "sshLogin", false); - - long terminalSessionStartTime = (long) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionStartTime"); - terminalCmd.setTime((int) (System.currentTimeMillis() - terminalSessionStartTime)); - terminalCmdService.save(terminalCmd); - - terminalSessionService.save(sessionEntity); - }else if(message.startsWith("ssh")) { - sshLoginHandle(session,message,sshLogin); - }else if(message.startsWith("telnet")){ - telnetLoginHandle(session,message); - }else if(message.equals("help")) { - session.sendMessage(new TextMessage("\r\n$: Internal Commands:\r\n" + - "ssh: Connects to a host using the SSH protocol.\r\n" + - "telnet: Connects to a host using the TELNET protocol.\r\n" + - "clear: Clears the screen/address/command history.\r\n" + - "help: Displays this help. \r\n" + - "quit: Quits Local Shell. 'exit' does the same.\r\n" + - "$: ")); - }else if(message.matches("help\\s+ssh")) { - session.sendMessage(new TextMessage("\r\n$: NAME \r\n" + - "\n ssh - connects to a host using the SSH protocol. \r\n" + - "SYNOPSYS \r\n" + - "\n ssh user@host[ port] \r\n" + - "OPTIONS \r\n" + - "\n user Indicates the user's login name.\r\n" + - "\n pass If pass is definded, use password authentication.\r\n" + - "\n host Indicates the name, alias, or Internet address of the \r\n" + - "\n remote host.\r\n" + - "\n port Indicates a port number (address of an application).\r\n" + - "\n If the port is not specified, the default ssh port (22) is used.\r\n"+ - "$: ")); - }else if(message.matches("help\\s+telnet")) { - session.sendMessage(new TextMessage("\r\n$: NAME \r\n" + - "\n telnet - connects to a host using the TELNET protocol. \r\n" + - "SYNOPSYS \r\n" + - "\n telnet [user@]host [port] \r\n" + - "OPTIONS \r\n" + - "\n host Indicates the name, alias, or Internet address of the \r\n" + - "\n remote host.\r\n" + - "\n port Indicates a port number (address of an application).\r\n" + - "\n If the port is not specified, the default telnet port (23) is used.\r\n"+ - "$: ")); - }else if(message.matches("help\\s+clear")) { - session.sendMessage(new TextMessage("\r\n$: NAME\n" + - "clear - clears the screen \r\n"+ - "$: ")); - }else if(message.matches("help\\s+quit")) { - session.sendMessage(new TextMessage("\r\n$: NAME \r\n" + - "\n quit - quits application or connection. \r\n" + - "DESCRIPTION \r\n" + - "\n When a connection is not establish, quits application.\r\n" + - "\n Otherwise, quits connection. No parameters are required.\r\n" + - "\n exit does the same. \r\n" + - "\n cf) Press Ctrl + Alt + ] to fall back to Xshell prompt \r\n" + - "\n whlie connection is alive. \r\n"+ - "$: ")); - }else if(message.equals("quit")) { - session.close(); - }else if(message.equals("clear")){ - byte[] fromHexAscii = ByteUtils.fromHexAscii("1b5b333b4a1b5b481b5b324a"); - session.sendMessage(new TextMessage(fromHexAscii)); - session.sendMessage(new TextMessage("$: ")); - }else { - // 其它未知指令提示信息 - session.sendMessage(new TextMessage("\r\n$: command not found...\r\n" + - "Type `help' to learn how to use Nezha Terminal prompt. \r\n"+ - "$: ")); - } - } - - public static void unloginUserHandle(WebSocketSession session) throws IOException { - StringBuilder sb=new StringBuilder(); - sb.append("Welcome to Nezha Terminal! \r\n"); - sb.append("Type `help' to learn how to use Nezha Terminal prompt. \r\n"); - sb.append("$: "); - session.sendMessage(new TextMessage(sb.toString())); - } - - public void sshLoginHandle(WebSocketSession session,String message,boolean sshLogin) throws IOException{ - // 清空之前缓存的ssh登录系信息 - TerminalSession.removeTerminalMessage(uuid+"user"); - TerminalSession.removeTerminalMessage(uuid+"ip"); - TerminalSession.removeTerminalMessage(uuid+"port"); - String userInfo=null; - String port=null; - String user=null; - String ip=null; - String[] split = message.split("\\s"); - for(int i =0;i<split.length;i++) { - if(i==1) { - userInfo = split[i]; - }else if(i==2) { - port=split[i]; - } - } - if(StringUtils.isNotEmpty(userInfo)&&userInfo.contains("@")) { - String[] split2 = userInfo.split("@"); - for(int i=0;i<split2.length;i++) { - if(i==0) { - user=split2[i]; - }else if(i==1){ - ip=split2[i]; - } - } - } - if(StringUtils.isEmpty(user)||StringUtils.isEmpty(ip)) { - sshLogin=false; - session.sendMessage(new TextMessage("\r\nUnable to resolve host Connection failed.\r\nType `help' to learn how to use Xshell prompt.\r\n$: ")); - }else { - if(StringUtils.isEmpty(port)) { - port="22"; - } - //校验端口ip有效性 - if(!(CommonUtils.checkIp(ip)&&CommonUtils.checkPort(port))) { - session.sendMessage(new TextMessage("\r\nUnable to resolve host Connection failed.\r\nType `help' to learn how to use Xshell prompt.\r\n$: ")); - }else { - //将用户登录信息存储到当前会话中 记录标识符等待用户输入登录密码完成ssh登录 - List<String> sshLoginInfo =new ArrayList<String>(); - sshLoginInfo.add(user); - sshLoginInfo.add(ip); - sshLoginInfo.add(port); - TerminalSession.setTerminalMessage(uuid+"user",user,null); - TerminalSession.setTerminalMessage(uuid+"ip",ip,null); - TerminalSession.setTerminalMessage(uuid+"port",port,null); - sshLogin=true; - session.sendMessage(new TextMessage("\r\n"+TerminalSession.getTerminalMessage(uuid+"user")+"@"+TerminalSession.getTerminalMessage(uuid+"ip")+"'s password: ")); - } - } - TerminalSession.setTerminalAttributeInfo(uuid, "sshLogin", sshLogin); - } - - public void telnetLoginHandle(WebSocketSession session,String message) throws IOException{ - // 清空之前缓存的telnet登录系信息 - TerminalSession.removeTerminalMessage(uuid+"telip"); - TerminalSession.removeTerminalMessage(uuid+"telport"); - TerminalSession.removeTerminalMessage(uuid+"teluser"); - String port=null; - String ip=null; - String userInfo=null; - String user=null; - String[] split = message.split("\\s"); - for(int i =0;i<split.length;i++) { - if(i==1) { - userInfo = split[i]; - }else if(i==2) { - port=split[i]; - } - } - if(StringUtils.isNotEmpty(userInfo)&&userInfo.contains("@")) { - String[] split2 = userInfo.split("@"); - for(int i=0;i<split2.length;i++) { - if(i==0&&split2.length==2) { - user=split2[i]; - }else if(i==1&&split2.length==2){ - ip=split2[i]; - }else if(i==0&&split2.length==1) { - ip=split2[i]; - } - } - }else { - ip=split[1]; - } - if(StringUtils.isBlank(ip)||!CommonUtils.checkIp(ip)) { - session.sendMessage(new TextMessage("\r\nPlease check your Ip is correct \r\n$: ")); - return; - } - if(StringUtils.isBlank(port)) { - port="23"; - } - if(!CommonUtils.checkPort(port)) { - session.sendMessage(new TextMessage("\r\nPlease check your port is correct \r\n$: ")); - return; - } - if(StringUtils.isBlank(user)) { - user=""; - } - TerminalSession.setTerminalMessage(uuid+"teluser",user,null); - TerminalSession.setTerminalMessage(uuid+"telip",ip,null); - TerminalSession.setTerminalMessage(uuid+"telport",port,null); - //获取到用户ssh pwd - AssetAsset terminal = new AssetAsset(); - terminal.setAuthProtocolPort(Integer.valueOf(port)); - terminal.setAuthUsername(user); - - // 连接服务 terminal session 信息保存 - TerminalSessionEntity sessionEntity = new TerminalSessionEntity(); - sessionEntity.setUuid(uuid); - sessionEntity.setUserId((Long) TerminalSession.getTerminalAttributeInfo(uuid).get("userId")); - sessionEntity.setRemoteAddr(session.getRemoteAddress().getHostString()); - sessionEntity.setAuthType(1); - sessionEntity.setProtocol("TELNET"); - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - sessionEntity.setHost(ip); - sessionEntity.setPort(Integer.valueOf(port)); - - try { - getClient(session, terminal); - int cols = toInt(session.getAttributes().get("cols").toString()); - int rows = toInt(session.getAttributes().get("rows").toString()); - int width = toInt(session.getAttributes().get("width").toString()); - int height = toInt(session.getAttributes().get("height").toString()); - terminalClient.openTelnetTerminal(cols, rows, width, height); - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionEntity", sessionEntity); - TerminalSession.setTerminalAttributeInfo(uuid, "terminalSessionStartTime", System.currentTimeMillis()); - } catch (IOException e) { - // 连接失败 更改 terminal session 状态 - sessionEntity.setStatus(Constants.SessionStatus.CONNECTION_FAILED.getValue()); - sessionEntity.setStartTime(new Date()); - sessionEntity.setEndTime(new Date()); - - terminalSessionService.save(sessionEntity); -// session.sendMessage(new TextMessage("\r\nCould not connect to '"+TerminalSession.getTerminalMessage(uuid+"telip")+"' (port "+TerminalSession.getTerminalMessage(uuid+"telport")+"): Connection failed."+"\r\n$: ")); - session.sendMessage(new TextMessage("Connection failed.")); - TerminalSession.remove(session); - } - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalOneProcessor.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalOneProcessor.java deleted file mode 100644 index 1efcbbbc..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalOneProcessor.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - - -import cn.hutool.log.Log; - -import com.jcraft.jsch.JSchException; -import com.jcraft.jsch.SftpException; -import com.nis.common.utils.*; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.List; - -@Component -public class TerminalOneProcessor { - private Log logger= Log.get(); - - public R sendAll(String token, String cmd) throws IOException,UnsupportedEncodingException,RuntimeException { - - cmd = URLDecoder.decode(cmd, Constants.CHARSET_UTF8); - List<TerminalClient> terminalClients=null; - if(StringUtils.isEmpty(token)){ - terminalClients=TerminalSession.findClient(); - }else{ - TerminalClient terminalClient = TerminalSession.get(token); - if (terminalClient != null) { - terminalClients= TerminalSession.findClient(terminalClient.getHttpSessionId()); - } - } - if(ToolUtil.isNotEmpty(terminalClients)){ - for (TerminalClient client : terminalClients) { - client.write(cmd); - } - } - - return R.ok(); - } - - public R theme(String token, String theme) throws RuntimeException { - TerminalClient terminalClient = TerminalSession.get(token); - return R.ok(); - } - - public R resize(String token, Integer cols, Integer rows, Integer width, Integer height) throws IOException { - List<TerminalClient> terminalClients = TerminalSession.getAllTerminalClient(token); - if (ToolUtil.isNotEmpty(terminalClients)) { - for(TerminalClient terminalClient : terminalClients) { - terminalClient.resize(cols, rows, width, height); - } - } - return R.ok(); - } - - public R upload(String token, File file, String name, long size) { - TerminalClient terminalClient = TerminalSession.get(token); - logger.info("terminalClient-->",terminalClient==null?null:terminalClient.getClientId()); - boolean success = true; - if(CommonUtils.isEmpty(terminalClient)) { - logger.info("terminalClient upload fail terminal is null"); - success=false; - return R.error(RCode.TERMINAL_ISNULL); - } - if(!terminalClient.isTransfer()) { - logger.info("terminalClient upload fail telnet can not transfer"); - success=false; - return R.error(RCode.TERMINAL_TELNET_TRANSFER); - } - if (!file.getParentFile().exists()) { - boolean mkdirs = file.getParentFile().mkdirs(); - if(mkdirs) { - logger.debug("批量文件创建成功"); - }else { - logger.debug("批量文件创建失败"); - } - } - try { - if (!file.exists()) { - boolean createNewFile = file.createNewFile(); - if(createNewFile) { - logger.debug("文件创建成功"); - }else { - logger.debug("文件创建失败"); - } - } - if (terminalClient != null) { - terminalClient.upload(file.getAbsolutePath(), name, size); - } - - logger.debug("上传完成"); - } catch (InterruptedException | JSchException | SftpException | IOException e) { - logger.error(e); - success = false; - } - - return R.ok(success); - } - - public void download(String uuid, String path,HttpServletResponse res) { - InputStream downloadFile =null; - TerminalClient terminalClient = TerminalSession.get(uuid); - logger.info("terminalClient-->",terminalClient==null?null:terminalClient.getClientId()); - if(CommonUtils.isEmpty(terminalClient)) { - logger.info("terminalClient download fail terminal is null"); - return; - } - if(!terminalClient.isTransfer()) { - logger.info("terminalClient upload fail telnet can not transfer"); - return; - } - try { - terminalClient.download(path,res); - } catch (IOException | SftpException | JSchException | InterruptedException e) { - logger.error(e); - } - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalSession.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalSession.java deleted file mode 100644 index de5b7f0f..00000000 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalSession.java +++ /dev/null @@ -1,363 +0,0 @@ -/** - * Copyright (c) 2015 The Nezha Project - * <p> - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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 com.nis.modules.terminal.config; - -import cn.hutool.core.util.StrUtil; -import com.nis.common.utils.DigestUtils; -import com.nis.common.utils.ToolUtil; -import org.apache.commons.lang3.StringUtils; -import org.springframework.http.HttpHeaders; -import org.springframework.util.ObjectUtils; -import org.springframework.web.socket.TextMessage; -import org.springframework.web.socket.WebSocketSession; - -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import static com.nis.common.utils.CommonUtils.notEmpty; - -public class TerminalSession implements Serializable { - - /** - * 当前websockt连接信息对应的服务器信息 将来可以实现远程连接列表 用以进行主动断开服务器连接功能 - */ - public static final Map<WebSocketSession, TerminalClient> terminalSession = new HashMap<WebSocketSession, TerminalClient>(); - - /** - * 保存所有正在连接的服务器列表信息 - */ - public static final Map<String, Set<String>> terminalInfo = new HashMap<String, Set<String>>(); - - /** - * terminal 对应的 monitors - */ - public static final Map<String, List<WebSocketSession>> terminalMonitorsMap = new ConcurrentHashMap<>(); - - /** - * 当前用户操作的服务器指令信息 - */ - public static final Map<String,String> terminalMessageInfo = new HashMap<String,String>(); - - // terminal cmd 信息 - public static final Map<String, List<Character>> terminalCmdInfo = new HashMap(); - - public static void removeTerminalCmd(String uuid) { - terminalCmdInfo.remove(uuid); - } - - /** - * 用以保存用户连接websocket后的指令历史记录信息 包含未登录以及登录服务器后的历史指令 - */ - public static final Map<String,List<String>> userInstructions =new HashMap<String,List<String>>(); - - /** - * 主要用于存放client相关需要属性 - */ - public static final Map<String,Object> clientAttributeInfo =new HashMap<String,Object>(); - /** - * 保存用户连接当前websocket的一些配置信息 包括光标位置、未登录时的一些状态信息 - * 每个连接功能会公用一个terminalHandler类 将各自属性根据uuid以及相应的状态信息进行保存 - */ - public static final Map<String,Map> terminalAttributeInfo = new HashMap<String,Map>(); - - /** - * 管理前端窗口数量 - */ - public static final Map<String,Integer> windowSize =new HashMap<String,Integer>(); - - public static Integer getWindowSize(String token) { - Integer result = windowSize.get(token); - if(ToolUtil.isEmpty(result)) { - result=1; - } - return result; - } - - public static void setWindowSize(String token) { - Integer result = windowSize.get(token); - if(ToolUtil.isEmpty(result)) { - result=1; - }else { - result+=1; - } - windowSize.put(token, result); - } - - public static void removeWindowSize(String token) { - Integer result = windowSize.get(token); - if(ToolUtil.isEmpty(result)||result==0) { - windowSize.remove(token); - }else { - result-=1; - } - windowSize.put(token, result); - } - - - public static void setTerminalAttributeInfo(String uuid,String key,Object value) { - Map map = terminalAttributeInfo.get(uuid); - if(!ObjectUtils.isEmpty(map)) { - map.put(key, value); - terminalAttributeInfo.put(uuid, map); - } - } - - public static Map getTerminalAttributeInfo(String uuid) { - Map map = terminalAttributeInfo.get(uuid); - if(ObjectUtils.isEmpty(map)) { - //第一次获取基础配置的时候 初始化配置信息 - map=new HashMap(); - //指令光标位置信息 - map.put("cursorIndex", 0); - //光标是否移动标识 - map.put("cursorFlag", false); - //历史记录位置信息 - map.put("historyIndex", 0); - //ssh连接登录标识 - map.put("sshLogin", false); - //tab键标识 - map.put("tabFlag", false); - - // 光标位置 - map.put("cmdCharPos", 0); - terminalAttributeInfo.put(uuid, map); - } - return map; - } - - public static void removeTerminalAttributeInfo(String uuid) { - terminalAttributeInfo.remove(uuid); - } - - public static String getHistoryInstruction(String uuid,Integer index) { - List<String> lists = userInstructions.get(uuid); - if(ObjectUtils.isEmpty(lists)) { - return ""; - }else if(index>lists.size()){ - return ""; - }else if(lists.size()-index==lists.size()){ - return ""; - }else { - return lists.get(lists.size()-index); - } - } - - public static void setHistoryInstruction(String uuid,String message) { - List<String> lists = userInstructions.get(uuid); - if(ObjectUtils.isEmpty(lists)) { - lists=new ArrayList<String>(); - lists.add(message); - userInstructions.put(uuid, lists); - }else { - lists.add(message); - } - } - - public static String getTerminalMessage(String uuid) { - return terminalMessageInfo.get(uuid); - } - - public static void setTerminalMessage(String uuid,String message,Integer cursorIndex) { - String string = terminalMessageInfo.get(uuid); - if (StrUtil.isNotBlank(string)) { - // 根据光标位置来追加字符出现的位置 - if(cursorIndex==null||cursorIndex==string.length()) { - string=string+message; - }else { - String prefix = string.substring(0, cursorIndex); - String suffix = string.substring(cursorIndex, string.length()); - string=prefix+message+suffix; - } - }else { - string=message; - } - terminalMessageInfo.put(uuid,string); - } - /** - * 清空当前用户指令 - * @param uuid - */ - public static void removeTerminalMessage(String uuid) { - terminalMessageInfo.remove(uuid); - } - - public static boolean backspaceMessage(String uuid,Integer cursorIndex) { - boolean flag=false; - String string = terminalMessageInfo.get(uuid); - if(StringUtils.isNotBlank(string)) { - if(cursorIndex==string.length()) { - string=string.substring(0, string.length()-1); - }else if(cursorIndex==0&&string.length()>0){ - // 如果用户将光标移到最开始的地方 则不进行任何删除操作 - return false; - }else { - String prefix = string.substring(0, cursorIndex-1); - String suffix = string.substring(cursorIndex, string.length()); - string=prefix+suffix; - } - if(StringUtils.isNotBlank(string)) { - terminalMessageInfo.put(uuid, string); - flag=true; - }else { - terminalMessageInfo.remove(uuid); - flag=true; - } - } - return flag; - } - - public static TerminalClient get(WebSocketSession key) { - return terminalSession.get(key); - } - - public static TerminalClient get(String key) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient client = entry.getValue(); - if(StrUtil.equals(client.getClientId(),key)) { - return client; - } - } - return null; - } - - public static List<TerminalClient> getAllTerminalClient(String token){ - List<TerminalClient> terminalClients=new ArrayList<TerminalClient>(); - Set<String> terminalInfos = terminalInfo.get(token); - Map<String,TerminalClient> map=new HashMap<String,TerminalClient>(); - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient client = entry.getValue(); - map.put(client.getClientId(), client); - } - if(ToolUtil.isNotEmpty(terminalInfos)) { - for(String terminalInfo : terminalInfos) { - TerminalClient terminalClient = map.get(terminalInfo); - if(terminalClient!=null) { - terminalClients.add(terminalClient); - } - } - } - return terminalClients; - } - - public static void put(WebSocketSession key, TerminalClient terminalClient) { - terminalSession.put(key, terminalClient); - } - - public static void putTerminalInfo(String token,String uuid) { - Set<String> terminalInfos = terminalInfo.get(token); - if(terminalInfos==null) { - terminalInfos=new HashSet<String>(); - terminalInfos.add(uuid); - terminalInfo.put(token, terminalInfos); - }else { - terminalInfos.add(uuid); - } - } - - public static TerminalClient remove(WebSocketSession key) { - return terminalSession.remove(key); - } - - /*public static boolean isOpened(Account terminal) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - if (entry.getValue().getTerminal().equals(terminal)) { - return true; - } - } - return false; - }*/ - - public static List<TerminalClient> findClient(Serializable sessionId) throws IOException { - List<TerminalClient> terminalClients = new ArrayList<TerminalClient>(0); - if (notEmpty(terminalSession)) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient terminalClient = entry.getValue(); - if (terminalClient != null && terminalClient.getTerminal() != null) { - if (StrUtil.equals(terminalClient.getHttpSessionId(),sessionId.toString())) { - terminalClients.add(terminalClient); - } - } - } - } - return terminalClients; - } - - public static List<TerminalClient> findClient(){ - List<TerminalClient> terminalClients = new ArrayList<TerminalClient>(0); - if (notEmpty(terminalSession)) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient terminalClient = entry.getValue(); - terminalClients.add(terminalClient); - } - } - return terminalClients; - } - - /*public static WebSocketSession findSession(Account terminal) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient client = entry.getValue(); - if (client.getTerminal().equals(terminal)) { - return entry.getKey(); - } - } - return null; - }*/ - - /** - * 通过 uuid 得到 webSocketSession 对象 - * @param uuid - * @return - */ - public static WebSocketSession findSession(String uuid) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient client = entry.getValue(); - if (client.getClientId().equalsIgnoreCase(uuid)) { - return entry.getKey(); - } - } - return null; - } - - public static void exit(HttpServletRequest request) throws IOException { - String userAgent = request.getHeader(HttpHeaders.USER_AGENT); - if (userAgent != null) { - userAgent = userAgent.replaceAll("\\s+", ""); - userAgent = DigestUtils.md5Hex(userAgent); - } - - if (notEmpty(terminalSession)) { - for (Map.Entry<WebSocketSession, TerminalClient> entry : terminalSession.entrySet()) { - TerminalClient terminalClient = entry.getValue(); - if(StrUtil.equals(terminalClient.getHttpSessionId(),request.getSession().getId()) - || terminalClient.getHttpSessionId().equals(userAgent)) { - terminalClient.disconnect(); - terminalClient.getWebSocketSession().sendMessage(new TextMessage("Sorry! Session was invalidated, so Nezha Terminal changed to closed. ")); - terminalClient.getWebSocketSession().close(); - } - } - } - } - -} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/WebSocketConfig.java b/nz-admin/src/main/java/com/nis/modules/terminal/config/WebSocketConfig.java index ada083e1..e317b327 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/WebSocketConfig.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/config/WebSocketConfig.java @@ -1,5 +1,9 @@ package com.nis.modules.terminal.config; +import com.nis.modules.terminal.backend.TerminalHandler; +import com.nis.modules.terminal.backend.TerminalMonitorHandler; +import com.nis.modules.terminal.interceptor.TerminalHandShakerInterceptor; +import com.nis.modules.terminal.interceptor.TerminalMonitorHandShakerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; @@ -11,8 +15,8 @@ import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(new TerminalHandler(),"/terminal.ws").setAllowedOrigins("*").addInterceptors(new TerminalHandShaker()); - registry.addHandler(new TerminalMonitorHandler(), "/terminal/monitor.ws").setAllowedOrigins("*").addInterceptors(new TerminalMonitorHandShaker()); + registry.addHandler(new TerminalHandler(),"/terminal.ws").setAllowedOrigins("*").addInterceptors(new TerminalHandShakerInterceptor()); + registry.addHandler(new TerminalMonitorHandler(), "/terminal/monitor.ws").setAllowedOrigins("*").addInterceptors(new TerminalMonitorHandShakerInterceptor()); } @Bean diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/controller/TerminalHandlerController.java b/nz-admin/src/main/java/com/nis/modules/terminal/controller/TerminalHandlerController.java index 160745f4..44dcccbe 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/controller/TerminalHandlerController.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/controller/TerminalHandlerController.java @@ -1,153 +1,77 @@ package com.nis.modules.terminal.controller;
-import cn.hutool.core.io.FileUtil;
import cn.hutool.log.Log;
-import com.nis.common.exception.NZException;
+import com.nis.common.annotation.SysLog;
import com.nis.common.smartvalidate.ValidateUtils;
import com.nis.common.utils.*;
import com.nis.common.xss.XssUtil;
-import com.nis.modules.terminal.config.TerminalOneProcessor;
+import com.nis.modules.terminal.backend.TerminalClient;
+import com.nis.modules.terminal.backend.TerminalSession;
import com.nis.modules.terminal.entity.TerminalConfigDto;
import com.nis.modules.terminal.service.TerminalCmdService;
import com.nis.modules.terminal.service.TerminalRecordService;
import com.nis.modules.terminal.service.TerminalSessionService;
-import org.apache.commons.lang3.StringUtils;
+import com.nis.modules.terminal.service.TerminalSftpLogService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import java.io.File;
-import java.io.IOException;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
@RestController
@RequestMapping("/terminal")
public class TerminalHandlerController {
-
- private Log logger = Log.get();
-
- @Autowired
- private TerminalOneProcessor terminalOneProcessor;
- @Autowired
- private TerminalSessionService terminalSessionService;
+ private static final Log log = Log.get();
- @Autowired
+ @Autowired
private TerminalCmdService terminalCmdService;
- @Autowired
+ @Autowired
private TerminalRecordService terminalRecordService;
-
- @Value("${nezha.uploadTempPath}")
+
+ @Autowired
+ private TerminalSftpLogService terminalSftpLogService;
+
+ @Autowired
+ private TerminalSessionService terminalSessionService;
+
+ @Value("${nezha.uploadTempPath}")
private String configUploadPath;
-
- @PostMapping(value = "resize")
- public R resize(ServletRequest req, @RequestBody TerminalConfigDto dto) throws IOException,RuntimeException {
- HttpServletRequest request=(HttpServletRequest) req;
- String token=request.getHeader(Constant.AUTH_TOKEN_CODE);
- Integer cols = dto.getCols();
- Integer height = dto.getHeight();
- Integer rows = dto.getRows();
- Integer width = dto.getWidth();
- if(cols==null||height==null||rows==null||width==null) {
- throw new NZException(RCode.TERMINAL_PARAM_ISNULL);
- }else {
- return terminalOneProcessor.resize(token, cols, rows, width, height);
- }
- }
-
- @PostMapping(value = "upload")
- public R upload(HttpSession httpSession, String uuid, @RequestParam(value = "file", required = false) MultipartFile file, String path) throws RuntimeException {
- if(StringUtils.isBlank(uuid)) {
- throw new NZException(RCode.TERMINAL_UUID_ISNULL);
- }
- if(StringUtils.isBlank(path)) {
- throw new NZException(RCode.TERMINAL_PATH_ISNULL);
- }
- if(CommonUtils.isEmpty(file)) {
- throw new NZException(RCode.TERMINAL_FILE_ISNULL);
- }
- String rootPath=null;
- try{
- File temp= FileUtil.file("");
- rootPath = temp.getAbsolutePath();
- logger.info("项目根目录["+rootPath+"]");
- }catch (RuntimeException e){
- logger.error("error info :",e);
- }
- String tmpPath=rootPath+configUploadPath;
- File uploadDir=FileUtil.file(tmpPath);
- if(!uploadDir.exists()){
- boolean mkdirs = uploadDir.mkdirs();
- if(mkdirs) {
- logger.debug("批量创建成功");
- }else {
- logger.debug("批量创建失败");
- }
- }else{//存在同名文件/文件夹
- if(!uploadDir.isDirectory()){//是一个同名文件
- boolean delete = uploadDir.delete();
- if(delete) {
- logger.debug("文件夹删除成功");
- }else {
- logger.debug("文件夹删除失败");
- }
- boolean mkdirs = uploadDir.mkdirs();
- if(mkdirs) {
- logger.debug("批量创建成功");
- }else {
- logger.debug("批量创建失败");
- }
- }
+ @PostMapping(value = "resize")
+ @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.TERMINAL)
+ public R resize(@RequestHeader(name = "Authorization", required = true) String token,
+ @RequestBody TerminalConfigDto dto) {
+ Integer cols = dto.getCols();
+ Integer height = dto.getHeight();
+ Integer rows = dto.getRows();
+ Integer width = dto.getWidth();
+ if (Tool.ObjectUtil.hasEmpty(cols, height, rows, width)) {
+ return R.error(RCode.TERMINAL_PARAM_ISNULL);
}
- File tempFile = FileUtil.file(tmpPath, file.getOriginalFilename());
- logger.debug("上传临时文件["+tempFile.getAbsolutePath()+"]");
+ log.info("[resize] [begin]");
try {
- file.transferTo(tempFile);
- if (CommonUtils.isEmpty(path)) {
- path = ".";
- } else {
- if (path.endsWith("/")) {
- path = path.substring(0, path.lastIndexOf("/"));
- }
+ List<TerminalClient> allTerminalClients = TerminalSession.TERMINAL_SESSION.values().stream().distinct().collect(Collectors.toList());
+ List<TerminalClient> resizeClients = allTerminalClients.stream().filter(terminalClient -> Tool.StrUtil.equals(token, terminalClient.getToken())).collect(Collectors.toList());
+ log.info("[resize] [all session: {}] [token: {}] [resize session: {}]", allTerminalClients.size(), token, resizeClients.size());
+
+ for (TerminalClient terminalClient : resizeClients) {
+ // resize
+ terminalClient.resize(cols, rows, width, height);
}
- logger.debug("上传目录:["+path+"]");
- // tempFile.delete();
- return terminalOneProcessor.upload(uuid, tempFile, path + "/" + file.getOriginalFilename(), file.getSize());
- } catch (IOException | IllegalStateException e) {
- logger.error("error info :",e);
- throw new NZException(RCode.SYS_ERROR);
- }
- }
-
- @PostMapping(value = "download")
- public void download(HttpSession httpSession,HttpServletResponse res, @RequestBody Map<String,String> param) throws RuntimeException {
- String uuid = param.get("uuid");
- String path = param.get("path");
- if(StringUtils.isBlank(uuid)) {
- throw new NZException(RCode.TERMINAL_UUID_ISNULL);
- }
- if(StringUtils.isBlank(path)) {
- throw new NZException(RCode.TERMINAL_PATH_ISNULL);
- }
- try {
- // 判断当前路径是绝对路径还是相对路径
- if(!path.startsWith("/")) {
- path="./"+path;
- }
- terminalOneProcessor.download(uuid,path,res);
- } catch (RuntimeException e) {
- logger.error("error info :",e);
- throw new NZException(RCode.SYS_ERROR);
+ log.info("[resize] [finshed]");
+ } catch (Exception e) {
+ log.error(e, "[resize] [error.]");
+ return R.error();
}
+ return R.ok();
}
/**
@@ -157,6 +81,7 @@ public class TerminalHandlerController { * @return
*/
@GetMapping("/session")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
public R querySessionPage(@RequestParam Map<String, Object> params) {
params = (Map<String, Object>) XssUtil.filterParameters((Map) params);
PageUtils page = terminalSessionService.queryPage(params);
@@ -170,6 +95,7 @@ public class TerminalHandlerController { * @return
*/
@GetMapping("/cmd")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
public R queryCmdPage(@RequestParam Map<String, Object> params) {
params = (Map<String, Object>) XssUtil.filterParameters((Map) params);
Map map = terminalCmdService.queryCmdInfos(params);
@@ -178,6 +104,7 @@ public class TerminalHandlerController { @PutMapping("/kill")
@RequiresPermissions({"terminal:kill"})
+ @SysLog(operation = OperationEnum.UNKNOWN, type = TypeEnum.TERMINAL)
public R killTerminal(@RequestBody Map<String, String> params) {
ValidateUtils.is(params.get("uuid")).notNull(RCode.TERMINAL_UUID_ISNULL);
@@ -186,10 +113,130 @@ public class TerminalHandlerController { }
@GetMapping("/record")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
public R queryTerminalRecord(@RequestParam Map<String, Object> params) {
params = (Map<String, Object>) XssUtil.filterParameters((Map) params);
Map map = terminalRecordService.queryTerminalRecordInfos(params);
return R.ok(map);
}
-
+
+ @PostMapping("/login")
+ @SysLog(operation = OperationEnum.ADD, type = TypeEnum.TERMINAL)
+ public Map<Object, Object> login(@RequestHeader(name = "Authorization") String token,
+ @RequestBody TerminalConfigDto configEntity) {
+ Map<Object, Object> map = terminalSessionService.login(token, configEntity);
+ return map;
+ }
+
+ @PostMapping("/login/duplicate")
+ @SysLog(operation = OperationEnum.ADD, type = TypeEnum.TERMINAL)
+ public R loginDuplicate(@RequestHeader(name = "Authorization") String token,
+ @RequestBody TerminalConfigDto terminalConfigDto) {
+ ValidateUtils.is(terminalConfigDto.getUuid()).notNull(RCode.TERMINAL_UUID_ISNULL);
+
+ String uuid = terminalConfigDto.getUuid();
+ Integer width = terminalConfigDto.getWidth();
+ Integer height = terminalConfigDto.getHeight();
+ Integer cols = terminalConfigDto.getCols();
+ Integer rows = terminalConfigDto.getRows();
+
+ return R.ok(
+ terminalSessionService.duplicateSession(token, uuid, width, height, cols, rows)
+ );
+ }
+
+ @PostMapping("/sftp/ls")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
+ public R ls(@RequestBody Map<String, String> param) {
+ String uuid = param.get("uuid");
+ String path = param.get("path");
+ ValidateUtils.is(uuid).notNull(RCode.TERMINAL_UUID_ISNULL);
+ return R.ok(
+ terminalSessionService.lsOfSftp(uuid, Tool.StrUtil.emptyToDefault(path, "/"))
+ );
+ }
+
+ @PostMapping("/sftp/mkdir")
+ @SysLog(operation = OperationEnum.ADD, type = TypeEnum.TERMINAL)
+ public R mkdir(@RequestBody Map<String, String> param) {
+ String uuid = param.get("uuid");
+ String path = param.get("path");
+ ValidateUtils.is(uuid).notNull(RCode.TERMINAL_UUID_ISNULL)
+ .and(path).notNull(RCode.TERMINAL_PATH_ISNULL);
+
+ terminalSessionService.mkdirOfSftp(uuid, path);
+ return R.ok();
+ }
+
+ @PostMapping("/sftp/rm")
+ @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.TERMINAL)
+ public R rm(@RequestBody Map<String, String> param) {
+ String uuid = param.get("uuid");
+ String path = param.get("path");
+ ValidateUtils.is(uuid).notNull(RCode.TERMINAL_UUID_ISNULL)
+ .and(path).notNull(RCode.TERMINAL_PATH_ISNULL);
+
+ terminalSessionService.rmOfSftp(uuid, path);
+ return R.ok();
+ }
+
+ @PutMapping("/sftp/upload")
+ @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.TERMINAL)
+ public R upload(@RequestParam(value = "file") MultipartFile file,
+ @RequestParam String uuid, @RequestParam String path) {
+
+ String tid = terminalSessionService.uploadOfSftp(uuid, path, file);
+ return R.ok().putData("tid", tid);
+ }
+
+
+ @GetMapping("/sftp/process/{tid}")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
+ public R querySftpUploadProcess(@PathVariable("tid") String tid) {
+ return R.ok(
+ terminalSessionService.querySftpUploadProcess(tid)
+ );
+ }
+
+ @DeleteMapping("/sftp/cancel/{tid}")
+ @SysLog(operation = OperationEnum.DELETE, type = TypeEnum.TERMINAL)
+ public R cancelUpload(@PathVariable("tid") String tid) {
+ terminalSessionService.cancelUpload(tid);
+ return R.ok();
+ }
+
+ @PostMapping("/sftp/download")
+ @SysLog(operation = OperationEnum.UNKNOWN, type = TypeEnum.TERMINAL)
+ public void download(@RequestBody Map<String, String> param, HttpServletResponse response) {
+ String uuid = param.get("uuid");
+ String path = param.get("path");
+ ValidateUtils.is(uuid).notNull(RCode.TERMINAL_UUID_ISNULL)
+ .and(path).notNull(RCode.TERMINAL_PATH_ISNULL);
+
+ terminalSessionService.downloadOfSftp(uuid, path, response);
+ }
+
+ @PutMapping("/sftp/rename")
+ @SysLog(operation = OperationEnum.UPDATE, type = TypeEnum.TERMINAL)
+ public R rename(@RequestBody Map<String, String> param) {
+ String uuid = param.get("uuid");
+ String oldPath = param.get("oldPath");
+ String newPath = param.get("newPath");
+
+ ValidateUtils.is(uuid).notNull(RCode.TERMINAL_UUID_ISNULL)
+ .and(oldPath).notNull(RCode.TERMINAL_PATH_ISNULL)
+ .and(newPath).notNull(RCode.TERMINAL_NEW_PATH_ISNULL);
+
+ terminalSessionService.renameFileOfSftp(uuid, oldPath, newPath);
+ return R.ok();
+ }
+
+
+ @GetMapping("/sftp/log")
+ @SysLog(operation = OperationEnum.QUERY, type = TypeEnum.TERMINAL)
+ public R querySftpLog(@RequestParam Map<String, Object> params) {
+ PageUtils page = terminalSftpLogService.querySftpLogPage(params);
+ return R.ok(page);
+ }
+
}
diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/dao/TerminalSftpLogDao.java b/nz-admin/src/main/java/com/nis/modules/terminal/dao/TerminalSftpLogDao.java new file mode 100644 index 00000000..d8032edb --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/dao/TerminalSftpLogDao.java @@ -0,0 +1,10 @@ +package com.nis.modules.terminal.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.nis.modules.terminal.entity.TerminalSftpLog; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TerminalSftpLogDao extends BaseMapper<TerminalSftpLog>{ + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalConfigDto.java b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalConfigDto.java index 5282de66..afda6c41 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalConfigDto.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalConfigDto.java @@ -4,8 +4,57 @@ import lombok.Data; @Data
public class TerminalConfigDto {
- private Integer height;
- private Integer width;
- private Integer cols;
- private Integer rows;
+
+ /**
+ * session id
+ */
+ private String uuid;
+
+ /**
+ * 窗口宽度
+ */
+ private Integer height;
+
+ /**
+ * 窗口高度
+ */
+ private Integer width;
+
+ /**
+ * 显示的列数
+ */
+ private Integer cols;
+
+ /**
+ * 显示的行数
+ */
+ private Integer rows;
+
+ /**
+ * asset id, 与其他连接信息参数互斥,
+ * 1. 不能同时为空
+ * 2. 同时存在时,以 asset id 为主
+ */
+ private Integer assetId;
+
+ private String host;
+
+ private Integer port;
+
+ private Integer authProtocol;
+
+ private Integer authProtocolPort;
+
+ private Integer authType;
+
+ private String authUsername;
+
+ private String authPin;
+
+ private String authPriKey;
+
+ private String authUserTip;
+
+ private String authPinTip;
+
}
diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalRecord.java b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalRecord.java index 8af8dc88..d8728e2e 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalRecord.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalRecord.java @@ -35,9 +35,19 @@ public class TerminalRecord { private Integer endTime; /** + * 存储模式,1: 本地存储,2:S3对象存储 + */ + private Integer storageType; + + /** + * S3 path + */ + private String path; + + /** * 文件内容 * 记录的是 session开始后的时间偏移量 * 超过定义临时文件大小后,再新增一条记录 */ private byte[] content; -}
\ No newline at end of file +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSessionEntity.java b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSessionEntity.java index 50306b12..4dd79d1e 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSessionEntity.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSessionEntity.java @@ -109,6 +109,12 @@ public class TerminalSessionEntity implements Serializable { */ @TableField(exist = false) private Integer cmdNum; + + /** + * 文件操作数量 + */ + @TableField(exist = false) + private Integer sftpNum; @Override public String toString() { diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSftpLog.java b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSftpLog.java new file mode 100644 index 00000000..f07c0bf0 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/entity/TerminalSftpLog.java @@ -0,0 +1,52 @@ +package com.nis.modules.terminal.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * terminal_sftp_log + * + * @author shizhendong + * @date 2022-10-31 + */ +@Data +@TableName("terminal_sftp_log") +@NoArgsConstructor +public class TerminalSftpLog { + + @TableId + private Integer id; + + /** + * session id + */ + private String uuid; + + /** + * type + * 1: 上传文件 + * 2:下载文件 + * 3:新建文件夹 + * 4:删除文件 + */ + private Integer type; + + /** + * 文件名 + */ + private String name; + + /** + * 时间戳 + */ + private Long ts; + + public TerminalSftpLog(String uuid, Integer type, String name, Long ts) { + this.uuid = uuid; + this.type = type; + this.name = name; + this.ts = ts; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalHandShaker.java b/nz-admin/src/main/java/com/nis/modules/terminal/interceptor/TerminalHandShakerInterceptor.java index 01c0d4af..3b8763cb 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalHandShaker.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/interceptor/TerminalHandShakerInterceptor.java @@ -19,9 +19,9 @@ * under the License. */ -package com.nis.modules.terminal.config; +package com.nis.modules.terminal.interceptor; -import org.apache.commons.lang.StringUtils; +import com.nis.modules.terminal.utils.TerminalConstant; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; @@ -32,56 +32,26 @@ import org.springframework.web.socket.server.support.HttpSessionHandshakeInterce import javax.servlet.http.HttpSession; import java.util.Map; +/** + * HttpSessionHandshakeInterceptor + */ @Component -public class TerminalHandShaker extends HttpSessionHandshakeInterceptor { +public class TerminalHandShakerInterceptor extends HttpSessionHandshakeInterceptor { @Override public synchronized boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; - HttpSession session = servletRequest.getServletRequest().getSession(); attributes.put("cols", servletRequest.getServletRequest().getParameter("cols")); attributes.put("rows", servletRequest.getServletRequest().getParameter("rows")); attributes.put("width", servletRequest.getServletRequest().getParameter("width")); attributes.put("height", servletRequest.getServletRequest().getParameter("height")); - // 线程安全的map是不允许value为null 所以存入空字符 - String assetId = servletRequest.getServletRequest().getParameter("assetId"); - String accountId = servletRequest.getServletRequest().getParameter("accountId"); - - String host = servletRequest.getServletRequest().getParameter("host"); - String port = servletRequest.getServletRequest().getParameter("port"); - String authProtocol = servletRequest.getServletRequest().getParameter("authProtocol"); - String authProtocolPort = servletRequest.getServletRequest().getParameter("authProtocolPort"); - String authType = servletRequest.getServletRequest().getParameter("authType"); - String authUsername = servletRequest.getServletRequest().getParameter("authUsername"); - String authPin = servletRequest.getServletRequest().getParameter("authPin"); - String authPriKey = servletRequest.getServletRequest().getParameter("authPriKey"); - String authUserTip = servletRequest.getServletRequest().getParameter("authUserTip"); - String authPinTip = servletRequest.getServletRequest().getParameter("authPinTip"); - - if(StringUtils.isBlank(assetId)) { - assetId=""; - } - if(StringUtils.isBlank(accountId)) { - accountId=""; - } - attributes.put("assetId", assetId); - attributes.put("accountId", accountId); - - attributes.put("host", StringUtils.isEmpty(host) ? "" : host); - attributes.put("port", StringUtils.isEmpty(port) ? "" : port); - attributes.put("authProtocol", StringUtils.isEmpty(authProtocol) ? "" : authProtocol); - attributes.put("authProtocolPort", StringUtils.isEmpty(authProtocolPort) ? "" : authProtocolPort); - attributes.put("authType", StringUtils.isEmpty(authType) ? "" : authType); - attributes.put("authUsername", StringUtils.isEmpty(authUsername) ? "" : authUsername); - attributes.put("authPin", StringUtils.isEmpty(authPin) ? "" : authPin); - attributes.put("authPriKey", StringUtils.isEmpty(authPriKey) ? "" : authPriKey); - attributes.put("authUserTip", StringUtils.isEmpty(authUserTip) ? "" : authUserTip); - attributes.put("authPinTip", StringUtils.isEmpty(authPinTip) ? "" : authPinTip); attributes.put("uuid", servletRequest.getServletRequest().getParameter("uuid")); attributes.put("terminalToken", servletRequest.getServletRequest().getParameter("token")); - attributes.put(Constants.PARAM_HTTP_SESSION_ID_KEY, session.getId()); + + HttpSession session = servletRequest.getServletRequest().getSession(); + attributes.put(TerminalConstant.PARAM_HTTP_SESSION_ID_KEY, session.getId()); } return super.beforeHandshake(request, response, wsHandler, attributes); } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalMonitorHandShaker.java b/nz-admin/src/main/java/com/nis/modules/terminal/interceptor/TerminalMonitorHandShakerInterceptor.java index 131e6669..7367746e 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/TerminalMonitorHandShaker.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/interceptor/TerminalMonitorHandShakerInterceptor.java @@ -1,5 +1,6 @@ -package com.nis.modules.terminal.config; +package com.nis.modules.terminal.interceptor; +import com.nis.modules.terminal.utils.TerminalConstant; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServletServerHttpRequest; @@ -10,8 +11,11 @@ import org.springframework.web.socket.server.support.HttpSessionHandshakeInterce import javax.servlet.http.HttpSession; import java.util.Map; +/** + * HttpSessionHandshakeInterceptor + */ @Component -public class TerminalMonitorHandShaker extends HttpSessionHandshakeInterceptor { +public class TerminalMonitorHandShakerInterceptor extends HttpSessionHandshakeInterceptor { @Override public synchronized boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { @@ -20,7 +24,7 @@ public class TerminalMonitorHandShaker extends HttpSessionHandshakeInterceptor { HttpSession session = servletRequest.getServletRequest().getSession(); attributes.put("uuid", servletRequest.getServletRequest().getParameter("uuid")); attributes.put("terminalToken", servletRequest.getServletRequest().getParameter("token")); - attributes.put(Constants.PARAM_HTTP_SESSION_ID_KEY, session.getId()); + attributes.put(TerminalConstant.PARAM_HTTP_SESSION_ID_KEY, session.getId()); } return super.beforeHandshake(request, response, wsHandler, attributes); } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanExpiredTerminalRecordDataJob.java b/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanExpiredTerminalRecordDataJob.java new file mode 100644 index 00000000..8da2113e --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanExpiredTerminalRecordDataJob.java @@ -0,0 +1,180 @@ +package com.nis.modules.terminal.job; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.amazonaws.SDKGlobalConfiguration; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.BucketLifecycleConfiguration; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.modules.sys.service.SysConfService; +import com.nis.modules.terminal.service.TerminalRecordService; +import com.nis.modules.terminal.service.TerminalSessionService; +import com.nis.modules.terminal.utils.TerminalConstant; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; + +@DisallowConcurrentExecution +public class CleanExpiredTerminalRecordDataJob extends QuartzJobBean { + + private static final Log log = Log.get(); + + static { + System.setProperty(SDKGlobalConfiguration.DISABLE_CERT_CHECKING_SYSTEM_PROPERTY, "true"); + } + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private SysConfService sysConfService; + + @Autowired + private TerminalSessionService terminalSessionService; + + @Autowired + private TerminalRecordService terminalRecordService; + + @Override + protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { + Thread.currentThread().setName("CleanExpiredTerminalRecordDataJob"); + + // 检查 haMode + String serverId = (String) redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); + log.info("[CleanExpiredTerminalRecordDataJob] [Get ha lock from redis] [server id: {}]", serverId); + if (!StrUtil.equals(serverId, Constant.SERVER_ID)) { + log.warn("[CleanExpiredTerminalRecordDataJob] [did not get the ha lock, not run job] [redis server id: {}] [system server id: {}]", serverId, Constant.SERVER_ID); + return; + } + + log.info("[CleanExpiredTerminalRecordDataJob] [start cleaning expired data]"); + + StopWatch sw = StopWatch.create("CleanExpiredTerminalRecordDataJob"); + sw.start(); + + try { + // clean Expired Terminal Record Data + this.cleanExpiredTerminalRecordData(); + } catch (Exception e) { + log.error(e, "[CleanExpiredTerminalRecordDataJob] [failed to clean data]"); + } finally { + sw.stop(); + } + + log.info("[CleanExpiredTerminalRecordDataJob] [clean data complete] [Run Time: {}]", sw.prettyPrint()); + } + + @Transactional(rollbackFor = Exception.class) + public void cleanExpiredTerminalRecordData() { + // 存储模式,1: 本地存储,2:S3对象存储 + String terminalStorageType = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_TYPE); + terminalStorageType = StrUtil.emptyToDefault(terminalStorageType, "1"); + log.info("[cleanExpiredTerminalRecordData] [record storage type] [value: {}]", terminalStorageType); + + DateTime now = Tool.DateUtil.date(); + + // 数据存储天数,默认 365 天 + String terminalRecordLocalRetention = sysConfService.getValue(TerminalConstant.TERMINAL_RECORD_LOCAL_RETENTION); + terminalRecordLocalRetention = Tool.StrUtil.emptyToDefault(terminalRecordLocalRetention, "365"); + + // 过期时间 + DateTime expireDate = Tool.DateUtil.offsetDay(now, -Integer.valueOf(terminalRecordLocalRetention)); + log.info("[cleanExpiredTerminalRecordData] [clear expired record date in db] [now: {}] [retention days: {}] [expire date: {}]", now, terminalRecordLocalRetention, expireDate); + terminalSessionService.cleanExpiredDataByTime(expireDate); + log.info("[cleanExpiredTerminalRecordData] [clear expired record date in db finshed]"); + + // 如果是 S3 存储内容信息,则配置存储桶过期策略 + if (StrUtil.equals("2", terminalStorageType)) { + AmazonS3 s3Client = terminalRecordService.buildTerminalStorageS3Client(); + try { + String bucketName = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_BUCKET); + log.info("[cleanExpiredTerminalRecordData] [config terminal record bucket lifecycle] [bucketName: {}] [retention days: {}]", bucketName, terminalRecordLocalRetention); + + if (s3Client.doesBucketExistV2(bucketName)) { + log.info("[cleanExpiredTerminalRecordData] [bucket exist] [bucketName: {}]", bucketName); + + Integer retentionDay = Integer.valueOf(terminalRecordLocalRetention); + String ruleId = "terminalRecordExpirationRule"; + + // Retrieve the configuration. + // Verify that the configuration now has one rules. prefix: fake/ expirationInDays: sysconfig.metricsStorageRetentionDay + BucketLifecycleConfiguration bucketLifecycleConfiguration = s3Client.getBucketLifecycleConfiguration(bucketName); + if (ObjectUtil.isNull(bucketLifecycleConfiguration)) { + log.info("[cleanExpiredTerminalRecordData] [bucket has empty lifecycle configuration] [bucketName: {}]", bucketName); + this.setBucketLifecycleConfiguration(s3Client, bucketName, ruleId, retentionDay); + } else { + List<BucketLifecycleConfiguration.Rule> bucketLifecycleConfigurationRules = bucketLifecycleConfiguration.getRules(); + bucketLifecycleConfigurationRules = Tool.CollUtil.defaultIfEmpty(bucketLifecycleConfigurationRules, Tool.ListUtil.empty()); + + BucketLifecycleConfiguration.Rule cortexExpirationRule = bucketLifecycleConfigurationRules.stream() + .filter(rule -> StrUtil.equals(rule.getId(), ruleId)) + .findFirst() + .orElse(null); + + if (ObjectUtil.isNull(cortexExpirationRule)) { + log.info("[cleanExpiredTerminalRecordData] [bucket has empty lifecycle configuration] [bucketName: {}]", bucketName); + this.setBucketLifecycleConfiguration(s3Client, bucketName, ruleId, retentionDay); + } else { + // 当前存在过期策略,判断规则是否发生变化 + boolean isUpdate = BooleanUtil.or( + ObjectUtil.notEqual(BucketLifecycleConfiguration.ENABLED, cortexExpirationRule.getStatus()), + ObjectUtil.notEqual(retentionDay, cortexExpirationRule.getExpirationInDays()) + ); + log.info("[cleanExpiredTerminalRecordData] [bucket lifecycle configuration] [bucketName: {}] [updated: {}]", bucketName, isUpdate); + if (isUpdate) { + this.setBucketLifecycleConfiguration(s3Client, bucketName, ruleId, retentionDay); + } + } + } + + // query the existing lifecycle configuration + bucketLifecycleConfiguration = s3Client.getBucketLifecycleConfiguration(bucketName); + List<BucketLifecycleConfiguration.Rule> rules1 = bucketLifecycleConfiguration.getRules(); + for (BucketLifecycleConfiguration.Rule l : rules1) { + log.info("[cleanExpiredTerminalRecordData] [current lifecycle config info] [bucketName: {}] [status: {}] [expiration days: {}]", bucketName, l.getStatus(), l.getExpirationInDays()); + } + } else { + log.warn("[cleanExpiredTerminalRecordData] [bucket does not exist] [bucketName: {}]", bucketName); + } + } catch (Exception e) { + log.error(e, "[cleanExpiredTerminalRecordData] [error]"); + } finally { + s3Client.shutdown(); + } + } + } + + /** + * set Bucket Lifecycle Configuration + * + * @param s3Client + * @param bucketName + * @param ruleId + * @param retentionDay + */ + private void setBucketLifecycleConfiguration(AmazonS3 s3Client, String bucketName, String ruleId, Integer retentionDay) { + log.info("[setBucketLifecycleConfiguration] [bucketName: {}] [ruleId: {}] [retentionDay: {}]", bucketName, ruleId, retentionDay); + + BucketLifecycleConfiguration.Rule rule = new BucketLifecycleConfiguration.Rule() + .withId(ruleId) + .withExpirationInDays(retentionDay) + .withStatus(BucketLifecycleConfiguration.ENABLED); + + BucketLifecycleConfiguration configuration = new BucketLifecycleConfiguration().withRules(Arrays.asList(rule)); + // Save the configuration. + s3Client.setBucketLifecycleConfiguration(bucketName, configuration); + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanNoRealUseTerminalConnJob.java b/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanNoRealUseTerminalConnJob.java new file mode 100644 index 00000000..04c0e86b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/job/CleanNoRealUseTerminalConnJob.java @@ -0,0 +1,132 @@ +package com.nis.modules.terminal.job; + +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.jcraft.jsch.Session; +import com.nis.common.utils.Constant; +import com.nis.common.utils.Tool; +import com.nis.common.utils.ToolUtil; +import com.nis.modules.sys.service.SysConfigService; +import com.nis.modules.terminal.backend.TerminalSession; +import org.apache.commons.net.telnet.TelnetClient; +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.web.socket.WebSocketSession; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 清理未实际使用的 ssh/telnet 连接 + * 以超过最后数据交互时间 30 分钟为准 (sys_config.session_timeout) + */ +@DisallowConcurrentExecution +public class CleanNoRealUseTerminalConnJob extends QuartzJobBean { + + private final Log log = Log.get(); + + @Autowired + private RedisTemplate redisTemplate; + + @Autowired + private SysConfigService sysConfigService; + + @SuppressWarnings("unchecked") + @Override + protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { + Thread.currentThread().setName("Clean No Real Use Connection Job"); + // 检查 haMode + String serverId = (String) redisTemplate.opsForValue().get(Constant.SYS_HA_LOCK); + if (!StrUtil.equals(serverId, Constant.SERVER_ID)) { + return; + } + + log.info("clean no real use ssh/telnet connection job start..."); + StopWatch sw = StopWatch.create("clean no real use ssh/telnet connection job"); + sw.start(); + try { + // 清理未实际使用的 ssh/telnet 连接 + // 以超过最后数据交互时间 30 分钟为准 (sys_config.session_timeout) + this.cleanNoRealUseConnection(); + } catch (Exception e) { + log.error(e, "clean no real use ssh/telnet connection job error"); + } finally { + sw.stop(); + } + log.info("clean no real use ssh/telnet connection job Run Time: {}", sw.prettyPrint()); + } + + /** + * 清理未实际使用的 ssh/telnet 连接 + * 以超过最后数据交互时间 30 分钟为准 (sys_config.session_timeout) + */ + private void cleanNoRealUseConnection() { + if (Tool.MapUtil.isEmpty(TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP)) { + log.warn("current no connection info, clean no real use ssh/telnet connection finshed. "); + return; + } + + // system session timeout (minute) + String sessionTimeoutConfStr = sysConfigService.getValue(Constant.SYSCONFIG_SESSION_TIMEOUT_KEY); + Integer sessionTimeout = Integer.valueOf(sessionTimeoutConfStr); + + long currentSeconds = Tool.DateUtil.currentSeconds(); + + List<Map.Entry<String, Long>> entries = TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.entrySet() + .stream() + .filter(entry -> { + Long lastActiveTime = entry.getValue(); + return currentSeconds - lastActiveTime > (sessionTimeout * 60); + }).collect(Collectors.toList()); + + for (Map.Entry<String, Long> entry : entries) { + String uuid = entry.getKey(); + Map<Object, Object> connObjMap = TerminalSession.TERMINAL_CONNECTED_CACHE.get(uuid); + if (Tool.MapUtil.isEmpty(connObjMap)) { + continue; + } + + log.info("disconnect no real use ssh/telnet connection. uuid: {}", uuid); + Object obj = connObjMap.get(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY); + try { + if (obj instanceof Session) { + Session session = (Session) obj; + session.disconnect(); + } + if (obj instanceof TelnetClient) { + TelnetClient telnetClient = (TelnetClient) obj; + telnetClient.disconnect(); + } + } catch (IOException e) { + log.error(e, "disconnect no real use ssh/telnet connection error. uuid: {}", uuid); + } finally { + // remove cache + TerminalSession.TERMINAL_CONNECTED_CACHE.remove(uuid); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.remove(uuid); + + // monitor + TerminalSession.TERMINAL_MONITORS_MAPPING.remove(uuid); + + // socket session + WebSocketSession socketSession = TerminalSession.findSession(uuid); + if (ToolUtil.isNotEmpty(socketSession)) { + TerminalSession.remove(socketSession); + } + + // session attribute info + TerminalSession.TERMINAL_ATTRIBUTE_INFO.remove(uuid); + + // session cmd info + TerminalSession.TERMINAL_CMD_INFO.remove(uuid); + } + } + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalRecordService.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalRecordService.java index 676e0b6e..7c5088bf 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalRecordService.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalRecordService.java @@ -1,5 +1,6 @@ package com.nis.modules.terminal.service; +import com.amazonaws.services.s3.AmazonS3; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.modules.terminal.entity.TerminalRecord; @@ -8,4 +9,18 @@ import java.util.Map; public interface TerminalRecordService extends IService<TerminalRecord> { Map queryTerminalRecordInfos(Map<String, Object> params); -}
\ No newline at end of file + + /** + * save Terminal Record Content + * + * @param record + */ + void saveTerminalRecordContent(TerminalRecord record); + + /** + * build Terminal Storage S3 Client + * + * @return + */ + AmazonS3 buildTerminalStorageS3Client(); +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSessionService.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSessionService.java index 55412004..33c28c2b 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSessionService.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSessionService.java @@ -3,8 +3,11 @@ package com.nis.modules.terminal.service; import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.extension.service.IService; import com.nis.common.utils.PageUtils; +import com.nis.modules.terminal.entity.TerminalConfigDto; import com.nis.modules.terminal.entity.TerminalSessionEntity; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.Map; public interface TerminalSessionService extends IService<TerminalSessionEntity> { @@ -13,6 +16,29 @@ public interface TerminalSessionService extends IService<TerminalSessionEntity> void killSession(String uuid); - // 清理过期的 terminal session cmd record 数据 + /** + * 清理过期的 terminal session cmd record 数据 + * @param startCleanTerminalTime + */ void cleanExpiredDataByTime(DateTime startCleanTerminalTime); + + Map<Object, Object> login(String token, TerminalConfigDto configEntity); + + Map<Object, Object> lsOfSftp(String uuid, String path); + + void mkdirOfSftp(String uuid, String path); + + void rmOfSftp(String uuid, String path); + + String uploadOfSftp(String uuid, String path, MultipartFile file); + + Map<Object, Object> querySftpUploadProcess(String tid); + + void downloadOfSftp(String uuid, String path, HttpServletResponse response); + + void cancelUpload(String tid); + + void renameFileOfSftp(String uuid, String oldPath, String newPath); + + Map<Object, Object> duplicateSession(String token, String uuid, Integer width, Integer height, Integer cols, Integer rows); } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSftpLogService.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSftpLogService.java new file mode 100644 index 00000000..64c55c1b --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/TerminalSftpLogService.java @@ -0,0 +1,15 @@ +package com.nis.modules.terminal.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.nis.common.utils.PageUtils; +import com.nis.modules.terminal.entity.TerminalSftpLog; + +import java.util.Map; + +public interface TerminalSftpLogService extends IService<TerminalSftpLog> { + + PageUtils querySftpLogPage(Map<String, Object> params); + + void saveSftpLog(String uuid, String path, Integer sftpOperType); + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalRecordServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalRecordServiceImpl.java index 492b82f9..a8062af8 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalRecordServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalRecordServiceImpl.java @@ -1,30 +1,53 @@ package com.nis.modules.terminal.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONPath; +import com.amazonaws.ClientConfiguration; +import com.amazonaws.Protocol; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.ObjectMetadata; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.JSONUtil; import com.nis.common.utils.RCode; import com.nis.common.utils.StringUtils; +import com.nis.common.utils.Tool; +import com.nis.modules.sys.service.SysConfService; import com.nis.modules.terminal.dao.TerminalRecordDao; import com.nis.modules.terminal.entity.TerminalRecord; import com.nis.modules.terminal.service.TerminalRecordService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections.CollectionUtils; +import com.nis.modules.terminal.utils.TerminalConstant; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.ByteArrayInputStream; import java.util.Collections; -import java.util.HashMap; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; -@Slf4j @Service("terminalRecordService") public class TerminalRecordServiceImpl extends ServiceImpl<TerminalRecordDao, TerminalRecord> implements TerminalRecordService { + private static final Log log = Log.get(); + + @Autowired + private SysConfService sysConfService; + @Override public Map queryTerminalRecordInfos(Map<String, Object> params) { // uuid 不能为空 @@ -37,49 +60,209 @@ public class TerminalRecordServiceImpl extends ServiceImpl<TerminalRecordDao, Te throw new NZException(RCode.TERMINAL_QUERYSIZE_INVALIDED); } - List<TerminalRecord> list = this.list(new LambdaQueryWrapper<TerminalRecord>() + Map<Object, Object> resultMap = Tool.MapUtil.builder().map(); + resultMap.put("uuid", params.get("uuid")); + resultMap.put("startTime", time); + resultMap.put("endTime", null); + resultMap.put("hasNext", 0); + resultMap.put("list", Collections.emptyList()); + + // content Str List of uuid + List<String> contentStrListOfUuid = Tool.ListUtil.list(true); + + // record List In Db + List<TerminalRecord> recordListInDb = this.list(new LambdaQueryWrapper<TerminalRecord>() .eq(TerminalRecord::getUuid, params.get("uuid")) .orderByAsc(TerminalRecord::getStartTime)); - Map map = new HashMap(8); - map.put("uuid", params.get("uuid")); + log.info("[queryTerminalRecordInfos] [record data in db] [uuid: {}] [size: {}]", params.get("uuid"), recordListInDb.size()); - if (CollectionUtils.isNotEmpty(list)) { - int hashNext = 0; + if (Tool.CollUtil.isNotEmpty(recordListInDb)) { + // storage type + Integer recordStorageType = recordListInDb.stream().findFirst().get().getStorageType(); + if (ObjectUtil.equals(1, recordStorageType)) { + log.info("[queryTerminalRecordInfos] [record data source is db] [uuid: {}] [size: {}]", params.get("uuid"), recordListInDb.size()); + // db 本地存储 + contentStrListOfUuid = recordListInDb.stream().map(record -> StrUtil.str(record.getContent(), CharsetUtil.charset("UTF-8"))).collect(Collectors.toList()); + } else if (ObjectUtil.equals(2, recordStorageType)) { + log.info("[queryTerminalRecordInfos] [record data source is s3] [uuid: {}] [size in db: {}]", params.get("uuid"), recordListInDb.size()); + // S3 对象存储 + AmazonS3 s3Client = this.buildTerminalStorageS3Client(); + try { + String bucketName = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_BUCKET); - StringBuilder builder = new StringBuilder(); - builder.append("["); - for (TerminalRecord record : list) { - builder.append(new String(record.getContent(), CharsetUtil.charset("UTF-8"))); - } - String str = builder.substring(0, builder.length() - 1); - List<Map> maps = JSONArray.parseArray(str += "]", Map.class); - maps = maps.stream().filter(tempEntity -> { - Integer t = (Integer) tempEntity.get("t"); - if (t > time) { - return true; + /* + // query objects in s3 + ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(); + listObjectsV2Request + .withBucketName(bucketName) + .withMaxKeys(1000) + .withPrefix(StrUtil.toString(params.get("uuid"))); + + ListObjectsV2Result listObjectsV2Result = s3Client.listObjectsV2(listObjectsV2Request); + List<S3ObjectSummary> S3ObjectSummarylist = listObjectsV2Result.getObjectSummaries(); + // 再次排序 + List<String> fileNameList = S3ObjectSummarylist.stream().map(S3ObjectSummary::getKey) + .sorted(Comparator.comparing(str -> Integer.valueOf(Tool.StrUtil.subAfter(str, "/", true)))).collect(Collectors.toList());*/ + + List<String> fileNameList = recordListInDb.stream().map(TerminalRecord::getPath) + .sorted(Comparator.comparing(str -> Integer.valueOf(Tool.StrUtil.subAfter(str, "/", true)))).collect(Collectors.toList()); + for (String fileName : fileNameList) { + String objectAsString = s3Client.getObjectAsString(bucketName, fileName); + contentStrListOfUuid.add(objectAsString); + } + log.info("[queryTerminalRecordInfos] [record data source is s3] [uuid: {}] [size in db: {}] [size in s3: {}]", params.get("uuid"), fileNameList.size(), contentStrListOfUuid.size()); + } finally { + s3Client.shutdown(); } - return false; - }).collect(Collectors.toList()); + } + } + if (Tool.CollUtil.isNotEmpty(contentStrListOfUuid)) { + // get List Of Content Obj Older Than Time Param + List<Map> contentObjList = this.getListOfContentObjOlderThanTimeParam(contentStrListOfUuid, time); // size 为 1 表示不限制条数 - if (!size.equals(1) && maps.size() > size) { - maps = maps.subList(0, size); - hashNext = 1; + if (BooleanUtil.and(ObjectUtil.notEqual(size, 1), + contentObjList.size() > size)) { + contentObjList = contentObjList.subList(0, size); + resultMap.put("hasNext", 1); + } + + Map endEntity = contentObjList.get(contentObjList.size() - 1); + resultMap.put("endTime", endEntity.get("t")); + resultMap.put("list", contentObjList); + } + return resultMap; + } + + /** + * get List Of Content Obj Older Than Time Param + * + * @param contentList + * @param time + * @return + */ + private List<Map> getListOfContentObjOlderThanTimeParam(List<String> contentList, Integer time) { + StringBuilder builder = new StringBuilder(); + builder.append("["); + + for (String content : contentList) { + builder.append(content); + } + + String str = builder.substring(0, builder.length() - 1); + + List<Map> maps = JSONArray.parseArray(str += "]", Map.class); + maps = maps.stream().filter(tempEntity -> { + Integer t = (Integer) tempEntity.get("t"); + if (t > time) { + return true; + } + return false; + }).collect(Collectors.toList()); + + return maps; + } + + @Override + public void saveTerminalRecordContent(TerminalRecord record) { + // 存储模式,1: 本地存储,2:S3对象存储 + String terminalStorageType = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_TYPE); + terminalStorageType = StrUtil.emptyToDefault(terminalStorageType, "1"); + log.info("[saveTerminalRecordContent] [storage type] [value: {}] [uuid: {}]", terminalStorageType, record.getUuid()); + + // storageType + record.setStorageType(Integer.valueOf(terminalStorageType)); + + switch (terminalStorageType) { + case "1": { + // 本地存储 + this.save(record); + log.info("[saveTerminalRecordContent] [local storage record succeeded] [uuid: {}]", record.getUuid()); + break; } + case "2": { + // 保存记录至 db,不包含 content 内容 + TerminalRecord saveRecordEntity = new TerminalRecord(); + BeanUtil.copyProperties(record, saveRecordEntity, "content"); + + + String uuid = record.getUuid(); + Integer startTime = record.getStartTime(); + + // 以 uuid 为文件路径,startTime 为文件名称 + String key = StrUtil.concat(true, uuid, "/", startTime.toString()); + + saveRecordEntity.setPath(key); + this.save(saveRecordEntity); + + // S3 对象存储 + AmazonS3 s3Client = this.buildTerminalStorageS3Client(); + + String bucketName = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_BUCKET); + boolean doesBucketExist = s3Client.doesBucketExistV2(bucketName); + log.info("[saveTerminalRecordContent] [bucketName: {}] [doesBucketExist: {}]", bucketName, doesBucketExist); + + if (!doesBucketExist) { + log.info("[saveTerminalRecordContent] [create bucket] [name: {}]", bucketName); + s3Client.createBucket(bucketName); + } - Map endEntity = maps.get(maps.size() - 1); - map.put("endTime", endEntity.get("t")); - map.put("hasNext", hashNext); + byte[] content = record.getContent(); + ByteArrayInputStream input = null; + try { + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType("application/json"); + metadata.setContentLength(content.length); + metadata.setHeader("x-hos-meta-message", "message"); - map.put("list", maps); - } else { - map.put("endTime", null); - map.put("hasNext", 0); - map.put("list", Collections.emptyList()); + input = new ByteArrayInputStream(content); + + // 以流方式上传对象,指定桶名、对象名、输入流、ObjectMetadata + s3Client.putObject(bucketName, key, input, metadata); + + log.info("[saveTerminalRecordContent] [remote storage record succeeded] [key: {}]", key); + } catch (Exception e) { + log.error(e, "[saveTerminalRecordContent] [upload record content to s3 error] [uuid: {}] [start: {}] [size: {}]", uuid, startTime, content.length); + } finally { + Tool.IoUtil.close(input); + // 关闭 AmazonS3Client + s3Client.shutdown(); + } + break; + } + default: + break; } - map.put("startTime", time); - return map; } -}
\ No newline at end of file + + /** + * build Terminal Storage S3 Client + * + * @return + */ + @Override + public AmazonS3 buildTerminalStorageS3Client() { + log.info("[buildTerminalStorageS3Client] [build Amazon S3 Client begin...]"); + + String s3Endpoint = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_ENDPOINT); + String accessKey = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_ACCESS_KEY); + String secretKey = sysConfService.getValue(TerminalConstant.TERMINAL_STORAGE_S3_SECRET_ACCESS_KEY); + + AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey); + ClientConfiguration clientConfig = new ClientConfiguration(); + clientConfig.setProtocol(Protocol.HTTP); + + AmazonS3 s3Client = AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .withClientConfiguration(clientConfig) + .withEndpointConfiguration( + new AwsClientBuilder.EndpointConfiguration(s3Endpoint, null) + ) + .build(); + + log.info("[buildTerminalStorageS3Client] [build Amazon S3 Client finshed] [ClientInfo: {}]", JSONPath.read(JSONUtil.toJsonStr(s3Client), "endpoint")); + return s3Client; + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java index cf2f0a61..b61d743b 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSessionServiceImpl.java @@ -1,41 +1,65 @@ package com.nis.modules.terminal.service.impl; +import cn.hutool.cache.impl.TimedCache; import cn.hutool.core.date.DateTime; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.ssh.Sftp; +import cn.hutool.http.HttpStatus; import cn.hutool.log.Log; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.nis.common.utils.DateUtil; -import com.nis.common.utils.PageUtils; -import com.nis.common.utils.Query; +import com.jcraft.jsch.*; +import com.nis.common.exception.NZException; +import com.nis.common.smartvalidate.ValidateUtils; +import com.nis.common.utils.*; +import com.nis.modules.asset.entity.AssetAsset; +import com.nis.modules.asset.entity.AssetTypeConf; +import com.nis.modules.asset.service.AssetAssetService; +import com.nis.modules.asset.service.AssetTypeConfService; +import com.nis.modules.sys.entity.SysConfigEntity; import com.nis.modules.sys.entity.SysUserEntity; +import com.nis.modules.sys.service.SysConfService; import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.shiro.ShiroUtils; -import com.nis.modules.terminal.config.Constants; -import com.nis.modules.terminal.config.TerminalHandler; -import com.nis.modules.terminal.config.TerminalSession; +import com.nis.modules.terminal.backend.TerminalClient; +import com.nis.modules.terminal.backend.TerminalHandler; +import com.nis.modules.terminal.backend.TerminalSession; import com.nis.modules.terminal.dao.TerminalSessionDao; +import com.nis.modules.terminal.entity.TerminalConfigDto; import com.nis.modules.terminal.entity.TerminalSessionEntity; -import com.nis.modules.terminal.service.TerminalRecordService; import com.nis.modules.terminal.service.TerminalSessionService; +import com.nis.modules.terminal.service.TerminalSftpLogService; +import com.nis.modules.terminal.utils.SFTPUploadMonitor; +import com.nis.modules.terminal.utils.TelnetUtil; +import com.nis.modules.terminal.utils.TerminalConstant; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.time.DateUtils; +import org.apache.commons.lang3.time.StopWatch; +import org.apache.commons.net.telnet.TelnetClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletResponse; +import java.io.File; import java.io.IOException; +import java.net.URLEncoder; import java.text.ParseException; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Service("terminalSessionService") public class TerminalSessionServiceImpl extends ServiceImpl<TerminalSessionDao, TerminalSessionEntity> implements TerminalSessionService { - private Log log = Log.get(); + private static final Log log = Log.get(); @Autowired private TerminalSessionDao terminalSessionDao; @@ -44,7 +68,31 @@ public class TerminalSessionServiceImpl extends ServiceImpl<TerminalSessionDao, private SysUserService sysUserService; @Autowired - private TerminalRecordService terminalRecordService; + private SysConfService sysConfService; + + @Autowired + private AssetAssetService assetService; + + @Autowired + private AssetTypeConfService assetTypeConfService; + + @Autowired + private TerminalSftpLogService sftpLogService; + + /** + * upload progress cache + */ + private static TimedCache<String, SFTPUploadMonitor> UPLOAD_PROGRESS_CACHE; + + private static Map<String, SftpUploadRunnable> SFTP_UPLOAD_THREAD_MAP = Tool.MapUtil.newConcurrentHashMap(); + + @PostConstruct + public void init() { + log.info("Setup sftp upload progress cache begin..."); + // 默认 30 分钟失效 + UPLOAD_PROGRESS_CACHE = Tool.CacheUtil.newTimedCache(60000 * 30); + log.info("Setup sftp upload progress cache finished"); + } /** * 处理请求参数 @@ -53,20 +101,20 @@ public class TerminalSessionServiceImpl extends ServiceImpl<TerminalSessionDao, */ private void handleQueryDateParam(Map<String, Object> params) { try { - if (params.get("startTime") != null && StringUtils.isNotEmpty(params.get("startTime").toString())) { + if (Tool.ObjectUtil.isNotEmpty(params.get("startTime"))) { Date searchStartAt = DateUtils.parseDate(params.get("startTime").toString(), "yyyy-MM-dd HH:mm:ss"); params.put("startTime", searchStartAt); } else { params.put("startTime", null); } - if (params.get("endTime") != null && StringUtils.isNotEmpty(params.get("endTime").toString())) { + if (Tool.ObjectUtil.isNotEmpty(params.get("endTime"))) { Date searchEndAt = DateUtils.parseDate(params.get("endTime").toString(), "yyyy-MM-dd HH:mm:ss"); params.put("endTime", searchEndAt); } else { params.put("endTime", null); } } catch (ParseException e) { - log.error("时间转换异常,参数是 {}", params, e); + log.error(e, "terminal session handle Query Date Param error, param: {}", Tool.JSONUtil.toJsonStr(params)); } } @@ -93,43 +141,738 @@ public class TerminalSessionServiceImpl extends ServiceImpl<TerminalSessionDao, @Override public void killSession(String uuid) { + log.info("[killSession] [begin] [uuid: {}]", uuid); WebSocketSession session = TerminalSession.findSession(uuid); - if (session == null) { - return; + + // 未找到 websocket session 信息,连接信息已不在,更新 db 中 terminal session 状态 + if (ObjectUtil.isNull(session)) { + log.warn("[killSession] [failed to get websocket connection through terminal session] [uuid: {}]", uuid); + + TerminalSessionEntity terminalSessionEntity = this.getOne(new LambdaQueryWrapper<TerminalSessionEntity>().eq(TerminalSessionEntity::getUuid, uuid)); + log.info("[killSession] [get the terminal session entity in the db] [uuid: {}] [status: {}]", uuid, ObjectUtil.isNull(terminalSessionEntity) ? null : terminalSessionEntity.getStatus()); + if (ObjectUtil.isNull(terminalSessionEntity)) { + log.error("[killSession] [failed to get terminal session information] [uuid: {}]", uuid); + throw new NZException(RCode.TERMINAL_SESSION_NOT_FOUND); + } + + log.info("[killSession] [update terminal session state] [uuid: {}]", uuid); + terminalSessionEntity.setEndTime(new Date()); + terminalSessionEntity.setKillUserId(ShiroUtils.getUserId()); + terminalSessionEntity.setStatus(TerminalConstant.SessionStatus.FORCE_QUIT.getValue()); + // update status + this.saveOrUpdate(terminalSessionEntity); + + // 根据 websocket 找到 terminal session,更新状态,设置结束时间 + } else { + try { + TerminalClient terminalClient = TerminalSession.TERMINAL_SESSION.get(session); + log.info("[killSession] [get connected session] [terminal session: {}]", JSONUtil.toJsonStr(terminalClient.getWebSocketSession())); + String clientId = terminalClient.getClientId(); + TerminalSessionEntity sessionEntity = this.getOne(new LambdaQueryWrapper<TerminalSessionEntity>().eq(TerminalSessionEntity::getUuid, clientId)); + + // TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); + if (sessionEntity.getStartTime() == null) { + sessionEntity.setStartTime(new Date()); + } + + log.info("[killSession] [update terminal session state] [uuid: {}]", uuid); + sessionEntity.setEndTime(new Date()); + sessionEntity.setKillUserId(ShiroUtils.getUserId()); + sessionEntity.setStatus(TerminalConstant.SessionStatus.FORCE_QUIT.getValue()); + // update status + this.saveOrUpdate(sessionEntity); + + try { + TerminalSession.remove(session); + StringBuilder sb = new StringBuilder(); + sb.append("\u001B[01;31m\u001B[K Administrator disconnected \u001B[m\u001B[K \r\n"); + sb.append("$: "); + session.sendMessage(new TextMessage(sb.toString())); + } catch (IOException e) { + log.error(e, "[killSession] [send exit prompt error] [uuid: {}]", uuid); + } + + // kill 之后,将剩余文件写到数据库中 + TerminalHandler.saveRecordContentAfterClientClosed(uuid); + } catch (Exception e) { + log.error(e, "[killSession] [error] [uuid: {}]", uuid); + throw new NZException(RCode.TERMINAL_STOP_SESSION_FAILED); + } + } + log.info("[killSession] [finshed] [uuid: {}]", uuid); + } + + @Override + public void cleanExpiredDataByTime(DateTime startCleanTerminalTime) { + terminalSessionDao.cleanExpiredDataByTime(startCleanTerminalTime); + } + + /** + * validateloginParam + * + * @param configEntity + */ + private void validateloginParam(TerminalConfigDto configEntity) { + Integer assetId = configEntity.getAssetId(); + if (Tool.ObjectUtil.isNotNull(assetId)) { + AssetAsset asset = assetService.getById(assetId); + ValidateUtils.is(asset).notNull(RCode.ASSET_NOT_EXIST); + + List<Integer> authProtocolEnumList = Arrays.asList(TerminalConstant.ProtocolType.values()).stream().map(TerminalConstant.ProtocolType::getValue).collect(Collectors.toList()); + AssetTypeConf typeConf = assetTypeConfService.getById(asset.getTypeId()); + // 不支持 ssh | telnet + if (!authProtocolEnumList.contains(typeConf.getAuthProtocol())) { + throw new NZException(RCode.TERMINAL_ASSET_NOT_SUPPORT); + } + + // 以 asset 为主时,只需校验是否存在 username & authType,其他属性添加 asset 时有校验 + // SSHT & ELNET + // username & authType required + String authUsername = asset.getAuthUsername(); + Integer authType = asset.getAuthType(); + ValidateUtils.is(authUsername).notNull(RCode.TERMINAL_CONNECTION_AUTHUSERNAME_ISNULL) + .and(authType).notNull(RCode.ASSET_TERMINAL_ACCOUNT_INFO_NOTFOUND); + } else { + // host + String host = configEntity.getHost(); + ValidateUtils.is(host).notNull(RCode.TERMINAL_CONNECTION_HOST_ISNULL); + + // port can not all empty + Integer port = configEntity.getPort(); + Integer authProtocolPort = configEntity.getAuthProtocolPort(); + if (Tool.ObjectUtil.isAllEmpty(port, authProtocolPort)) { + throw new NZException(RCode.TERMINAL_CONNECTION_HOST_ISNULL); + } + + List<Integer> authProtocolEnumList = Arrays.asList(TerminalConstant.ProtocolType.values()).stream().map(TerminalConstant.ProtocolType::getValue).collect(Collectors.toList()); + Integer authProtocol = configEntity.getAuthProtocol(); + if (!authProtocolEnumList.contains(authProtocol)) { + throw new NZException(RCode.TERMINAL_CONNECTION_AUTHPROTOCOL_INVALIDED); + } + + // username required + String authUsername = configEntity.getAuthUsername(); + ValidateUtils.is(authUsername).notNull(RCode.TERMINAL_CONNECTION_AUTHUSERNAME_ISNULL); + + // SSH + if (TerminalConstant.ProtocolType.SSH.getValue().equals(authProtocol)) { + List<Integer> authTypeEnumList = Arrays.asList(TerminalConstant.SshAuthType.values()).stream().map(TerminalConstant.SshAuthType::getType).collect(Collectors.toList()); + Integer authType = configEntity.getAuthType(); + if (!authTypeEnumList.contains(authType)) { + throw new NZException(RCode.TERMINAL_CONNECTION_AUTHTYPE_INVALIDED); + } + + if (Tool.ObjectUtil.equal(authType, TerminalConstant.SshAuthType.PIN.getType())) { + String authPin = configEntity.getAuthPin(); + ValidateUtils.is(authPin).notNull(RCode.TERMINAL_CONNECTION_AUTHPIN_ISNULL); + } + if (Tool.ObjectUtil.equal(authType, TerminalConstant.SshAuthType.KEY.getType())) { + String authPriKey = configEntity.getAuthPriKey(); + ValidateUtils.is(authPriKey).notNull(RCode.TERMINAL_CONNECTION_AUTHPRIKEY_ISNULL); + } + } + + // TELNET + if (TerminalConstant.ProtocolType.TELNET.getValue().equals(authProtocol)) { + String authPin = configEntity.getAuthPin(); + ValidateUtils.is(authPin).notNull(RCode.TERMINAL_CONNECTION_AUTHPIN_ISNULL); + } + + // allow to be empty + String authPinTip = configEntity.getAuthPinTip(); + String authUserTip = configEntity.getAuthUserTip(); + } + } + + /** + * get Terminal Connection Info Entity + * + * @param configEntity + * @return + */ + private AssetAsset getTerminalConnectionInfoEntity(TerminalConfigDto configEntity) { + // terminal Connection Info + AssetAsset terminalConnectionInfo = new AssetAsset(); + if (Tool.ObjectUtil.isNotNull(configEntity.getAssetId())) { + AssetAsset asset = assetService.getById(configEntity.getAssetId()); + AssetTypeConf typeConf = assetTypeConfService.getById(asset.getTypeId()); + asset.setAuthProtocol(typeConf.getAuthProtocol()); + + // clone + terminalConnectionInfo = ObjectUtil.clone(asset); + } else { + AssetAsset asset = new AssetAsset(); + // copy Properties val + Tool.BeanUtil.copyProperties(configEntity, asset, true); + + // different name attribute set val + asset.setManageIp(configEntity.getHost()); + + Integer port = configEntity.getPort(); + // priority config authProtocolPort + Integer authProtocolPort = configEntity.getAuthProtocolPort(); + asset.setAuthProtocolPort(ObjectUtil.defaultIfNull(authProtocolPort, port)); + + // 尝试用 host 补充 assetId + AssetAsset queryAssetByHost = assetService.getOne(new LambdaQueryWrapper<AssetAsset>().eq(AssetAsset::getManageIp, configEntity.getHost())); + if (ObjectUtil.isNotNull(queryAssetByHost)) { + asset.setId(queryAssetByHost.getId()); + } + + // decode auth pin + String decodeAuthPin = Tool.URLUtil.decode(asset.getAuthPin()); + asset.setAuthPin(decodeAuthPin); + + // clone + terminalConnectionInfo = ObjectUtil.clone(asset); + } + return terminalConnectionInfo; + } + + @Override + public Map<Object, Object> login(String token, TerminalConfigDto configEntity) { + // validate login Param + this.validateloginParam(configEntity); + + // uuid + String uuid = Tool.StrUtil.uuid(); + + // terminal Connection Info + AssetAsset terminalConnInfo = this.getTerminalConnectionInfoEntity(configEntity); + log.info("Open terminal, uuid: {}, connection Info: {}", uuid, JSONUtil.toJsonStr(terminalConnInfo)); + + Map<Object, Object> resultMap = Tool.MapUtil.builder().map(); + + Integer authProtocol = terminalConnInfo.getAuthProtocol(); + // SSH + if (TerminalConstant.ProtocolType.SSH.getValue().equals(authProtocol)) { + try { + log.info("Open SSH terminal begin. uuid: {}", uuid); + Session session = SshUtil.getSshConnection(terminalConnInfo); + // connected terminal cache session info + TerminalSession.TERMINAL_CONNECTED_CACHE.put(uuid, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, session) + .put(Constant.AUTH_TOKEN_CODE, token) + .map()); + // connected last active time + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(uuid, Tool.DateUtil.currentSeconds()); + resultMap.putAll(R.ok()); + log.info("Open SSH terminal success. uuid: {}", uuid); + } catch (Exception e) { + log.error(e, "Open SSH terminal error. uuid: {}", uuid); + if (e instanceof JSchException) { + resultMap.putAll(R.error(400, e.getCause() != null ? e.getCause().getMessage() : e.getMessage())); + } else { + resultMap.putAll(R.error(RCode.ERROR.getCode(), RCode.ERROR.getMsg())); + } + } + } + + // TELNET + if (TerminalConstant.ProtocolType.TELNET.getValue().equals(authProtocol)) { + try { + log.info("Open TELNET terminal begin. uuid: {}", uuid); + TelnetUtil telnetUtil = new TelnetUtil(); + telnetUtil.connect(terminalConnInfo.getManageIp(), terminalConnInfo.getAuthProtocolPort()); + + String authUsername = terminalConnInfo.getAuthUsername(); + String pin = StringUtils.str(Base64.getDecoder().decode(terminalConnInfo.getAuthPin())); + + List<SysConfigEntity> configList = sysConfService.list(new LambdaQueryWrapper<SysConfigEntity>() + .in(SysConfigEntity::getParamKey, "terminal_telnet_user_tip", "terminal_telnet_pin_tip")); + Map<String, String> systemTipConfigMap = configList.stream().collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + + String authUserTip = terminalConnInfo.getAuthUserTip(); + String authPinTip = terminalConnInfo.getAuthPinTip(); + + authUserTip = TelnetUtil.getTelenetLoginTip(authUserTip, systemTipConfigMap, "terminal_telnet_user_tip"); + authPinTip = TelnetUtil.getTelenetLoginTip(authPinTip, systemTipConfigMap, "terminal_telnet_pin_tip"); + boolean isLogin = telnetUtil.login(authUsername, pin, authUserTip, authPinTip); + if (isLogin) { + log.info("Open TELNET terminal success. uuid: {}", uuid); + TelnetClient telnetClient = telnetUtil.getTelnetClient(); + // connected terminal cache telnet client info + TerminalSession.TERMINAL_CONNECTED_CACHE.put(uuid, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, telnetClient) + .put(Constant.AUTH_TOKEN_CODE, token) + .map()); + // connected last active time + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(uuid, Tool.DateUtil.currentSeconds()); + resultMap.putAll(R.ok()); + } else { + log.warn("Open TELNET terminal fail. uuid: {}", uuid); + resultMap.putAll(R.error(400, "Login incorrect")); + } + } catch (Exception e) { + log.error(e, "Open TELNET terminal error. uuid: {}", uuid); + resultMap.putAll(R.error(400, e.getMessage())); + } + } + + // client info + Map<Object, Object> terminalConnInfoMap = Tool.MapUtil.builder() + .put("uuid", uuid) + .put("host", terminalConnInfo.getManageIp()) + .put("port", terminalConnInfo.getAuthProtocolPort()) + .put("authProtocol", terminalConnInfo.getAuthProtocol()) + .put("authUsername", terminalConnInfo.getAuthUsername()) + .map(); + resultMap.put("data", terminalConnInfoMap); + return resultMap; + } + + /** + * get Sftp Channel + * + * @param uuid + * @return + */ + private Sftp getSftpChannel(String uuid) { + Map<Object, Object> connObjMap = TerminalSession.TERMINAL_CONNECTED_CACHE.get(uuid); + if (ObjectUtil.isNull(connObjMap)) { + throw new NZException(RCode.TERMINAL_SESSION_NOT_FOUND); + } + + Session session = (Session) connObjMap.get(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY); + if (ObjectUtil.isNull(session)) { + throw new NZException(RCode.TERMINAL_TELNET_TRANSFER); + } + + // sftp channel + Sftp sftp = new Sftp(session); + // connected last active time + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(uuid, Tool.DateUtil.currentSeconds()); + return sftp; + } + + @Override + public Map<Object, Object> lsOfSftp(String uuid, String path) { + Map<Object, Object> resultData; + Sftp sftp = this.getSftpChannel(uuid); + ChannelSftp channelSftp = null; + try { + boolean isPathDir = sftp.cd(path); + log.info("[lsOfSftp] [is the path a directory] [path: {}] [isDir: {}]", path, isPathDir); + if (!isPathDir) { + log.warn("[lsOfSftp] [cannot display remote folder] [path: {}]", path); + throw new NZException(RCode.TERMINAL_LS_FOLDER_ERROR); + } + + log.info("[lsOfSftp] [ls directory] [path: {}]", path); + + channelSftp = sftp.getClient(); + List<ChannelSftp.LsEntry> lsEntries = sftp.lsEntries(path); + + List<Object> list = Tool.ListUtil.list(true); + for (ChannelSftp.LsEntry lsEntry : lsEntries) { + SftpATTRS attrs = lsEntry.getAttrs(); + + String fullName = StrUtil.EMPTY; + if (isPathDir) { + fullName = new File(path, lsEntry.getFilename()).toString(); + } else { + fullName = path; + } + boolean isLink = attrs.isLink(); + boolean isDir = attrs.isDir(); + boolean isBlk = attrs.isBlk(); + boolean isFifo = attrs.isFifo(); + boolean isReg = attrs.isReg(); + boolean isSock = attrs.isSock(); + long size = attrs.getSize(); + String linkName = null; + // 当文件为链接时,需要进一步判断文件类型和链接文件名称 + if(isLink) { + try { + linkName = channelSftp.readlink(fullName); + SftpATTRS stat = channelSftp.stat(fullName); + isDir = stat.isDir(); + isBlk = stat.isBlk(); + isFifo = stat.isFifo(); + isReg = stat.isReg(); + isSock = stat.isSock(); + size = stat.getSize(); + } catch (Exception e) { + log.warn(e,"link error: {}", fullName); + } + } + Map<Object, Object> map = Tool.MapUtil.builder() + .put("name", lsEntry.getFilename()) + .put("fullName", fullName) + .put("permissions", attrs.getPermissions()) + .put("permissionsString", attrs.getPermissionsString()) + .put("gid", attrs.getGId()) + .put("uid", attrs.getUId()) + .put("extended", attrs.getExtended()) + .put("size", size) + .put("isDir", isDir) + .put("isBlk", isBlk) + .put("isFifo", isFifo) + .put("isLink", isLink) + .put("isReg", isReg) + .put("isSock", isSock) + .put("cts", attrs.getATime()) + .put("uts", attrs.getMTime()) + .put("linkName", linkName) + .map(); + + list.add(map); + } + + resultData = Tool.MapUtil.builder() + .put("list", list) + .put("path", path) + .map(); + } finally { + Tool.JschUtil.close(channelSftp); + } + return resultData; + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public void mkdirOfSftp(String uuid, String path) { + Sftp sftp = this.getSftpChannel(uuid); + try { + boolean exist = sftp.exist(path); + log.info("[mkdirOfSftp] [the path exist] [path: {}] [value: {}]", path, exist); + if (exist) { + log.warn("[mkdirOfSftp] [The specified file name already exists, please enter another name] [path: {}]", path); + throw new NZException(RCode.TERMINAL_MKDIR_DIR_ALREADY_EXISTS); + } else { + log.info("[mkdirOfSftp] [create path] [path: {}]", path); + + // mkdir + sftp.mkDirs(path); + // save log + sftpLogService.saveSftpLog(uuid, path, TerminalConstant.SftpOperType.MKDIR.getValue()); + } + } finally { + // disconnect + sftp.getClient().disconnect(); } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void rmOfSftp(String uuid, String path) { + Sftp sftp = this.getSftpChannel(uuid); + try { + boolean cd = sftp.cd(path); + if (cd) { + throw new NZException(RCode.TERMINAL_CANNOT_DELETE_DIR); + } + // delFile + sftp.delFile(path); - /** - * session 已经结束,更新状态,设置结束时间 - */ - TerminalSessionEntity sessionEntity = (TerminalSessionEntity) TerminalSession.getTerminalAttributeInfo(uuid).get("terminalSessionEntity"); - if (sessionEntity.getStartTime() == null) { - sessionEntity.setStartTime(new Date()); + sftpLogService.saveSftpLog(uuid, path, TerminalConstant.SftpOperType.RM.getValue()); + } finally { + // disconnect + sftp.getClient().disconnect(); } + } - sessionEntity.setEndTime(new Date()); - sessionEntity.setKillUserId(ShiroUtils.getUserId()); - sessionEntity.setStatus(Constants.SessionStatus.FORCE_QUIT.getValue()); - TerminalSessionService terminalSessionService = (TerminalSessionService) TerminalSession.clientAttributeInfo.get("terminalSessionService"); - terminalSessionService.saveOrUpdate(sessionEntity); + @Override + public String uploadOfSftp(String uuid, String path, MultipartFile multipartFile) { + Sftp sftp = this.getSftpChannel(uuid); + String tid = StrUtil.uuid(); + + boolean exist = sftp.exist(path); + if (!exist) { + log.warn("upload file directory does not exist create a file directory, path: {}", path); + this.mkdirOfSftp(uuid, path); + } + boolean isDir = sftp.cd(path); + if (isDir) { + File tempFile = Tool.FileUtil.newFile(Tool.StrUtil.concat(true, Constant.TEMP_PATH, File.separator, multipartFile.getOriginalFilename())); + try { + // copy stream + FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), tempFile); + // upload thread + SftpUploadRunnable sftpUploadRunnable = new SftpUploadRunnable(tid, path, sftp, tempFile); + SFTP_UPLOAD_THREAD_MAP.put(tid, sftpUploadRunnable); + + // record log + String fullName = FileUtil.file(path, multipartFile.getOriginalFilename()).toString(); + sftpLogService.saveSftpLog(uuid, fullName, TerminalConstant.SftpOperType.UPLOAD.getValue()); + + // run upload + Tool.ThreadUtil.execAsync(sftpUploadRunnable); + } catch (IOException e) { + log.error(e); + FileUtil.del(tempFile); + } + } else { + // disconnect + sftp.getClient().disconnect(); + throw new NZException(RCode.TERMINAL_UPLOAD_DIRECTORY_ERROR); + } + return tid; + } + + @Override + public Map<Object, Object> querySftpUploadProcess(String tid) { + SFTPUploadMonitor sftpUploadMonitor = UPLOAD_PROGRESS_CACHE.get(tid); + if (ObjectUtil.isNull(sftpUploadMonitor)) { + throw new NZException(RCode.TERMINAL_UPLOAD_PROGRESS_NOT_FOUND); + } + + Map<Object, Object> map = Tool.MapUtil.builder() + .put("tid", tid) + // type 暂时支持上传,不支持下载 + .put("type", TerminalConstant.SftpOperType.UPLOAD.getValue()) + .put("total", sftpUploadMonitor.getTotalSize()) + .put("done", sftpUploadMonitor.getUploadProgress()) + .put("sts", sftpUploadMonitor.getStartTime()) + .put("cts", System.currentTimeMillis()) + .map(); + return map; + } + + @Override + public void cancelUpload(String tid) { + SftpUploadRunnable uploadRunnable = SFTP_UPLOAD_THREAD_MAP.get(tid); + if (ObjectUtil.isNotNull(uploadRunnable)) { + // interrupt + uploadRunnable.interrupt(); + } + } + + @Override + public void renameFileOfSftp(String uuid, String oldPath, String newPath) { + Sftp sftp = this.getSftpChannel(uuid); + ChannelSftp channelSftp = null; try { - TerminalSession.remove(session); - // TerminalHandler.unloginUserHandle(session); - StringBuilder sb = new StringBuilder(); - sb.append("\u001B[01;31m\u001B[K Administrator disconnected \u001B[m\u001B[K \r\n"); - sb.append("$: "); - session.sendMessage(new TextMessage(sb.toString())); - } catch (IOException e) { - log.error(String.format("terminal session kill failed,uuid = %s,错误信息 = %s", uuid, e.getMessage()), e); + channelSftp = sftp.getClient(); + + boolean exist = sftp.exist(newPath); + log.info("[renameFileOfSftp] [rename newpath exist] [newPath: {}] [exist: {}]", newPath, exist); + if (exist && !StrUtil.equals(oldPath, newPath)) { + log.warn("[renameFileOfSftp] [The specified file name already exists, please enter another name] [path: {}]", newPath); + throw new NZException(RCode.TERMINAL_MKDIR_DIR_ALREADY_EXISTS); + } + + // rename + channelSftp.rename(oldPath, newPath); + + // record sftp log + // sftpLogService.saveSftpLog(uuid); + } catch (SftpException e) { + log.error(e, "[renameFileOfSftp] [rename file error] [uuid: {}] [oldPath: {}] [newPath: {}]", uuid, oldPath, newPath); + throw new NZException(e.getMessage(), HttpStatus.HTTP_INTERNAL_ERROR); + } finally { + // disconnect + Tool.JschUtil.close(channelSftp); } + } + + @Override + public Map<Object, Object> duplicateSession(String token, String uuid, Integer width, Integer height, Integer cols, Integer rows) { + log.info("[duplicateSession] [begin] [uuid: {}]", uuid); + Map<Object, Object> connObjMap = TerminalSession.TERMINAL_CONNECTED_CACHE.get(uuid); + log.info("[duplicateSession] [source sesion] [uuid: {}] [exist: {}]", uuid, Tool.MapUtil.isNotEmpty(connObjMap)); - // kill 之后,将剩余文件写到数据库中 - TerminalHandler.handleRecodeAfterClientClose(uuid, terminalRecordService); + if (Tool.MapUtil.isEmpty(connObjMap)) { + log.warn("[duplicateSession] [source sesion does not exist] [uuid: {}]", uuid); + throw new NZException(RCode.TERMINAL_SESSION_NOT_FOUND); + } + + String duplicateSessionUUID = StrUtil.uuid(); + log.info("[duplicateSession] [source session exists. duplicate session info] [source uuid: {}] [duplicate uuid: {}]", uuid, duplicateSessionUUID); + + // terminal Connection Info + AssetAsset terminalConnInfo = (AssetAsset) connObjMap.get(TerminalSession.CONNECTION_ASSET_KEY); + log.info("[duplicateSession] [duplicate session source information] [asset: {}]", JSONUtil.toJsonStr(terminalConnInfo)); + + // SSH + if (TerminalConstant.ProtocolType.SSH.getValue().equals(terminalConnInfo.getAuthProtocol())) { + try { + log.info("[duplicateSession] [reopen SSH connection begin.] [duplicate uuid: {}]", duplicateSessionUUID); + Session session = SshUtil.getSshConnection(terminalConnInfo); + TerminalSession.TERMINAL_CONNECTED_CACHE.put(duplicateSessionUUID, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, session) + .put(Constant.AUTH_TOKEN_CODE, token) + .map()); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(duplicateSessionUUID, Tool.DateUtil.currentSeconds()); + log.info("[duplicateSession] [reopen SSH connection success.] [duplicate uuid: {}]", duplicateSessionUUID); + } catch (Exception e) { + log.error(e, "[duplicateSession] [reopen SSH connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } + + // TELNET + if (TerminalConstant.ProtocolType.TELNET.getValue().equals(terminalConnInfo.getAuthProtocol())) { + try { + log.info("[duplicateSession] [reopen TELNET connection begin.] [duplicate uuid: {}]", duplicateSessionUUID); + TelnetUtil telnetUtil = new TelnetUtil(); + telnetUtil.connect(terminalConnInfo.getManageIp(), terminalConnInfo.getAuthProtocolPort()); + List<SysConfigEntity> configList = sysConfService.list(new LambdaQueryWrapper<SysConfigEntity>().in(SysConfigEntity::getParamKey, "terminal_telnet_user_tip", "terminal_telnet_pin_tip")); + Map<String, String> systemTipConfigMap = configList.stream().collect(Collectors.toMap(SysConfigEntity::getParamKey, SysConfigEntity::getParamValue)); + + String authUserTip = TelnetUtil.getTelenetLoginTip(terminalConnInfo.getAuthUserTip(), systemTipConfigMap, "terminal_telnet_user_tip"); + String authPinTip = TelnetUtil.getTelenetLoginTip(terminalConnInfo.getAuthPinTip(), systemTipConfigMap, "terminal_telnet_pin_tip"); + boolean isLogin = telnetUtil.login(terminalConnInfo.getAuthUsername(), StringUtils.str(Base64.getDecoder().decode(terminalConnInfo.getAuthPin())), authUserTip, authPinTip); + if (isLogin) { + TerminalSession.TERMINAL_CONNECTED_CACHE.put(duplicateSessionUUID, + Tool.MapUtil.builder() + .put(TerminalSession.CONNECTION_ASSET_KEY, terminalConnInfo) + .put(TerminalSession.CONNECTION_CONNECTION_ENTITY_KEY, telnetUtil.getTelnetClient()) + .put(Constant.AUTH_TOKEN_CODE, token) + .map()); + TerminalSession.TERMINAL_CONNECTED_LAST_ACTIVE_MAP.put(duplicateSessionUUID, Tool.DateUtil.currentSeconds()); + log.info("[duplicateSession] [reopen TELNET connection success.] [duplicate uuid: {}]", duplicateSessionUUID); + } else { + log.warn("[duplicateSession] [reopen TELNET connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } catch (Exception e) { + log.error(e, "[duplicateSession] [reopen TELNET connection error.] [duplicate uuid: {}]", duplicateSessionUUID); + throw new NZException(RCode.TERMINAL_DUPLICATE_SESSION_FAILED); + } + } + + // return duplicate session map + Map<Object, Object> duplicateSessionMap = Tool.MapUtil.builder() + .put("uuid", duplicateSessionUUID) + .put("host", terminalConnInfo.getManageIp()) + .put("port", terminalConnInfo.getAuthProtocolPort()) + .put("authProtocol", terminalConnInfo.getAuthProtocol()) + .put("authUsername", terminalConnInfo.getAuthUsername()) + .map(); + log.info("[duplicateSession] [duplicate session finshed] [source uuid: {}] [duplicate uuid: {}]", uuid, duplicateSessionUUID); + return duplicateSessionMap; } @Override - public void cleanExpiredDataByTime(DateTime startCleanTerminalTime) { - terminalSessionDao.cleanExpiredDataByTime(startCleanTerminalTime); + @Transactional(rollbackFor = Exception.class) + public void downloadOfSftp(String uuid, String path, HttpServletResponse response) { + Sftp sftp = this.getSftpChannel(uuid); + + StopWatch sw = new StopWatch(); + sw.start(); + long fileSize = 0; + try { + boolean exist = sftp.exist(path); + if (!exist) { + log.info("[downloadOfSftp] [no such file] [path: {}]", path); + throw new NZException(RCode.TERMINAL_DOWNLOAD_NO_SUCH_FILE); + } + boolean isDir = sftp.cd(path); + if (isDir) { + log.info("[downloadOfSftp] [not supported to get directory] [path: {}]", path); + throw new NZException(RCode.TERMINAL_DOWNLOAD_NOT_SUPPORTED_DIRECTORY); + } + + List<ChannelSftp.LsEntry> entryList = sftp.lsEntries(path); + ChannelSftp.LsEntry fileEntity = Tool.CollUtil.getFirst(entryList); + if (ObjectUtil.isNull(fileEntity)) { + log.info("[downloadOfSftp] [no such file] [path: {}]", path); + throw new NZException(RCode.TERMINAL_DOWNLOAD_NO_SUCH_FILE); + } + + // file size + fileSize = fileEntity.getAttrs().getSize(); + + log.info("[downloadOfSftp] [download file begin] [path: {}] [file size: {}]", path, fileSize); + + String fileName = fileEntity.getFilename(); + response.setCharacterEncoding("utf-8"); + response.setContentType("multipart/form-data"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8")); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.addHeader("Content-Length", Tool.StrUtil.toString(fileSize)); + + // download + ChannelSftp channelSftp = sftp.getClient(); + channelSftp.get(path, response.getOutputStream()); + + // record sftp log + sftpLogService.saveSftpLog(uuid, path, TerminalConstant.SftpOperType.DOWNLOAD.getValue()); + } catch (Exception e) { + log.error(e, "[downloadOfSftp] [download file error] [path: {}] [file size: {}]", path, fileSize); + } finally { + sw.stop(); + // disconnect + sftp.getClient().disconnect(); + } + log.info("[downloadOfSftp] [download file finshed] [uuid: {}] [path: {}] [file size: {}] [Run Time: {}]", uuid, path, fileSize, sw.toString()); + } + + private class SftpUploadRunnable extends Thread { + + private String tid; + private String path; + + private Sftp sftp; + private File tempFile; + + public SftpUploadRunnable(String tid, String path, Sftp sftp, File tempFile) { + this.tid = tid; + this.path = path; + + this.sftp = sftp; + this.tempFile = tempFile; + } + + @Override + public void run() { + StopWatch sw = new StopWatch(); + sw.start(); + try { + // SFTP Upload Monitor query upload progress + SFTPUploadMonitor sftpUploadMonitor = new SFTPUploadMonitor(tempFile.length()); + UPLOAD_PROGRESS_CACHE.put(tid, sftpUploadMonitor); + + log.info("upload file begin... tid: {}, path: {}", tid, path); + // upload + sftp.put(Tool.FileUtil.getAbsolutePath(tempFile), path, sftpUploadMonitor, Sftp.Mode.OVERWRITE); + } catch (Exception e) { + log.error(e); + } finally { + sw.stop(); + + FileUtil.del(tempFile); + + // disconnect + sftp.getClient().disconnect(); + + // del tid & thread mapping + SFTP_UPLOAD_THREAD_MAP.remove(tid); + } + log.info("upload file finshed tid: {}, path: {}, length: {}, Run Time: {}", tid, path, tempFile.length(), sw.toString()); + } + + @Override + public void interrupt() { + super.interrupt(); + log.warn("upload file thread is interrupted. tid: {}, path: {}", tid, path); + + // del temp file + FileUtil.del(tempFile); + + try { + // disconnect channel + sftp.getClient().disconnect(); + } catch (Exception e) { + log.error(e, "sftp close error, thread interrupting. tid: {}, path: {}", tid, path); + } + + // del tid & thread mapping + SFTP_UPLOAD_THREAD_MAP.remove(tid); + + // progress + SFTPUploadMonitor sftpUploadMonitor = UPLOAD_PROGRESS_CACHE.get(tid); + log.warn("upload file thread is interrupted. tid: {}, progress: {}, path: {}", tid, sftpUploadMonitor.getUploadProgress() + '%', path); + } } } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSftpLogServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSftpLogServiceImpl.java new file mode 100644 index 00000000..a7f23705 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/service/impl/TerminalSftpLogServiceImpl.java @@ -0,0 +1,45 @@ +package com.nis.modules.terminal.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.nis.common.utils.PageUtils; +import com.nis.common.utils.Query; +import com.nis.common.utils.Tool; +import com.nis.common.utils.ToolUtil; +import com.nis.modules.asset.entity.AssetBrand; +import com.nis.modules.terminal.dao.TerminalSftpLogDao; +import com.nis.modules.terminal.entity.TerminalSftpLog; +import com.nis.modules.terminal.service.TerminalSftpLogService; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +public class TerminalSftpLogServiceImpl extends ServiceImpl<TerminalSftpLogDao, TerminalSftpLog> implements TerminalSftpLogService { + + + @Override + public PageUtils querySftpLogPage(Map<String, Object> params) { + String uuid = Tool.StrUtil.nullToDefault((String) params.get("uuid"), ""); + String name = Tool.StrUtil.nullToDefault((String) params.get("name"), ""); + + LambdaQueryWrapper<TerminalSftpLog> queryWrapper = new LambdaQueryWrapper<TerminalSftpLog>() + .eq(ToolUtil.isNotEmpty(uuid), TerminalSftpLog::getUuid, uuid) + .eq(ToolUtil.isNotEmpty(params.get("type")), TerminalSftpLog::getType, ToolUtil.isNotEmpty(params.get("type")) ? params.get("type").toString() : null) + .like(ToolUtil.isNotEmpty(name), TerminalSftpLog::getName, Tool.StrUtil.likeEscape(name)); + + IPage page = this.page(new Query(AssetBrand.class).getPage(params), queryWrapper); + return new PageUtils(page); + } + + @Override + public void saveSftpLog(String uuid, String path, Integer sftpOperType) { + TerminalSftpLog sftpLog = new TerminalSftpLog( + uuid, + sftpOperType, + path, + System.currentTimeMillis()); + this.save(sftpLog); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/utils/SFTPUploadMonitor.java b/nz-admin/src/main/java/com/nis/modules/terminal/utils/SFTPUploadMonitor.java new file mode 100644 index 00000000..0ff72372 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/utils/SFTPUploadMonitor.java @@ -0,0 +1,53 @@ +package com.nis.modules.terminal.utils; + +import cn.hutool.core.util.NumberUtil; +import com.jcraft.jsch.SftpProgressMonitor; +import lombok.Data; + +@Data +public class SFTPUploadMonitor implements SftpProgressMonitor { + + /** + * 总大小 + */ + private long totalSize = 0; + + /** + * 已上传大小 + */ + private long uploadedSize = 0; + + private long startTime = 0L; + + public SFTPUploadMonitor(long totalSize) { + this.totalSize = totalSize; + } + + @Override + public void init(int op, String src, String dest, long max) { + this.startTime = System.currentTimeMillis(); + } + + @Override + public boolean count(long count) { + this.uploadedSize += count; + if (count > 0) { + return true; + } + return false; + } + + @Override + public void end() { + } + + /** + * 上传进度 + * + * @return + */ + public String getUploadProgress() { + String percent = NumberUtil.formatPercent((double) this.uploadedSize / this.totalSize, 2); + return percent.replace("%", ""); + } +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/config/SshUserInfo.java b/nz-admin/src/main/java/com/nis/modules/terminal/utils/SshUserInfo.java index 72aad2b3..5520d65e 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/config/SshUserInfo.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/utils/SshUserInfo.java @@ -19,39 +19,49 @@ * under the License. */ -package com.nis.modules.terminal.config; +package com.nis.modules.terminal.utils; import cn.hutool.log.Log; import com.jcraft.jsch.UserInfo; public class SshUserInfo implements UserInfo { - //private String passphrase = null; - private Log logger = Log.get(); + + private static final Log log = Log.get(); + + // private String passphrase = null; + public SshUserInfo() { //this.passphrase = passphrase; } + @Override public String getPassphrase() { - return null;//passphrase; + //passphrase; + return null; } + @Override public String getPassword() { return null; } + @Override public boolean promptPassphrase(String s) { return true; } + @Override public boolean promptPassword(String s) { return true; } + @Override public boolean promptYesNo(String s) { return true; } + @Override public void showMessage(String s) { - logger.debug(s); + log.info(s); } -}
\ No newline at end of file +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/utils/TelnetUtil.java b/nz-admin/src/main/java/com/nis/modules/terminal/utils/TelnetUtil.java new file mode 100644 index 00000000..b03d371c --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/utils/TelnetUtil.java @@ -0,0 +1,235 @@ +package com.nis.modules.terminal.utils; + +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import com.nis.common.utils.Tool; +import lombok.Data; +import org.apache.commons.net.telnet.TelnetClient; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import java.util.concurrent.*; + +/** + * TelnetUtil + * user login + * + * @author HUAWEI + */ +@Data +public class TelnetUtil { + + private static final Log log = Log.get(); + + private byte[] buff = new byte[2048]; + + private TelnetClient telnetClient = new TelnetClient(); + + private InputStream inputStream = null; + private OutputStream outputStream = null; + + private String host; + private Integer port; + + /** + * default Prompt str + */ + private static final String USER_PROMPT = ".*ogin:"; + private static final String PIN_PROMPT = ".*assword:"; + + /** + * init TelnetClient + */ + public TelnetUtil() { + // VT100 VT52 VT220 VTNT ANSI + telnetClient = new TelnetClient("VT100"); + } + + /** + * connect + * + * @param ip + * @throws IOException + */ + public void connect(String ip, Integer port) throws IOException { + this.host = ip; + this.port = Tool.ObjectUtil.defaultIfNull(port, 23); + telnetClient.connect(ip, Tool.ObjectUtil.defaultIfNull(port, 23)); + inputStream = telnetClient.getInputStream(); + outputStream = telnetClient.getOutputStream(); + } + + /** + * login + * 防止该方法出现解析失败情况,陷入死循环,设置 3 分钟登录超时,超时则视为登录失败 + * + * @param user + * @param pin + * @param userPrompt + * @param pinPrompt + * @return + * @throws IOException + */ + public boolean login(String user, String pin, String userPrompt, String pinPrompt) throws IOException { + log.info("[login begin] [host: {}] [user: {}] [userPrompt: {}] [pinPrompt: {}]", this.host, user, userPrompt, pinPrompt); + userPrompt = Tool.StrUtil.emptyToDefault(userPrompt, USER_PROMPT); + pinPrompt = Tool.StrUtil.emptyToDefault(pinPrompt, PIN_PROMPT); + + String finalUserPrompt = userPrompt; + String finalPinPrompt = pinPrompt; + Callable<Boolean> task = new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + // user name + String read = readString(); + while (true) { + log.info("[login] [read the response content. find user name prompt] [host: {}] [response: {}] [user tip: {}]", host, read, finalUserPrompt); + if (Tool.ReUtil.isMatch(finalUserPrompt, read.trim())) { + break; + } else { + read = readString(); + } + } + log.info("[login] [write user name] [host: {}] [user: {}]", host, user); + write(user); + + // pin + read = readString(); + while (true) { + log.info("[login] [read the response content. find password prompt] [host: {}] [response: {}] [password tip: {}]", host, read, finalPinPrompt); + if (Tool.ReUtil.isMatch(finalPinPrompt, read.trim())) { + break; + } else { + read = readString(); + } + } + log.info("[login] [write password] [host: {}] [pin: {}]", host, "******"); + write(pin); + + for (; ; ) { + read = readString(); + log.info("[login] [server response] [content: {}]", read); + if (StrUtil.containsIgnoreCase(read, "Last login")) { + log.info("[login] [login success] [host: {}] [user: {}]", host, user); + return true; + } else if (StrUtil.containsIgnoreCase(read, "Login incorrect")) { + log.warn("[login] [login failed] [host: {}] [user: {}]", host, user); + return false; + } + } + } + }; + Boolean loginResult = false; + ExecutorService executorService = Tool.ThreadUtil.newExecutor(); + try { + Future<Boolean> future = executorService.submit(task); + if (!future.isCancelled()) { + // 防止该方法出现解析失败情况,陷入死循环,设置 3分钟登录超时,超时则视为登录失败 + loginResult = future.get(3, TimeUnit.MINUTES); + } + } catch (InterruptedException | ExecutionException e) { + log.error(e, "[login] [error] [host: {}] [user: {}] [userPrompt: {}] [pinPrompt: {}]", this.host, user, userPrompt, pinPrompt); + } catch (TimeoutException e) { + log.error(e, "[login] [login timeout] [host: {}] [user: {}] [userPrompt: {}] [pinPrompt: {}]", this.host, user, userPrompt, pinPrompt); + } finally { + executorService.shutdown(); + } + log.info("[TelnetUtil] [login finshed] [host: {}] [user: {}]", this.host, user); + return loginResult; + } + + + /** + * read + * + * @return + * @throws IOException + */ + public String readString() throws IOException { + int size = inputStream.read(this.buff); + if (size == Tool.StrUtil.INDEX_NOT_FOUND) { + throw new IndexOutOfBoundsException(); + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + char chr = (char) (buff[i] & 0xff); + sb.append(chr); + } + + return sb.toString().trim(); + } + + + /** + * 向服务器写字符串 + * + * @param text + * @throws IOException + */ + public void write(String text) { + IoUtil.write(outputStream, false, text.getBytes()); + IoUtil.write(outputStream, false, Tool.StrUtil.CRLF.getBytes()); + IoUtil.flush(outputStream); + // sleep for wait response + Tool.ThreadUtil.sleep(200); + } + + /** + * simply write + * + * @param cmd + * @return + * @throws IOException + */ + public String exec(String cmd) throws IOException { + write(cmd); + return readString(); + } + + /** + * close + */ + public void close() { + try { + write("exit"); + write("exit"); + write("exit"); + } catch (Exception ex) { + } + + // close + IoUtil.close(inputStream); + IoUtil.close(outputStream); + + try { + if (null != telnetClient) { + telnetClient.disconnect(); + } + } catch (Exception e) { + } + } + + /** + * get Telenet Login Tip + * prompt information for priority use of assets + * + * @param assetTip + * @param systemTipConfigMap + * @param configKey + * @return + */ + public static String getTelenetLoginTip(String assetTip, Map<String, String> systemTipConfigMap, String configKey) { + // main asset tip + if (Tool.StrUtil.isNotEmpty(assetTip)) { + return ".*" + assetTip.trim(); + } + // system tip config + String systemConfigTip = systemTipConfigMap.get(configKey); + return ".*" + systemConfigTip; + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/utils/TerminalConstant.java b/nz-admin/src/main/java/com/nis/modules/terminal/utils/TerminalConstant.java new file mode 100644 index 00000000..2937ed18 --- /dev/null +++ b/nz-admin/src/main/java/com/nis/modules/terminal/utils/TerminalConstant.java @@ -0,0 +1,214 @@ +package com.nis.modules.terminal.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class TerminalConstant { + + public static final String PARAM_HTTP_SESSION_ID_KEY = "http_session_id"; + public static final String NZ_USER_HOME = System.getProperty("user.home") + File.separator + ".nezha"; + public static final String PARAM_TERMINAL_PREFIX_KEY = "nezha_term_"; + + /** + * 单位为 byte , 10485760 byte = 10Mb + */ + public static final Integer RECORD_TEMPFILE_MAX_LENGTH = 10485760; + + + // 存储模式,1: 本地存储,2:S3对象存储 + public static final String TERMINAL_STORAGE_TYPE = "terminal_storage_type"; + + public static final String TERMINAL_STORAGE_S3_ENDPOINT = "terminal_storage_s3_endpoint"; + public static final String TERMINAL_STORAGE_S3_BUCKET = "terminal_storage_s3_bucket"; + public static final String TERMINAL_STORAGE_S3_ACCESS_KEY = "terminal_storage_s3_access_key"; + public static final String TERMINAL_STORAGE_S3_SECRET_ACCESS_KEY = "terminal_storage_s3_secret_access_key"; + + // 存储天数 + public static final String TERMINAL_RECORD_LOCAL_RETENTION = "terminal_record_local_retention"; + + /** + * 不可见字符 + */ + public static final List<Integer> INVISIBLE_CHAR; + + /** + * 未登录提示信息 + */ + public static final String UNLOGIN_MESSAGE; + + static { + INVISIBLE_CHAR = new ArrayList<>(); + INVISIBLE_CHAR.add(7); + INVISIBLE_CHAR.add(8); + INVISIBLE_CHAR.add(12); + INVISIBLE_CHAR.add(10); + INVISIBLE_CHAR.add(13); + INVISIBLE_CHAR.add(9); + INVISIBLE_CHAR.add(11); + INVISIBLE_CHAR.add(92); + INVISIBLE_CHAR.add(63); + INVISIBLE_CHAR.add(39); + INVISIBLE_CHAR.add(34); + INVISIBLE_CHAR.add(0); + + StringBuilder sb = new StringBuilder(); + sb.append("\r\nlogout\r\n"); + sb.append("Welcome to Nezha Terminal! \r\n"); + sb.append("Type `help' to learn how to use Nz Terminal prompt. \r\n"); + sb.append("$: "); + UNLOGIN_MESSAGE = sb.toString(); + } + + /** + * SSH 认证类型 + */ + public enum SshAuthType { + // password + PIN(1, "password"), + // private key + KEY(2, "key"); + + private Integer type; + private String value; + + SshAuthType(Integer type, String value) { + this.type = type; + this.value = value; + } + + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public static SshAuthType getEntityByType(Integer type) { + for (SshAuthType v : values()) { + if (v.getType().equals(type)) { + return v; + } + } + throw new IllegalArgumentException(); + } + + public static SshAuthType getEntityByValue(String value) { + for (SshAuthType v : values()) { + if (v.getValue().equals(value)) { + return v; + } + } + throw new IllegalArgumentException(); + } + } + + /** + * ProtocolType + */ + public enum ProtocolType { + // ssh + SSH(1), + // telnet + TELNET(2); + + private Integer value; + + ProtocolType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + + public static ProtocolType getEntityByValue(Integer value) { + for (ProtocolType v : values()) { + if (v.getValue().equals(value)) { + return v; + } + } + throw new IllegalArgumentException(); + } + } + + + public enum SessionStatus { + + /** + * 连接中 + */ + CONNECTING(0), + + /** + * 连接失败 + */ + CONNECTION_FAILED(1), + + /** + * 已结束 + */ + OVER(2), + + /** + * 强制退出 + */ + FORCE_QUIT(3), + + /** + * 未知错误 + */ + UNKNOWN_ERROR(4); + + + private int value; + + SessionStatus(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + /** + * SftpOperType + */ + public enum SftpOperType { + // upload + UPLOAD(1), + // download + DOWNLOAD(2), + // cmd mkdir + MKDIR(3), + // cmd rm + RM(4); + + private Integer value; + + SftpOperType(Integer value) { + this.value = value; + } + + public Integer getValue() { + return value; + } + + } + +} diff --git a/nz-admin/src/main/java/com/nis/modules/tool/controller/TracerouteController.java b/nz-admin/src/main/java/com/nis/modules/tool/controller/TracerouteController.java index 0aa9a147..a005b0ea 100644 --- a/nz-admin/src/main/java/com/nis/modules/tool/controller/TracerouteController.java +++ b/nz-admin/src/main/java/com/nis/modules/tool/controller/TracerouteController.java @@ -13,11 +13,11 @@ import com.nis.common.exception.NZException; import com.nis.common.utils.R; import com.nis.common.utils.RCode; import com.nis.common.utils.Tool; +import com.nis.modules.agent.entity.Agent; +import com.nis.modules.agent.service.AgentService; import com.nis.modules.agent.util.AgentUtil; import com.nis.modules.asset.entity.Dc; import com.nis.modules.asset.service.DcService; -import com.nis.modules.agent.entity.Agent; -import com.nis.modules.agent.service.AgentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; diff --git a/nz-admin/src/main/java/com/nis/modules/vsys/entity/VsysResult.java b/nz-admin/src/main/java/com/nis/modules/vsys/entity/VsysResult.java index 0197068e..3518d64f 100644 --- a/nz-admin/src/main/java/com/nis/modules/vsys/entity/VsysResult.java +++ b/nz-admin/src/main/java/com/nis/modules/vsys/entity/VsysResult.java @@ -57,6 +57,11 @@ public class VsysResult implements Serializable { private String msg; /** + * sf ruleSet chain 三个接口请求参数记录 + */ + private String reqParam; + + /** * 执行第几次 默认:1 */ private Integer num; diff --git a/nz-admin/src/main/java/com/nis/modules/vsys/service/impl/VsysTaskServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/vsys/service/impl/VsysTaskServiceImpl.java index a404d0b0..21fa2090 100644 --- a/nz-admin/src/main/java/com/nis/modules/vsys/service/impl/VsysTaskServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/vsys/service/impl/VsysTaskServiceImpl.java @@ -8,6 +8,7 @@ import cn.hutool.http.HttpStatus; import cn.hutool.log.Log; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONPath; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -75,6 +76,7 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl @Autowired private AssetFieldValueService assetFieldValueService; + private static ThreadLocal<Map<Object, Object>> VSYS_REQ_PARAM_MAP = new ThreadLocal(); /** * 校验 task info list @@ -488,6 +490,13 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl default: break; } + + // req param + Map<Object, Object> reqParamMap = VSYS_REQ_PARAM_MAP.get(); + reqParamMap = Tool.MapUtil.defaultIfEmpty(reqParamMap, Tool.MapUtil.newHashMap()); + res.setReqParam(JSONObject.toJSONString(reqParamMap, SerializerFeature.MapSortField)); + VSYS_REQ_PARAM_MAP.remove(); + // 本次执行结束 更新 result log vsysResultService.update(res, new LambdaUpdateWrapper<VsysResult>() .eq(VsysResult::getTaskId, vsysTask.getId()) @@ -572,6 +581,15 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String path = "/restconf/data"; + + // record request body & path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Add ServiceFunction Request Path", path) + .put("Add ServiceFunction Request Body", sfBody) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestPost(manageIp, path, sfBody); return resultMp; } @@ -672,6 +690,15 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String path = "/restconf/data"; + + // record request body & path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Add RuleSet Request Path", path) + .put("Add RuleSet Request Body", ruleSetBody) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestPost(manageIp, path, ruleSetBody); return resultMp; } @@ -717,6 +744,15 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String path = String.format("%s%s", "/restconf/data", "/tsg-os-mgnt-srv:service_function_chain=Default"); + + // record request body & path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Add Chain Request Path", path) + .put("Add Chain Request Body", chainBody) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestPostWithoutEncodeUrl(manageIp, path, chainBody); return resultMp; } @@ -734,6 +770,14 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String path = String.format("%s%s=%s", "/restconf/data", "/tsg-os-mgnt-srv:service_function", sfName); + + // record request path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Delete ServiceFunction Request Path", path) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestDeleteWithoutEncodeUrl(manageIp, path, null); return resultMp; } @@ -751,6 +795,14 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String path = String.format("%s%s=%s", "/restconf/data", "/tsg-os-mgnt-srv:ruleset", ruleSetName); + + // record request path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Delete RuleSet Request Path", path) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestDeleteWithoutEncodeUrl(manageIp, path, null); return resultMp; } @@ -768,8 +820,31 @@ public class VsysTaskServiceImpl extends ServiceImpl<VsysTaskDao, VsysTask> impl // request String indexq = "/index=" + vsysId; String path = String.format("%s%s%s", "/restconf/data", "/tsg-os-mgnt-srv:service_function_chain=Default", indexq); + + // record request path + this.updateVsysReqParamMap( + Tool.MapUtil.builder() + .put("Delete Chain Request Path", path) + .map() + ); + Map<Object, Object> resultMp = VsysConfigUtil.requestDeleteWithoutEncodeUrl(manageIp, path, null); return resultMp; } + /** + * update Vsys Req Param Map + * + * @param reqParamMap + */ + private void updateVsysReqParamMap(Map<Object, Object> reqParamMap) { + // get value + Map<Object, Object> reqParam = VSYS_REQ_PARAM_MAP.get(); + reqParam = Tool.MapUtil.defaultIfEmpty(reqParam, Tool.MapUtil.newHashMap()); + reqParam.putAll(reqParamMap); + + // update value + VSYS_REQ_PARAM_MAP.set(reqParam); + } + } diff --git a/nz-admin/src/main/resources/db/R__AZ_sys_config.sql b/nz-admin/src/main/resources/db/R__AZ_sys_config.sql index 62aa08ec..03d66f9f 100644 --- a/nz-admin/src/main/resources/db/R__AZ_sys_config.sql +++ b/nz-admin/src/main/resources/db/R__AZ_sys_config.sql @@ -45,7 +45,7 @@ REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'snmp_exporter_prometheus_host', '127.0.0.1', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'blackbox_exporter_prometheus_scheme', 'http', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'blackbox_exporter_prometheus_host', '127.0.0.1', 1, NULL); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (NULL, 'system_version', '22.10', 1, 'NZ系统版本'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (NULL, 'system_version', '23.01', 1, 'NZ系统版本'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (NULL, 'prometheus_default_retention_time_when_s3', '1', 1, 'metrics 对象存储时普罗米修斯默认保留时间 单位: d'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'interface_name', 'eth0,en0,bond0,ens2f0,enp0s31f6', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'stat_query_json', '[\r\n {\r\n \"name\": \"asset\",\r\n \"datasql\": \"SELECT t.name as asset,t.*,atc.vm,atc.vmh,atc.NAME AS type,assc.NAME AS state,ab.NAME AS brand,am.NAME AS model,dc.NAME AS datacenter,cabinet.NAME AS cabinet,(CASE ap.`status` WHEN 1 THEN \'Up\' ELSE \'Down\' END) AS ping,(CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END) AS alert_message_count,(CASE WHEN mc.c IS NULL THEN 0 ELSE mc.c END) AS endpoint_count FROM asset_asset t LEFT JOIN asset_type_conf atc ON t.type_id=atc.id LEFT JOIN asset_state_conf assc ON t.state_id=assc.id LEFT JOIN asset_brand ab ON t.brand_id=ab.id LEFT JOIN asset_model am ON t.model_id=am.id LEFT JOIN dc ON t.dc_id=dc.id LEFT JOIN cabinet ON t.cabinet_id=cabinet.id LEFT JOIN asset_ping ap ON t.id=ap.asset_id LEFT JOIN (SELECT asset_id,count(1) AS c FROM alert_message_active ama WHERE ama.asset_id IS NOT NULL GROUP BY asset_id) amc ON amc.asset_id=t.id LEFT JOIN (SELECT asset_id,count(1) AS c FROM monitor_endpoint me GROUP BY asset_id) mc ON mc.asset_id=t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"ping\",\r\n \"expr\": \"ping\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"asset_type\",\r\n \"expr\": \"type\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"asset_state\",\r\n \"expr\": \"state\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"brand\",\r\n \"expr\": \"brand\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"model\",\r\n \"expr\": \"model\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"expr\": \"datacenter\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"cabinet\",\r\n \"expr\": \"cabinet\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"expr\": \"asset\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"endpoint_sum\",\r\n \"expr\": \"sum(endpoint_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"datacenter\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_datacenter_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"dc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"dc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"dc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"dc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset type\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_type_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"atc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"atc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"atc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"atc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset state\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_state_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"assc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"assc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"assc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"assc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset brand\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_brand_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"ab.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"ab.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"ab.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"ab.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset model\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_model_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"am.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"am.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"am.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"am.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"id\",\r\n \"type\": 1,\r\n \"rule\": [\r\n {\r\n \"regex\": \"\\\\d+\",\r\n \"tip\": \"filter_asset_id_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \">\",\r\n \"expr\": \"t.id > {{value}}\"\r\n },\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.id = {{value}}\"\r\n },\r\n {\r\n \"name\": \"<\",\r\n \"expr\": \"t.id < {{value}}\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.id != {{value}}\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"datasql\": \"SELECT t.id,t.name as datacenter,(CASE WHEN cc.c IS NULL THEN 0 ELSE cc.c END) AS cabinet_count,(CASE WHEN ac.c IS NULL THEN 0 ELSE ac.c END) AS asset_count,(CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END) AS alert_message_count FROM dc t LEFT JOIN (SELECT dc_id,count(1) AS c FROM cabinet GROUP BY dc_id) cc ON cc.dc_id=t.id LEFT JOIN (SELECT dc_id,count(1) AS c FROM asset_asset GROUP BY dc_id) ac ON ac.dc_id=t.id LEFT JOIN (SELECT dc_id,count(1) AS c FROM alert_message_active ama WHERE ama.dc_id IS NOT NULL GROUP BY dc_id) amc ON amc.dc_id=t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"datacenter\",\r\n \"expr\": \"datacenter\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"cabinet_sum\",\r\n \"expr\": \"sum(cabinet_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"asset_sum\",\r\n \"expr\": \"sum(asset_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"datacenter\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_datacenter_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"project\",\r\n \"datasql\": \"SELECT t.id,t.name as project,(CASE WHEN mm.c IS NULL THEN 0 ELSE mm.c END) AS module_count,(CASE WHEN aec.c IS NULL THEN 0 ELSE aec.c END) AS endpoint_count,(CASE WHEN aec.ac IS NULL THEN 0 ELSE aec.ac END) AS asset_count,(CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END) AS alert_message_count FROM monitor_project t LEFT JOIN (SELECT project_id,count(1) AS c FROM monitor_module GROUP BY project_id) mm ON mm.project_id=t.id LEFT JOIN (SELECT project_id,count(1) AS c FROM alert_message_active ama WHERE ama.project_id IS NOT NULL GROUP BY project_id) amc ON amc.project_id=t.id LEFT JOIN (SELECT project_id,count(1) AS c,count(DISTINCT e.asset_id) AS ac FROM monitor_endpoint e LEFT JOIN monitor_module m ON m.id=e.module_id GROUP BY m.project_id) aec ON aec.project_id=t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"project\",\r\n \"expr\": \"project\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"module_sum\",\r\n \"expr\": \"sum(module_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"endpoint_sum\",\r\n \"expr\": \"sum(endpoint_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"asset_sum\",\r\n \"expr\": \"sum(asset_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"project\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_project_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"datasql\": \"SELECT t.id,t.NAME AS module,mp.NAME AS project,(CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END) AS alert_message_count,(CASE WHEN mc.c IS NULL THEN 0 ELSE mc.c END) AS endpoint_count,(CASE WHEN mc.ac IS NULL THEN 0 ELSE mc.ac END) AS asset_count FROM monitor_module t LEFT JOIN monitor_project mp ON t.project_id=mp.id LEFT JOIN (SELECT module_id,count(1) AS c FROM alert_message_active ama WHERE ama.module_id IS NOT NULL GROUP BY module_id) amc ON amc.module_id=t.id LEFT JOIN (SELECT module_id,count(1) AS c,count(DISTINCT asset_id) AS ac FROM monitor_endpoint me GROUP BY module_id) mc ON mc.module_id=t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"project\",\r\n \"expr\": \"project\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"expr\": \"module\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"endpoint_sum\",\r\n \"expr\": \"sum(endpoint_count)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"asset_sum\",\r\n \"expr\": \"sum(asset_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"project\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_project_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"mp.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"mp.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"mp.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"mp.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_module_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"endpoint\",\r\n \"datasql\": \"SELECT \\tt.NAME AS endpoint, \\tt.*, \\tmm.NAME AS module, \\tmp.NAME AS project, \\tdc.NAME AS datacenter, \\taa.NAME AS asset, \\tatc.vm, \\tatc.vmh, \\tatc.NAME AS type, \\tassc.NAME AS state, \\tab.NAME AS brand, \\tam.NAME AS model, \\tcabinet.NAME AS cabinet, \\t( CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END ) AS alert_message_count FROM \\tmonitor_endpoint t \\tLEFT JOIN monitor_module mm ON t.module_id = mm.id \\tLEFT JOIN monitor_project mp ON mm.project_id = mp.id \\tLEFT JOIN asset_asset aa ON t.asset_id = aa.id \\tLEFT JOIN asset_type_conf atc ON aa.type_id = atc.id \\tLEFT JOIN asset_state_conf assc ON aa.state_id = assc.id \\tLEFT JOIN asset_brand ab ON aa.brand_id = ab.id \\tLEFT JOIN asset_model am ON aa.model_id = am.id \\tLEFT JOIN dc ON aa.dc_id = dc.id \\tLEFT JOIN cabinet ON aa.cabinet_id = cabinet.id \\tLEFT JOIN asset_ping ap ON aa.id = ap.asset_id \\tLEFT JOIN ( SELECT endpoint_id, count( 1 ) AS c FROM alert_message_active ama WHERE ama.endpoint_id IS NOT NULL GROUP BY endpoint_id ) amc ON amc.endpoint_id = t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"project\",\r\n \"expr\": \"project\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"expr\": \"module\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"expr\": \"datacenter\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"expr\": \"asset\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"endpoint\",\r\n \"expr\": \"endpoint\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"project\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_project_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"mp.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"mp.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"mp.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"mp.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_module_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"mm.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"mm.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"mm.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"mm.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"endpoint\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_endpoint_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_datacenter_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"dc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"dc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"dc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"dc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"aa.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"aa.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"aa.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"aa.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"alert rule\",\r\n \"datasql\": \"SELECT t.id,t.NAME AS \'alertRule\',(CASE t.state WHEN 1 THEN \'Enabled\' WHEN 0 THEN \'Disabled\' ELSE \'Unkown\' END) AS state,(CASE t.type WHEN 1 THEN \'Metrics\' WHEN 2 THEN \'Logs\' WHEN 3 THEN \'SNMPTRAP\' ELSE \'Unkown\' END) AS typename,alsc.NAME AS priority,(CASE WHEN amc.c IS NULL THEN 0 ELSE amc.c END) AS alert_message_count FROM alert_rule t LEFT JOIN alert_severity_conf alsc ON t.severity_id=alsc.id LEFT JOIN (SELECT rule_id,count(1) AS c FROM alert_message_active ama WHERE ama.rule_id IS NOT NULL GROUP BY rule_id) amc ON amc.rule_id=t.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"type\",\r\n \"expr\": \"typename\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"state\",\r\n \"expr\": \"state\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"priority\",\r\n \"expr\": \"priority\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"alert_rule\",\r\n \"expr\": \"alertRule\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"alert_message_sum\",\r\n \"expr\": \"sum(alert_message_count)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"priority\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_priority_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"alsc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"alsc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"alsc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"alsc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"alert rule\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_alert_rule_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"t.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"t.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"t.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"t.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"alert message\",\r\n \"datasql\": \"SELECT t.id,t.asset_id,t.endpoint_id,t.rule_id,t.project_id,t.module_id,t.dc_id,alsc.NAME AS severity,ar.NAME AS alert,(CASE ar.type WHEN 1 THEN \'Metrics\' WHEN 2 THEN \'Logs\' WHEN 3 THEN \'SNMPTRAP\' ELSE \'Unkown\' END) AS alertType,mp.NAME AS project,mm.NAME AS module,me.NAME AS endpoint,aa.NAME AS asset,dc.NAME AS datacenter FROM alert_message_active t LEFT JOIN alert_rule ar ON t.rule_id=ar.id LEFT JOIN monitor_project mp ON t.project_id=mp.id LEFT JOIN monitor_module mm ON t.module_id=mm.id LEFT JOIN monitor_endpoint me ON t.endpoint_id=me.id LEFT JOIN asset_asset aa ON t.asset_id=aa.id LEFT JOIN dc ON t.dc_id=dc.id LEFT JOIN alert_severity_conf alsc ON t.severity_id=alsc.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"datacenter\",\r\n \"expr\": \"datacenter\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"project\",\r\n \"expr\": \"project\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"expr\": \"module\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"endpoint\",\r\n \"expr\": \"endpoint\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"expr\": \"asset\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"alert_rule\",\r\n \"expr\": \"alert\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"priority\",\r\n \"expr\": \"severity\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_asset\",\r\n \"expr\": \"count(DISTINCT t.asset_id)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_datacenter\",\r\n \"expr\": \"count(DISTINCT t.dc_id)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_project\",\r\n \"expr\": \"count(DISTINCT t.project_id)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_module\",\r\n \"expr\": \"count(DISTINCT t.module_id)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_endpoint\",\r\n \"expr\": \"count(DISTINCT t.endpoint_id)\",\r\n \"type\": 1\r\n },\r\n {\r\n \"name\": \"affected_alert_rule\",\r\n \"expr\": \"count(DISTINCT t.rule_id)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"project\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_project_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"mp.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"mp.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"mp.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"mp.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"module\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_module_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"mm.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"mm.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"mm.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"mm.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"endpoint\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_endpoint_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"me.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"me.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"me.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"me.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_datacenter_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"dc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"dc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"dc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"dc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"asset\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_asset_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"aa.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"aa.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"aa.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"aa.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"priority\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_priority_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"alsc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"alsc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"alsc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"alsc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"alert rule\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_alert_rule_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"ar.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"ar.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"ar.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"ar.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n },\r\n {\r\n \"name\": \"agent\",\r\n \"datasql\": \"SELECT \\tt.id, \\tt.type, \\t( CASE t.STATUS WHEN 1 THEN \'Up\' ELSE \'Down\' END ) AS STATUS, \\t( CASE t.type WHEN 1 THEN \'Global\' WHEN 2 THEN \'Per-datacenter\' ELSE \'Unkown\' END ) AS typename, \\tdc.NAME AS datacenter FROM \\tagent t \\tLEFT JOIN dc ON t.dc_id = dc.id\",\r\n \"group\": [\r\n {\r\n \"name\": \"type\",\r\n \"expr\": \"type\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"state\",\r\n \"expr\": \"status\",\r\n \"type\": 2\r\n },\r\n {\r\n \"name\": \"datacenter\",\r\n \"expr\": \"datacenter\",\r\n \"type\": 2\r\n }\r\n ],\r\n \"select\": [\r\n {\r\n \"name\": \"count\",\r\n \"expr\": \"count(1)\",\r\n \"type\": 1\r\n }\r\n ],\r\n \"filter\": [\r\n {\r\n \"name\": \"datacenter\",\r\n \"type\": 2,\r\n \"rule\": [\r\n {\r\n \"regex\": \".+\",\r\n \"tip\": \"filter_datacenter_is_null\"\r\n }\r\n ],\r\n \"opers\": [\r\n {\r\n \"name\": \"=\",\r\n \"expr\": \"dc.name = \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"~=\",\r\n \"expr\": \"dc.name like \'%{{value}}%\'\"\r\n },\r\n {\r\n \"name\": \"!=\",\r\n \"expr\": \"dc.name != \'{{value}}\'\"\r\n },\r\n {\r\n \"name\": \"!~\",\r\n \"expr\": \"dc.name not like \'%{{value}}%\'\"\r\n }\r\n ]\r\n }\r\n ]\r\n }\r\n]', 1, NULL); @@ -53,29 +53,34 @@ REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'system_favicon', '', 1, null); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'system_bgImg', '', 1, null); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'system_name', 'Network Zodiac', 1, null); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'cortex_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": <#if port?default(\"\")?trim?length gt 0> ${port?c} <#else>10093</#if>,\r\n \"grpc_listen_port\":10094,\r\n \"grpc_server_max_recv_msg_size\": 104857600,\r\n \"grpc_server_max_send_msg_size\": 104857600,\r\n \"grpc_server_max_concurrent_streams\": 1000\r\n },\r\n \"distributor\": {\r\n \"shard_by_all_labels\": true,\r\n \"pool\": {\r\n \"health_check_ingesters\": true\r\n }\r\n },\r\n \"ingester_client\": {\r\n \"grpc_client_config\": {\r\n \"max_recv_msg_size\": 104857600,\r\n \"max_send_msg_size\": 104857600,\r\n \"grpc_compression\": \"gzip\"\r\n }\r\n },\r\n <#if isMemberlistStore && !isLocalStorage>\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"id\": \"${localAgent.name}-${localAgent.id}\",\r\n \"join_after\": \"10s\",\r\n \"min_ready_duration\": \"0s\",\r\n \"final_sleep\": \"5s\",\r\n \"num_tokens\": 512,\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"memberlist\"\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"memberlist\": {\r\n \"node_name\": \"${localAgent.name}-${localAgent.id}\",\r\n \"bind_port\": <#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7946</#if>,\r\n \"join_members\": [\r\n <#list joinMemberList as joinIp>\r\n \"${joinIp}:<#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7946</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ],\r\n \"abort_if_cluster_join_fails\": false,\r\n \"rejoin_interval\": \"10s\"\r\n },\r\n <#else>\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"id\": \"${localAgent.name}-${localAgent.id}\",\r\n \"join_after\": \"10s\",\r\n \"min_ready_duration\": \"0s\",\r\n \"final_sleep\": \"5s\",\r\n \"num_tokens\": 512,\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n </#if>\r\n \r\n \"storage\": {\r\n \"engine\": \"blocks\"\r\n },\r\n \"blocks_storage\": {\r\n \"tsdb\": {\r\n \"dir\": \"${systemConfig.metrics_storage_local_path}/tsdb\"\r\n },\r\n \"bucket_store\": {\r\n \"sync_dir\": \"${systemConfig.metrics_storage_local_path}/tsdb-sync\"\r\n },\r\n <#if isLocalStorage>\r\n \"backend\": \"filesystem\",\r\n \"filesystem\": {\r\n \"dir\": \"${systemConfig.metrics_storage_local_path}/data/tsdb\"\r\n }\r\n <#else>\r\n \"backend\": \"s3\",\r\n \"s3\": {\r\n \"endpoint\": \"${objectStroageUrl}\",\r\n \"bucket_name\": \"${bucketName}\",\r\n \"access_key_id\": \"${accessKey}\",\r\n \"secret_access_key\": \"${secret}\",\r\n \"insecure\": <#if insecure?default(\"\")?trim?length gt 0>${insecure}<#else>true</#if>,\r\n \"region\": <#if systemConfig.metrics_storage_s3_region?default(\"\")?trim?length gt 0>\"${systemConfig.metrics_storage_s3_region}\"<#else>\"\"</#if>\r\n }\r\n </#if>\r\n },\r\n \"store_gateway\": {\r\n \"sharding_enabled\": true,\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"compactor\": {\r\n \"data_dir\": \"${systemConfig.metrics_storage_local_path}/compactor\",\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"frontend_worker\": {\r\n \"match_max_concurrent\": true\r\n },\r\n \r\n <#if isAlert>\r\n \"ruler\": {\r\n \"enable_api\": true,\r\n \"enable_sharding\": true,\r\n \"rule_path\": \"${systemConfig.metrics_storage_local_path}/rules\",\r\n \"ring\": {\r\n \"num_tokens\": 512,\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n },\r\n \"alertmanager_url\":\"${systemConfig.alert_api}${systemConfig.alert_path_prefix}\"\r\n },\r\n \"ruler_storage\":{\r\n \"backend\":\"local\",\r\n \"local\":{\r\n \"directory\":\"${systemConfig.metrics_storage_local_path}/rules\"\r\n }\r\n },\r\n </#if>\r\n \"limits\":{\r\n \"max_series_per_metric\": 500000000,\r\n \"ingestion_rate\": 500000000,\r\n \"max_metadata_per_user\": 500000000\r\n },\r\n \"api\":{\r\n \"alertmanager_http_prefix\":\"/\"\r\n },\r\n \"table_manager\":{\r\n \"retention_deletes_enabled\": true,\r\n \"retention_period\": \"${(((systemConfig.metrics_storage_retention!30)?number)*24)?c}h\"\r\n }\r\n}', 1, 'cortex.yml 配置文件模板'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (NULL, 'loki_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": <#if httpPort?default(\"\")?trim?length gt 0> ${httpPort?c} <#else>13100</#if>,\r\n \"grpc_listen_port\":10095\r\n },\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"final_sleep\": \"0s\",\r\n \"join_after\":\"30s\",\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n },\r\n \"chunk_idle_period\": \"5m\",\r\n \"chunk_retain_period\": \"30s\"\r\n },\r\n <#if isMemberlistStore> \r\n \"memberlist\": {\r\n \"node_name\": \"${localAgent.name}-${localAgent.id}\",\r\n \"bind_port\": <#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7947</#if>,\r\n \"join_members\": [\r\n <#list joinMemberList as joinIp>\r\n \"${joinIp}:<#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7947</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ],\r\n \"abort_if_cluster_join_fails\": false,\r\n \"rejoin_interval\": \"10s\"\r\n },\r\n </#if>\r\n \"schema_config\": {\r\n \"configs\": [\r\n {\r\n \"from\": \"${schemaConfigFrom}\",\r\n <#if openAws>\r\n \"store\": \"boltdb-shipper\",\r\n \"object_store\": \"aws\",\r\n \"schema\": \"v11\",\r\n \"index\": {\r\n \"prefix\": \"index_\",\r\n \"period\": \"24h\"\r\n }\r\n <#else> \r\n \"store\": \"boltdb\",\r\n \"object_store\": \"filesystem\",\r\n \"schema\": \"v11\",\r\n \"index\": {\r\n \"prefix\": \"index_\",\r\n \"period\": \"168h\"\r\n }\r\n </#if>\r\n }\r\n ]\r\n },\r\n<#if openAws>\r\n \"compactor\": {\r\n \"working_directory\": \"/loki/compactor\",\r\n \"shared_store\": \"aws\"\r\n },\r\n \"storage_config\": {\r\n \"boltdb_shipper\": {\r\n \"shared_store\": \"aws\",\r\n \"active_index_directory\": \"/loki/index\",\r\n \"cache_location\": \"/loki/boltdb-cache\"\r\n },\r\n \"aws\": {\r\n \"s3\": \"s3://${accessKey}:${secret}@${objectStroageUrl}/${bucketName}\",\r\n \"s3forcepathstyle\": true,\r\n \"region\": <#if systemConfig.logs_storage_s3_region?default(\"\")?trim?length gt 0>\"${systemConfig.logs_storage_s3_region}\"<#else>\"\"</#if>,\r\n \"insecure\": <#if insecure?default(\"\")?trim?length gt 0>${insecure}<#else>false</#if>\r\n }\r\n }\r\n<#else> \r\n \"storage_config\": {\r\n \"boltdb\": {\r\n \"directory\": \"${storageLocalPath}/index\"\r\n },\r\n \"filesystem\": {\r\n \"directory\": \"${storageLocalPath}/chunks\"\r\n }\r\n },\r\n \"limits_config\": {\r\n \"enforce_metric_name\": false,\r\n \"reject_old_samples\": true,\r\n \"reject_old_samples_max_age\": \"${storageRetention}h\",\r\n \"ingestion_rate_mb\": 15\r\n },\r\n \"chunk_store_config\": {\r\n \"max_look_back_period\": \"2160h\"\r\n }\r\n</#if>\r\n ,\"table_manager\":{\r\n \"retention_deletes_enabled\": true,\r\n \"retention_period\": \"${(((((systemConfig.logs_storage_retention!7)?number)/7)?ceiling)*7*24)?c}h\"\r\n }\r\n}', 1, 'loki.yml 配置文件模板'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'cortex_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": <#if port?default(\"\")?trim?length gt 0> ${port?c} <#else>10093</#if>,\r\n \"grpc_listen_port\":10094,\r\n \"grpc_server_max_recv_msg_size\": 104857600,\r\n \"grpc_server_max_send_msg_size\": 104857600,\r\n \"grpc_server_max_concurrent_streams\": 1000\r\n },\r\n \"distributor\": {\r\n \"shard_by_all_labels\": true,\r\n \"pool\": {\r\n \"health_check_ingesters\": true\r\n }\r\n },\r\n \"ingester_client\": {\r\n \"grpc_client_config\": {\r\n \"max_recv_msg_size\": 104857600,\r\n \"max_send_msg_size\": 104857600,\r\n \"grpc_compression\": \"gzip\"\r\n }\r\n },\r\n <#if isMemberlistStore && !isLocalStorage>\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"id\": \"${localAgent.name}-${localAgent.id}\",\r\n \"join_after\": \"10s\",\r\n \"min_ready_duration\": \"0s\",\r\n \"final_sleep\": \"5s\",\r\n \"num_tokens\": 512,\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"memberlist\"\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"memberlist\": {\r\n \"node_name\": \"${localAgent.name}-${localAgent.id}\",\r\n \"bind_port\": <#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7946</#if>,\r\n \"join_members\": [\r\n <#list joinMemberList as joinIp>\r\n \"${joinIp}:<#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7946</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ],\r\n \"abort_if_cluster_join_fails\": false,\r\n \"rejoin_interval\": \"10s\"\r\n },\r\n <#else>\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"id\": \"${localAgent.name}-${localAgent.id}\",\r\n \"join_after\": \"10s\",\r\n \"min_ready_duration\": \"0s\",\r\n \"final_sleep\": \"5s\",\r\n \"num_tokens\": 512,\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n </#if>\r\n \r\n \"storage\": {\r\n \"engine\": \"blocks\"\r\n },\r\n \"blocks_storage\": {\r\n \"tsdb\": {\r\n \"dir\": \"${systemConfig.metrics_storage_local_path}/tsdb\"\r\n },\r\n \"bucket_store\": {\r\n \"sync_dir\": \"${systemConfig.metrics_storage_local_path}/tsdb-sync\"\r\n },\r\n <#if isLocalStorage>\r\n \"backend\": \"filesystem\",\r\n \"filesystem\": {\r\n \"dir\": \"${systemConfig.metrics_storage_local_path}/data/tsdb\"\r\n }\r\n <#else>\r\n \"backend\": \"s3\",\r\n \"s3\": {\r\n \"endpoint\": \"${objectStroageUrl}\",\r\n \"bucket_name\": \"${bucketName}\",\r\n \"access_key_id\": \"${accessKey}\",\r\n \"secret_access_key\": \"${secret}\",\r\n \"insecure\": <#if insecure?default(\"\")?trim?length gt 0>${insecure}<#else>true</#if>,\r\n \"region\": <#if systemConfig.metrics_storage_s3_region?default(\"\")?trim?length gt 0>\"${systemConfig.metrics_storage_s3_region}\"<#else>\"\"</#if>\r\n }\r\n </#if>\r\n },\r\n \"store_gateway\": {\r\n \"sharding_enabled\": true,\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"compactor\": {\r\n \"data_dir\": \"${systemConfig.metrics_storage_local_path}/compactor\",\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"frontend_worker\": {\r\n \"match_max_concurrent\": true\r\n },\r\n \r\n <#if isAlert>\r\n \"ruler\": {\r\n \"enable_api\": true,\r\n \"enable_sharding\": true,\r\n \"rule_path\": \"${systemConfig.metrics_storage_local_path}/rules\",\r\n \"ring\": {\r\n \"num_tokens\": 512,\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore && !isLocalStorage> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"instance_interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n },\r\n \"alertmanager_url\":\"${systemConfig.alert_api}${systemConfig.alert_path_prefix}\"\r\n },\r\n \"ruler_storage\":{\r\n \"backend\":\"local\",\r\n \"local\":{\r\n \"directory\":\"${systemConfig.metrics_storage_local_path}/rules\"\r\n }\r\n },\r\n </#if>\r\n \"limits\":{\r\n \"max_series_per_metric\": 500000000,\r\n \"ingestion_rate\": 500000000,\r\n \"max_metadata_per_user\": 500000000,\r\n \"max_label_names_per_series\": 40,\r\n \"max_metadata_per_metric\": 20\r\n },\r\n \"api\":{\r\n \"alertmanager_http_prefix\":\"/\"\r\n },\r\n \"table_manager\":{\r\n \"retention_deletes_enabled\": true,\r\n \"retention_period\": \"${(((systemConfig.metrics_storage_retention!30)?number)*24)?c}h\"\r\n }\r\n}', 1, 'cortex.yml 配置文件模板'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'loki_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": <#if httpPort?default(\"\")?trim?length gt 0> ${httpPort?c} <#else>13100</#if>,\r\n \"grpc_listen_port\":10095\r\n },\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": <#if isMemberlistStore> \"memberlist\" <#else> \"inmemory\" </#if>\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"final_sleep\": \"0s\",\r\n \"join_after\":\"30s\",\r\n \"interface_names\":[\r\n <#list interfaceNameList as name>\r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ]\r\n },\r\n \"chunk_idle_period\": \"5m\",\r\n \"chunk_retain_period\": \"30s\"\r\n },\r\n <#if isMemberlistStore> \r\n \"memberlist\": {\r\n \"node_name\": \"${localAgent.name}-${localAgent.id}\",\r\n \"bind_port\": <#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7947</#if>,\r\n \"join_members\": [\r\n <#list joinMemberList as joinIp>\r\n \"${joinIp}:<#if gossIp?default(\"\")?trim?length gt 0>${gossIp?c}<#else>7947</#if>\"\r\n <#sep>,</#sep>\r\n </#list>\r\n ],\r\n \"abort_if_cluster_join_fails\": false,\r\n \"rejoin_interval\": \"10s\"\r\n },\r\n </#if>\r\n \"schema_config\": {\r\n \"configs\": [\r\n {\r\n \"from\": \"${schemaConfigFrom}\",\r\n <#if openAws>\r\n \"store\": \"boltdb-shipper\",\r\n \"object_store\": \"aws\",\r\n \"schema\": \"v11\",\r\n \"index\": {\r\n \"prefix\": \"index_\",\r\n \"period\": \"24h\"\r\n }\r\n <#else> \r\n \"store\": \"boltdb\",\r\n \"object_store\": \"filesystem\",\r\n \"schema\": \"v11\",\r\n \"index\": {\r\n \"prefix\": \"index_\",\r\n \"period\": \"168h\"\r\n }\r\n </#if>\r\n }\r\n ]\r\n },\r\n <#if openAws>\r\n \"compactor\": {\r\n \"working_directory\": \"/loki/compactor\",\r\n \"shared_store\": \"aws\"\r\n },\r\n \"storage_config\": {\r\n \"boltdb_shipper\": {\r\n \"shared_store\": \"aws\",\r\n \"active_index_directory\": \"/loki/index\",\r\n \"cache_location\": \"/loki/boltdb-cache\"\r\n },\r\n \"aws\": {\r\n \"s3\": \"s3://${accessKey}:${secret}@${objectStroageUrl}/${bucketName}\",\r\n \"s3forcepathstyle\": true,\r\n \"region\": <#if systemConfig.logs_storage_s3_region?default(\"\")?trim?length gt 0>\"${systemConfig.logs_storage_s3_region}\"<#else>\"\"</#if>,\r\n \"insecure\": <#if insecure?default(\"\")?trim?length gt 0>${insecure}<#else>false</#if>\r\n }\r\n },\r\n <#else> \r\n \"storage_config\": {\r\n \"boltdb\": {\r\n \"directory\": \"${storageLocalPath}/index\"\r\n },\r\n \"filesystem\": {\r\n \"directory\": \"${storageLocalPath}/chunks\"\r\n }\r\n },\r\n \"limits_config\": {\r\n \"enforce_metric_name\": false,\r\n \"reject_old_samples\": true,\r\n \"reject_old_samples_max_age\": \"${storageRetention}h\",\r\n \"ingestion_rate_mb\": 15\r\n },\r\n \"chunk_store_config\": {\r\n \"max_look_back_period\": \"2160h\"\r\n },\r\n </#if>\r\n \"table_manager\": {\r\n \"retention_deletes_enabled\": true,\r\n \"retention_period\": \"${(((((systemConfig.logs_storage_retention!7)?number)/7)?ceiling)*7*24)?c}h\"\r\n },\r\n \"ruler\": {\r\n \"remote_write\": {\r\n \"client\": {\r\n \"url\": \"\"\r\n }\r\n }\r\n }\r\n}', 1, 'loki.yml 配置文件模板'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'license_product_name', 'NZ', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'nz_alerts_metrics_enabled', 'on', 1, 'nz-web metrics 是否暴露 alert active message labels 监控项'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'snapshot_template_path', '/opt/nezha/nz-web/public', 1, null); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'chart_export_header', '[{\"name\":\"panel name\",\"i18n\":\"dashboard.panel.panelForm.panelName\",\"comment\":\"dashboard.panel.panelForm.panelName.comment\"},{\"name\":\"group\",\"i18n\":\"dashboard.panel.chartForm.group\",\"comment\":\"dashboard.panel.chartForm.group.comment\"},{\"name\":\"title\",\"i18n\":\"project.topology.title\",\"comment\":\"dashboard.panel.chartForm.name.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"dashboard.panel.chartForm.type.comment\"},{\"name\":\"width\",\"i18n\":\"dashboard.panel.chartForm.width\",\"comment\":\"dashboard.panel.chartForm.width.comment\"},{\"name\":\"high\",\"i18n\":\"dashboard.panel.chartForm.high\",\"comment\":\"dashboard.panel.chartForm.high.comment\"},{\"name\":\"unit\",\"i18n\":\"dashboard.panel.chartForm.unit\",\"comment\":\"dashboard.panel.chartForm.unit.comment\"},{\"name\":\"legendValue\",\"i18n\":\"dashboard.panel.chartForm.legendValue\",\"comment\":\"dashboard.panel.chartForm.legendValue.comment\"},{\"name\":\"element\",\"i18n\":\"dashboard.panel.chartForm.element\",\"comment\":\"dashboard.panel.chartForm.element.comment\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"dashboard.panel.chartForm.remark.comment\"},{\"name\":\"Datasource\",\"i18n\":\"dashboard.panel.chartForm.datasource\",\"comment\":\"dashboard.panel.chartForm.datasource.comment\"},{\"name\":\"x\",\"i18n\":\"dashboard.panel.chartForm.x\",\"comment\":\"dashboard.panel.chartForm.x.comment\"},{\"name\":\"y\",\"i18n\":\"dashboard.panel.chartForm.y\",\"comment\":\"dashboard.panel.chartForm.y.comment\"}]', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'chart_export_header', '[{\"name\":\"Chart name\",\"i18n\":\"dashboard.dashboard.chartForm.name\",\"comment\":\"dashboard.dashboard.chartForm.name.comment\"},{\"name\":\"Width\",\"i18n\":\"dashboard.dashboard.chartForm.width\",\"comment\":\"dashboard.dashboard.chartForm.width.comment\"},{\"name\":\"High\",\"i18n\":\"dashboard.dashboard.chartForm.high\",\"comment\":\"dashboard.dashboard.chartForm.high.comment\"},{\"name\":\"Type\",\"i18n\":\"overall.type\",\"comment\":\"dashboard.dashboard.chartForm.type.comment\"},{\"name\":\"Unit\",\"i18n\":\"dashboard.dashboard.chartForm.unit\",\"comment\":\"dashboard.dashboard.chartForm.unit.comment\"},{\"name\":\"Weight\",\"i18n\":\"dashboard.dashboard.chartForm.weight\"},{\"name\":\"LegendValue\",\"i18n\":\"dashboard.dashboard.chartForm.legendValue\",\"comment\":\"dashboard.dashboard.chartForm.legendValue.comment\"},{\"name\":\"Remark\",\"i18n\":\"overall.remark\",\"comment\":\"dashboard.dashboard.chartForm.remark.comment\"},{\"name\":\"X\",\"i18n\":\"dashboard.dashboard.chartForm.x\",\"comment\":\"dashboard.dashboard.chartForm.x.comment\"},{\"name\":\"Y\",\"i18n\":\"dashboard.dashboard.chartForm.y\",\"comment\":\"dashboard.dashboard.chartForm.y.comment\"},{\"name\":\"Element\",\"i18n\":\"dashboard.dashboard.chartForm.element\",\"comment\":\"dashboard.dashboard.chartForm.element.comment\"},{\"name\":\"Datasource\",\"i18n\":\"dashboard.dashboard.chartForm.datasource\",\"comment\":\"dashboard.dashboard.chartForm.datasource.comment\"},{\"name\":\"Children\",\"i18n\":\"dashboard.dashboard.chartForm.children\"}]', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'dc_export_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"config.dc.name.comment\"},{\"name\":\"Location\",\"i18n\":\"asset.location\",\"comment\":\"config.dc.location.comment\"},{\"name\":\"Telephone\",\"i18n\":\"config.dc.tel\",\"comment\":\"config.dc.tel.comment\"},{\"name\":\"Principal\",\"i18n\":\"config.dc.principal\",\"comment\":\"config.dc.principal.comment\"},{\"name\":\"Longitude\",\"i18n\":\"config.dc.longitude\",\"comment\":\"config.dc.longitude.comment\"},{\"name\":\"Latitude\",\"i18n\":\"config.dc.latitude\",\"comment\":\"config.dc.latitude.comment\"},{\"name\":\"State\",\"i18n\":\"overall.state\",\"comment\":\"config.dc.state.comment\"}]', 1, 'dc 导入导出表头信息'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'model_export_header', '[{\"name\":\"Name\",\"i18n\":\"config.model.name\",\"comment\":\"config.model.name.comment\"},{\"name\":\"Brand\",\"i18n\":\"asset.brand\",\"comment\":\"config.model.brand.comment\"},{\"name\":\"chart template\",\"i18n\":\"overall.chartTemp\",\"comment\":\"config.model.ChartTemplate.comment\"},{\"name\":\"Description\",\"i18n\":\"overall.remark\",\"comment\":\"config.model.remark.comment\"},{\"name\":\"Type\",\"i18n\":\"asset.assetType\",\"comment\":\"asset.assetType.comment\"},{\"name\":\"SysObjectId\",\"i18n\":\"config.model.sysObjectId\",\"comment\":\"config.model.sysObjectId.comment\"}]', 1, 'asset model 导入导出表头信息'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'model_export_header', '[{\"name\":\"Name\",\"i18n\":\"config.model.name\",\"comment\":\"config.model.name.comment\"},{\"name\":\"Brand\",\"i18n\":\"asset.brand\",\"comment\":\"config.model.brand.comment\"},{\"name\":\"dashboard template\",\"i18n\":\"model.dashboardtemplate\",\"comment\":\"config.model.dashboardtemplate.comment\"},{\"name\":\"Description\",\"i18n\":\"overall.remark\",\"comment\":\"config.model.remark.comment\"},{\"name\":\"Type\",\"i18n\":\"overall.type\",\"comment\":\"asset.assetType.comment\"},{\"name\":\"SysObjectId\",\"i18n\":\"config.model.sysObjectId\",\"comment\":\"config.model.sysObjectId.comment\"}]', 1, 'asset model 导入导出表头信息'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'monitor_endpoint_export_header', '[{\"name\":\"Project Name\",\"i18n\":\"project.project.projectName\",\"comment\":\"project.project.projectName.comment\"},{\"name\":\"Module Name\",\"i18n\":\"overall.module\",\"comment\":\"project.endpoint.moduleName.comment\"},{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"project.endpoint.name.comment\"},{\"name\":\"Asset Name\",\"i18n\":\"asset.asset\",\"comment\":\"project.endpoint.asset.comment\"},{\"name\":\"Config\",\"i18n\":\"overall.config\",\"comment\":\"project.endpoint.configs.comment\"}]', 1, 'monitor endpoint 导入表头'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'rule_export_header', '[{\"name\":\"name\",\"i18n\":\"overall.name\",\"comment\":\"alert.config.name.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"alert.type.comment\"},{\"name\":\"Execution cycle\",\"i18n\":\"alert.config.inr\",\"comment\":\"alert.config.inr.comment\"},{\"name\":\"timeout\",\"i18n\":\"alert.config.timeout\",\"comment\":\"alert.config.timeout.comment\"},{\"name\":\"expr\",\"i18n\":\"alert.config.expr\",\"comment\":\"alert.config.expr.comment\"},{\"name\":\"operator\",\"i18n\":\"alert.config.operator\",\"comment\":\"alert.config.operator.comment\"},{\"name\":\"threshold\",\"i18n\":\"alert.config.threshold\",\"comment\":\"alert.config.threshold.comment\"},{\"name\":\"unit\",\"i18n\":\"dashboard.panel.chartForm.unit\",\"comment\":\"alert.config.unit.comment\"},{\"name\":\"last\",\"i18n\":\"alert.config.for\",\"comment\":\"alert.config.for.comment\"},{\"name\":\"severity\",\"i18n\":\"alert.severity\",\"comment\":\"alert.severity.comment\"},{\"name\":\"summary\",\"i18n\":\"alert.summary\",\"comment\":\"alert.summary.comment\"},{\"name\":\"description\",\"i18n\":\"overall.remark\",\"comment\":\"alert.description.comment\"},{\"name\":\"receiver\",\"i18n\":\"alert.receiver\",\"comment\":\"alert.receiver.comment\"},{\"name\":\"notify\",\"i18n\":\"alert.notify\",\"comment\":\"alert.notify.comment\"},{\"name\":\"state\",\"i18n\":\"overall.state\",\"comment\":\"alert.state.comment\"},{\"name\":\"autoExpired\",\"i18n\":\"alert.config.autoExpired\",\"comment\":\"alert.config.autoExpired.comment\"},{\"name\":\"schedEnable\",\"i18n\":\"alert.config.schedEnable\",\"comment\":\"alert.config.schedEnable.comment\"},{\"name\":\"schedDays\",\"i18n\":\"alert.config.schedDays\",\"comment\":\"alert.config.schedDays.comment\"},{\"name\":\"startAt\",\"i18n\":\"overall.startTime\",\"comment\":\"alert.startAt.comment\"},{\"name\":\"endAt\",\"i18n\":\"overall.endTime\",\"comment\":\"alert.endAt.comment\"},{\"name\":\"notifyActive\",\"i18n\":\"alert.config.notifyActive\",\"comment\":\"alert.config.notifyActive.comment\"},{\"name\":\"notifyExpired\",\"i18n\":\"alert.config.notifyExpired\",\"comment\":\"alert.config.notifyExpired.comment\"},{\"name\":\"trbShot\",\"i18n\":\"alert.config.trbShot\",\"comment\":\"alert.config.trbShot.comment\"}]', 1, NULL); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'asset_chart_export_header', '[{\"name\":\"group\",\"i18n\":\"dashboard.panel.chartForm.group\",\"comment\":\"dashboard.panel.chartForm.group.comment\"},{\"name\":\"title\",\"i18n\":\"overall.name\",\"comment\":\"dashboard.panel.chartForm.name.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"dashboard.panel.chartForm.type.comment\"},{\"name\":\"varType\",\"i18n\":\"dashboard.panel.chartForm.varType\",\"comment\":\"dashboard.panel.chartForm.varType.comment\"},{\"name\":\"width\",\"i18n\":\"dashboard.panel.chartForm.width\",\"comment\":\"dashboard.panel.chartForm.width.comment\"},{\"name\":\"high\",\"i18n\":\"dashboard.panel.chartForm.high\",\"comment\":\"dashboard.panel.chartForm.high.comment\"},{\"name\":\"unit\",\"i18n\":\"dashboard.panel.chartForm.unit\",\"comment\":\"dashboard.panel.chartForm.unit.comment\"},{\"name\":\"legendValue\",\"i18n\":\"dashboard.panel.chartForm.legendValue\",\"comment\":\"dashboard.panel.chartForm.legendValue.comment\"},{\"name\":\"element\",\"i18n\":\"dashboard.panel.chartForm.element\",\"comment\":\"dashboard.panel.chartForm.element.comment\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"dashboard.panel.chartForm.remark.comment\"},{\"name\":\"Datasource\",\"i18n\":\"dashboard.panel.chartForm.datasource\",\"comment\":\"dashboard.panel.chartForm.datasource.comment\"},{\"name\":\"x\",\"i18n\":\"dashboard.panel.chartForm.x\",\"comment\":\"dashboard.panel.chartForm.x.comment\"},{\"name\":\"y\",\"i18n\":\"dashboard.panel.chartForm.y\",\"comment\":\"dashboard.panel.chartForm.y.comment\"}]', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'rule_export_header', '[{\"name\":\"name\",\"i18n\":\"overall.name\",\"comment\":\"alert.config.name.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"alert.type.comment\"},{\"name\":\"Execution cycle\",\"i18n\":\"alert.config.inr\",\"comment\":\"alert.config.inr.comment\"},{\"name\":\"timeout\",\"i18n\":\"alert.config.timeout\",\"comment\":\"alert.config.timeout.comment\"},{\"name\":\"expr\",\"i18n\":\"alert.config.expr\",\"comment\":\"alert.config.expr.comment\"},{\"name\":\"operator\",\"i18n\":\"alert.config.operator\",\"comment\":\"alert.config.operator.comment\"},{\"name\":\"threshold\",\"i18n\":\"alert.config.threshold\",\"comment\":\"alert.config.threshold.comment\"},{\"name\":\"unit\",\"i18n\":\"dashboard.dashboard.chartForm.unit\",\"comment\":\"alert.config.unit.comment\"},{\"name\":\"last\",\"i18n\":\"alert.config.for\",\"comment\":\"alert.config.for.comment\"},{\"name\":\"severity\",\"i18n\":\"alert.severity\",\"comment\":\"alert.severity.comment\"},{\"name\":\"summary\",\"i18n\":\"alert.summary\",\"comment\":\"alert.summary.comment\"},{\"name\":\"description\",\"i18n\":\"overall.remark\",\"comment\":\"alert.description.comment\"},{\"name\":\"receiver\",\"i18n\":\"alert.receiver\",\"comment\":\"alert.receiver.comment\"},{\"name\":\"notify\",\"i18n\":\"alert.notify\",\"comment\":\"alert.notify.comment\"},{\"name\":\"state\",\"i18n\":\"overall.state\",\"comment\":\"alert.state.comment\"},{\"name\":\"autoExpired\",\"i18n\":\"alert.config.autoExpired\",\"comment\":\"alert.config.autoExpired.comment\"},{\"name\":\"schedEnable\",\"i18n\":\"alert.config.schedEnable\",\"comment\":\"alert.config.schedEnable.comment\"},{\"name\":\"schedDays\",\"i18n\":\"alert.config.schedDays\",\"comment\":\"alert.config.schedDays.comment\"},{\"name\":\"startAt\",\"i18n\":\"overall.startTime\",\"comment\":\"alert.startAt.comment\"},{\"name\":\"endAt\",\"i18n\":\"overall.endTime\",\"comment\":\"alert.endAt.comment\"},{\"name\":\"notifyActive\",\"i18n\":\"alert.config.notifyActive\",\"comment\":\"alert.config.notifyActive.comment\"},{\"name\":\"notifyExpired\",\"i18n\":\"alert.config.notifyExpired\",\"comment\":\"alert.config.notifyExpired.comment\"},{\"name\":\"trbShot\",\"i18n\":\"alert.config.trbShot\",\"comment\":\"alert.config.trbShot.comment\"}]', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'asset_chart_export_header', '[{\"name\":\"group\",\"i18n\":\"dashboard.dashboard.chartForm.group\",\"comment\":\"dashboard.dashboard.chartForm.group.comment\"},{\"name\":\"title\",\"i18n\":\"overall.name\",\"comment\":\"dashboard.dashboard.chartForm.name.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"dashboard.dashboard.chartForm.type.comment\"},{\"name\":\"varType\",\"i18n\":\"dashboard.dashboard.chartForm.varType\",\"comment\":\"dashboard.dashboard.chartForm.varType.comment\"},{\"name\":\"width\",\"i18n\":\"dashboard.dashboard.chartForm.width\",\"comment\":\"dashboard.dashboard.chartForm.width.comment\"},{\"name\":\"high\",\"i18n\":\"dashboard.dashboard.chartForm.high\",\"comment\":\"dashboard.dashboard.chartForm.high.comment\"},{\"name\":\"unit\",\"i18n\":\"dashboard.dashboard.chartForm.unit\",\"comment\":\"dashboard.dashboard.chartForm.unit.comment\"},{\"name\":\"legendValue\",\"i18n\":\"dashboard.dashboard.chartForm.legendValue\",\"comment\":\"dashboard.dashboard.chartForm.legendValue.comment\"},{\"name\":\"element\",\"i18n\":\"dashboard.dashboard.chartForm.element\",\"comment\":\"dashboard.dashboard.chartForm.element.comment\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"dashboard.dashboard.chartForm.remark.comment\"},{\"name\":\"Datasource\",\"i18n\":\"dashboard.dashboard.chartForm.datasource\",\"comment\":\"dashboard.dashboard.chartForm.datasource.comment\"},{\"name\":\"x\",\"i18n\":\"dashboard.dashboard.chartForm.x\",\"comment\":\"dashboard.dashboard.chartForm.x.comment\"},{\"name\":\"y\",\"i18n\":\"dashboard.dashboard.chartForm.y\",\"comment\":\"dashboard.dashboard.chartForm.y.comment\"}]', 1, NULL); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'ipam_subnet_import_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"config.ipamsubnet.name.comment\"},{\"name\":\"Type\",\"i18n\":\"overall.type\",\"comment\":\"config.ipamsubnet.type.comment\"},{\"name\":\"addr\",\"i18n\":\"overall.addr\",\"comment\":\"config.ipam.addr.comment\"},{\"name\":\"mask\",\"i18n\":\"overall.mask\",\"comment\":\"config.ipamsubnet.mask.comment\"},{\"name\":\"vlan\",\"i18n\":\"overall.vlan\",\"comment\":\"config.ipamsubnet.vlan.comment\"},{\"name\":\"Datacenter\",\"i18n\":\"ipamsubnet.dc.dcId\",\"comment\":\"ipamsubnet.dc.dcId.comment\"},{\"name\":\"Remark\",\"i18n\":\"overall.remark\",\"comment\":\"overall.remark.comment\"}]', 1, 'ipamsubnet导出模板'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'ipam_ip_import_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"config.ipamip.name.comment\"},{\"name\":\"ipamsubnet\",\"i18n\":\"config.ipamip.ipamsubnet\",\"comment\":\"config.ipamip.ipamsubnet.comment\"},{\"name\":\"addr\",\"i18n\":\"overall.addr\",\"comment\":\"config.ipam.addr.comment\"},{\"name\":\"mac\",\"i18n\":\"config.ipamip.mac\",\"comment\":\"config.ipamip.mac.comment\"},{\"name\":\"asset\",\"i18n\":\"asset.asset\",\"comment\":\"config.ipamip.asset.comment\"},{\"name\":\"state\",\"i18n\":\"overall.state\",\"comment\":\"config.ipamip.state.comment\"},{\"name\":\"Remark\",\"i18n\":\"overall.remark\",\"comment\":\"overall.remark.comment\"}]', 1, 'ipamip导入头模板'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'asset_asset_export_header', '[{\"name\":\"name\",\"i18n\":\"overall.name\",\"comment\":\"asset.name.comment\"},{\"name\":\"sn\",\"i18n\":\"asset.sn\",\"comment\":\"asset.sn.comment\"},{\"name\":\"parent\",\"i18n\":\"asset.parent\",\"comment\":\"asset.parent.comment\"},{\"name\":\"manageIp\",\"i18n\":\"asset.manageIp\",\"comment\":\"asset.manageIp.comment\"},{\"name\":\"brand\",\"i18n\":\"asset.brand\",\"comment\":\"asset.brand.comment\"},{\"name\":\"model\",\"i18n\":\"asset.model\",\"comment\":\"asset.model.comment\"},{\"name\":\"dc\",\"i18n\":\"overall.dc\",\"comment\":\"asset.dc.comment\"},{\"name\":\"cabinet\",\"i18n\":\"asset.cabinet\",\"comment\":\"asset.cabinet.comment\"},{\"name\":\"startU\",\"i18n\":\"asset.startU\",\"comment\":\"asset.startU.comment\"},{\"name\":\"endU\",\"i18n\":\"asset.endU\",\"comment\":\"asset.endU.comment\"},{\"name\":\"assetState\",\"i18n\":\"overall.state\",\"comment\":\"asset.assetState.comment\"},{\"name\":\"assetType\",\"i18n\":\"asset.assetType\",\"comment\":\"asset.assetType.comment\"},{\"name\":\"purchaseDate\",\"i18n\":\"asset.purchaseDate\",\"comment\":\"asset.purchaseDate.comment\"},{\"name\":\"tag\",\"i18n\":\"overall.tag\",\"comment\":\"overall.tag.comment\"},{\"name\":\"port\",\"i18n\":\"asset.port\",\"comment\":\"asset.port.comment\"},{\"name\":\"authType\",\"i18n\":\"asset.authType\",\"comment\":\"asset.authType.comment\"},{\"name\":\"userName\",\"i18n\":\"profile.username\",\"comment\":\"asset.userName.comment\"},{\"name\":\"pin\",\"i18n\":\"asset.password\",\"comment\":\"asset.pin.comment\"},{\"name\":\"privateKey\",\"i18n\":\"asset.privateKey\",\"comment\":\"asset.privateKey.comment\"},{\"name\":\"usernamePrompt\",\"i18n\":\"asset.usernamePrompt\",\"comment\":\"asset.usernamePrompt.comment\"},{\"name\":\"pinPrompt\",\"i18n\":\"asset.pinPrompt\",\"comment\":\"asset.pinPrompt.comment\"},{\"name\":\"snmpCredential\",\"i18n\":\"asset.snmpCredential\",\"comment\":\"asset.snmpCredential.comment\"},{\"name\":\"talon.username\",\"i18n\":\"asset.talon.username\",\"comment\":\"asset.talon.username.comment\"},{\"name\":\"talon.pin\",\"i18n\":\"asset.talon.pin\",\"comment\":\"asset.talon.pin.comment\"},{\"name\":\"token\",\"i18n\":\"asset.talon.token\",\"comment\":\"asset.talon.token.comment\"},{\"name\":\"port\",\"i18n\":\"asset.talon.port\",\"comment\":\"asset.talon.port.comment\"},{\"name\":\"enable\",\"i18n\":\"overall.enabled\",\"comment\":\"asset.talon.enable.comment\"}]', 1, 'asset 导入导出表头信息'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'cabinet_export_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"config.cab.name.comment\"},{\"name\":\"Data center\",\"i18n\":\"overall.dc\",\"comment\":\"config.dc.name.comment\"},{\"name\":\"USize\",\"i18n\":\"config.cab.uSize\",\"comment\":\"config.cab.uSize.comment\"},{\"name\":\"row\",\"i18n\":\"dashboard.panel.chartForm.y\",\"comment\":\"config.cab.y.comment\"},{\"name\":\"col\",\"i18n\":\"dashboard.panel.chartForm.x\",\"comment\":\"config.cab.x.comment\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"overall.remark.comment\"}]', 1, 'cabinet 导入导出表头信息'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'module_export_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"project.module.moduleName.comment\"},{\"name\":\"Project\",\"i18n\":\"project.project.projectName\",\"comment\":\"project.project.projectName.comment\"},{\"name\":\"Endpoint name tmpl\",\"i18n\":\"overall.endpointTemplate\",\"comment\":\"project.module.endpointTemplate.comment\"},{\"name\":\"Config\",\"i18n\":\"project.module.configs\",\"comment\":\"project.module.configs.comment\"},{\"name\":\"Chart templates\",\"i18n\":\"overall.chartTemp\",\"comment\":\"project.module.ChartTemplate.comment\"},{\"name\":\"Description\",\"i18n\":\"overall.remark\",\"comment\":\"project.module.description.comment\"}]', 1, 'module 导入导出模板'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'asset_asset_export_header', '[{\"name\":\"name\",\"i18n\":\"overall.name\",\"comment\":\"asset.name.comment\"},{\"name\":\"sn\",\"i18n\":\"asset.sn\",\"comment\":\"asset.sn.comment\"},{\"name\":\"parent\",\"i18n\":\"asset.parent\",\"comment\":\"asset.parent.comment\"},{\"name\":\"manageIp\",\"i18n\":\"asset.manageIp\",\"comment\":\"asset.manageIp.comment\"},{\"name\":\"ipmiIp\",\"i18n\":\"asset.ipmiIp\",\"comment\":\"asset.ipmiIp.comment\"},{\"name\":\"brand\",\"i18n\":\"asset.brand\",\"comment\":\"asset.brand.comment\"},{\"name\":\"model\",\"i18n\":\"asset.model\",\"comment\":\"asset.model.comment\"},{\"name\":\"dc\",\"i18n\":\"overall.dc\",\"comment\":\"asset.dc.comment\"},{\"name\":\"cabinet\",\"i18n\":\"asset.cabinet\",\"comment\":\"asset.cabinet.comment\"},{\"name\":\"startU\",\"i18n\":\"asset.startU\",\"comment\":\"asset.startU.comment\"},{\"name\":\"endU\",\"i18n\":\"asset.endU\",\"comment\":\"asset.endU.comment\"},{\"name\":\"assetState\",\"i18n\":\"overall.state\",\"comment\":\"asset.assetState.comment\"},{\"name\":\"assetType\",\"i18n\":\"asset.assetType\",\"comment\":\"asset.assetType.comment\"},{\"name\":\"purchaseDate\",\"i18n\":\"asset.purchaseDate\",\"comment\":\"asset.purchaseDate.comment\"},{\"name\":\"tag\",\"i18n\":\"overall.tag\",\"comment\":\"overall.tag.comment\"},{\"name\":\"port\",\"i18n\":\"asset.port\",\"comment\":\"asset.port.comment\"},{\"name\":\"authType\",\"i18n\":\"asset.authType\",\"comment\":\"asset.authType.comment\"},{\"name\":\"userName\",\"i18n\":\"profile.username\",\"comment\":\"asset.userName.comment\"},{\"name\":\"pin\",\"i18n\":\"asset.password\",\"comment\":\"asset.pin.comment\"},{\"name\":\"privateKey\",\"i18n\":\"asset.privateKey\",\"comment\":\"asset.privateKey.comment\"},{\"name\":\"usernamePrompt\",\"i18n\":\"asset.usernamePrompt\",\"comment\":\"asset.usernamePrompt.comment\"},{\"name\":\"pinPrompt\",\"i18n\":\"asset.pinPrompt\",\"comment\":\"asset.pinPrompt.comment\"},{\"name\":\"snmpCredential\",\"i18n\":\"asset.snmpCredential\",\"comment\":\"asset.snmpCredential.comment\"},{\"name\":\"talon.username\",\"i18n\":\"asset.talon.username\",\"comment\":\"asset.talon.username.comment\"},{\"name\":\"talon.pin\",\"i18n\":\"asset.talon.pin\",\"comment\":\"asset.talon.pin.comment\"},{\"name\":\"token\",\"i18n\":\"asset.talon.token\",\"comment\":\"asset.talon.token.comment\"},{\"name\":\"port\",\"i18n\":\"asset.talon.port\",\"comment\":\"asset.talon.port.comment\"},{\"name\":\"enable\",\"i18n\":\"overall.enabled\",\"comment\":\"asset.talon.enable.comment\"}]', 1, 'asset 导入导出表头信息'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'cabinet_export_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"config.cab.name.comment\"},{\"name\":\"Data center\",\"i18n\":\"overall.dc\",\"comment\":\"config.dc.name.comment\"},{\"name\":\"USize\",\"i18n\":\"config.cab.uSize\",\"comment\":\"config.cab.uSize.comment\"},{\"name\":\"row\",\"i18n\":\"dashboard.dashboard.chartForm.y\",\"comment\":\"config.cab.y.comment\"},{\"name\":\"col\",\"i18n\":\"dashboard.dashboard.chartForm.x\",\"comment\":\"config.cab.x.comment\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"overall.remark.comment\"}]', 1, 'cabinet 导入导出表头信息'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'module_export_header', '[{\"name\":\"Name\",\"i18n\":\"overall.name\",\"comment\":\"project.module.moduleName.comment\"},{\"name\":\"Project\",\"i18n\":\"project.project.projectName\",\"comment\":\"project.project.projectName.comment\"},{\"name\":\"Endpoint name tmpl\",\"i18n\":\"overall.endpointTemplate\",\"comment\":\"project.module.endpointTemplate.comment\"},{\"name\":\"Config\",\"i18n\":\"project.module.configs\",\"comment\":\"project.module.configs.comment\"},{\"name\":\"dashboard template\",\"i18n\":\"overall.dashboardTemplate\",\"comment\":\"project.module.dashboardtemplate.comment\"},{\"name\":\"Description\",\"i18n\":\"overall.remark\",\"comment\":\"project.module.description.comment\"}]', 1, 'module 导入导出模板'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'alert_export_header', '[{\"name\": \"id\",\"i18n\": \"asset.id\",\"comment\": \"config.alert.id.comment\"},{\"name\": \"rule\",\"i18n\": \"alert.alertRule\",\"comment\": \"alert.config.name.comment\"},{\"name\": \"dc\",\"i18n\": \"overall.dc\",\"comment\": \"config.dc.name.comment\"},{\"name\": \"project\",\"i18n\": \"overall.project\",\"comment\": \"project.project.projectName.comment\"},{\"name\": \"module\",\"i18n\": \"overall.module\",\"comment\": \"project.endpoint.moduleName.comment\"},{\"name\": \"endpoint\",\"i18n\": \"asset.endpoint\",\"comment\": \"project.endpoint.name.comment\"},{\"name\": \"asset\",\"i18n\": \"overall.asset\",\"comment\": \"asset.name.comment\"},{\"name\": \"labels\",\"i18n\": \"alert.list.labels\",\"comment\": \"config.alert.labels.comment\"},{\"name\": \"severity\",\"i18n\": \"alert.severity\",\"comment\": \"alert.severity.comment\"},{\"name\": \"summary\",\"i18n\": \"alert.summary\",\"comment\": \"alert.summary.comment\"},{\"name\": \"description\",\"i18n\": \"overall.remark\",\"comment\": \"overall.remark.comment\"},{\"name\": \"startAt\",\"i18n\": \"overall.startTime\",\"comment\": \"alert.startAt.comment\"},{\"name\": \"endAt\",\"i18n\": \"overall.endTime\",\"comment\": \"alert.endAt.comment\"},{\"name\": \"duration\",\"i18n\": \"config.terminallog.duration\",\"comment\": \"alert.config.for.comment\"},{\"name\": \"state\",\"i18n\": \"overall.state\",\"comment\": \"config.ipamip.state.comment\"}]', 1, 'alert_message导出表头'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'report_email_template', '<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"></head><body><div style=\"padding:40px 0; height:auto; min-height:100px; text-align:center;\"><span align=\"center\" style=\"margin:0 auto; min-width:290px; max-width:750px;\">${panel.name} dashboard snapshot file.</span></div></body></html>', 1, 'report 通知模板'); -REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'reset_table_infos', '[\"Delete from alert_rule where build_in !=1 \",\"Delete from asset_asset\",\"Delete from cabinet\",\"Delete from monitor_endpoint\",\"Delete from monitor_endpoint_state\",\"Delete from dc\",\"Delete from maintenance_record\",\"Delete from asset_ping\",\"Delete from asset_model\",\"Delete from asset_brand\",\"Delete from asset_feature\",\"Delete from asset_field_value\",\"Delete from asset_field_group where build_in !=1 \",\"Delete from asset_field_meta where build_in !=1 \",\"Delete from monitor_module where build_in !=1 \",\"Delete from monitor_project where build_in !=1 \",\"Delete from project_topo\",\"Delete from agent\",\"Delete from snmp_credential\",\"Delete from sys_api_key\",\"Delete from snmp_mib\",\"Delete from terminal_cmd\",\"Delete from terminal_record\",\"Delete from terminal_session\",\"Delete from sys_log\",\"Delete from sys_user where username!=\'admin\'\",\"Delete from alert_notify_log\",\"Delete from alert_notify_method where build_in !=1 \",\"Delete from alert_silence_conf\",\"Delete from alert_silence_message_rel\",\"Delete from link where build_in !=1 \",\"Delete from visual_panel where build_in !=1 \",\"Delete from visual_chart where build_in !=1 \",\"Delete from visual_chart_element where build_in !=1 \",\"Delete from visual_expression_tmpl where build_in !=1 \"]', 1, '清空项目数据信息'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'report_email_template', '<html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"></head><body><div style=\"padding:40px 0; height:auto; min-height:100px; text-align:center;\"><span align=\"center\" style=\"margin:0 auto; min-width:290px; max-width:750px;\">${dashboard.name} dashboard snapshot file.</span></div></body></html>', 1, 'report 通知模板'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'reset_table_infos', '[\"Delete from alert_rule where build_in !=1 \",\"Delete from asset_asset\",\"Delete from cabinet\",\"Delete from monitor_endpoint\",\"Delete from monitor_endpoint_state\",\"Delete from dc\",\"Delete from maintenance_record\",\"Delete from asset_ping\",\"Delete from asset_model\",\"Delete from asset_brand\",\"Delete from asset_feature\",\"Delete from asset_field_value\",\"Delete from asset_field_group where build_in !=1 \",\"Delete from asset_field_meta where build_in !=1 \",\"Delete from monitor_module where build_in !=1 \",\"Delete from monitor_project where build_in !=1 \",\"Delete from project_topo\",\"Delete from agent\",\"Delete from snmp_credential\",\"Delete from sys_api_key\",\"Delete from snmp_mib\",\"Delete from terminal_cmd\",\"Delete from terminal_record\",\"Delete from terminal_session\",\"Delete from sys_log\",\"Delete from sys_user where username!=\'admin\'\",\"Delete from alert_notify_log\",\"Delete from alert_notify_method where build_in !=1 \",\"Delete from alert_silence_conf\",\"Delete from alert_silence_message_rel\",\"Delete from link where build_in !=1 \",\"Delete from visual_dashboard where build_in !=1 \",\"Delete from visual_chart where build_in !=1 \",\"Delete from visual_chart_element where build_in !=1 \",\"Delete from visual_expression_tmpl where build_in !=1 \"]', 1, '清空项目数据信息'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'nz_talon_oshi_mode', '1', 1, '1:nz-agent 代理模式,通过nz-agent 代理访问 nz-talon 接口 2:直连模式,nz-web 直接访问 nz-talon oshi 接口。默认为1'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'vsys_concurrency', '10', 1, 'vsys 任务并发数量 默认: 10'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'vsys_retry', '5', 1, 'vsys 任务失败重试次数 默认: 5'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'vsys_restconf_auth', '{\"protocol\":\"http\",\"port\":8447,\"type\":\"none\",\"username\":\"admin\",\"password\":\"admin\"}', 1, 'type 可选值:basicAuth , none'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'record_rule_import_header', '[{\"name\": \"Name\",\"i18n\": \"overall.name\",\"comment\": \"config.ipamip.name.comment\"},{\"name\": \"Type\",\"i18n\": \"overall.type\",\"comment\": \"alert.type.comment\"},{\"name\": \"Expr\",\"i18n\": \"config.exprTemp.expression\",\"comment\": \"alert.config.expr.comment\"},{\"name\": \"Inr\",\"i18n\": \"config.record.inr\",\"comment\": \"config.record.inr.comment\"},{\"name\": \"State\",\"i18n\": \"overall.state\",\"comment\": \"alert.state.comment\"},{\"name\": \"Labels\",\"i18n\": \"project.endpoint.labels2\",\"comment\": \"config.record.labels.comment\"},{\"name\": \"Remark\",\"i18n\": \"config.exprTemp.remark\",\"comment\": \"config.exprTemp.remark.comment\"}]', 1, 'record headea'); REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'vsys_default_rule_config', '[{\"id\":1}]', 1, 'VSYS 默认流量规则配置'); - +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'terminal_storage_type', '1', 1, '存储模式,1: 本地存储,2:S3对象存储'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'cortex_init_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": 10093,\r\n \"grpc_listen_port\": 10094\r\n },\r\n \"distributor\": {\r\n \"shard_by_all_labels\": true,\r\n \"pool\": {\r\n \"health_check_ingesters\": true\r\n }\r\n },\r\n \"ingester_client\": {\r\n \"grpc_client_config\": {\r\n \"max_recv_msg_size\": 104857600,\r\n \"max_send_msg_size\": 104857600,\r\n \"grpc_compression\": \"gzip\"\r\n }\r\n },\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n }\r\n },\r\n \"interface_names\": [\r\n <#list systemConfig.interface_name?default(\"eth0,en0,bond0,ens2f0,enp0s31f6\")?split(\",\") as name> \r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"<#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"storage\": {\r\n \"engine\": \"blocks\"\r\n },\r\n \"blocks_storage\": {\r\n \"tsdb\": {\r\n \"dir\": \"/opt/nezha/nz-agent/cortex/tsdb\"\r\n },\r\n \"bucket_store\": {\r\n \"sync_dir\": \"/opt/nezha/nz-agent/cortex/tsdb-sync\"\r\n },\r\n \"backend\": \"filesystem\",\r\n \"filesystem\": {\r\n \"dir\": \"/opt/nezha/nz-agent/cortex/data/tsdb\"\r\n }\r\n },\r\n \"store_gateway\": {\r\n \"sharding_enabled\": true,\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"instance_interface_names\": [\r\n <#list systemConfig.interface_name?default(\"eth0,en0,bond0,ens2f0,enp0s31f6\")?split(\",\") as name> \r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"<#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"compactor\": {\r\n \"data_dir\": \"/opt/nezha/nz-agent/cortex/compactor\",\r\n \"sharding_ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"instance_interface_names\": [\r\n <#list systemConfig.interface_name?default(\"eth0,en0,bond0,ens2f0,enp0s31f6\")?split(\",\") as name> \r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"<#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"frontend_worker\": {\r\n \"match_max_concurrent\": true\r\n },\r\n \"ruler\": {\r\n \"enable_api\": true,\r\n \"enable_sharding\": true,\r\n \"ring\": {\r\n \"num_tokens\": 512,\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"instance_interface_names\": [\r\n <#list systemConfig.interface_name?default(\"eth0,en0,bond0,ens2f0,enp0s31f6\")?split(\",\") as name> \r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"<#sep>,</#sep>\r\n </#list>\r\n ]\r\n }\r\n },\r\n \"ruler_storage\": {\r\n \"backend\": \"local\",\r\n \"local\": {\r\n \"directory\": \"/opt/nezha/nz-agent/cortex/rules\"\r\n }\r\n }\r\n}', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'loki_init_yml_tmpl', '{\r\n \"auth_enabled\": false,\r\n \"server\": {\r\n \"http_listen_port\": 13100,\r\n \"grpc_listen_port\": 10095\r\n },\r\n \"ingester\": {\r\n \"lifecycler\": {\r\n \"address\": \"127.0.0.1\",\r\n \"ring\": {\r\n \"kvstore\": {\r\n \"store\": \"inmemory\"\r\n },\r\n \"replication_factor\": 1\r\n },\r\n \"final_sleep\": \"0s\",\r\n \"interface_names\":[\r\n <#list systemConfig.interface_name?default(\"eth0,en0,bond0,ens2f0,enp0s31f6\")?split(\",\") as name> \r\n \"<#if name?default(\"\")?trim?length gt 0>${name}</#if>\"<#sep>,</#sep>\r\n </#list>\r\n ]\r\n },\r\n \"chunk_idle_period\": \"5m\",\r\n \"chunk_retain_period\": \"30s\"\r\n },\r\n \"schema_config\": {\r\n \"configs\": [\r\n {\r\n \"from\": \"2021-09-15\",\r\n \"store\": \"boltdb\",\r\n \"object_store\": \"filesystem\",\r\n \"schema\": \"v11\",\r\n \"index\": {\r\n \"prefix\": \"index_\",\r\n \"period\": \"168h\"\r\n }\r\n }\r\n ]\r\n },\r\n \"storage_config\": {\r\n \"boltdb\": {\r\n \"directory\": \"/tmp/loki/index\"\r\n },\r\n \"filesystem\": {\r\n \"directory\": \"/tmp/loki/chunks\"\r\n }\r\n },\r\n \"limits_config\": {\r\n \"enforce_metric_name\": false,\r\n \"reject_old_samples\": true,\r\n \"reject_old_samples_max_age\": \"168h\"\r\n },\r\n \"ruler\": {\r\n \"remote_write\": {\r\n \"client\": {\r\n \"url\": \"\"\r\n }\r\n }\r\n }\r\n}', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'dashboard_export_header', '[{\"name\":\"dashboard name\",\"i18n\":\"dashboard.dashboard.dashboardForm.dashboardName\",\"comment\":\"dashboard.dashboard.dashboardForm.dashboardName.comment\"},{\"name\":\"type\",\"i18n\":\"overall.type\",\"comment\":\"dashboard.dashboard.chartForm.type.comment\"},{\"name\":\"Template type\",\"i18n\":\"dashboard.dashboard.chartForm.varType\",\"comment\":\"dashboard.dashboard.chartForm.varType.comment\"},{\"name\":\"Params\",\"i18n\":\"config.assetLabel.params\"},{\"name\":\"remark\",\"i18n\":\"overall.remark\",\"comment\":\"dashboard.dashboard.chartForm.remark.comment\"},{\"name\":\"Charts\",\"i18n\":\"dashboard.dashboard.chartForm.charts\"},{\"name\":\"Children\",\"i18n\":\"dashboard.dashboard.children\"}]', 1, NULL); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'asset_chart_tpl', '{\"name\":\"Asset information\",\"type\":\"assetInfo\",\"span\":12,\"height\":4,\"unit\":2}', 1, 'asset添加时,默认chart配置'); +REPLACE INTO `sys_config`(`id`, `param_key`, `param_value`, `status`, `remark`) VALUES (null, 'endpoint_chart_tpl', '{\"name\":\"Endpoint information\",\"type\":\"endpointInfo\",\"span\":12,\"height\":4,\"unit\":2}', 1, 'endpoint添加时,默认chart配置'); diff --git a/nz-admin/src/main/resources/db/R__AZ_sys_dict.sql b/nz-admin/src/main/resources/db/R__AZ_sys_dict.sql index d1a2b75d..d4da86e8 100644 --- a/nz-admin/src/main/resources/db/R__AZ_sys_dict.sql +++ b/nz-admin/src/main/resources/db/R__AZ_sys_dict.sql @@ -12,27 +12,27 @@ REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `ord Delete from sys_dict where type = 'chartType'; -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 8, 'text', 'dashboard.panel.chartForm.typeVal.text.label', 8, '告警', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 9, 'pie', 'dashboard.panel.chartForm.typeVal.pie.label', 9, '饼图', 0, 1, '2021-02-05 10:57:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 10, 'group', 'dashboard.panel.chartForm.group', 10, '组', 0, 0, '2021-04-07 14:30:18', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 11, 'diagram', 'dashboard.panel.chartForm.typeVal.diagram.label', 0, 'diagram图表', 0, 1, '2021-06-24 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 12, 'log', 'dashboard.panel.chartForm.typeVal.log.label', 0, 'logs图表', 0, 1, '2021-06-24 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 1, 'line', 'dashboard.panel.chartForm.typeVal.line.label', 1, '折线图', 0, 1, '2019-12-13 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 2, 'bar', 'dashboard.panel.chartForm.typeVal.bar.label', 2, '条形图', 0, 1, '2019-12-13 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 3, 'table', 'dashboard.panel.chartForm.typeVal.table.label', 3, '表格', 0, 1, '2019-12-13 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 4, 'area', 'dashboard.panel.chartForm.typeVal.stackArea.label', 4, '堆栈面积图', 0, 1, '2019-12-13 17:53:19', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 5, 'stat', 'dashboard.panel.chartForm.typeVal.singleStat.label', 5, 'singleStat', 0, 1, '2020-03-31 10:57:30', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 6, 'url', 'dashboard.panel.chartForm.url', 6, 'url', 0, 1, '2020-03-31 10:57:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 8, 'text', 'dashboard.dashboard.chartForm.typeVal.text.label', 8, '告警', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 9, 'pie', 'dashboard.dashboard.chartForm.typeVal.pie.label', 9, '饼图', 0, 1, '2021-02-05 10:57:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 10, 'group', 'dashboard.dashboard.chartForm.group', 10, '组', 0, 0, '2021-04-07 14:30:18', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 11, 'diagram', 'dashboard.dashboard.chartForm.typeVal.diagram.label', 0, 'diagram图表', 0, 1, '2021-06-24 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 12, 'log', 'dashboard.dashboard.chartForm.typeVal.log.label', 0, 'logs图表', 0, 1, '2021-06-24 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 1, 'line', 'dashboard.dashboard.chartForm.typeVal.line.label', 1, '折线图', 0, 1, '2019-12-13 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 2, 'bar', 'dashboard.dashboard.chartForm.typeVal.bar.label', 2, '条形图', 0, 1, '2019-12-13 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 3, 'table', 'dashboard.dashboard.chartForm.typeVal.table.label', 3, '表格', 0, 1, '2019-12-13 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 4, 'area', 'dashboard.dashboard.chartForm.typeVal.stackArea.label', 4, '堆栈面积图', 0, 1, '2019-12-13 17:53:19', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 5, 'stat', 'dashboard.dashboard.chartForm.typeVal.singleStat.label', 5, 'singleStat', 0, 1, '2020-03-31 10:57:30', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 6, 'url', 'dashboard.dashboard.chartForm.url', 6, 'url', 0, 1, '2020-03-31 10:57:33', NULL); REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 7, 'alertList', '', 0, '告警', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 13, 'point', 'dashboard.panel.chartForm.typeVal.point.label', 0, '点', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 14, 'gauge', 'dashboard.panel.chartForm.typeVal.gauge.label', 0, 'gauge', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 15, 'treemap', 'dashboard.panel.chartForm.typeVal.treemap.label', 0, '树状图', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 13, 'point', 'dashboard.dashboard.chartForm.typeVal.point.label', 0, '点', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 14, 'gauge', 'dashboard.dashboard.chartForm.typeVal.gauge.label', 0, 'gauge', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 15, 'treemap', 'dashboard.dashboard.chartForm.typeVal.treemap.label', 0, '树状图', 0, 1, '2020-05-27 17:50:33', NULL); REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 16, 'assetInfo', '', 0, '资产详情图', 0, 1, '2020-05-27 17:50:33', NULL); REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 17, 'endpointInfo', '', 0, 'endpoint图', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 18, 'topology', 'dashboard.panel.chartForm.typeVal.topology.label', 0, '拓扑图', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 19, 'map', 'dashboard.panel.chartForm.typeVal.map.label', 0, '图', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 21, 'hexagon', 'dashboard.panel.chartForm.typeVal.hexagonFigure.label', 0, 'hexagon', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 23, 'clock', 'dashboard.panel.chartForm.typeVal.clock.label', 0, 'clock', 0, 1, '2020-05-27 17:50:33', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 24, 'bubble', 'dashboard.panel.chartForm.typeVal.bubble.label', 0, 'bubble', 0, 1, '2022-07-20 10:00:00', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 25, 'sankey', 'dashboard.panel.chartForm.typeVal.sankey.label', 0, 'sankey', 0, 1, '2022-08-17 10:00:00', NULL); -REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 26, 'rank', 'dashboard.panel.chartForm.typeVal.rank.label', 0, 'rank', 0, 1, '2022-09-06 10:00:00', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 18, 'topology', 'dashboard.dashboard.chartForm.typeVal.topology.label', 0, '拓扑图', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 19, 'map', 'dashboard.dashboard.chartForm.typeVal.map.label', 0, '图', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 21, 'hexagon', 'dashboard.dashboard.chartForm.typeVal.hexagonFigure.label', 0, 'hexagon', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 23, 'clock', 'dashboard.dashboard.chartForm.typeVal.clock.label', 0, 'clock', 0, 1, '2020-05-27 17:50:33', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 24, 'bubble', 'dashboard.dashboard.chartForm.typeVal.bubble.label', 0, 'bubble', 0, 1, '2022-07-20 10:00:00', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 25, 'sankey', 'dashboard.dashboard.chartForm.typeVal.sankey.label', 0, 'sankey', 0, 1, '2022-08-17 10:00:00', NULL); +REPLACE INTO `sys_dict`(`id`, `name`, `type`, `code`, `value`, `i18n_code`, `order_num`, `remark`, `del_flag`, `operator`, `op_time`, `seq`) VALUES (NULL, '图表类型', 'chartType', 26, 'rank', 'dashboard.dashboard.chartForm.typeVal.rank.label', 0, 'rank', 0, 1, '2022-09-06 10:00:00', NULL); diff --git a/nz-admin/src/main/resources/db/R__AZ_sys_i18n.sql b/nz-admin/src/main/resources/db/R__AZ_sys_i18n.sql index 36bd763e..48107c0a 100644 --- a/nz-admin/src/main/resources/db/R__AZ_sys_i18n.sql +++ b/nz-admin/src/main/resources/db/R__AZ_sys_i18n.sql @@ -33,19 +33,19 @@ CREATE TABLE `sys_i18n` ( -- ---------------------------- -- Records of sys_i18n -- ---------------------------- -INSERT INTO `sys_i18n` VALUES (1, 'date.week.six', 'en', 'date.week.six', 'SAT', ' \npanel/header 时间处理/', '2022-10-10 08:45:13', 416); -INSERT INTO `sys_i18n` VALUES (2, 'date.week.four', 'en', 'date.week.four', 'THU', ' \npanel/header 时间处理/', '2022-07-25 05:57:42', 425); -INSERT INTO `sys_i18n` VALUES (3, 'date.week.one', 'en', 'date.week.one', 'MON', 'panel/header 时间处理/', '2022-07-25 05:58:05', 425); -INSERT INTO `sys_i18n` VALUES (4, 'date.week.seven', 'en', 'date.week.seven', 'SUN', ' \npanel/header 时间处理/', '2022-07-25 05:58:47', 425); -INSERT INTO `sys_i18n` VALUES (5, 'date.week.two', 'en', 'date.week.two', 'TUE', ' \npanel/header 时间处理/', '2022-07-25 05:59:13', 425); -INSERT INTO `sys_i18n` VALUES (6, 'date.week.three', 'en', 'date.week.three', 'WED', 'panel/header 时间处理/', '2022-07-25 05:59:40', 425); -INSERT INTO `sys_i18n` VALUES (7, 'date.week.five', 'en', 'date.week.five', 'FRI', ' \npanel/header 时间处理/', '2022-07-25 06:00:20', 425); +INSERT INTO `sys_i18n` VALUES (1, 'date.week.six', 'en', 'date.week.six', 'SAT', ' \ndashboard/header 时间处理/', '2022-10-10 08:45:13', 416); +INSERT INTO `sys_i18n` VALUES (2, 'date.week.four', 'en', 'date.week.four', 'THU', ' \ndashboard/header 时间处理/', '2022-07-25 05:57:42', 425); +INSERT INTO `sys_i18n` VALUES (3, 'date.week.one', 'en', 'date.week.one', 'MON', 'dashboard/header 时间处理/', '2022-07-25 05:58:05', 425); +INSERT INTO `sys_i18n` VALUES (4, 'date.week.seven', 'en', 'date.week.seven', 'SUN', ' \ndashboard/header 时间处理/', '2022-07-25 05:58:47', 425); +INSERT INTO `sys_i18n` VALUES (5, 'date.week.two', 'en', 'date.week.two', 'TUE', 'dashboard/header 时间处理/', '2023-01-03 03:29:53', 407); +INSERT INTO `sys_i18n` VALUES (6, 'date.week.three', 'en', 'date.week.three', 'WED', 'dashboard/header 时间处理/', '2022-07-25 05:59:40', 425); +INSERT INTO `sys_i18n` VALUES (7, 'date.week.five', 'en', 'date.week.five', 'FRI', ' \ndashboard/header 时间处理/', '2022-07-25 06:00:20', 425); INSERT INTO `sys_i18n` VALUES (8, 'buttons.add', 'en', 'buttons.add', 'Add', '监控/应用/新增按钮;\n仪表盘/新增按钮;\n管理/用户/新增按钮;\n管理/角色/新增按钮;\n系统配置/客户端/新增按钮;\n系统配置/PAM/新增按钮;\n系统配置/导航/新增按钮;\n告警/告警规则/新增按钮;\n告警/告警静默/新增按钮;\n系统配置/通知配置/自定义通知方式/新增按钮;', '2022-07-26 03:04:07', 425); INSERT INTO `sys_i18n` VALUES (14, 'buttons.system.ldap', 'en', 'buttons.system.ldap', 'LDAP setting', '', '2022-07-08 14:23:50', 415); INSERT INTO `sys_i18n` VALUES (15, 'buttons.system.terminal', 'en', 'buttons.system.terminal', 'Web terminal setting', '', '2022-07-12 05:17:59', 415); INSERT INTO `sys_i18n` VALUES (17, 'buttons.system.email', 'en', 'buttons.system.email', 'Email server', '', '2022-07-08 14:31:45', 415); INSERT INTO `sys_i18n` VALUES (24, 'buttons.terminalLog.kill', 'en', 'buttons.terminalLog.kill', 'Kill', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (30, 'buttons.panel.deleteChart', 'en', 'buttons.panel.deleteChart', 'Delete chart', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (30, 'buttons.dashboard.deleteChart', 'en', 'buttons.dashboard.deleteChart', 'Delete chart', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (36, 'week.Thu', 'en', 'week.Thu', 'Thursday', '告警/告警规则/修改告警规则/有效时间/一周/; 管理/备份/编辑备份配置/每周/一周/;', '2022-07-21 06:17:59', 425); INSERT INTO `sys_i18n` VALUES (37, 'week.SunAbbreviation', 'en', 'week.SunAbbreviation', 'Sun', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (38, 'week.Tue', 'en', 'week.Tue', 'Tuesday', ' \n告警/告警规则/修改告警规则/有效时间/一周/; 管理/备份/编辑备份配置/每周/一周/;\n', '2022-07-21 06:18:36', 425); @@ -75,7 +75,7 @@ INSERT INTO `sys_i18n` VALUES (64, 'profile.editProfile', 'en', 'profile.editPro INSERT INTO `sys_i18n` VALUES (67, 'profile.twoFactorAuthentication', 'en', 'profile.twoFactorAuthentication', 'Two-factor authentication', '登录/认证;\n', '2022-07-08 13:48:04', 415); INSERT INTO `sys_i18n` VALUES (68, 'profile.confirmPassword', 'en', 'profile.confirmPassword', 'Confirm password', '管理/用户/编辑/修改密码/确认密码;\n个人中心/修改密码/确认密码;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (69, 'profile.close', 'en', 'profile.close', 'disable', '管理/用户/状态/禁用;', '2022-07-07 07:59:23', 415); -INSERT INTO `sys_i18n` VALUES (71, 'profile.username', 'en', 'profile.username', 'User name', '个人中心/用户名称;\n告警/告警信息/名称;\n资产/资产列表/名称;\n表头->资产导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (71, 'profile.username', 'en', 'profile.username', 'User name', '个人中心/用户名称;\n告警/告警信息/名称;\n资产/资产列表/名称;\n表头->资产导入/导出/模板下载', '2022-12-15 06:24:12', 415); INSERT INTO `sys_i18n` VALUES (72, 'pageSize', 'en', 'pageSize', '/page', '告警/告警信息/分页\n告警/告警规则/分页\n告警/告警静默/分页\n审计/分页\n\n', '2022-07-07 07:59:43', 415); INSERT INTO `sys_i18n` VALUES (73, 'project.endpoint.authTypeToken', 'en', 'project.endpoint.authTypeToken', 'Bearer token', '监控/应用/token;\n', '2022-07-06 06:55:48', 415); INSERT INTO `sys_i18n` VALUES (75, 'project.endpoint.basicTypeSyslog', 'en', 'project.endpoint.basicTypeSyslog', 'Listen address', '监控/应用/监控地址;', '2021-11-02 00:00:00', 1); @@ -96,7 +96,7 @@ INSERT INTO `sys_i18n` VALUES (110, 'project.endpoint.pattern', 'en', 'project.e INSERT INTO `sys_i18n` VALUES (111, 'project.endpoint.allselect', 'en', 'project.endpoint.allselect', 'The current page has all been selected', '监控/应用实例/当前页已全部选择;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (112, 'project.endpoint.endpoint', 'en', 'project.endpoint.endpoint', 'Endpoints', '监控/应用实例/名称;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (116, 'project.endpoint.authTypeWord', 'en', 'project.endpoint.authTypeWord', 'Basic auth', '监控/应用/修改模块/认证;', '2022-09-30 08:10:35', 407); -INSERT INTO `sys_i18n` VALUES (119, 'project.endpoint.relabel', 'en', 'project.endpoint.relabel', 'Metric relabels', '', '2022-07-08 09:19:17', 415); +INSERT INTO `sys_i18n` VALUES (119, 'project.endpoint.relabel', 'en', 'project.endpoint.relabel', 'Metric relabel', '', '2022-12-13 08:56:19', 415); INSERT INTO `sys_i18n` VALUES (120, 'project.endpoint.promExpr', 'en', 'project.endpoint.promExpr', 'Please input expression', '监控/应用实例/请输入表达式;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (122, 'project.endpoint.endpointId', 'en', 'project.endpoint.endpointId', 'Endpoint ID', '告警/告警信息/id;\n监控/应用实例/id;\n监控/应用/id;\n监控/应用组/id;\n告警/id;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (124, 'project.endpoint.stateInfo_230009', 'en', 'project.endpoint.stateInfo_230009', 'Promserver unavailable', '\n', '2021-11-02 00:00:00', 1); @@ -108,7 +108,7 @@ INSERT INTO `sys_i18n` VALUES (134, 'project.topology.previewExit', 'en', 'proje INSERT INTO `sys_i18n` VALUES (137, 'project.topology.bac', 'en', 'project.topology.bac', 'Background', '监控/应用组/背景', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (138, 'project.topology.defaultEndArrow', 'en', 'project.topology.defaultEndArrow', 'Default end arrow', '监控/应用组\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (139, 'project.topology.bounce', 'en', 'project.topology.bounce', 'bounce', '监控/应用组/按钮\n', '2022-07-07 08:00:11', 415); -INSERT INTO `sys_i18n` VALUES (140, 'project.topology.ruleColor', 'en', 'project.topology.ruleColor', 'Rule Color', '', '2022-07-21 01:17:24', 425); +INSERT INTO `sys_i18n` VALUES (140, 'project.topology.ruleColor', 'en', 'project.topology.ruleColor', 'Rule color', '', '2022-12-14 03:47:25', 415); INSERT INTO `sys_i18n` VALUES (141, 'project.topology.none', 'en', 'project.topology.none', 'None', '\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (142, 'project.topology.grids', 'en', 'project.topology.grids', 'Grids', '监控/应用组/按钮\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (143, 'project.topology.animationColor', 'en', 'project.topology.animationColor', 'Animation color', '', '2022-07-20 02:12:06', 425); @@ -129,15 +129,15 @@ INSERT INTO `sys_i18n` VALUES (161, 'project.topology.left', 'en', 'project.topo INSERT INTO `sys_i18n` VALUES (162, 'project.topology.shakeX', 'en', 'project.topology.shakeX', 'shakeX', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (163, 'project.topology.transparency', 'en', 'project.topology.transparency', 'Transparency', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (164, 'project.topology.style', 'en', 'project.topology.style', 'Style', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (165, 'project.topology.fontSize', 'en', 'project.topology.fontSize', 'Font Size', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (165, 'project.topology.fontSize', 'en', 'project.topology.fontSize', 'Font size', '监控/应用组/画布属性', '2022-12-14 07:03:43', 415); INSERT INTO `sys_i18n` VALUES (166, 'project.topology.flash', 'en', 'project.topology.flash', 'flash', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (167, 'project.topology.cut', 'en', 'project.topology.cut', 'Cut', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (168, 'project.topology.curve', 'en', 'project.topology.curve', 'curve', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (169, 'project.topology.circularBead', 'en', 'project.topology.circularBead', 'Circular bead', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (171, 'project.topology.dot', 'en', 'project.topology.dot', 'dot', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (172, 'project.topology.lineName', 'en', 'project.topology.lineName', 'Line Name', '监控/应用组/画布属性', '2022-07-21 06:21:28', 425); +INSERT INTO `sys_i18n` VALUES (172, 'project.topology.lineName', 'en', 'project.topology.lineName', 'Line name', '监控/应用组/画布属性', '2022-12-14 07:05:39', 415); INSERT INTO `sys_i18n` VALUES (173, 'project.topology.lineWidth', 'en', 'project.topology.lineWidth', 'Line width', '监控/应用组/画布属性', '2022-07-21 06:21:33', 425); -INSERT INTO `sys_i18n` VALUES (174, 'project.topology.endpoint', 'en', 'project.topology.endpoint', 'Endpoint Table', '监控/应用组/画布属性', '2022-06-21 06:08:28', 1); +INSERT INTO `sys_i18n` VALUES (174, 'project.topology.endpoint', 'en', 'project.topology.endpoint', 'Endpoint table', '监控/应用组/画布属性', '2022-12-14 07:06:00', 415); INSERT INTO `sys_i18n` VALUES (175, 'project.topology.placeholderImg', 'en', 'project.topology.placeholderImg', 'Please enter name', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (176, 'project.topology.fade', 'en', 'project.topology.fade', 'fade', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (177, 'project.topology.lineStyle', 'en', 'project.topology.lineStyle', 'Line dash', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); @@ -152,8 +152,8 @@ INSERT INTO `sys_i18n` VALUES (187, 'project.topology.nodeHeight', 'en', 'projec INSERT INTO `sys_i18n` VALUES (189, 'project.topology.selTwoNode', 'en', 'project.topology.selTwoNode', 'Please select two module', '监控/应用组/画布属性', '2022-07-21 06:22:07', 425); INSERT INTO `sys_i18n` VALUES (191, 'project.topology.swing', 'en', 'project.topology.swing', 'swing', '监控/应用组/画布属性', '2022-07-21 06:22:16', 425); INSERT INTO `sys_i18n` VALUES (192, 'project.topology.topOffsetY', 'en', 'project.topology.topOffsetY', 'top', '监控/应用组/画布属性', '2022-07-21 06:22:12', 425); -INSERT INTO `sys_i18n` VALUES (193, 'project.topology.lineDash', 'en', 'project.topology.lineDash', 'lineDash', '监控/应用组/画布属性', '2022-07-21 06:22:21', 425); -INSERT INTO `sys_i18n` VALUES (195, 'project.topology.gridColor', 'en', 'project.topology.gridColor', 'Grid Color', '监控/应用组/画布属性网格颜色', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (193, 'project.topology.lineDash', 'en', 'project.topology.lineDash', 'Line dash', '监控/应用组/画布属性', '2022-12-14 07:02:50', 415); +INSERT INTO `sys_i18n` VALUES (195, 'project.topology.gridColor', 'en', 'project.topology.gridColor', 'Grid color', '监控/应用组/画布属性网格颜色', '2022-12-14 03:47:16', 415); INSERT INTO `sys_i18n` VALUES (198, 'project.topology.defaultLineWidth', 'en', 'project.topology.defaultLineWidth', 'Default line width', '监控/应用组/画布属性默认线宽', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (199, 'project.topology.rotate', 'en', 'project.topology.rotate', 'Rotate', '监控/应用组/画布属性旋转', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (200, 'project.topology.arrowColor', 'en', 'project.topology.arrowColor', 'Arrow color', '监控/应用组/画布属性箭头颜色', '2021-11-02 00:00:00', 1); @@ -161,7 +161,7 @@ INSERT INTO `sys_i18n` VALUES (201, 'project.topology.data', 'en', 'project.topo INSERT INTO `sys_i18n` VALUES (202, 'project.topology.arrows', 'en', 'project.topology.arrows', 'arrows', '监控/应用组/画布属性箭头方向', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (203, 'project.topology.align', 'en', 'project.topology.align', 'Align', '监控/应用组/画布属性对齐', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (204, 'project.topology.unitError', 'en', 'project.topology.unitError', 'Please select the folder', '监控/应用组/画布属性请选择对应的目录', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (205, 'project.topology.gridSize', 'en', 'project.topology.gridSize', 'Grid Size', '监控/应用组/画布属性网格大小', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (205, 'project.topology.gridSize', 'en', 'project.topology.gridSize', 'Grid size', '监控/应用组/画布属性网格大小', '2022-12-14 07:11:27', 415); INSERT INTO `sys_i18n` VALUES (206, 'project.topology.lineType', 'en', 'project.topology.lineType', 'Line type', '监控/应用组/画布属性线型', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (207, 'project.topology.textOffsetX', 'en', 'project.topology.textOffsetX', 'Text offsetX', '监控/应用组/画布属性水平偏移', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (208, 'project.topology.textOffsetY', 'en', 'project.topology.textOffsetY', 'Text offsetY', '监控/应用组/画布属性垂直偏移', '2021-11-02 00:00:00', 1); @@ -176,15 +176,15 @@ INSERT INTO `sys_i18n` VALUES (220, 'project.topology.addLine', 'en', 'project.t INSERT INTO `sys_i18n` VALUES (222, 'project.topology.selMod', 'en', 'project.topology.selMod', 'Please bind module for all nodes', '监控/应用组/画布属性请为所有节点绑定module', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (224, 'project.topology.polyline', 'en', 'project.topology.polyline', 'polyline', '监控/应用组/画布属性折线', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (227, 'project.topology.imgFormat', 'en', 'project.topology.imgFormat', 'Upload picture can only be JPG/ PNG format!', '监控/应用组/画布属性上传图片只能是 JPG/png 格式!u0027', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (228, 'project.topology.color', 'en', 'project.topology.color', 'color', '监控/应用组/画布属性颜色', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (228, 'project.topology.color', 'en', 'project.topology.color', 'Color', '监控/应用组/画布属性颜色', '2022-12-14 03:46:35', 415); INSERT INTO `sys_i18n` VALUES (229, 'project.topology.line', 'en', 'project.topology.line', 'line', '监控/应用组/画布属性线条', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (231, 'project.topology.toArrow', 'en', 'project.topology.toArrow', 'To arrow', '监控/应用组/画布属性终点箭头', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (232, 'project.topology.rule', 'en', 'project.topology.rule', 'Ruler', '监控/应用组/画布属性标尺', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (233, 'project.topology.paste', 'en', 'project.topology.paste', 'Paste', '监控/应用组/画布属性粘贴', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (234, 'project.topology.title', 'en', 'project.topology.title', 'Title', '监控/应用组/画布属性标题;\n\n表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (234, 'project.topology.title', 'en', 'project.topology.title', 'Title', '监控/应用组/画布属性标题;\n\n表头->dashboard /导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (235, 'project.topology.maxCount', 'en', 'project.topology.maxCount', 'Max count', '监控/应用组/画布属性水平个数', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (237, 'project.topology.animationType', 'en', 'project.topology.animationType', 'Animation type', '监控/应用组/画布属性动画类型', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (239, 'project.topology.alert', 'en', 'project.topology.alert', 'Alert Message', '告警/告警信息/告警信息;\n资产/资产列表/告警;\n监控/应用实例/告警;', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (239, 'project.topology.alert', 'en', 'project.topology.alert', 'Alert message', '告警/告警信息/告警信息;\n资产/资产列表/告警;\n监控/应用实例/告警;', '2022-12-13 08:28:24', 415); INSERT INTO `sys_i18n` VALUES (242, 'project.topology.defaultStartArrow', 'en', 'project.topology.defaultStartArrow', 'Default start arrow', '监控/应用组/画布属性默认开始箭头', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (243, 'project.topology.textBaseline', 'en', 'project.topology.textBaseline', 'Text baseline', '监控/应用组/画布属性垂直对齐', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (244, 'project.topology.center', 'en', 'project.topology.center', 'center', '监控/应用组/画布属性居中', '2021-11-02 00:00:00', 1); @@ -195,7 +195,7 @@ INSERT INTO `sys_i18n` VALUES (249, 'project.topology.pb', 'en', 'project.topolo INSERT INTO `sys_i18n` VALUES (250, 'project.topology.heartBeat', 'en', 'project.topology.heartBeat', 'heartBeat', '监控/应用组/画布属性心跳', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (251, 'project.topology.iconColor', 'en', 'project.topology.iconColor', 'Icon color', '监控/应用组/画布属性图标颜色', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (252, 'project.topology.pl', 'en', 'project.topology.pl', 'Padding left', '监控/应用组/画布属性内边距 - 左', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (253, 'project.topology.fontColor', 'en', 'project.topology.fontColor', 'Font Color', '监控/应用组/画布属性字体颜色', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (253, 'project.topology.fontColor', 'en', 'project.topology.fontColor', 'Font color', '监控/应用组/画布属性字体颜色', '2022-12-14 03:46:51', 415); INSERT INTO `sys_i18n` VALUES (254, 'project.topology.spaceWidth', 'en', 'project.topology.spaceWidth', 'Space width', '监控/应用组/画布属性水平间距', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (256, 'project.module.batchEndpoint', 'en', 'project.module.batchEndpoint', 'Batch endpoint', '监控/应用组/画布属性批量 ', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (258, 'project.module.editModule', 'en', 'project.module.editModule', 'Edit module', '监控/应用/标题\n', '2021-11-02 00:00:00', 1); @@ -226,7 +226,7 @@ INSERT INTO `sys_i18n` VALUES (308, 'login.upload', 'en', 'login.upload', 'Uploa INSERT INTO `sys_i18n` VALUES (309, 'login.verify', 'en', 'login.verify', 'Verify code', '登录/验证;\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (310, 'login.verifyPlaceholder', 'en', 'login.verifyPlaceholder', 'Verification code', '登录/验证码;', '2022-06-21 09:57:13', 1); INSERT INTO `sys_i18n` VALUES (311, 'login.login', 'en', 'login.login', 'Login', '登录/登录按钮;', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (312, 'login.username', 'en', 'login.username', 'Username', '登录/登录名;\n管理/用户/名称;', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (312, 'login.username', 'en', 'login.username', 'Username', '登录/登录名;\n管理/用户/名称;', '2022-12-15 06:23:38', 415); INSERT INTO `sys_i18n` VALUES (314, 'search.recentSearch', 'en', 'search.recentSearch', 'Search history', '历史记录/搜索记录;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (315, 'search.noRecentSearch', 'en', 'search.noRecentSearch', 'No recent search', '历史记录/无搜索记录;', '2022-07-12 09:57:26', 415); INSERT INTO `sys_i18n` VALUES (316, 'search.searchTip', 'en', 'search.searchTip', 'Enter to search', '点击或回车执行搜索', '2021-11-02 00:00:00', 1); @@ -235,7 +235,7 @@ INSERT INTO `sys_i18n` VALUES (318, 'system.apikey.apiKey', 'en', 'system.apikey INSERT INTO `sys_i18n` VALUES (320, 'alert.severity', 'en', 'alert.severity', 'Priority', '告警/告警信息/表头等级;\n告警/告警规则/表头等级', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (321, 'alert.summary', 'en', 'alert.summary', 'Summary', '告警/告警信息/概要;\n告警/告警规则/概要', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (322, 'alert.P1Rule', 'en', 'alert.P1Rule', 'P1: Critical, alert that can cause business paralysis', '', '2022-07-20 02:16:50', 425); -INSERT INTO `sys_i18n` VALUES (324, 'alert.alertNum', 'en', 'alert.alertNum', 'Alert nums', '告警/告警信息/告警数量;\n告警/告警规则/告警数量;', '2022-06-17 02:26:34', 381); +INSERT INTO `sys_i18n` VALUES (324, 'alert.alertNum', 'en', 'alert.alertNum', 'Alert num', '告警/告警信息/告警数量;\n告警/告警规则/告警数量;', '2022-12-13 08:31:58', 415); INSERT INTO `sys_i18n` VALUES (326, 'alert.P3Rule', 'en', 'alert.P3Rule', 'P3: Minor, alert that needs to be dealt with, but not urgent', '', '2022-07-20 02:17:04', 425); INSERT INTO `sys_i18n` VALUES (327, 'alert.rule', 'en', 'alert.rule', 'Rule', '告警/告警规则;\n仪表盘/告警规则;\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (330, 'alert.alertRule', 'en', 'alert.alertRule', 'Rules', '告警/根据告警规则统计告警消息数量TOP10;\n表头->告警信息导出', '2022-07-21 06:18:50', 416); @@ -263,7 +263,7 @@ INSERT INTO `sys_i18n` VALUES (377, 'alert.config.timeout', 'en', 'alert.config. INSERT INTO `sys_i18n` VALUES (378, 'alert.config.second', 'en', 'alert.config.second', 'second', '系统配置/APM配置/秒;\n系统配置/个性配置/秒;\n告警/告警规则/秒;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (379, 'alert.config.trbShot', 'en', 'alert.config.trbShot', 'Trouble shooting', '告警/告警规则/修改告警规则/故障排除;\n表头->告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (380, 'alert.config.expr', 'en', 'alert.config.expr', 'Expression/OID', '告警/告警规则/表达式/OID;\n表头->告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (381, 'alert.config.notifyActive', 'en', 'alert.config.notifyActive', 'Active Notification', '表头->告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (381, 'alert.config.notifyActive', 'en', 'alert.config.notifyActive', 'Active notification', '表头->告警规则导入/导出/模板下载', '2022-12-15 03:03:14', 415); INSERT INTO `sys_i18n` VALUES (385, 'alert.config.P1', 'en', 'alert.config.P1', 'P1', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (386, 'alert.config.P2', 'en', 'alert.config.P2', 'P2', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (387, 'alert.config.P3', 'en', 'alert.config.P3', 'P3', '', '2021-11-02 00:00:00', 1); @@ -274,7 +274,7 @@ INSERT INTO `sys_i18n` VALUES (396, 'alert.config.inr', 'en', 'alert.config.inr' INSERT INTO `sys_i18n` VALUES (397, 'alert.config.editAlertConfig', 'en', 'alert.config.editAlertConfig', 'Edit alert rule', '告警/告警规则/修改告警规则;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (399, 'alert.config.inrPlaceholder', 'en', 'alert.config.inrPlaceholder', 'Default global scrape interval', '告警/修改告警规则/默认全局抓取间隔;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (401, 'alert.config.autoExpired', 'en', 'alert.config.autoExpired', 'Automatic expired', '告警/告警规则/修改告警规则/失效时间;\n表头->告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (402, 'alert.config.schedDays', 'en', 'alert.config.schedDays', 'Effective time', '告警/告警规则/修改告警规则/有效时间;\n表头->告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (402, 'alert.config.schedDays', 'en', 'alert.config.schedDays', 'Effective times', '告警/告警规则/修改告警规则/有效时间;\n表头->告警规则导入/导出/模板下载', '2022-12-15 06:12:17', 415); INSERT INTO `sys_i18n` VALUES (403, 'alert.config.notificationConfig', 'en', 'alert.config.notificationConfig', 'Notification configurations', '告警/告警规则/修改告警规则/通知配置;', '2022-07-12 03:36:43', 415); INSERT INTO `sys_i18n` VALUES (404, 'alert.config.chart.alertNumTrend', 'en', 'alert.config.chart.alertNumTrend', 'Alert num trend', '告警/告警数量趋势;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (405, 'alert.config.chart.affectEntity', 'en', 'alert.config.chart.affectEntity', 'Affect entity', '', '2022-07-20 02:19:40', 425); @@ -293,12 +293,12 @@ INSERT INTO `sys_i18n` VALUES (421, 'overall.AddByTemplate', 'en', 'overall.AddB INSERT INTO `sys_i18n` VALUES (422, 'overall.createRole', 'en', 'overall.createRole', 'New role', '管理/角色/新增角色;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (423, 'overall.tempPrev', 'en', 'overall.tempPrev', 'Template preview', '仪表盘/模板预览', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (424, 'overall.createProject', 'en', 'overall.createProject', 'New project', '监控/应用/应用实例/新增系统', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (425, 'overall.type', 'en', 'overall.type', 'Type', '仪表盘/类型;\n系统配置/个性化配置/类型;\n表头->告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导出/导入/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (425, 'overall.type', 'en', 'overall.type', 'Type', '仪表盘/类型;\n系统配置/个性化配置/类型;\n表头->告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导出/导入/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (426, 'overall.createPrometheusServer', 'en', 'overall.createPrometheusServer', 'New agent', '系统配置/客户端/新增客户端;\n\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (427, 'overall.cover', 'en', 'overall.cover', 'Override', '', '2022-07-20 02:23:29', 425); INSERT INTO `sys_i18n` VALUES (429, 'overall.moreOption', 'en', 'overall.moreOption', 'More option', '告警/告警信息/更多选项;\n告警/告警规则/更多选项;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (430, 'overall.toolBox.stack', 'en', 'overall.toolBox.stack', 'Show stack chart', '', '2022-07-20 02:23:33', 425); -INSERT INTO `sys_i18n` VALUES (431, 'overall.toolBox.back', 'en', 'overall.toolBox.back', 'Area scaling restore', '仪表盘/区域缩放还原;', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (431, 'overall.toolBox.back', 'en', 'overall.toolBox.back', 'Area scaling restore', '仪表盘/区域缩放还原;', '2022-12-20 09:14:00', 415); INSERT INTO `sys_i18n` VALUES (432, 'overall.toolBox.zoom', 'en', 'overall.toolBox.zoom', 'Area scaling', '仪表盘/区域缩放;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (433, 'overall.toolBox.stackBack', 'en', 'overall.toolBox.stackBack', 'Back to original chart', '', '2022-07-20 02:23:37', 425); INSERT INTO `sys_i18n` VALUES (434, 'overall.createModel', 'en', 'overall.createModel', 'New model', '资产配置/型号/新增型号;', '2021-11-02 00:00:00', 1); @@ -372,7 +372,7 @@ INSERT INTO `sys_i18n` VALUES (521, 'overall.logs', 'en', 'overall.logs', 'Logs' INSERT INTO `sys_i18n` VALUES (522, 'overall.generate', 'en', 'overall.generate', 'Generate', '管理/证书/生产', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (524, 'overall.placeHolder', 'en', 'overall.placeHolder', 'Please enter', '监控/应用实例/\n', '2022-07-20 02:53:15', 425); INSERT INTO `sys_i18n` VALUES (525, 'overall.clickUpload', 'en', 'overall.clickUpload', 'Click to upload', '更过/点击上传;', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (527, 'overall.all', 'en', 'overall.all', 'All', 'panel/全选', '2022-07-20 02:55:14', 425); +INSERT INTO `sys_i18n` VALUES (527, 'overall.all', 'en', 'overall.all', 'All', 'dashboard/全选', '2022-07-20 02:55:14', 425); INSERT INTO `sys_i18n` VALUES (528, 'overall.configEndpoint', 'en', 'overall.configEndpoint', 'Config', '', '2022-07-20 02:55:47', 425); INSERT INTO `sys_i18n` VALUES (529, 'overall.query', 'en', 'overall.query', 'Query', '监控/查询;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (530, 'overall.duplicate', 'en', 'overall.duplicate', 'Duplicate', '个人中心/按钮标题\n', '2022-07-20 02:57:35', 425); @@ -388,7 +388,7 @@ INSERT INTO `sys_i18n` VALUES (544, 'overall.week', 'en', 'overall.week', '1 wee INSERT INTO `sys_i18n` VALUES (546, 'overall.configuration', 'en', 'overall.configuration', 'Custom assets', '资产/资产配置;', '2022-07-08 14:20:25', 415); INSERT INTO `sys_i18n` VALUES (547, 'overall.batchEdit', 'en', 'overall.batchEdit', 'Batch edit', '资产/资产列表/更多/批量修改;\n监控/应用实例/更多/批量修改;', '2022-07-08 13:11:35', 415); INSERT INTO `sys_i18n` VALUES (548, 'overall.back', 'en', 'overall.back', 'Back', '仪表盘/返回;\n监控/应用实例/返回;\n', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (549, 'overall.remark', 'en', 'overall.remark', 'Description', '监控/描述;\n资产/资产配置/型号/描述;\n\n告警/告警规则》描述;\n系统配置/IPAM/描述;\n\n表头->dashboard panel导入/导出/模板下载、资产model导入/导出/模板下载、告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载、告警信息导出', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (549, 'overall.remark', 'en', 'overall.remark', 'Description', '监控/描述;\n资产/资产配置/型号/描述;\n\n告警/告警规则》描述;\n系统配置/IPAM/描述;\n\n表头->dashboard 导入/导出/模板下载、资产model导入/导出/模板下载、告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载、告警信息导出', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (550, 'overall.relabelConfigReplacement', 'en', 'overall.relabelConfigReplacement', 'Default is $1', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (551, 'overall.oid', 'en', 'overall.oid', 'OID format check error', '告警/OID格式校验错误;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (552, 'overall.delete', 'en', 'overall.delete', 'Delete', '系统配置/IPAM/删除;\n资产/数据中心/删除;\n\n\n', '2021-11-02 00:00:00', 1); @@ -457,12 +457,12 @@ INSERT INTO `sys_i18n` VALUES (628, 'tip.assetConfirmDelete', 'en', 'tip.assetCo INSERT INTO `sys_i18n` VALUES (629, 'tip.noImportFile', 'en', 'tip.noImportFile', 'No import file found', '告警/告警信息/更多/导入msg提示语句; 告警/告警规则/更多/导入msg提示语句; 告警/告警静默/更多/导入msg提示语句; 监控/应用实例/更多/导入msg提示语句; 监控/应用/更多/导入msg提示语句; 监控/应用组/更多/导入msg提示语句; 资产/资产列表/更多/导入msg提示语句; 资产/数据中心/更多/导入msg提示语句; 资产/资产配置/属性/更多/导入msg提示语句; 资产/资产配置/型号/更多/导入msg提示语句;\n', '2022-07-21 08:31:16', 425); INSERT INTO `sys_i18n` VALUES (630, 'tip.zoomStatusPrompt', 'en', 'tip.zoomStatusPrompt', 'Your browser is currently in zoom state, the page may appear dislocation, the proposed 100% size.', '系统配置/SNMP/MIB浏览器/msg提示語句', '2022-07-21 08:25:52', 425); INSERT INTO `sys_i18n` VALUES (631, 'tip.deleteSuccess', 'en', 'tip.deleteSuccess', 'Delete success', '告警/告警信息/删除成功msg提示语句; 告警/告警规则/删除成功msg提示语句; 告警/告警静默/删除成功msg提示语句; 监控/应用实例/删除成功msg提示语句; 监控/应用/删除成功msg提示语句; 监控/应用组/删除成功msg提示语句; 资产/资产列表/删除成功msg提示语句; 资产/数据中心/删除成功msg提示语句; 资产/资产配置/属性/删除成功msg提示语句; 资产/资产配置/型号/删除成功msg提示语句', '2022-07-21 08:32:38', 425); -INSERT INTO `sys_i18n` VALUES (632, 'tip.saveSuccess', 'en', 'tip.saveSuccess', 'Save success', '告警/告警信息/保存成功msg提示语句; 告警/告警规则/保存成功msg提示语句; 告警/告警静默/保存成功msg提示语句; 监控/应用实例/保存成功msg提示语句; 监控/应用/保存成功msg提示语句; 监控/应用组/保存成功msg提示语句; 资产/资产列表/保存成功msg提示语句; 资产/数据中心/保存成功msg提示语句; 资产/资产配置/属性/保存成功msg提示语句; 资产/资产配置/型号/保存成功msg提示语句;', '2022-07-21 08:33:38', 425); +INSERT INTO `sys_i18n` VALUES (632, 'tip.saveSuccess', 'en', 'tip.saveSuccess', 'Save success', '告警/告警信息/保存成功msg提示语句; 告警/告警规则/保存成功msg提示语句; 告警/告警静默/保存成功msg提示语句; 监控/应用实例/保存成功msg提示语句; 监控/应用/保存成功msg提示语句; 监控/应用组/保存成功msg提示语句; 资产/资产列表/保存成功msg提示语句; 资产/数据中心/保存成功msg提示语句; 资产/资产配置/属性/保存成功msg提示语句; 资产/资产配置/型号/保存成功msg提示语句;', '2023-01-04 02:17:30', 1); INSERT INTO `sys_i18n` VALUES (633, 'tip.downloadSuccess', 'en', 'tip.downloadSuccess', 'Download success', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (634, 'tip.killTerm', 'en', 'tip.killTerm', 'Are you sure you want to kill terminal?', '管理/审计/终端日志/msg提示語句', '2022-07-21 08:19:23', 425); INSERT INTO `sys_i18n` VALUES (635, 'tip.refreshLater', 'en', 'tip.refreshLater', 'Refresh later', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (637, 'tip.testSuccess', 'en', 'tip.testSuccess', 'Test success', '系統配置/msg提示語句', '2022-07-21 08:18:17', 425); -INSERT INTO `sys_i18n` VALUES (638, 'tip.syncTip', 'en', 'tip.syncTip', 'This operation may cause the original data or chart to be overwritten. Are you sure to synchronize?', 'panel/msg提示語句', '2022-07-21 08:17:15', 425); +INSERT INTO `sys_i18n` VALUES (638, 'tip.syncTip', 'en', 'tip.syncTip', 'This operation may cause the original data or chart to be overwritten. Are you sure to synchronize?', 'dashboard/msg提示語句', '2022-07-21 08:17:15', 425); INSERT INTO `sys_i18n` VALUES (639, 'tip.noAccess', 'en', 'tip.noAccess', 'No access', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (640, 'tip.resetPrompt', 'en', 'tip.resetPrompt', 'Are you sure to reset?', '系统配置/个性化配置/msg提示語句', '2022-07-21 08:15:59', 425); INSERT INTO `sys_i18n` VALUES (641, 'tip.yes', 'en', 'tip.yes', 'Yes', ' \n告警/告警信息/msg提示语句; 告警/告警规则/msg提示语句; 告警/告警静默/msg提示语句; 监控/应用实例/msg提示语句; 监控/应用/msg提示语句; 监控/应用组/msg提示语句; 资产/资产列表/msg提示语句; 资产/数据中心/msg提示语句; 资产/资产配置/属性/msg提示语句; 资产/资产配置/型号/msg提示语句;', '2022-07-21 08:14:50', 425); @@ -472,7 +472,7 @@ INSERT INTO `sys_i18n` VALUES (644, 'tip.confirmDelete', 'en', 'tip.confirmDelet INSERT INTO `sys_i18n` VALUES (645, 'tip.confirmOvertime', 'en', 'tip.confirmOvertime', 'Are you sure it\'s off?', '系统配置/模板/表达式模板/msg提示语句', '2022-07-21 08:08:16', 425); INSERT INTO `sys_i18n` VALUES (646, 'tip.confirmDuplicate', 'en', 'tip.confirmDuplicate', 'Are you sure to duplicate this chart?', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (647, 'tip.confirmExpired', 'en', 'tip.confirmExpired', 'Are you sure you want to expired?', '告警/告警信息/msg提示语句; 告警/告警规则/msg提示语句; 告警/告警静默/msg提示语句;', '2022-07-21 08:02:23', 425); -INSERT INTO `sys_i18n` VALUES (648, 'tip.syncSuccess', 'en', 'tip.syncSuccess', 'Synchronize success', 'panel/msg提示语句', '2022-07-21 07:45:45', 425); +INSERT INTO `sys_i18n` VALUES (648, 'tip.syncSuccess', 'en', 'tip.syncSuccess', 'Synchronize success', 'dashboard/msg提示语句', '2022-07-21 07:45:45', 425); INSERT INTO `sys_i18n` VALUES (649, 'tip.confirmBatchDelete', 'en', 'tip.confirmBatchDelete', 'Are you sure to delete these {0} pieces of data', '告警/告警信息/删除/删除语句', '2022-07-21 07:44:45', 425); INSERT INTO `sys_i18n` VALUES (650, 'tip.pressEnterToAdd', 'en', 'tip.pressEnterToAdd', 'Press enter to add new line', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (651, 'tip.uploadSuccess', 'en', 'tip.uploadSuccess', 'Upload success', '', '2021-11-02 00:00:00', 1); @@ -630,7 +630,7 @@ INSERT INTO `sys_i18n` VALUES (926, 'config.system.notification.filePathReg', 'e INSERT INTO `sys_i18n` VALUES (929, 'config.system.notification.notification', 'en', 'config.system.notification.notification', 'Notification', ' \n系统配置/个性化配置/通知方式', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (932, 'config.system.notification.create', 'en', 'config.system.notification.create', 'New notification', '系统配置/个性化配置/新建通知方式', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (936, 'config.system.notification.account', 'en', 'config.system.notification.account', 'Notify account', '\n系统配置/个性化配置/\n', '2022-06-20 09:29:53', 1); -INSERT INTO `sys_i18n` VALUES (937, 'config.system.system', 'en', 'config.system.system', 'Appearance', ' \n系统配置/个性化配置/', '2022-08-01 03:47:32', 415); +INSERT INTO `sys_i18n` VALUES (937, 'config.system.system', 'en', 'config.system.system', 'Appearances', '系统配置/个性化配置/', '2022-12-15 01:59:45', 415); INSERT INTO `sys_i18n` VALUES (938, 'config.system.apiKey.creatAt', 'en', 'config.system.apiKey.creatAt', 'Create at', ' \n系统配置/个性化配置/创建时间', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (939, 'config.system.apiKey.noExpire', 'en', 'config.system.apiKey.noExpire', 'No expiration date', '系统配置/个性化配置/无有效期', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (941, 'config.system.apiKey.apiKey', 'en', 'config.system.apiKey.apiKey', 'API key', '\n系统配置/个性化配置/', '2021-11-02 00:00:00', 1); @@ -739,7 +739,7 @@ INSERT INTO `sys_i18n` VALUES (1099, 'config.assetLabel.email', 'en', 'config.as INSERT INTO `sys_i18n` VALUES (1103, 'config.assetLabel.double', 'en', 'config.assetLabel.double', 'DOUBLE', '资产/资产列表\n/小数', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1104, 'config.assetLabel.display', 'en', 'config.assetLabel.display', 'Display', '资产/资产列表\n/显示', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1105, 'config.assetLabel.params', 'en', 'config.assetLabel.params', 'Params', '资产/资产列表\n/参数', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1107, 'config.assetLabel.infoLabel', 'en', 'config.assetLabel.infoLabel', 'Label Info', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1107, 'config.assetLabel.infoLabel', 'en', 'config.assetLabel.infoLabel', 'Label info', '', '2022-12-14 09:37:57', 415); INSERT INTO `sys_i18n` VALUES (1108, 'config.assetLabel.isCheck', 'en', 'config.assetLabel.isCheck', 'Is check', '资产/资产列表 /', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1109, 'config.assetLabel.labelOptionNull', 'en', 'config.assetLabel.labelOptionNull', 'Please input option', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1110, 'config.assetLabel.operate', 'en', 'config.assetLabel.operate', 'Operate', '资产/资产列表\n/操作', '2021-11-02 00:00:00', 1); @@ -796,10 +796,10 @@ INSERT INTO `sys_i18n` VALUES (1214, 'dashboard.overview.dataCenter.promServer', INSERT INTO `sys_i18n` VALUES (1218, 'dashboard.overview.alert.ruleNum', 'en', 'dashboard.overview.alert.ruleNum', 'Rule num', ' \noverview/', '2022-07-21 07:26:26', 425); INSERT INTO `sys_i18n` VALUES (1219, 'dashboard.overview.alert.top', 'en', 'dashboard.overview.alert.top', 'Top', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1221, 'dashboard.overview.alert.alertRuleTopN', 'en', 'dashboard.overview.alert.alertRuleTopN', 'Top10 alert message', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1222, 'dashboard.overview.alert.moduleTopN', 'en', 'dashboard.overview.alert.moduleTopN', 'Top alert message by Module', ' \noverview/第三个图title', '2022-07-25 08:13:41', 425); -INSERT INTO `sys_i18n` VALUES (1224, 'dashboard.overview.alert.assetTopN', 'en', 'dashboard.overview.alert.assetTopN', 'Top alert message by Asset', 'overview/第二个图title', '2022-07-25 08:14:44', 425); -INSERT INTO `sys_i18n` VALUES (1225, 'dashboard.overview.alert.chart.chartTitle', 'en', 'dashboard.overview.alert.chart.chartTitle', 'Alert Trend', '', '2022-07-25 08:15:18', 425); -INSERT INTO `sys_i18n` VALUES (1231, 'dashboard.overview.contentTitle', 'en', 'dashboard.overview.contentTitle', 'Nezha Management System', ' \noverview/标题', '2022-07-25 08:16:00', 425); +INSERT INTO `sys_i18n` VALUES (1222, 'dashboard.overview.alert.moduleTopN', 'en', 'dashboard.overview.alert.moduleTopN', 'Top alert message by module', 'overview/第三个图title', '2022-12-14 09:35:58', 415); +INSERT INTO `sys_i18n` VALUES (1224, 'dashboard.overview.alert.assetTopN', 'en', 'dashboard.overview.alert.assetTopN', 'Top alert message by asset', 'overview/第二个图title', '2022-12-14 09:36:06', 415); +INSERT INTO `sys_i18n` VALUES (1225, 'dashboard.overview.alert.chart.chartTitle', 'en', 'dashboard.overview.alert.chart.chartTitle', 'Alert trend', '', '2022-12-14 09:36:20', 415); +INSERT INTO `sys_i18n` VALUES (1231, 'dashboard.overview.contentTitle', 'en', 'dashboard.overview.contentTitle', 'Nezha management system', 'overview/标题', '2022-12-14 09:36:37', 415); INSERT INTO `sys_i18n` VALUES (1232, 'dashboard.overview.title', 'en', 'dashboard.overview.title', 'Overview', '仪表盘/', '2022-07-20 03:27:07', 425); INSERT INTO `sys_i18n` VALUES (1233, 'dashboard.overview.asset.num', 'en', 'dashboard.overview.asset.num', 'Num', ' \n仪表盘/', '2022-07-20 03:28:06', 425); INSERT INTO `sys_i18n` VALUES (1241, 'dashboard.overview.asset.total', 'en', 'dashboard.overview.asset.total', 'Total', ' \n仪表盘/', '2022-07-20 03:28:03', 425); @@ -812,7 +812,7 @@ INSERT INTO `sys_i18n` VALUES (1275, 'dashboard.metricPreview.inputTip', 'en', ' INSERT INTO `sys_i18n` VALUES (1276, 'dashboard.explore.wrapLines', 'en', 'dashboard.explore.wrapLines', 'Wrap lines', '个人中心/\n', '2022-07-25 01:47:08', 425); INSERT INTO `sys_i18n` VALUES (1277, 'dashboard.explore.descending', 'en', 'dashboard.explore.descending', 'Descending', ' \n监控/探索/指标/', '2022-07-25 01:48:44', 425); INSERT INTO `sys_i18n` VALUES (1280, 'dashboard.refresh', 'en', 'dashboard.refresh', 'Refresh', '\n告警/告警信息/\n', '2022-07-25 01:50:17', 425); -INSERT INTO `sys_i18n` VALUES (1281, 'dashboard.screen', 'en', 'dashboard.screen', 'Full screen', 'panel/筛选', '2022-07-25 01:53:00', 425); +INSERT INTO `sys_i18n` VALUES (1281, 'dashboard.screen', 'en', 'dashboard.screen', 'Full screen', 'dashboard/筛选', '2022-07-25 01:53:00', 425); INSERT INTO `sys_i18n` VALUES (1285, 'dashboard.metric.normal', 'en', 'dashboard.metric.normal', 'Normal', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1286, 'dashboard.metric.previewChart', 'en', 'dashboard.metric.previewChart', 'Preview', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1287, 'dashboard.metric.expert', 'en', 'dashboard.metric.expert', 'Expert', '', '2021-11-02 00:00:00', 1); @@ -820,102 +820,102 @@ INSERT INTO `sys_i18n` VALUES (1288, 'dashboard.metric.multiChartsShow', 'en', ' INSERT INTO `sys_i18n` VALUES (1289, 'dashboard.metric.singleChartShow', 'en', 'dashboard.metric.singleChartShow', 'Signle chart', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1290, 'dashboard.metric.saveChart', 'en', 'dashboard.metric.saveChart', 'Save chart', '\n监控/应用实例/保存按钮\n', '2022-07-25 01:55:29', 425); INSERT INTO `sys_i18n` VALUES (1292, 'dashboard.metric.addMetric', 'en', 'dashboard.metric.addMetric', 'Add metric', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1295, 'dashboard.metric.selectPanel', 'en', 'dashboard.metric.selectPanel', 'Exist panel', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1296, 'dashboard.metric.saveChartToPanel', 'en', 'dashboard.metric.saveChartToPanel', 'Save chart to panel', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1297, 'dashboard.metric.goPanelTip', 'en', 'dashboard.metric.goPanelTip', 'View created panel?', '\n监控/应用实例/msg提示语句\n', '2022-07-25 02:11:58', 425); +INSERT INTO `sys_i18n` VALUES (1295, 'dashboard.metric.selectDashboard', 'en', 'dashboard.metric.selectDashboard', 'Exist dashboard', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1296, 'dashboard.metric.saveChartToDashboard', 'en', 'dashboard.metric.saveChartToDashboard', 'Save chart to dashboard', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1297, 'dashboard.metric.goDashboardTip', 'en', 'dashboard.metric.goDashboardTip', 'View created dashboard?', '\n监控/应用实例/msg提示语句\n', '2022-07-25 02:11:58', 425); INSERT INTO `sys_i18n` VALUES (1298, 'dashboard.metric.name', 'en', 'dashboard.metric.name', 'Metric name', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1299, 'dashboard.addChartTemp', 'en', 'dashboard.addChartTemp', 'Add chart temp', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1300, 'dashboard.panel.lastThirtyMin', 'en', 'dashboard.panel.lastThirtyMin', 'Last 30 minutes', '\n告警/告警信息/最近时间/最近三十分钟;\npanel/overview/最近时间/最近三十分钟;\n', '2022-07-25 02:20:59', 425); -INSERT INTO `sys_i18n` VALUES (1302, 'dashboard.panel.beforeTwentyFourHour', 'en', 'dashboard.panel.beforeTwentyFourHour', 'Previous 24 hours', ' \n告警/告警信息/最近时间/', '2022-07-25 02:22:36', 425); -INSERT INTO `sys_i18n` VALUES (1304, 'dashboard.panel.editChartTitle', 'en', 'dashboard.panel.editChartTitle', 'Edit chart', 'panel/overview/编辑/修改图表', '2022-07-25 02:18:23', 425); -INSERT INTO `sys_i18n` VALUES (1305, 'dashboard.panel.lastMonth', 'en', 'dashboard.panel.lastMonth', 'Last month', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1306, 'dashboard.panel.lastTwentyFourHour', 'en', 'dashboard.panel.lastTwentyFourHour', 'Last 24 hours', ' panel/overview/最近时间/最近24小时;', '2022-07-25 02:24:13', 425); -INSERT INTO `sys_i18n` VALUES (1307, 'dashboard.panel.lastSevenDay', 'en', 'dashboard.panel.lastSevenDay', 'Last 7 days', 'panel/overview/最近时间/最近7天;', '2022-07-25 02:24:55', 425); -INSERT INTO `sys_i18n` VALUES (1308, 'dashboard.panel.beforeThirtyDay', 'en', 'dashboard.panel.beforeThirtyDay', 'Previous 30 days', ' \npanel/overview/最近时间/最近30天;', '2022-07-25 02:26:19', 425); -INSERT INTO `sys_i18n` VALUES (1309, 'dashboard.panel.selectPanelTitle', 'en', 'dashboard.panel.selectPanelTitle', 'Select', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1310, 'dashboard.panel.beforeOneHour', 'en', 'dashboard.panel.beforeOneHour', 'Previous 1 hour', '\n告警/告警信息/之前1小时\n', '2022-07-25 02:32:07', 425); -INSERT INTO `sys_i18n` VALUES (1312, 'dashboard.panel.beforeFiveMin', 'en', 'dashboard.panel.beforeFiveMin', 'Previous 5 minutes', '告警/告警信息/之前5分钟', '2022-07-25 02:31:43', 425); -INSERT INTO `sys_i18n` VALUES (1313, 'dashboard.panel.recOneMonth', 'en', 'dashboard.panel.recOneMonth', 'Last 1 month', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1314, 'dashboard.panel.lastFifteenMin', 'en', 'dashboard.panel.lastFifteenMin', 'Last 15 minutes', 'panel/最近时间/最近15分钟', '2022-07-25 02:33:13', 425); -INSERT INTO `sys_i18n` VALUES (1315, 'dashboard.panel.moreTitleOther', 'en', 'dashboard.panel.moreTitleOther', 'Showing only 10 the data. ', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1316, 'dashboard.panel.customTimeRange', 'en', 'dashboard.panel.customTimeRange', 'Custom time range', ' \n告警/告警信息/自定义时间区间', '2022-07-25 02:36:23', 425); -INSERT INTO `sys_i18n` VALUES (1317, 'dashboard.panel.lastTwoDay', 'en', 'dashboard.panel.lastTwoDay', 'Last 2 days', ' \npanel/最近时间/最近2天', '2022-07-25 02:37:12', 425); -INSERT INTO `sys_i18n` VALUES (1318, 'dashboard.panel.editPanelTitle', 'en', 'dashboard.panel.editPanelTitle', 'Edit dashboard', 'panel/ \n编辑仪表盘', '2022-07-25 02:38:11', 425); -INSERT INTO `sys_i18n` VALUES (1319, 'dashboard.panel.recFour', 'en', 'dashboard.panel.recFour', 'Last 4 hours', ' \npanel/最近时间/ \n最近4小时', '2022-07-25 02:38:59', 425); -INSERT INTO `sys_i18n` VALUES (1321, 'dashboard.panel.refreshInterval.threeMinutes', 'en', 'dashboard.panel.refreshInterval.threeMinutes', '3 minutes', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1322, 'dashboard.panel.refreshInterval.tenMinutes', 'en', 'dashboard.panel.refreshInterval.tenMinutes', '10 minutes', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1323, 'dashboard.panel.refreshInterval.oneMinute', 'en', 'dashboard.panel.refreshInterval.oneMinute', '1 minute', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1324, 'dashboard.panel.refreshInterval.fiveMinutes', 'en', 'dashboard.panel.refreshInterval.fiveMinutes', '5 minutes', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1325, 'dashboard.panel.beforeTwelveHour', 'en', 'dashboard.panel.beforeTwelveHour', 'Previous 12 hours', '\n告警/告警信息/之前12小时\n', '2022-07-25 06:47:42', 425); -INSERT INTO `sys_i18n` VALUES (1327, 'dashboard.panel.beforeFifteenMin', 'en', 'dashboard.panel.beforeFifteenMin', 'Previous 15 minutes', '告警/告警信息/之前15分钟', '2022-07-25 06:48:51', 425); -INSERT INTO `sys_i18n` VALUES (1328, 'dashboard.panel.lastFiveMin', 'en', 'dashboard.panel.lastFiveMin', 'Last 5 minutes', 'panel/最近时间/ 最近5分钟', '2022-07-25 06:49:54', 425); -INSERT INTO `sys_i18n` VALUES (1329, 'dashboard.panel.createPanelTitleSec', 'en', 'dashboard.panel.createPanelTitleSec', 'New panel', 'panel/新增面板按钮', '2022-07-25 06:50:48', 425); -INSERT INTO `sys_i18n` VALUES (1330, 'dashboard.panel.lastThreeHour', 'en', 'dashboard.panel.lastThreeHour', 'Last 3 hours', ' \npanel/最近时间/ 最近3小时', '2022-07-25 06:52:28', 425); -INSERT INTO `sys_i18n` VALUES (1331, 'dashboard.panel.addChartTemp', 'en', 'dashboard.panel.addChartTemp', 'addChartTemp', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1332, 'dashboard.panel.lastTwelveHour', 'en', 'dashboard.panel.lastTwelveHour', 'Last 12 hours', 'panel/最近时间/ 最近12小时', '2022-07-25 06:53:27', 425); -INSERT INTO `sys_i18n` VALUES (1333, 'dashboard.panel.createPanelTitle', 'en', 'dashboard.panel.createPanelTitle', 'New dashboard', '', '2022-06-14 06:16:50', 1); -INSERT INTO `sys_i18n` VALUES (1334, 'dashboard.panel.singleStatErrorTip', 'en', 'dashboard.panel.singleStatErrorTip', 'Only queries that return single series/table is supported', '系统配置/模板/图表模板/提示语句\n', '2022-07-25 02:51:27', 425); -INSERT INTO `sys_i18n` VALUES (1335, 'dashboard.panel.recSevenDay', 'en', 'dashboard.panel.recSevenDay', 'Last 7 day', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1336, 'dashboard.panel.createChartTempTitle', 'en', 'dashboard.panel.createChartTempTitle', 'New chart template', ' \n系统配置/模板/图表模板/ 新增图表模板', '2022-07-25 02:52:52', 425); -INSERT INTO `sys_i18n` VALUES (1337, 'dashboard.panel.title', 'en', 'dashboard.panel.title', 'Main', 'panel/主面板', '2022-07-25 02:53:51', 425); -INSERT INTO `sys_i18n` VALUES (1338, 'dashboard.panel.yesterday', 'en', 'dashboard.panel.yesterday', 'Yesterday', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1339, 'dashboard.panel.beforeTwoDay', 'en', 'dashboard.panel.beforeTwoDay', 'Previous 2 days', '告警/告警信息/之前2天', '2022-07-25 03:06:01', 425); -INSERT INTO `sys_i18n` VALUES (1340, 'dashboard.panel.showAll', 'en', 'dashboard.panel.showAll', 'Show all ', 'panel/全部显示', '2022-07-25 02:55:40', 425); -INSERT INTO `sys_i18n` VALUES (1341, 'dashboard.panel.chartTotal', 'en', 'dashboard.panel.chartTotal', 'total', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1342, 'dashboard.panel.lastSixHour', 'en', 'dashboard.panel.lastSixHour', 'Last 6 hours', ' \npanel/最近时间/ 最近6小时', '2022-07-25 03:00:50', 425); -INSERT INTO `sys_i18n` VALUES (1344, 'dashboard.panel.beforeThirtyMin', 'en', 'dashboard.panel.beforeThirtyMin', 'Previous 30 minutes', '\n告警/告警信息/之前30分钟\n', '2022-07-25 03:05:26', 425); -INSERT INTO `sys_i18n` VALUES (1345, 'dashboard.panel.beforeSevenDay', 'en', 'dashboard.panel.beforeSevenDay', 'Previous 7 days', ' \n告警/告警信息/之前7天', '2022-07-25 03:06:44', 425); -INSERT INTO `sys_i18n` VALUES (1346, 'dashboard.panel.recOneDay', 'en', 'dashboard.panel.recOneDay', 'Last 1 day', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1347, 'dashboard.panel.curMonth', 'en', 'dashboard.panel.curMonth', 'This month', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1348, 'dashboard.panel.beforeThreeHour', 'en', 'dashboard.panel.beforeThreeHour', 'Previous 3 hours', ' \n告警/告警信息/之前3小时', '2022-07-25 03:07:42', 425); -INSERT INTO `sys_i18n` VALUES (1349, 'dashboard.panel.createChartByTemp', 'en', 'dashboard.panel.createChartByTemp', 'New chart by template', '系统配置/模板/图表模板/通过模板添加图表\n', '2022-07-25 03:08:57', 425); -INSERT INTO `sys_i18n` VALUES (1350, 'dashboard.panel.editChartTempTitle', 'en', 'dashboard.panel.editChartTempTitle', 'Edit chart template', 'panel/修改图表模板标题', '2022-07-25 03:09:43', 425); -INSERT INTO `sys_i18n` VALUES (1357, 'dashboard.panel.beforeSixHour', 'en', 'dashboard.panel.beforeSixHour', 'Previous 6 hours', ' \n告警/告警信息/之前6小时', '2022-07-25 03:10:37', 425); -INSERT INTO `sys_i18n` VALUES (1360, 'dashboard.panel.panelForm.panelName', 'en', 'dashboard.panel.panelForm.panelName', 'Panel name', '表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1361, 'dashboard.panel.moreTitle', 'en', 'dashboard.panel.moreTitle', 'Showing only 20 time series. ', 'panel/按钮title', '2022-07-25 03:11:48', 425); -INSERT INTO `sys_i18n` VALUES (1363, 'dashboard.panel.chartForm.legend', 'en', 'dashboard.panel.chartForm.legend', 'Legend', 'panel/图例', '2022-07-21 07:20:42', 425); -INSERT INTO `sys_i18n` VALUES (1370, 'dashboard.panel.chartForm.valMapping.range', 'en', 'dashboard.panel.chartForm.valMapping.range', 'Range', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1371, 'dashboard.panel.chartForm.valMapping.from', 'en', 'dashboard.panel.chartForm.valMapping.from', 'From', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1375, 'dashboard.panel.chartForm.tooltip', 'en', 'dashboard.panel.chartForm.tooltip', 'Tooltip', 'panel/tooltip', '2022-07-21 07:16:49', 425); -INSERT INTO `sys_i18n` VALUES (1379, 'dashboard.panel.chartForm.aggregation', 'en', 'dashboard.panel.chartForm.aggregation', 'Aggregation', 'panel/聚合', '2022-07-21 07:14:18', 425); -INSERT INTO `sys_i18n` VALUES (1384, 'dashboard.panel.chartForm.content', 'en', 'dashboard.panel.chartForm.content', 'Content', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1386, 'dashboard.panel.chartForm.high', 'en', 'dashboard.panel.chartForm.high', 'Height', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1387, 'dashboard.panel.chartForm.varType', 'en', 'dashboard.panel.chartForm.varType', 'Variable type', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1390, 'dashboard.panel.chartForm.alignList.right', 'en', 'dashboard.panel.chartForm.alignList.right', 'Right', 'chart组件/对齐方式', '2022-07-21 07:06:51', 425); -INSERT INTO `sys_i18n` VALUES (1392, 'dashboard.panel.chartForm.statisticsVal.average', 'en', 'dashboard.panel.chartForm.statisticsVal.average', 'Avg', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1395, 'dashboard.panel.chartForm.statisticsVal.last', 'en', 'dashboard.panel.chartForm.statisticsVal.last', 'Last', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1399, 'dashboard.panel.chartForm.statisticsVal.different', 'en', 'dashboard.panel.chartForm.statisticsVal.different', 'Different', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1400, 'dashboard.panel.chartForm.statisticsVal.first', 'en', 'dashboard.panel.chartForm.statisticsVal.first', 'First', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1402, 'dashboard.panel.chartForm.lock', 'en', 'dashboard.panel.chartForm.lock', 'Lock', '', '2022-07-21 07:01:46', 425); -INSERT INTO `sys_i18n` VALUES (1403, 'dashboard.panel.chartForm.group', 'en', 'dashboard.panel.chartForm.group', 'Group', ' panel/chartType数据;\n表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 425); -INSERT INTO `sys_i18n` VALUES (1404, 'dashboard.panel.chartForm.typeVal.stackArea.label', 'en', 'dashboard.panel.chartForm.typeVal.stackArea.label', 'Area chart', 'panel/chartType数据', '2022-07-21 07:01:50', 425); -INSERT INTO `sys_i18n` VALUES (1405, 'dashboard.panel.chartForm.typeVal.diagram.label', 'en', 'dashboard.panel.chartForm.typeVal.diagram.label', 'Diagram', 'panel/chartTypeList数据', '2022-07-21 07:00:08', 425); -INSERT INTO `sys_i18n` VALUES (1406, 'dashboard.panel.chartForm.typeVal.bar.label', 'en', 'dashboard.panel.chartForm.typeVal.bar.label', 'Bar Chart', 'panel/chartType数据', '2022-07-21 06:59:48', 425); -INSERT INTO `sys_i18n` VALUES (1407, 'dashboard.panel.chartForm.typeVal.line.label', 'en', 'dashboard.panel.chartForm.typeVal.line.label', 'Line Chart', ' panel/chartType数据', '2022-07-21 06:59:55', 425); -INSERT INTO `sys_i18n` VALUES (1408, 'dashboard.panel.chartForm.typeVal.singleStat.label', 'en', 'dashboard.panel.chartForm.typeVal.singleStat.label', 'Stat', 'panel/chartType数据', '2022-07-21 06:59:59', 425); -INSERT INTO `sys_i18n` VALUES (1409, 'dashboard.panel.chartForm.typeVal.alertList.label', 'en', 'dashboard.panel.chartForm.typeVal.alertList.label', 'Alert list', '全局搜索组件/chartType数据', '2022-07-21 06:51:47', 425); -INSERT INTO `sys_i18n` VALUES (1410, 'dashboard.panel.chartForm.typeVal.text.label', 'en', 'dashboard.panel.chartForm.typeVal.text.label', 'Text', '全局搜索组件/chartType数据', '2022-07-21 06:50:56', 425); -INSERT INTO `sys_i18n` VALUES (1411, 'dashboard.panel.chartForm.typeVal.pie.label', 'en', 'dashboard.panel.chartForm.typeVal.pie.label', 'Pie Chart', ' \n全局搜索组件/chartType数据', '2022-07-21 06:51:13', 425); -INSERT INTO `sys_i18n` VALUES (1413, 'dashboard.panel.chartForm.typeVal.table.label', 'en', 'dashboard.panel.chartForm.typeVal.table.label', 'Table', '监控/探索/表格\n', '2022-07-21 06:43:57', 425); -INSERT INTO `sys_i18n` VALUES (1414, 'dashboard.panel.chartForm.typeVal.url.staticTip', 'en', 'dashboard.panel.chartForm.typeVal.url.staticTip', 'The content in the double curly braces will be replaced on the Asset page', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1417, 'dashboard.panel.chartForm.legendTip', 'en', 'dashboard.panel.chartForm.legendTip', 'Controls the name of the time series, using name or pattern. For example {{hostname}} will be replaced with label value for the label hostname.', '系统配置/模板/图表模板/名称\n', '2022-07-21 06:41:16', 425); -INSERT INTO `sys_i18n` VALUES (1418, 'dashboard.panel.chartForm.lockList.off', 'en', 'dashboard.panel.chartForm.lockList.off', 'OFF', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1419, 'dashboard.panel.chartForm.lockList.on', 'en', 'dashboard.panel.chartForm.lockList.on', 'ON', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1421, 'dashboard.panel.chartForm.selectAsset', 'en', 'dashboard.panel.chartForm.selectAsset', 'Please select the Asset', 'web-ssh/plshoder提示语句', '2022-07-21 06:37:20', 425); -INSERT INTO `sys_i18n` VALUES (1422, 'dashboard.panel.chartForm.sync', 'en', 'dashboard.panel.chartForm.sync', 'Sync to assets', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1423, 'dashboard.panel.chartForm.url', 'en', 'dashboard.panel.chartForm.url', 'URL', '搜索框组件/chartType数据', '2022-07-21 06:33:58', 425); -INSERT INTO `sys_i18n` VALUES (1424, 'dashboard.panel.chartForm.unit', 'en', 'dashboard.panel.chartForm.unit', 'Unit', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1425, 'dashboard.panel.chartForm.thresholds', 'en', 'dashboard.panel.chartForm.thresholds', 'Thresholds', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1427, 'dashboard.panel.chartForm.legendValue', 'en', 'dashboard.panel.chartForm.legendValue', 'Legend option', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1428, 'dashboard.panel.chartForm.valueMappingTip', 'en', 'dashboard.panel.chartForm.valueMappingTip', 'Use {{name}} and {{value}} to display the original name and value\nFor example: Total Alive: {{value}}\nThe result is: Total Alive: 100', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1431, 'dashboard.panel.chartForm.width', 'en', 'dashboard.panel.chartForm.width', 'Width', 'panel/修改图表/显示配置/宽;\n表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (1432, 'dashboard.panel.chartForm.selectEndpoint', 'en', 'dashboard.panel.chartForm.selectEndpoint', 'Please select the Endpoint', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1434, 'dashboard.panel.chartForm.collapse', 'en', 'dashboard.panel.chartForm.collapse', 'Default collapse', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1435, 'dashboard.panel.chartForm.statistics', 'en', 'dashboard.panel.chartForm.statistics', 'Statistics', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1439, 'dashboard.panel.to', 'en', 'dashboard.panel.to', 'to', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1440, 'dashboard.panel.lastOneHour', 'en', 'dashboard.panel.lastOneHour', 'Last 1 hour', ' \npanel/最近时间/最近1小时', '2022-07-25 03:27:03', 425); -INSERT INTO `sys_i18n` VALUES (1441, 'dashboard.panel.noDate', 'en', 'dashboard.panel.noDate', 'All time', ' \npanel/全部时间;\n监控/应用实例/全部时间\n', '2022-07-25 03:25:38', 425); -INSERT INTO `sys_i18n` VALUES (1442, 'dashboard.panel.lastThirtyDay', 'en', 'dashboard.panel.lastThirtyDay', 'Last 30 days', 'panel/最近时间/最近30天', '2022-07-25 03:27:24', 425); +INSERT INTO `sys_i18n` VALUES (1300, 'dashboard.dashboard.lastThirtyMin', 'en', 'dashboard.dashboard.lastThirtyMin', 'Last 30 minutes', '\n告警/告警信息/最近时间/最近三十分钟;\ndashboard/overview/最近时间/最近三十分钟;\n', '2022-07-25 02:20:59', 425); +INSERT INTO `sys_i18n` VALUES (1302, 'dashboard.dashboard.beforeTwentyFourHour', 'en', 'dashboard.dashboard.beforeTwentyFourHour', 'Previous 24 hours', ' \n告警/告警信息/最近时间/', '2022-07-25 02:22:36', 425); +INSERT INTO `sys_i18n` VALUES (1304, 'dashboard.dashboard.editChartTitle', 'en', 'dashboard.dashboard.editChartTitle', 'Edit chart', 'dashboard/overview/编辑/修改图表', '2022-07-25 02:18:23', 425); +INSERT INTO `sys_i18n` VALUES (1305, 'dashboard.dashboard.lastMonth', 'en', 'dashboard.dashboard.lastMonth', 'Last month', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1306, 'dashboard.dashboard.lastTwentyFourHour', 'en', 'dashboard.dashboard.lastTwentyFourHour', 'Last 24 hours', ' dashboard/overview/最近时间/最近24小时;', '2022-07-25 02:24:13', 425); +INSERT INTO `sys_i18n` VALUES (1307, 'dashboard.dashboard.lastSevenDay', 'en', 'dashboard.dashboard.lastSevenDay', 'Last 7 days', 'dashboard/overview/最近时间/最近7天;', '2022-07-25 02:24:55', 425); +INSERT INTO `sys_i18n` VALUES (1308, 'dashboard.dashboard.beforeThirtyDay', 'en', 'dashboard.dashboard.beforeThirtyDay', 'Previous 30 days', ' \ndashboard/overview/最近时间/最近30天;', '2022-07-25 02:26:19', 425); +INSERT INTO `sys_i18n` VALUES (1309, 'dashboard.dashboard.selectDashboardTitle', 'en', 'dashboard.dashboard.selectDashboardTitle', 'Select', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1310, 'dashboard.dashboard.beforeOneHour', 'en', 'dashboard.dashboard.beforeOneHour', 'Previous 1 hour', '\n告警/告警信息/之前1小时\n', '2022-07-25 02:32:07', 425); +INSERT INTO `sys_i18n` VALUES (1312, 'dashboard.dashboard.beforeFiveMin', 'en', 'dashboard.dashboard.beforeFiveMin', 'Previous 5 minutes', '告警/告警信息/之前5分钟', '2022-07-25 02:31:43', 425); +INSERT INTO `sys_i18n` VALUES (1313, 'dashboard.dashboard.recOneMonth', 'en', 'dashboard.dashboard.recOneMonth', 'Last 1 month', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1314, 'dashboard.dashboard.lastFifteenMin', 'en', 'dashboard.dashboard.lastFifteenMin', 'Last 15 minutes', 'dashboard/最近时间/最近15分钟', '2022-07-25 02:33:13', 425); +INSERT INTO `sys_i18n` VALUES (1315, 'dashboard.dashboard.moreTitleOther', 'en', 'dashboard.dashboard.moreTitleOther', 'Showing only 10 the data. ', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1316, 'dashboard.dashboard.customTimeRange', 'en', 'dashboard.dashboard.customTimeRange', 'Custom time range', ' \n告警/告警信息/自定义时间区间', '2022-07-25 02:36:23', 425); +INSERT INTO `sys_i18n` VALUES (1317, 'dashboard.dashboard.lastTwoDay', 'en', 'dashboard.dashboard.lastTwoDay', 'Last 2 days', ' \ndashboard/最近时间/最近2天', '2022-07-25 02:37:12', 425); +INSERT INTO `sys_i18n` VALUES (1318, 'dashboard.dashboard.editDashboardTitle', 'en', 'dashboard.dashboard.editDashboardTitle', 'Edit dashboard', 'dashboard/ \n编辑仪表盘', '2022-07-25 02:38:11', 425); +INSERT INTO `sys_i18n` VALUES (1319, 'dashboard.dashboard.recFour', 'en', 'dashboard.dashboard.recFour', 'Last 4 hours', ' \ndashboard/最近时间/ \n最近4小时', '2022-07-25 02:38:59', 425); +INSERT INTO `sys_i18n` VALUES (1321, 'dashboard.dashboard.refreshInterval.threeMinutes', 'en', 'dashboard.dashboard.refreshInterval.threeMinutes', '3 minutes', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1322, 'dashboard.dashboard.refreshInterval.tenMinutes', 'en', 'dashboard.dashboard.refreshInterval.tenMinutes', '10 minutes', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1323, 'dashboard.dashboard.refreshInterval.oneMinute', 'en', 'dashboard.dashboard.refreshInterval.oneMinute', '1 minute', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1324, 'dashboard.dashboard.refreshInterval.fiveMinutes', 'en', 'dashboard.dashboard.refreshInterval.fiveMinutes', '5 minutes', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1325, 'dashboard.dashboard.beforeTwelveHour', 'en', 'dashboard.dashboard.beforeTwelveHour', 'Previous 12 hours', '\n告警/告警信息/之前12小时\n', '2022-07-25 06:47:42', 425); +INSERT INTO `sys_i18n` VALUES (1327, 'dashboard.dashboard.beforeFifteenMin', 'en', 'dashboard.dashboard.beforeFifteenMin', 'Previous 15 minutes', '告警/告警信息/之前15分钟', '2022-07-25 06:48:51', 425); +INSERT INTO `sys_i18n` VALUES (1328, 'dashboard.dashboard.lastFiveMin', 'en', 'dashboard.dashboard.lastFiveMin', 'Last 5 minutes', 'dashboard/最近时间/ 最近5分钟', '2022-07-25 06:49:54', 425); +INSERT INTO `sys_i18n` VALUES (1329, 'dashboard.dashboard.createDashboardTitleSec', 'en', 'dashboard.dashboard.createDashboardTitleSec', 'New dashboard', 'dashboard/新增面板按钮', '2022-07-25 06:50:48', 425); +INSERT INTO `sys_i18n` VALUES (1330, 'dashboard.dashboard.lastThreeHour', 'en', 'dashboard.dashboard.lastThreeHour', 'Last 3 hours', ' \ndashboard/最近时间/ 最近3小时', '2022-07-25 06:52:28', 425); +INSERT INTO `sys_i18n` VALUES (1331, 'dashboard.dashboard.addChartTemp', 'en', 'dashboard.dashboard.addChartTemp', 'addChartTemp', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1332, 'dashboard.dashboard.lastTwelveHour', 'en', 'dashboard.dashboard.lastTwelveHour', 'Last 12 hours', 'dashboard/最近时间/ 最近12小时', '2022-07-25 06:53:27', 425); +INSERT INTO `sys_i18n` VALUES (1333, 'dashboard.dashboard.createDashboardTitle', 'en', 'dashboard.dashboard.createDashboardTitle', 'New dashboard', '', '2022-06-14 06:16:50', 1); +INSERT INTO `sys_i18n` VALUES (1334, 'dashboard.dashboard.singleStatErrorTip', 'en', 'dashboard.dashboard.singleStatErrorTip', 'Only queries that return single series/table is supported', '系统配置/模板/图表模板/提示语句\n', '2022-07-25 02:51:27', 425); +INSERT INTO `sys_i18n` VALUES (1335, 'dashboard.dashboard.recSevenDay', 'en', 'dashboard.dashboard.recSevenDay', 'Last 7 day', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1336, 'dashboard.dashboard.createChartTempTitle', 'en', 'dashboard.dashboard.createChartTempTitle', 'New chart template', ' \n系统配置/模板/图表模板/ 新增图表模板', '2022-07-25 02:52:52', 425); +INSERT INTO `sys_i18n` VALUES (1337, 'dashboard.dashboard.title', 'en', 'dashboard.dashboard.title', 'Main', 'dashboard/主面板', '2022-07-25 02:53:51', 425); +INSERT INTO `sys_i18n` VALUES (1338, 'dashboard.dashboard.yesterday', 'en', 'dashboard.dashboard.yesterday', 'Yesterday', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1339, 'dashboard.dashboard.beforeTwoDay', 'en', 'dashboard.dashboard.beforeTwoDay', 'Previous 2 days', '告警/告警信息/之前2天', '2022-07-25 03:06:01', 425); +INSERT INTO `sys_i18n` VALUES (1340, 'dashboard.dashboard.showAll', 'en', 'dashboard.dashboard.showAll', 'Show all ', 'dashboard/全部显示', '2022-07-25 02:55:40', 425); +INSERT INTO `sys_i18n` VALUES (1341, 'dashboard.dashboard.chartTotal', 'en', 'dashboard.dashboard.chartTotal', 'Total', '', '2022-12-13 03:33:10', 415); +INSERT INTO `sys_i18n` VALUES (1342, 'dashboard.dashboard.lastSixHour', 'en', 'dashboard.dashboard.lastSixHour', 'Last 6 hours', ' \ndashboard/最近时间/ 最近6小时', '2022-07-25 03:00:50', 425); +INSERT INTO `sys_i18n` VALUES (1344, 'dashboard.dashboard.beforeThirtyMin', 'en', 'dashboard.dashboard.beforeThirtyMin', 'Previous 30 minutes', '\n告警/告警信息/之前30分钟\n', '2022-07-25 03:05:26', 425); +INSERT INTO `sys_i18n` VALUES (1345, 'dashboard.dashboard.beforeSevenDay', 'en', 'dashboard.dashboard.beforeSevenDay', 'Previous 7 days', ' \n告警/告警信息/之前7天', '2022-07-25 03:06:44', 425); +INSERT INTO `sys_i18n` VALUES (1346, 'dashboard.dashboard.recOneDay', 'en', 'dashboard.dashboard.recOneDay', 'Last 1 day', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1347, 'dashboard.dashboard.curMonth', 'en', 'dashboard.dashboard.curMonth', 'This month', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1348, 'dashboard.dashboard.beforeThreeHour', 'en', 'dashboard.dashboard.beforeThreeHour', 'Previous 3 hours', ' \n告警/告警信息/之前3小时', '2022-07-25 03:07:42', 425); +INSERT INTO `sys_i18n` VALUES (1349, 'dashboard.dashboard.createChartByTemp', 'en', 'dashboard.dashboard.createChartByTemp', 'New chart by template', '系统配置/模板/图表模板/通过模板添加图表\n', '2022-07-25 03:08:57', 425); +INSERT INTO `sys_i18n` VALUES (1350, 'dashboard.dashboard.editChartTempTitle', 'en', 'dashboard.dashboard.editChartTempTitle', 'Edit chart template', 'dashboard/修改图表模板标题', '2022-07-25 03:09:43', 425); +INSERT INTO `sys_i18n` VALUES (1357, 'dashboard.dashboard.beforeSixHour', 'en', 'dashboard.dashboard.beforeSixHour', 'Previous 6 hours', ' \n告警/告警信息/之前6小时', '2022-07-25 03:10:37', 425); +INSERT INTO `sys_i18n` VALUES (1360, 'dashboard.dashboard.dashboardForm.dashboardName', 'en', 'dashboard.dashboard.dashboardForm.dashboardName', 'Dashboard name', '表头->dashboard dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1361, 'dashboard.dashboard.moreTitle', 'en', 'dashboard.dashboard.moreTitle', 'Showing only 20 time series. ', 'dashboard/按钮title', '2022-07-25 03:11:48', 425); +INSERT INTO `sys_i18n` VALUES (1363, 'dashboard.dashboard.chartForm.legend', 'en', 'dashboard.dashboard.chartForm.legend', 'Legend', 'dashboard/图例', '2022-07-21 07:20:42', 425); +INSERT INTO `sys_i18n` VALUES (1370, 'dashboard.dashboard.chartForm.valMapping.range', 'en', 'dashboard.dashboard.chartForm.valMapping.range', 'Range', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1371, 'dashboard.dashboard.chartForm.valMapping.from', 'en', 'dashboard.dashboard.chartForm.valMapping.from', 'From', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1375, 'dashboard.dashboard.chartForm.tooltip', 'en', 'dashboard.dashboard.chartForm.tooltip', 'Tooltip', 'dashboard/tooltip', '2022-07-21 07:16:49', 425); +INSERT INTO `sys_i18n` VALUES (1379, 'dashboard.dashboard.chartForm.aggregation', 'en', 'dashboard.dashboard.chartForm.aggregation', 'Aggregation', 'dashboard/聚合', '2022-07-21 07:14:18', 425); +INSERT INTO `sys_i18n` VALUES (1384, 'dashboard.dashboard.chartForm.content', 'en', 'dashboard.dashboard.chartForm.content', 'Content', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1386, 'dashboard.dashboard.chartForm.high', 'en', 'dashboard.dashboard.chartForm.high', 'Height', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1387, 'dashboard.dashboard.chartForm.varType', 'en', 'dashboard.dashboard.chartForm.varType', 'Variable type', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1390, 'dashboard.dashboard.chartForm.alignList.right', 'en', 'dashboard.dashboard.chartForm.alignList.right', 'Right', 'chart组件/对齐方式', '2022-07-21 07:06:51', 425); +INSERT INTO `sys_i18n` VALUES (1392, 'dashboard.dashboard.chartForm.statisticsVal.average', 'en', 'dashboard.dashboard.chartForm.statisticsVal.average', 'Avg', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1395, 'dashboard.dashboard.chartForm.statisticsVal.last', 'en', 'dashboard.dashboard.chartForm.statisticsVal.last', 'Last', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1399, 'dashboard.dashboard.chartForm.statisticsVal.different', 'en', 'dashboard.dashboard.chartForm.statisticsVal.different', 'Different', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1400, 'dashboard.dashboard.chartForm.statisticsVal.first', 'en', 'dashboard.dashboard.chartForm.statisticsVal.first', 'First', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1402, 'dashboard.dashboard.chartForm.lock', 'en', 'dashboard.dashboard.chartForm.lock', 'Lock', '', '2022-07-21 07:01:46', 425); +INSERT INTO `sys_i18n` VALUES (1403, 'dashboard.dashboard.chartForm.group', 'en', 'dashboard.dashboard.chartForm.group', 'Group', ' dashboard/chartType数据;\n表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (1404, 'dashboard.dashboard.chartForm.typeVal.stackArea.label', 'en', 'dashboard.dashboard.chartForm.typeVal.stackArea.label', 'Area chart', 'dashboard/chartType数据', '2022-07-21 07:01:50', 425); +INSERT INTO `sys_i18n` VALUES (1405, 'dashboard.dashboard.chartForm.typeVal.diagram.label', 'en', 'dashboard.dashboard.chartForm.typeVal.diagram.label', 'Diagram', 'dashboard/chartTypeList数据', '2022-07-21 07:00:08', 425); +INSERT INTO `sys_i18n` VALUES (1406, 'dashboard.dashboard.chartForm.typeVal.bar.label', 'en', 'dashboard.dashboard.chartForm.typeVal.bar.label', 'Bar chart', 'dashboard/chartType数据', '2022-12-13 03:25:42', 415); +INSERT INTO `sys_i18n` VALUES (1407, 'dashboard.dashboard.chartForm.typeVal.line.label', 'en', 'dashboard.dashboard.chartForm.typeVal.line.label', 'Line chart', 'dashboard/chartType数据', '2022-12-13 03:25:10', 415); +INSERT INTO `sys_i18n` VALUES (1408, 'dashboard.dashboard.chartForm.typeVal.singleStat.label', 'en', 'dashboard.dashboard.chartForm.typeVal.singleStat.label', 'Stat', 'dashboard/chartType数据', '2022-07-21 06:59:59', 425); +INSERT INTO `sys_i18n` VALUES (1409, 'dashboard.dashboard.chartForm.typeVal.alertList.label', 'en', 'dashboard.dashboard.chartForm.typeVal.alertList.label', 'Alert list', '全局搜索组件/chartType数据', '2022-07-21 06:51:47', 425); +INSERT INTO `sys_i18n` VALUES (1410, 'dashboard.dashboard.chartForm.typeVal.text.label', 'en', 'dashboard.dashboard.chartForm.typeVal.text.label', 'Text', '全局搜索组件/chartType数据', '2022-07-21 06:50:56', 425); +INSERT INTO `sys_i18n` VALUES (1411, 'dashboard.dashboard.chartForm.typeVal.pie.label', 'en', 'dashboard.dashboard.chartForm.typeVal.pie.label', 'Pie chart', '全局搜索组件/chartType数据', '2022-12-13 03:26:07', 415); +INSERT INTO `sys_i18n` VALUES (1413, 'dashboard.dashboard.chartForm.typeVal.table.label', 'en', 'dashboard.dashboard.chartForm.typeVal.table.label', 'Table', '监控/探索/表格\n', '2022-07-21 06:43:57', 425); +INSERT INTO `sys_i18n` VALUES (1414, 'dashboard.dashboard.chartForm.typeVal.url.staticTip', 'en', 'dashboard.dashboard.chartForm.typeVal.url.staticTip', 'The content in the double curly braces will be replaced on the Asset page', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1417, 'dashboard.dashboard.chartForm.legendTip', 'en', 'dashboard.dashboard.chartForm.legendTip', 'Controls the name of the time series, using name or pattern. For example {{hostname}} will be replaced with label value for the label hostname.', '系统配置/模板/图表模板/名称\n', '2022-07-21 06:41:16', 425); +INSERT INTO `sys_i18n` VALUES (1418, 'dashboard.dashboard.chartForm.lockList.off', 'en', 'dashboard.dashboard.chartForm.lockList.off', 'OFF', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1419, 'dashboard.dashboard.chartForm.lockList.on', 'en', 'dashboard.dashboard.chartForm.lockList.on', 'ON', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1421, 'dashboard.dashboard.chartForm.selectAsset', 'en', 'dashboard.dashboard.chartForm.selectAsset', 'Please select the Asset', 'web-ssh/plshoder提示语句', '2022-07-21 06:37:20', 425); +INSERT INTO `sys_i18n` VALUES (1422, 'dashboard.dashboard.chartForm.sync', 'en', 'dashboard.dashboard.chartForm.sync', 'Sync to assets', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1423, 'dashboard.dashboard.chartForm.url', 'en', 'dashboard.dashboard.chartForm.url', 'URL', '搜索框组件/chartType数据', '2022-07-21 06:33:58', 425); +INSERT INTO `sys_i18n` VALUES (1424, 'dashboard.dashboard.chartForm.unit', 'en', 'dashboard.dashboard.chartForm.unit', 'Unit', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1425, 'dashboard.dashboard.chartForm.thresholds', 'en', 'dashboard.dashboard.chartForm.thresholds', 'Thresholds', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1427, 'dashboard.dashboard.chartForm.legendValue', 'en', 'dashboard.dashboard.chartForm.legendValue', 'Legend option', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1428, 'dashboard.dashboard.chartForm.valueMappingTip', 'en', 'dashboard.dashboard.chartForm.valueMappingTip', 'Use {{name}} and {{value}} to display the original name and value\nFor example: Total Alive: {{value}}\nThe result is: Total Alive: 100', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1431, 'dashboard.dashboard.chartForm.width', 'en', 'dashboard.dashboard.chartForm.width', 'Width', 'dashboard/修改图表/显示配置/宽;\n表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1432, 'dashboard.dashboard.chartForm.selectEndpoint', 'en', 'dashboard.dashboard.chartForm.selectEndpoint', 'Please select the Endpoint', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1434, 'dashboard.dashboard.chartForm.collapse', 'en', 'dashboard.dashboard.chartForm.collapse', 'Default collapse', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1435, 'dashboard.dashboard.chartForm.statistics', 'en', 'dashboard.dashboard.chartForm.statistics', 'Statistics', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1439, 'dashboard.dashboard.to', 'en', 'dashboard.dashboard.to', 'to', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1440, 'dashboard.dashboard.lastOneHour', 'en', 'dashboard.dashboard.lastOneHour', 'Last 1 hour', ' \ndashboard/最近时间/最近1小时', '2022-07-25 03:27:03', 425); +INSERT INTO `sys_i18n` VALUES (1441, 'dashboard.dashboard.noDate', 'en', 'dashboard.dashboard.noDate', 'All time', ' \ndashboard/全部时间;\n监控/应用实例/全部时间\n', '2022-07-25 03:25:38', 425); +INSERT INTO `sys_i18n` VALUES (1442, 'dashboard.dashboard.lastThirtyDay', 'en', 'dashboard.dashboard.lastThirtyDay', 'Last 30 days', 'dashboard/最近时间/最近30天', '2022-07-25 03:27:24', 425); INSERT INTO `sys_i18n` VALUES (1444, 'guide.agent', 'en', 'guide.agent', 'Agents', '系统配置/客户端/客户端\n', '2022-07-11 08:13:50', 415); INSERT INTO `sys_i18n` VALUES (1445, 'guide.visualization', 'en', 'guide.visualization', 'Visualization', 'header/guide/可视化', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1447, 'guide.monitorTip', 'en', 'guide.monitorTip', 'Help user to monitor components and contents based on project requirement', 'header/guide/tip', '2022-07-25 03:35:07', 425); @@ -928,7 +928,7 @@ INSERT INTO `sys_i18n` VALUES (1459, 'guide.importEndpoint', 'en', 'guide.import INSERT INTO `sys_i18n` VALUES (1460, 'guide.addEndpoint', 'en', 'guide.addEndpoint', 'New endpoint', 'header/guide/新增', '2022-07-25 03:40:10', 425); INSERT INTO `sys_i18n` VALUES (1461, 'guide.importAsset', 'en', 'guide.importAsset', 'Import asset', '资产/资产列表/更多/导入\n', '2022-07-25 03:41:38', 425); INSERT INTO `sys_i18n` VALUES (1462, 'guide.downloadAgent', 'en', 'guide.downloadAgent', 'Download agent', 'header/guide/按钮;\n系统配置/客户端/下载客户端\n', '2022-07-25 03:43:23', 425); -INSERT INTO `sys_i18n` VALUES (1465, 'guide.visualizationTip', 'en', 'guide.visualizationTip', 'Panels consist of different sets of customized charts. You can create several panels and switch between them.', 'header/guide/tip', '2022-07-25 03:44:03', 425); +INSERT INTO `sys_i18n` VALUES (1465, 'guide.visualizationTip', 'en', 'guide.visualizationTip', 'Dashboards consist of different sets of customized charts. You can create several dashboards and switch between them.', 'header/guide/tip', '2022-07-25 03:44:03', 425); INSERT INTO `sys_i18n` VALUES (1466, 'guide.dcTip', 'en', 'guide.dcTip', 'Data center associated with Prometheus servers contains cabinets and assets; cabinet is a container for assets.', 'header/guide/tip', '2022-07-25 03:44:29', 425); INSERT INTO `sys_i18n` VALUES (1472, 'validate.telephone', 'en', 'validate.telephone', 'Phone number cannot be empty', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1473, 'validate.integer', 'en', 'validate.integer', 'Must be integer', '', '2022-06-21 08:24:53', 1); @@ -944,24 +944,24 @@ INSERT INTO `sys_i18n` VALUES (1483, 'validate.port', 'en', 'validate.port', 'In INSERT INTO `sys_i18n` VALUES (1484, 'validate.positiveInteger', 'en', 'validate.positiveInteger', 'Positive integer', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1485, 'validate.domain', 'en', 'validate.domain', 'Invalid domain', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1486, 'validate.repeat', 'en', 'validate.repeat', 'Repeat', '资产/数据中心/复制;\n', '2022-07-25 09:05:03', 425); -INSERT INTO `sys_i18n` VALUES (1487, 'validate.host', 'en', 'validate.host', 'Invalid Host', '工具箱/Ping/\n', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1487, 'validate.host', 'en', 'validate.host', 'Invalid host', '工具箱/Ping/', '2022-12-14 09:31:26', 415); INSERT INTO `sys_i18n` VALUES (1488, 'validate.tel', 'en', 'validate.tel', 'Invalid phone number', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1489, 'validate.onlyWord', 'en', 'validate.onlyWord', 'only input a-z、A-Z、0-9、\"_\" ', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1490, 'validate.email', 'en', 'validate.email', 'Invalid email', '管理/用户/;\n系统配置/个性化配置/;\n\n', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1491, 'validate.key', 'en', 'validate.key', 'Invalid key', '仪表盘/Overview/\n', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1492, 'date.week.six', 'zh', 'date.week.six', '星期六', ' \npanel/header 时间处理/', '2022-07-25 05:57:16', 425); -INSERT INTO `sys_i18n` VALUES (1493, 'date.week.four', 'zh', 'date.week.four', '星期四', ' \npanel/header 时间处理/', '2022-07-25 05:57:46', 425); -INSERT INTO `sys_i18n` VALUES (1494, 'date.week.one', 'zh', 'date.week.one', '星期一', 'panel/header 时间处理/', '2022-07-25 05:58:11', 425); -INSERT INTO `sys_i18n` VALUES (1495, 'date.week.seven', 'zh', 'date.week.seven', '星期日', ' \npanel/header 时间处理/', '2022-07-25 05:58:53', 425); -INSERT INTO `sys_i18n` VALUES (1496, 'date.week.two', 'zh', 'date.week.two', '星期二', ' \npanel/header 时间处理/', '2022-07-25 05:59:16', 425); -INSERT INTO `sys_i18n` VALUES (1497, 'date.week.three', 'zh', 'date.week.three', '星期三', 'panel/header 时间处理/', '2022-07-25 05:59:44', 425); -INSERT INTO `sys_i18n` VALUES (1498, 'date.week.five', 'zh', 'date.week.five', '星期五', ' \npanel/header 时间处理/', '2022-07-25 06:00:24', 425); +INSERT INTO `sys_i18n` VALUES (1492, 'date.week.six', 'zh', 'date.week.six', '星期六', ' \ndashboard/header 时间处理/', '2022-07-25 05:57:16', 425); +INSERT INTO `sys_i18n` VALUES (1493, 'date.week.four', 'zh', 'date.week.four', '星期四', ' \ndashboard/header 时间处理/', '2022-07-25 05:57:46', 425); +INSERT INTO `sys_i18n` VALUES (1494, 'date.week.one', 'zh', 'date.week.one', '星期一', 'dashboard/header 时间处理/', '2022-07-25 05:58:11', 425); +INSERT INTO `sys_i18n` VALUES (1495, 'date.week.seven', 'zh', 'date.week.seven', '星期日', ' \ndashboard/header 时间处理/', '2022-07-25 05:58:53', 425); +INSERT INTO `sys_i18n` VALUES (1496, 'date.week.two', 'zh', 'date.week.two', '星期二', ' \ndashboard/header 时间处理/', '2022-07-25 05:59:16', 425); +INSERT INTO `sys_i18n` VALUES (1497, 'date.week.three', 'zh', 'date.week.three', '星期三', 'dashboard/header 时间处理/', '2022-07-25 05:59:44', 425); +INSERT INTO `sys_i18n` VALUES (1498, 'date.week.five', 'zh', 'date.week.five', '星期五', ' \ndashboard/header 时间处理/', '2022-07-25 06:00:24', 425); INSERT INTO `sys_i18n` VALUES (1499, 'buttons.add', 'zh', 'buttons.add', '新增', '监控/应用/新增按钮;\n仪表盘/新增按钮;\n管理/用户/新增按钮;\n管理/角色/新增按钮;\n系统配置/客户端/新增按钮;\n系统配置/PAM/新增按钮;\n系统配置/导航/新增按钮;\n告警/告警规则/新增按钮;\n告警/告警静默/新增按钮;\n系统配置/通知配置/自定义通知方式/新增按钮;', '2022-07-26 03:04:11', 425); INSERT INTO `sys_i18n` VALUES (1505, 'buttons.system.ldap', 'zh', 'buttons.system.ldap', 'LDAP配置', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1506, 'buttons.system.terminal', 'zh', 'buttons.system.terminal', '终端配置', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1508, 'buttons.system.email', 'zh', 'buttons.system.email', '邮件服务器', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1515, 'buttons.terminalLog.kill', 'zh', 'buttons.terminalLog.kill', 'Kill', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1521, 'buttons.panel.deleteChart', 'zh', 'buttons.panel.deleteChart', '删除图表', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (1521, 'buttons.dashboard.deleteChart', 'zh', 'buttons.dashboard.deleteChart', '删除图表', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1527, 'week.Thu', 'zh', 'week.Thu', '周四', '告警/告警规则/修改告警规则/有效时间/一周/; 管理/备份/编辑备份配置/每周/一周/;', '2022-07-21 06:17:55', 425); INSERT INTO `sys_i18n` VALUES (1528, 'week.SunAbbreviation', 'zh', 'week.SunAbbreviation', '周日', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1529, 'week.Tue', 'zh', 'week.Tue', '周二', ' \n告警/告警规则/修改告警规则/有效时间/一周/; 管理/备份/编辑备份配置/每周/一周/;', '2022-07-21 06:18:30', 425); @@ -1156,7 +1156,7 @@ INSERT INTO `sys_i18n` VALUES (1807, 'project.topology.line', 'zh', 'project.top INSERT INTO `sys_i18n` VALUES (1809, 'project.topology.toArrow', 'zh', 'project.topology.toArrow', '终点箭头', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1810, 'project.topology.rule', 'zh', 'project.topology.rule', '标尺', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1811, 'project.topology.paste', 'zh', 'project.topology.paste', '粘贴', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (1812, 'project.topology.title', 'zh', 'project.topology.title', '标题', '监控/应用组/画布属性标题;\n\n表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (1812, 'project.topology.title', 'zh', 'project.topology.title', '标题', '监控/应用组/画布属性标题;\n\n表头->dashboard dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (1813, 'project.topology.maxCount', 'zh', 'project.topology.maxCount', '水平个数', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1815, 'project.topology.animationType', 'zh', 'project.topology.animationType', '动画类型', '监控/应用组/画布属性', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (1817, 'project.topology.alert', 'zh', 'project.topology.alert', '告警信息', '告警/告警信息/告警信息; 资产/资产列表/告警; 监控/应用实例/告警;', '2022-07-21 06:13:29', 425); @@ -1268,11 +1268,11 @@ INSERT INTO `sys_i18n` VALUES (2001, 'overall.createRole', 'zh', 'overall.create INSERT INTO `sys_i18n` VALUES (2002, 'overall.tempPrev', 'zh', 'overall.tempPrev', '模板预览', '仪表盘/模板预览', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2003, 'overall.createProject', 'zh', 'overall.createProject', '新增系统', '监控/应用/应用实例/新增系统', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2004, 'overall.createPrometheusServer', 'zh', 'overall.createPrometheusServer', '新增客户端', ' \n系统配置/客户端/新增客户端;', '2022-06-21 08:28:30', 1); -INSERT INTO `sys_i18n` VALUES (2005, 'overall.type', 'zh', 'overall.type', '类型', '仪表盘/类型;\n系统配置/个性化配置/类型;\n表头->告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导出/导入/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (2005, 'overall.type', 'zh', 'overall.type', '类型', '仪表盘/类型;\n系统配置/个性化配置/类型;\n表头->告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导出/导入/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (2007, 'overall.cover', 'zh', 'overall.cover', '覆盖', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2009, 'overall.moreOption', 'zh', 'overall.moreOption', '更多选项', ' \n告警/告警信息/更多选项; 告警/告警规则/更多选项;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2010, 'overall.toolBox.stack', 'zh', 'overall.toolBox.stack', '查看堆叠图', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2011, 'overall.toolBox.back', 'zh', 'overall.toolBox.back', '区域缩放还原', '仪表盘/区域缩放还原;', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2011, 'overall.toolBox.back', 'zh', 'overall.toolBox.back', '区域缩放还原', '仪表盘/区域缩放还原;', '2022-12-20 09:14:06', 415); INSERT INTO `sys_i18n` VALUES (2012, 'overall.toolBox.zoom', 'zh', 'overall.toolBox.zoom', '区域缩放', '仪表盘/区域缩放;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2013, 'overall.toolBox.stackBack', 'zh', 'overall.toolBox.stackBack', '返回原始图', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2014, 'overall.createModel', 'zh', 'overall.createModel', '新增型号', ' \n资产配置/型号/新增型号;', '2021-11-02 00:00:00', 1); @@ -1363,7 +1363,7 @@ INSERT INTO `sys_i18n` VALUES (2124, 'overall.week', 'zh', 'overall.week', '1 � INSERT INTO `sys_i18n` VALUES (2126, 'overall.configuration', 'zh', 'overall.configuration', '资产配置', '资产/资产配置;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2127, 'overall.batchEdit', 'zh', 'overall.batchEdit', '批量修改', '资产/资产列表/更多/批量修改; 监控/应用实例/更多/批量修改;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2128, 'overall.back', 'zh', 'overall.back', '返回', ' \n仪表盘/返回; 监控/应用实例/返回;', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2129, 'overall.remark', 'zh', 'overall.remark', '描述', '监控/描述;\n资产/资产配置/型号/描述;\n\n告警/告警规则》描述;\n系统配置/IPAM/描述;\n\n表头->dashboard panel导入/导出/模板下载、资产model导入/导出/模板下载、告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载、告警信息导出', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (2129, 'overall.remark', 'zh', 'overall.remark', '描述', '监控/描述;\n资产/资产配置/型号/描述;\n\n告警/告警规则》描述;\n系统配置/IPAM/描述;\n\n表头->dashboard dashboard导入/导出/模板下载、资产model导入/导出/模板下载、告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载、告警信息导出', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (2130, 'overall.relabelConfigReplacement', 'zh', 'overall.relabelConfigReplacement', '默认是 $1', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2131, 'overall.oid', 'zh', 'overall.oid', 'OID格式校验错误', '告警/OID格式校验错误;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2132, 'overall.delete', 'zh', 'overall.delete', '删除', '系统配置/IPAM/删除; 资产/数据中心/删除;', '2021-11-02 00:00:00', 1); @@ -1436,7 +1436,7 @@ INSERT INTO `sys_i18n` VALUES (2212, 'tip.downloadSuccess', 'zh', 'tip.downloadS INSERT INTO `sys_i18n` VALUES (2213, 'tip.killTerm', 'zh', 'tip.killTerm', '确认关闭 terminal 吗?', '管理/审计/终端日志/msg提示語句\n', '2022-07-21 08:19:09', 425); INSERT INTO `sys_i18n` VALUES (2214, 'tip.refreshLater', 'zh', 'tip.refreshLater', '请稍后刷新', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2216, 'tip.testSuccess', 'zh', 'tip.testSuccess', '测试成功', '系統配置/msg提示語句', '2022-07-21 08:17:59', 425); -INSERT INTO `sys_i18n` VALUES (2217, 'tip.syncTip', 'zh', 'tip.syncTip', '此操作可能造成原有数据或图表被覆盖,确认同步吗?', 'panel/msg提示語句', '2022-07-21 08:16:55', 425); +INSERT INTO `sys_i18n` VALUES (2217, 'tip.syncTip', 'zh', 'tip.syncTip', '此操作可能造成原有数据或图表被覆盖,确认同步吗?', 'dashboard/msg提示語句', '2022-07-21 08:16:55', 425); INSERT INTO `sys_i18n` VALUES (2218, 'tip.noAccess', 'zh', 'tip.noAccess', '无访问权限', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2219, 'tip.resetPrompt', 'zh', 'tip.resetPrompt', '确认重置吗?', '系统配置/个性化配置/msg提示語句\n', '2022-07-21 08:15:43', 425); INSERT INTO `sys_i18n` VALUES (2220, 'tip.yes', 'zh', 'tip.yes', '是', ' \n告警/告警信息/msg提示语句; 告警/告警规则/msg提示语句; 告警/告警静默/msg提示语句; 监控/应用实例/msg提示语句; 监控/应用/msg提示语句; 监控/应用组/msg提示语句; 资产/资产列表/msg提示语句; 资产/数据中心/msg提示语句; 资产/资产配置/属性/msg提示语句; 资产/资产配置/型号/msg提示语句;', '2022-07-21 08:14:47', 425); @@ -1446,7 +1446,7 @@ INSERT INTO `sys_i18n` VALUES (2223, 'tip.confirmDelete', 'zh', 'tip.confirmDele INSERT INTO `sys_i18n` VALUES (2224, 'tip.confirmOvertime', 'zh', 'tip.confirmOvertime', '确定关闭吗?', '系统配置/模板/表达式模板/msg提示语句\n', '2022-07-21 08:07:56', 425); INSERT INTO `sys_i18n` VALUES (2225, 'tip.confirmDuplicate', 'zh', 'tip.confirmDuplicate', '确认复制吗?', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2226, 'tip.confirmExpired', 'zh', 'tip.confirmExpired', '确认失效吗?', '告警/告警信息/msg提示语句;\n\n告警/告警规则/msg提示语句;\n告警/告警静默/msg提示语句;\n\n', '2022-07-21 08:02:07', 425); -INSERT INTO `sys_i18n` VALUES (2227, 'tip.syncSuccess', 'zh', 'tip.syncSuccess', '同步成功', 'panel/msg提示语句', '2022-07-21 07:45:41', 425); +INSERT INTO `sys_i18n` VALUES (2227, 'tip.syncSuccess', 'zh', 'tip.syncSuccess', '同步成功', 'dashboard/msg提示语句', '2022-07-21 07:45:41', 425); INSERT INTO `sys_i18n` VALUES (2228, 'tip.confirmBatchDelete', 'zh', 'tip.confirmBatchDelete', '确定删除这{0}条数据吗?', '告警/告警信息/删除/删除语句\n', '2022-07-21 07:44:23', 425); INSERT INTO `sys_i18n` VALUES (2229, 'tip.pressEnterToAdd', 'zh', 'tip.pressEnterToAdd', '回车添加新行', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2230, 'tip.uploadSuccess', 'zh', 'tip.uploadSuccess', '上传成功', '', '2021-11-02 00:00:00', 1); @@ -1778,7 +1778,7 @@ INSERT INTO `sys_i18n` VALUES (2858, 'dashboard.metricPreview.inputTip', 'zh', ' INSERT INTO `sys_i18n` VALUES (2859, 'dashboard.explore.wrapLines', 'zh', 'dashboard.explore.wrapLines', '换行', '个人中心/', '2022-07-25 01:47:42', 425); INSERT INTO `sys_i18n` VALUES (2860, 'dashboard.explore.descending', 'zh', 'dashboard.explore.descending', '降序', ' \n监控/探索/指标/', '2022-07-25 01:48:58', 425); INSERT INTO `sys_i18n` VALUES (2862, 'dashboard.refresh', 'zh', 'dashboard.refresh', '刷新', '告警/告警信息/', '2022-07-25 01:50:33', 425); -INSERT INTO `sys_i18n` VALUES (2863, 'dashboard.screen', 'zh', 'dashboard.screen', '全屏', 'panel/筛选', '2022-07-25 01:53:21', 425); +INSERT INTO `sys_i18n` VALUES (2863, 'dashboard.screen', 'zh', 'dashboard.screen', '全屏', 'dashboard/筛选', '2022-07-25 01:53:21', 425); INSERT INTO `sys_i18n` VALUES (2867, 'dashboard.metric.normal', 'zh', 'dashboard.metric.normal', '普通', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2868, 'dashboard.metric.previewChart', 'zh', 'dashboard.metric.previewChart', '预览图表', '仪表盘/', '2022-07-20 03:34:11', 425); INSERT INTO `sys_i18n` VALUES (2869, 'dashboard.metric.expert', 'zh', 'dashboard.metric.expert', '专家', '', '2021-11-02 00:00:00', 1); @@ -1786,102 +1786,102 @@ INSERT INTO `sys_i18n` VALUES (2870, 'dashboard.metric.multiChartsShow', 'zh', ' INSERT INTO `sys_i18n` VALUES (2871, 'dashboard.metric.singleChartShow', 'zh', 'dashboard.metric.singleChartShow', '单图展示', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2872, 'dashboard.metric.saveChart', 'zh', 'dashboard.metric.saveChart', '保存图表', ' \n监控/应用实例/保存按钮', '2022-07-25 01:55:45', 425); INSERT INTO `sys_i18n` VALUES (2874, 'dashboard.metric.addMetric', 'zh', 'dashboard.metric.addMetric', '添加指标', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2877, 'dashboard.metric.selectPanel', 'zh', 'dashboard.metric.selectPanel', '选择已有面板', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2878, 'dashboard.metric.saveChartToPanel', 'zh', 'dashboard.metric.saveChartToPanel', '保存图表到看板', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2879, 'dashboard.metric.goPanelTip', 'zh', 'dashboard.metric.goPanelTip', '是否前去看板,查看创建的图表?', '监控/应用实例/msg提示语句', '2022-07-25 02:12:35', 425); +INSERT INTO `sys_i18n` VALUES (2877, 'dashboard.metric.selectDashboard', 'zh', 'dashboard.metric.selectDashboard', '选择已有面板', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2878, 'dashboard.metric.saveChartToDashboard', 'zh', 'dashboard.metric.saveChartToDashboard', '保存图表到看板', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2879, 'dashboard.metric.goDashboardTip', 'zh', 'dashboard.metric.goDashboardTip', '是否前去看板,查看创建的图表?', '监控/应用实例/msg提示语句', '2022-07-25 02:12:35', 425); INSERT INTO `sys_i18n` VALUES (2880, 'dashboard.metric.name', 'zh', 'dashboard.metric.name', '指标名称', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (2881, 'dashboard.addChartTemp', 'zh', 'dashboard.addChartTemp', '添加图表模板', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2882, 'dashboard.panel.lastThirtyMin', 'zh', 'dashboard.panel.lastThirtyMin', '最近30分钟', ' \n告警/告警信息/最近时间/最近三十分钟; panel/overview/最近时间/最近三十分钟;', '2022-07-25 02:21:14', 425); -INSERT INTO `sys_i18n` VALUES (2884, 'dashboard.panel.beforeTwentyFourHour', 'zh', 'dashboard.panel.beforeTwentyFourHour', '之前24小时', '告警/告警信息/最近时间/', '2022-07-25 02:22:51', 425); -INSERT INTO `sys_i18n` VALUES (2886, 'dashboard.panel.editChartTitle', 'zh', 'dashboard.panel.editChartTitle', '修改图表', ' \npanel/overview/编辑/修改图表', '2022-07-25 02:18:40', 425); -INSERT INTO `sys_i18n` VALUES (2887, 'dashboard.panel.lastMonth', 'zh', 'dashboard.panel.lastMonth', '上月', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2888, 'dashboard.panel.lastTwentyFourHour', 'zh', 'dashboard.panel.lastTwentyFourHour', '最近24小时', ' \npanel/overview/最近时间/最近24小时;', '2022-07-25 02:24:29', 425); -INSERT INTO `sys_i18n` VALUES (2889, 'dashboard.panel.lastSevenDay', 'zh', 'dashboard.panel.lastSevenDay', '最近7天', ' \npanel/overview/最近时间/最近7天;', '2022-07-25 02:25:07', 425); -INSERT INTO `sys_i18n` VALUES (2890, 'dashboard.panel.beforeThirtyDay', 'zh', 'dashboard.panel.beforeThirtyDay', '之前30天', ' \npanel/overview/最近时间/最近30天;', '2022-07-25 02:26:22', 425); -INSERT INTO `sys_i18n` VALUES (2891, 'dashboard.panel.selectPanelTitle', 'zh', 'dashboard.panel.selectPanelTitle', '选择面板', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2892, 'dashboard.panel.beforeOneHour', 'zh', 'dashboard.panel.beforeOneHour', '之前1小时', '\n告警/告警信息/之前1小时\n', '2022-07-25 02:32:12', 425); -INSERT INTO `sys_i18n` VALUES (2894, 'dashboard.panel.beforeFiveMin', 'zh', 'dashboard.panel.beforeFiveMin', '之前5分钟', '告警/告警信息/之前5分钟', '2022-07-25 02:31:47', 425); -INSERT INTO `sys_i18n` VALUES (2895, 'dashboard.panel.recOneMonth', 'zh', 'dashboard.panel.recOneMonth', '最近1月', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2896, 'dashboard.panel.lastFifteenMin', 'zh', 'dashboard.panel.lastFifteenMin', '最近15分钟', 'panel/最近时间/最近15分钟', '2022-07-25 02:33:09', 425); -INSERT INTO `sys_i18n` VALUES (2897, 'dashboard.panel.moreTitleOther', 'zh', 'dashboard.panel.moreTitleOther', '仅显示 10 条数据。', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2898, 'dashboard.panel.customTimeRange', 'zh', 'dashboard.panel.customTimeRange', '自定义时间区间', ' \n告警/告警信息/自定义时间区间', '2022-07-25 02:36:19', 425); -INSERT INTO `sys_i18n` VALUES (2899, 'dashboard.panel.lastTwoDay', 'zh', 'dashboard.panel.lastTwoDay', '最近2天', ' \npanel/最近时间/最近2天', '2022-07-25 02:37:16', 425); -INSERT INTO `sys_i18n` VALUES (2900, 'dashboard.panel.editPanelTitle', 'zh', 'dashboard.panel.editPanelTitle', '编辑仪表盘', 'panel/ \n编辑仪表盘', '2022-07-25 02:38:07', 425); -INSERT INTO `sys_i18n` VALUES (2901, 'dashboard.panel.recFour', 'zh', 'dashboard.panel.recFour', '最近4小时', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2903, 'dashboard.panel.refreshInterval.threeMinutes', 'zh', 'dashboard.panel.refreshInterval.threeMinutes', '3 分钟', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2904, 'dashboard.panel.refreshInterval.tenMinutes', 'zh', 'dashboard.panel.refreshInterval.tenMinutes', '10 分钟', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2905, 'dashboard.panel.refreshInterval.oneMinute', 'zh', 'dashboard.panel.refreshInterval.oneMinute', '1 分钟', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2906, 'dashboard.panel.refreshInterval.fiveMinutes', 'zh', 'dashboard.panel.refreshInterval.fiveMinutes', '5 分钟', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2907, 'dashboard.panel.beforeTwelveHour', 'zh', 'dashboard.panel.beforeTwelveHour', '之前12小时', '\n告警/告警信息/之前12小时\n', '2022-07-25 06:47:38', 425); -INSERT INTO `sys_i18n` VALUES (2909, 'dashboard.panel.beforeFifteenMin', 'zh', 'dashboard.panel.beforeFifteenMin', '之前15分钟', '告警/告警信息/之前15分钟', '2022-07-25 06:48:48', 425); -INSERT INTO `sys_i18n` VALUES (2910, 'dashboard.panel.lastFiveMin', 'zh', 'dashboard.panel.lastFiveMin', '最近5分钟', 'panel/最近时间/ 最近5分钟', '2022-07-25 06:49:51', 425); -INSERT INTO `sys_i18n` VALUES (2911, 'dashboard.panel.createPanelTitleSec', 'zh', 'dashboard.panel.createPanelTitleSec', '新增面板', 'panel/新增面板按钮', '2022-07-25 06:50:44', 425); -INSERT INTO `sys_i18n` VALUES (2912, 'dashboard.panel.lastThreeHour', 'zh', 'dashboard.panel.lastThreeHour', '最近3小时', ' \npanel/最近时间/ 最近3小时', '2022-07-25 06:52:25', 425); -INSERT INTO `sys_i18n` VALUES (2913, 'dashboard.panel.addChartTemp', 'zh', 'dashboard.panel.addChartTemp', '添加图表', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2914, 'dashboard.panel.lastTwelveHour', 'zh', 'dashboard.panel.lastTwelveHour', '最近12小时', 'panel/最近时间/ 最近12小时', '2022-07-25 06:53:24', 425); -INSERT INTO `sys_i18n` VALUES (2915, 'dashboard.panel.createPanelTitle', 'zh', 'dashboard.panel.createPanelTitle', '新增仪表盘', '', '2022-06-14 06:17:06', 1); -INSERT INTO `sys_i18n` VALUES (2916, 'dashboard.panel.singleStatErrorTip', 'zh', 'dashboard.panel.singleStatErrorTip', '仅支持返回单个系列/表的查询', '系统配置/模板/图表模板/提示语句\n', '2022-07-25 02:51:35', 425); -INSERT INTO `sys_i18n` VALUES (2917, 'dashboard.panel.recSevenDay', 'zh', 'dashboard.panel.recSevenDay', '最近7日', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2918, 'dashboard.panel.createChartTempTitle', 'zh', 'dashboard.panel.createChartTempTitle', '新增图表模板', '系统配置/模板/图表模板/ \n新增图表模板', '2022-07-25 02:52:46', 425); -INSERT INTO `sys_i18n` VALUES (2919, 'dashboard.panel.title', 'zh', 'dashboard.panel.title', '主面板', 'panel/主面板', '2022-07-25 02:53:45', 425); -INSERT INTO `sys_i18n` VALUES (2920, 'dashboard.panel.yesterday', 'zh', 'dashboard.panel.yesterday', '昨日', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2921, 'dashboard.panel.beforeTwoDay', 'zh', 'dashboard.panel.beforeTwoDay', '之前2天', '告警/告警信息/之前2天', '2022-07-25 03:06:06', 425); -INSERT INTO `sys_i18n` VALUES (2922, 'dashboard.panel.showAll', 'zh', 'dashboard.panel.showAll', '全部显示 ', 'panel/全部显示 ', '2022-07-25 02:55:33', 425); -INSERT INTO `sys_i18n` VALUES (2923, 'dashboard.panel.chartTotal', 'zh', 'dashboard.panel.chartTotal', '总和', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2924, 'dashboard.panel.lastSixHour', 'zh', 'dashboard.panel.lastSixHour', '最近6小时', ' \npanel/最近时间/ 最近6小时', '2022-07-25 03:00:47', 425); -INSERT INTO `sys_i18n` VALUES (2926, 'dashboard.panel.beforeThirtyMin', 'zh', 'dashboard.panel.beforeThirtyMin', '之前30分钟', '告警/告警信息/之前30分钟', '2022-07-25 03:05:39', 425); -INSERT INTO `sys_i18n` VALUES (2927, 'dashboard.panel.beforeSevenDay', 'zh', 'dashboard.panel.beforeSevenDay', '之前7天', ' \n告警/告警信息/之前7天', '2022-07-25 03:06:40', 425); -INSERT INTO `sys_i18n` VALUES (2928, 'dashboard.panel.recOneDay', 'zh', 'dashboard.panel.recOneDay', '最近1日', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2929, 'dashboard.panel.curMonth', 'zh', 'dashboard.panel.curMonth', '本月', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2931, 'dashboard.panel.beforeThreeHour', 'zh', 'dashboard.panel.beforeThreeHour', '之前3小时', ' \n告警/告警信息/之前3小时', '2022-07-25 03:07:39', 425); -INSERT INTO `sys_i18n` VALUES (2932, 'dashboard.panel.createChartByTemp', 'zh', 'dashboard.panel.createChartByTemp', '通过模板添加图表', '系统配置/模板/图表模板/通过模板添加图表\n', '2022-07-25 03:08:55', 425); -INSERT INTO `sys_i18n` VALUES (2933, 'dashboard.panel.editChartTempTitle', 'zh', 'dashboard.panel.editChartTempTitle', '修改图表模板', 'panel/修改图表模板标题', '2022-07-25 03:09:59', 425); -INSERT INTO `sys_i18n` VALUES (2940, 'dashboard.panel.beforeSixHour', 'zh', 'dashboard.panel.beforeSixHour', '之前6小时', ' \n告警/告警信息/之前6小时', '2022-07-25 03:10:34', 425); -INSERT INTO `sys_i18n` VALUES (2943, 'dashboard.panel.panelForm.panelName', 'zh', 'dashboard.panel.panelForm.panelName', '面板名称', '表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (2944, 'dashboard.panel.moreTitle', 'zh', 'dashboard.panel.moreTitle', '仅显示 20 个时间序列。', 'panel/按钮title', '2022-07-25 03:11:44', 425); -INSERT INTO `sys_i18n` VALUES (2946, 'dashboard.panel.chartForm.legend', 'zh', 'dashboard.panel.chartForm.legend', '图例', 'panel/图例', '2022-07-21 07:20:39', 425); -INSERT INTO `sys_i18n` VALUES (2953, 'dashboard.panel.chartForm.valMapping.range', 'zh', 'dashboard.panel.chartForm.valMapping.range', '范围', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2954, 'dashboard.panel.chartForm.valMapping.from', 'zh', 'dashboard.panel.chartForm.valMapping.from', '从', '', '2022-07-08 13:13:39', 415); -INSERT INTO `sys_i18n` VALUES (2958, 'dashboard.panel.chartForm.tooltip', 'zh', 'dashboard.panel.chartForm.tooltip', '工具提示', 'panel/tooltip', '2022-07-21 07:17:12', 425); -INSERT INTO `sys_i18n` VALUES (2962, 'dashboard.panel.chartForm.aggregation', 'zh', 'dashboard.panel.chartForm.aggregation', '聚合', 'panel/聚合', '2022-07-21 07:14:14', 425); -INSERT INTO `sys_i18n` VALUES (2967, 'dashboard.panel.chartForm.content', 'zh', 'dashboard.panel.chartForm.content', '内容', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2969, 'dashboard.panel.chartForm.high', 'zh', 'dashboard.panel.chartForm.high', '高', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (2970, 'dashboard.panel.chartForm.varType', 'zh', 'dashboard.panel.chartForm.varType', '变量类型', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (2973, 'dashboard.panel.chartForm.alignList.right', 'zh', 'dashboard.panel.chartForm.alignList.right', '右对齐', 'chart组件/对齐方式', '2022-07-21 07:07:07', 425); -INSERT INTO `sys_i18n` VALUES (2975, 'dashboard.panel.chartForm.statisticsVal.average', 'zh', 'dashboard.panel.chartForm.statisticsVal.average', '平均值', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2978, 'dashboard.panel.chartForm.statisticsVal.last', 'zh', 'dashboard.panel.chartForm.statisticsVal.last', '最后一个值', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2982, 'dashboard.panel.chartForm.statisticsVal.different', 'zh', 'dashboard.panel.chartForm.statisticsVal.different', '差值', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2983, 'dashboard.panel.chartForm.statisticsVal.first', 'zh', 'dashboard.panel.chartForm.statisticsVal.first', '第一个值', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2985, 'dashboard.panel.chartForm.lock', 'zh', 'dashboard.panel.chartForm.lock', '锁', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2986, 'dashboard.panel.chartForm.group', 'zh', 'dashboard.panel.chartForm.group', '组', 'panel/chartType数据; 表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 425); -INSERT INTO `sys_i18n` VALUES (2987, 'dashboard.panel.chartForm.typeVal.stackArea.label', 'zh', 'dashboard.panel.chartForm.typeVal.stackArea.label', '区域图', ' \npanel/chartType数据', '2022-07-21 07:02:06', 425); -INSERT INTO `sys_i18n` VALUES (2988, 'dashboard.panel.chartForm.typeVal.diagram.label', 'zh', 'dashboard.panel.chartForm.typeVal.diagram.label', '示意图', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (2989, 'dashboard.panel.chartForm.typeVal.bar.label', 'zh', 'dashboard.panel.chartForm.typeVal.bar.label', '柱状图', 'panel/chartType数据', '2022-07-21 07:00:59', 425); -INSERT INTO `sys_i18n` VALUES (2990, 'dashboard.panel.chartForm.typeVal.line.label', 'zh', 'dashboard.panel.chartForm.typeVal.line.label', '曲线图', ' \npanel/chartType数据', '2022-07-21 07:00:39', 425); -INSERT INTO `sys_i18n` VALUES (2991, 'dashboard.panel.chartForm.typeVal.singleStat.label', 'zh', 'dashboard.panel.chartForm.typeVal.singleStat.label', '单值', 'panel/chartType数据', '2022-07-21 07:00:22', 425); -INSERT INTO `sys_i18n` VALUES (2992, 'dashboard.panel.chartForm.typeVal.alertList.label', 'zh', 'dashboard.panel.chartForm.typeVal.alertList.label', '告警列表', ' \n全局搜索组件/chartType数据', '2022-07-21 06:52:01', 425); -INSERT INTO `sys_i18n` VALUES (2993, 'dashboard.panel.chartForm.typeVal.text.label', 'zh', 'dashboard.panel.chartForm.typeVal.text.label', '文本', '全局搜索组件/chartType数据', '2022-07-21 06:51:31', 425); -INSERT INTO `sys_i18n` VALUES (2994, 'dashboard.panel.chartForm.typeVal.pie.label', 'zh', 'dashboard.panel.chartForm.typeVal.pie.label', '饼图', ' \n全局搜索组件/chartType数据', '2022-07-21 06:51:09', 425); -INSERT INTO `sys_i18n` VALUES (2996, 'dashboard.panel.chartForm.typeVal.table.label', 'zh', 'dashboard.panel.chartForm.typeVal.table.label', '表格', '监控/探索/表格', '2022-07-21 06:43:53', 425); -INSERT INTO `sys_i18n` VALUES (2997, 'dashboard.panel.chartForm.typeVal.url.staticTip', 'zh', 'dashboard.panel.chartForm.typeVal.url.staticTip', '双大括号中的内容将会在asset页面被替换', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3000, 'dashboard.panel.chartForm.lockList.off', 'zh', 'dashboard.panel.chartForm.lockList.off', '关', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3001, 'dashboard.panel.chartForm.lockList.on', 'zh', 'dashboard.panel.chartForm.lockList.on', '开', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3002, 'dashboard.panel.chartForm.legendTip', 'zh', 'dashboard.panel.chartForm.legendTip', '使用名称或表达式控制时间序列的名称。例如{{hostname}将替换为标签主机名的标签值。', '系统配置/模板/图表模板/名称\n', '2022-07-21 06:41:20', 425); -INSERT INTO `sys_i18n` VALUES (3004, 'dashboard.panel.chartForm.selectAsset', 'zh', 'dashboard.panel.chartForm.selectAsset', '请选择资产', 'web-ssh/plshoder提示语句', '2022-07-21 06:37:25', 425); -INSERT INTO `sys_i18n` VALUES (3005, 'dashboard.panel.chartForm.sync', 'zh', 'dashboard.panel.chartForm.sync', '同步到设备', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3006, 'dashboard.panel.chartForm.url', 'zh', 'dashboard.panel.chartForm.url', 'URL', '搜索框组件/chartType数据', '2022-07-21 06:34:35', 425); -INSERT INTO `sys_i18n` VALUES (3007, 'dashboard.panel.chartForm.thresholds', 'zh', 'dashboard.panel.chartForm.thresholds', '阈值', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3008, 'dashboard.panel.chartForm.unit', 'zh', 'dashboard.panel.chartForm.unit', '单位', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (3010, 'dashboard.panel.chartForm.legendValue', 'zh', 'dashboard.panel.chartForm.legendValue', '图例选项', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (3012, 'dashboard.panel.chartForm.valueMappingTip', 'zh', 'dashboard.panel.chartForm.valueMappingTip', '使用{{name}}和{{value}}显示原名和原值\n例如:total alive: {{value}}\n结果为:total alive: 100', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3014, 'dashboard.panel.chartForm.width', 'zh', 'dashboard.panel.chartForm.width', '宽', 'panel/修改图表/显示配置/宽;\n表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 425); -INSERT INTO `sys_i18n` VALUES (3015, 'dashboard.panel.chartForm.selectEndpoint', 'zh', 'dashboard.panel.chartForm.selectEndpoint', '请选择端点', 'panel/msg提示语句', '2022-08-01 06:12:22', 415); -INSERT INTO `sys_i18n` VALUES (3017, 'dashboard.panel.chartForm.collapse', 'zh', 'dashboard.panel.chartForm.collapse', '默认折叠', ' \n工具箱/路由跟踪/默认折叠', '2022-07-21 01:38:44', 425); -INSERT INTO `sys_i18n` VALUES (3018, 'dashboard.panel.chartForm.statistics', 'zh', 'dashboard.panel.chartForm.statistics', '统计数据', '工具箱/路由跟踪/统计数据\n', '2022-07-21 01:38:49', 425); -INSERT INTO `sys_i18n` VALUES (3022, 'dashboard.panel.to', 'zh', 'dashboard.panel.to', '至', 'panel/至', '2022-07-21 01:37:09', 425); -INSERT INTO `sys_i18n` VALUES (3023, 'dashboard.panel.lastOneHour', 'zh', 'dashboard.panel.lastOneHour', '最近1小时', 'panel/最近时间/最近1小时', '2022-07-25 03:27:51', 425); -INSERT INTO `sys_i18n` VALUES (3024, 'dashboard.panel.noDate', 'zh', 'dashboard.panel.noDate', '全部时间', ' \npanel/全部时间;\n监控/应用实例/全部时间\n', '2022-07-25 03:25:35', 425); -INSERT INTO `sys_i18n` VALUES (3025, 'dashboard.panel.lastThirtyDay', 'zh', 'dashboard.panel.lastThirtyDay', '最近30天', 'panel/最近时间/最近30天', '2022-07-25 03:27:21', 425); +INSERT INTO `sys_i18n` VALUES (2882, 'dashboard.dashboard.lastThirtyMin', 'zh', 'dashboard.dashboard.lastThirtyMin', '最近30分钟', ' \n告警/告警信息/最近时间/最近三十分钟; dashboard/overview/最近时间/最近三十分钟;', '2022-07-25 02:21:14', 425); +INSERT INTO `sys_i18n` VALUES (2884, 'dashboard.dashboard.beforeTwentyFourHour', 'zh', 'dashboard.dashboard.beforeTwentyFourHour', '之前24小时', '告警/告警信息/最近时间/', '2022-07-25 02:22:51', 425); +INSERT INTO `sys_i18n` VALUES (2886, 'dashboard.dashboard.editChartTitle', 'zh', 'dashboard.dashboard.editChartTitle', '修改图表', ' \ndashboard/overview/编辑/修改图表', '2022-07-25 02:18:40', 425); +INSERT INTO `sys_i18n` VALUES (2887, 'dashboard.dashboard.lastMonth', 'zh', 'dashboard.dashboard.lastMonth', '上月', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2888, 'dashboard.dashboard.lastTwentyFourHour', 'zh', 'dashboard.dashboard.lastTwentyFourHour', '最近24小时', ' \ndashboard/overview/最近时间/最近24小时;', '2022-07-25 02:24:29', 425); +INSERT INTO `sys_i18n` VALUES (2889, 'dashboard.dashboard.lastSevenDay', 'zh', 'dashboard.dashboard.lastSevenDay', '最近7天', ' \ndashboard/overview/最近时间/最近7天;', '2022-07-25 02:25:07', 425); +INSERT INTO `sys_i18n` VALUES (2890, 'dashboard.dashboard.beforeThirtyDay', 'zh', 'dashboard.dashboard.beforeThirtyDay', '之前30天', ' \ndashboard/overview/最近时间/最近30天;', '2022-07-25 02:26:22', 425); +INSERT INTO `sys_i18n` VALUES (2891, 'dashboard.dashboard.selectDashboardTitle', 'zh', 'dashboard.dashboard.selectDashboardTitle', '选择面板', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2892, 'dashboard.dashboard.beforeOneHour', 'zh', 'dashboard.dashboard.beforeOneHour', '之前1小时', '\n告警/告警信息/之前1小时\n', '2022-07-25 02:32:12', 425); +INSERT INTO `sys_i18n` VALUES (2894, 'dashboard.dashboard.beforeFiveMin', 'zh', 'dashboard.dashboard.beforeFiveMin', '之前5分钟', '告警/告警信息/之前5分钟', '2022-07-25 02:31:47', 425); +INSERT INTO `sys_i18n` VALUES (2895, 'dashboard.dashboard.recOneMonth', 'zh', 'dashboard.dashboard.recOneMonth', '最近1月', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2896, 'dashboard.dashboard.lastFifteenMin', 'zh', 'dashboard.dashboard.lastFifteenMin', '最近15分钟', 'dashboard/最近时间/最近15分钟', '2022-07-25 02:33:09', 425); +INSERT INTO `sys_i18n` VALUES (2897, 'dashboard.dashboard.moreTitleOther', 'zh', 'dashboard.dashboard.moreTitleOther', '仅显示 10 条数据。', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2898, 'dashboard.dashboard.customTimeRange', 'zh', 'dashboard.dashboard.customTimeRange', '自定义时间区间', ' \n告警/告警信息/自定义时间区间', '2022-07-25 02:36:19', 425); +INSERT INTO `sys_i18n` VALUES (2899, 'dashboard.dashboard.lastTwoDay', 'zh', 'dashboard.dashboard.lastTwoDay', '最近2天', ' \ndashboard/最近时间/最近2天', '2022-07-25 02:37:16', 425); +INSERT INTO `sys_i18n` VALUES (2900, 'dashboard.dashboard.editDashboardTitle', 'zh', 'dashboard.dashboard.editDashboardTitle', '编辑仪表盘', 'dashboard/ \n编辑仪表盘', '2022-07-25 02:38:07', 425); +INSERT INTO `sys_i18n` VALUES (2901, 'dashboard.dashboard.recFour', 'zh', 'dashboard.dashboard.recFour', '最近4小时', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2903, 'dashboard.dashboard.refreshInterval.threeMinutes', 'zh', 'dashboard.dashboard.refreshInterval.threeMinutes', '3 分钟', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2904, 'dashboard.dashboard.refreshInterval.tenMinutes', 'zh', 'dashboard.dashboard.refreshInterval.tenMinutes', '10 分钟', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2905, 'dashboard.dashboard.refreshInterval.oneMinute', 'zh', 'dashboard.dashboard.refreshInterval.oneMinute', '1 分钟', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2906, 'dashboard.dashboard.refreshInterval.fiveMinutes', 'zh', 'dashboard.dashboard.refreshInterval.fiveMinutes', '5 分钟', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2907, 'dashboard.dashboard.beforeTwelveHour', 'zh', 'dashboard.dashboard.beforeTwelveHour', '之前12小时', '\n告警/告警信息/之前12小时\n', '2022-07-25 06:47:38', 425); +INSERT INTO `sys_i18n` VALUES (2909, 'dashboard.dashboard.beforeFifteenMin', 'zh', 'dashboard.dashboard.beforeFifteenMin', '之前15分钟', '告警/告警信息/之前15分钟', '2022-07-25 06:48:48', 425); +INSERT INTO `sys_i18n` VALUES (2910, 'dashboard.dashboard.lastFiveMin', 'zh', 'dashboard.dashboard.lastFiveMin', '最近5分钟', 'dashboard/最近时间/ 最近5分钟', '2022-07-25 06:49:51', 425); +INSERT INTO `sys_i18n` VALUES (2911, 'dashboard.dashboard.createDashboardTitleSec', 'zh', 'dashboard.dashboard.createDashboardTitleSec', '新增面板', 'dashboard/新增面板按钮', '2022-07-25 06:50:44', 425); +INSERT INTO `sys_i18n` VALUES (2912, 'dashboard.dashboard.lastThreeHour', 'zh', 'dashboard.dashboard.lastThreeHour', '最近3小时', ' \ndashboard/最近时间/ 最近3小时', '2022-07-25 06:52:25', 425); +INSERT INTO `sys_i18n` VALUES (2913, 'dashboard.dashboard.addChartTemp', 'zh', 'dashboard.dashboard.addChartTemp', '添加图表', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2914, 'dashboard.dashboard.lastTwelveHour', 'zh', 'dashboard.dashboard.lastTwelveHour', '最近12小时', 'dashboard/最近时间/ 最近12小时', '2022-07-25 06:53:24', 425); +INSERT INTO `sys_i18n` VALUES (2915, 'dashboard.dashboard.createDashboardTitle', 'zh', 'dashboard.dashboard.createDashboardTitle', '新增仪表盘', '', '2022-06-14 06:17:06', 1); +INSERT INTO `sys_i18n` VALUES (2916, 'dashboard.dashboard.singleStatErrorTip', 'zh', 'dashboard.dashboard.singleStatErrorTip', '仅支持返回单个系列/表的查询', '系统配置/模板/图表模板/提示语句\n', '2022-07-25 02:51:35', 425); +INSERT INTO `sys_i18n` VALUES (2917, 'dashboard.dashboard.recSevenDay', 'zh', 'dashboard.dashboard.recSevenDay', '最近7日', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2918, 'dashboard.dashboard.createChartTempTitle', 'zh', 'dashboard.dashboard.createChartTempTitle', '新增图表模板', '系统配置/模板/图表模板/ \n新增图表模板', '2022-07-25 02:52:46', 425); +INSERT INTO `sys_i18n` VALUES (2919, 'dashboard.dashboard.title', 'zh', 'dashboard.dashboard.title', '主面板', 'dashboard/主面板', '2022-07-25 02:53:45', 425); +INSERT INTO `sys_i18n` VALUES (2920, 'dashboard.dashboard.yesterday', 'zh', 'dashboard.dashboard.yesterday', '昨日', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2921, 'dashboard.dashboard.beforeTwoDay', 'zh', 'dashboard.dashboard.beforeTwoDay', '之前2天', '告警/告警信息/之前2天', '2022-07-25 03:06:06', 425); +INSERT INTO `sys_i18n` VALUES (2922, 'dashboard.dashboard.showAll', 'zh', 'dashboard.dashboard.showAll', '全部显示 ', 'dashboard/全部显示 ', '2022-07-25 02:55:33', 425); +INSERT INTO `sys_i18n` VALUES (2923, 'dashboard.dashboard.chartTotal', 'zh', 'dashboard.dashboard.chartTotal', '总和', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2924, 'dashboard.dashboard.lastSixHour', 'zh', 'dashboard.dashboard.lastSixHour', '最近6小时', ' \ndashboard/最近时间/ 最近6小时', '2022-07-25 03:00:47', 425); +INSERT INTO `sys_i18n` VALUES (2926, 'dashboard.dashboard.beforeThirtyMin', 'zh', 'dashboard.dashboard.beforeThirtyMin', '之前30分钟', '告警/告警信息/之前30分钟', '2022-07-25 03:05:39', 425); +INSERT INTO `sys_i18n` VALUES (2927, 'dashboard.dashboard.beforeSevenDay', 'zh', 'dashboard.dashboard.beforeSevenDay', '之前7天', ' \n告警/告警信息/之前7天', '2022-07-25 03:06:40', 425); +INSERT INTO `sys_i18n` VALUES (2928, 'dashboard.dashboard.recOneDay', 'zh', 'dashboard.dashboard.recOneDay', '最近1日', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2929, 'dashboard.dashboard.curMonth', 'zh', 'dashboard.dashboard.curMonth', '本月', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2931, 'dashboard.dashboard.beforeThreeHour', 'zh', 'dashboard.dashboard.beforeThreeHour', '之前3小时', ' \n告警/告警信息/之前3小时', '2022-07-25 03:07:39', 425); +INSERT INTO `sys_i18n` VALUES (2932, 'dashboard.dashboard.createChartByTemp', 'zh', 'dashboard.dashboard.createChartByTemp', '通过模板添加图表', '系统配置/模板/图表模板/通过模板添加图表\n', '2022-07-25 03:08:55', 425); +INSERT INTO `sys_i18n` VALUES (2933, 'dashboard.dashboard.editChartTempTitle', 'zh', 'dashboard.dashboard.editChartTempTitle', '修改图表模板', 'dashboard/修改图表模板标题', '2022-07-25 03:09:59', 425); +INSERT INTO `sys_i18n` VALUES (2940, 'dashboard.dashboard.beforeSixHour', 'zh', 'dashboard.dashboard.beforeSixHour', '之前6小时', ' \n告警/告警信息/之前6小时', '2022-07-25 03:10:34', 425); +INSERT INTO `sys_i18n` VALUES (2943, 'dashboard.dashboard.dashboardForm.dashboardName', 'zh', 'dashboard.dashboard.dashboardForm.dashboardName', '面板名称', '表头->dashboard dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (2944, 'dashboard.dashboard.moreTitle', 'zh', 'dashboard.dashboard.moreTitle', '仅显示 20 个时间序列。', 'dashboard/按钮title', '2022-07-25 03:11:44', 425); +INSERT INTO `sys_i18n` VALUES (2946, 'dashboard.dashboard.chartForm.legend', 'zh', 'dashboard.dashboard.chartForm.legend', '图例', 'dashboard/图例', '2022-07-21 07:20:39', 425); +INSERT INTO `sys_i18n` VALUES (2953, 'dashboard.dashboard.chartForm.valMapping.range', 'zh', 'dashboard.dashboard.chartForm.valMapping.range', '范围', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2954, 'dashboard.dashboard.chartForm.valMapping.from', 'zh', 'dashboard.dashboard.chartForm.valMapping.from', '从', '', '2022-07-08 13:13:39', 415); +INSERT INTO `sys_i18n` VALUES (2958, 'dashboard.dashboard.chartForm.tooltip', 'zh', 'dashboard.dashboard.chartForm.tooltip', '工具提示', 'dashboard/tooltip', '2022-07-21 07:17:12', 425); +INSERT INTO `sys_i18n` VALUES (2962, 'dashboard.dashboard.chartForm.aggregation', 'zh', 'dashboard.dashboard.chartForm.aggregation', '聚合', 'dashboard/聚合', '2022-07-21 07:14:14', 425); +INSERT INTO `sys_i18n` VALUES (2967, 'dashboard.dashboard.chartForm.content', 'zh', 'dashboard.dashboard.chartForm.content', '内容', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2969, 'dashboard.dashboard.chartForm.high', 'zh', 'dashboard.dashboard.chartForm.high', '高', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (2970, 'dashboard.dashboard.chartForm.varType', 'zh', 'dashboard.dashboard.chartForm.varType', '变量类型', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (2973, 'dashboard.dashboard.chartForm.alignList.right', 'zh', 'dashboard.dashboard.chartForm.alignList.right', '右对齐', 'chart组件/对齐方式', '2022-07-21 07:07:07', 425); +INSERT INTO `sys_i18n` VALUES (2975, 'dashboard.dashboard.chartForm.statisticsVal.average', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.average', '平均值', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2978, 'dashboard.dashboard.chartForm.statisticsVal.last', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.last', '最后一个值', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2982, 'dashboard.dashboard.chartForm.statisticsVal.different', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.different', '差值', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2983, 'dashboard.dashboard.chartForm.statisticsVal.first', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.first', '第一个值', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2985, 'dashboard.dashboard.chartForm.lock', 'zh', 'dashboard.dashboard.chartForm.lock', '锁', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2986, 'dashboard.dashboard.chartForm.group', 'zh', 'dashboard.dashboard.chartForm.group', '组', 'dashboard/chartType数据; 表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (2987, 'dashboard.dashboard.chartForm.typeVal.stackArea.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.stackArea.label', '区域图', ' \ndashboard/chartType数据', '2022-07-21 07:02:06', 425); +INSERT INTO `sys_i18n` VALUES (2988, 'dashboard.dashboard.chartForm.typeVal.diagram.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.diagram.label', '示意图', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (2989, 'dashboard.dashboard.chartForm.typeVal.bar.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.bar.label', '柱状图', 'dashboard/chartType数据', '2022-07-21 07:00:59', 425); +INSERT INTO `sys_i18n` VALUES (2990, 'dashboard.dashboard.chartForm.typeVal.line.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.line.label', '曲线图', ' \ndashboard/chartType数据', '2022-07-21 07:00:39', 425); +INSERT INTO `sys_i18n` VALUES (2991, 'dashboard.dashboard.chartForm.typeVal.singleStat.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.singleStat.label', '单值', 'dashboard/chartType数据', '2022-07-21 07:00:22', 425); +INSERT INTO `sys_i18n` VALUES (2992, 'dashboard.dashboard.chartForm.typeVal.alertList.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.alertList.label', '告警列表', ' \n全局搜索组件/chartType数据', '2022-07-21 06:52:01', 425); +INSERT INTO `sys_i18n` VALUES (2993, 'dashboard.dashboard.chartForm.typeVal.text.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.text.label', '文本', '全局搜索组件/chartType数据', '2022-07-21 06:51:31', 425); +INSERT INTO `sys_i18n` VALUES (2994, 'dashboard.dashboard.chartForm.typeVal.pie.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.pie.label', '饼图', ' \n全局搜索组件/chartType数据', '2022-07-21 06:51:09', 425); +INSERT INTO `sys_i18n` VALUES (2996, 'dashboard.dashboard.chartForm.typeVal.table.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.table.label', '表格', '监控/探索/表格', '2022-07-21 06:43:53', 425); +INSERT INTO `sys_i18n` VALUES (2997, 'dashboard.dashboard.chartForm.typeVal.url.staticTip', 'zh', 'dashboard.dashboard.chartForm.typeVal.url.staticTip', '双大括号中的内容将会在asset页面被替换', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3000, 'dashboard.dashboard.chartForm.lockList.off', 'zh', 'dashboard.dashboard.chartForm.lockList.off', '关', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3001, 'dashboard.dashboard.chartForm.lockList.on', 'zh', 'dashboard.dashboard.chartForm.lockList.on', '开', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3002, 'dashboard.dashboard.chartForm.legendTip', 'zh', 'dashboard.dashboard.chartForm.legendTip', '使用名称或表达式控制时间序列的名称。例如{{hostname}将替换为标签主机名的标签值。', '系统配置/模板/图表模板/名称\n', '2022-07-21 06:41:20', 425); +INSERT INTO `sys_i18n` VALUES (3004, 'dashboard.dashboard.chartForm.selectAsset', 'zh', 'dashboard.dashboard.chartForm.selectAsset', '请选择资产', 'web-ssh/plshoder提示语句', '2022-07-21 06:37:25', 425); +INSERT INTO `sys_i18n` VALUES (3005, 'dashboard.dashboard.chartForm.sync', 'zh', 'dashboard.dashboard.chartForm.sync', '同步到设备', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3006, 'dashboard.dashboard.chartForm.url', 'zh', 'dashboard.dashboard.chartForm.url', 'URL', '搜索框组件/chartType数据', '2022-07-21 06:34:35', 425); +INSERT INTO `sys_i18n` VALUES (3007, 'dashboard.dashboard.chartForm.thresholds', 'zh', 'dashboard.dashboard.chartForm.thresholds', '阈值', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3008, 'dashboard.dashboard.chartForm.unit', 'zh', 'dashboard.dashboard.chartForm.unit', '单位', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、告警规则导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (3010, 'dashboard.dashboard.chartForm.legendValue', 'zh', 'dashboard.dashboard.chartForm.legendValue', '图例选项', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (3012, 'dashboard.dashboard.chartForm.valueMappingTip', 'zh', 'dashboard.dashboard.chartForm.valueMappingTip', '使用{{name}}和{{value}}显示原名和原值\n例如:total alive: {{value}}\n结果为:total alive: 100', '', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3014, 'dashboard.dashboard.chartForm.width', 'zh', 'dashboard.dashboard.chartForm.width', '宽', 'dashboard/修改图表/显示配置/宽;\n表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (3015, 'dashboard.dashboard.chartForm.selectEndpoint', 'zh', 'dashboard.dashboard.chartForm.selectEndpoint', '请选择端点', 'dashboard/msg提示语句', '2022-08-01 06:12:22', 415); +INSERT INTO `sys_i18n` VALUES (3017, 'dashboard.dashboard.chartForm.collapse', 'zh', 'dashboard.dashboard.chartForm.collapse', '默认折叠', ' \n工具箱/路由跟踪/默认折叠', '2022-07-21 01:38:44', 425); +INSERT INTO `sys_i18n` VALUES (3018, 'dashboard.dashboard.chartForm.statistics', 'zh', 'dashboard.dashboard.chartForm.statistics', '统计数据', '工具箱/路由跟踪/统计数据\n', '2022-07-21 01:38:49', 425); +INSERT INTO `sys_i18n` VALUES (3022, 'dashboard.dashboard.to', 'zh', 'dashboard.dashboard.to', '至', 'dashboard/至', '2022-07-21 01:37:09', 425); +INSERT INTO `sys_i18n` VALUES (3023, 'dashboard.dashboard.lastOneHour', 'zh', 'dashboard.dashboard.lastOneHour', '最近1小时', 'dashboard/最近时间/最近1小时', '2022-07-25 03:27:51', 425); +INSERT INTO `sys_i18n` VALUES (3024, 'dashboard.dashboard.noDate', 'zh', 'dashboard.dashboard.noDate', '全部时间', ' \ndashboard/全部时间;\n监控/应用实例/全部时间\n', '2022-07-25 03:25:35', 425); +INSERT INTO `sys_i18n` VALUES (3025, 'dashboard.dashboard.lastThirtyDay', 'zh', 'dashboard.dashboard.lastThirtyDay', '最近30天', 'dashboard/最近时间/最近30天', '2022-07-25 03:27:21', 425); INSERT INTO `sys_i18n` VALUES (3027, 'guide.agent', 'zh', 'guide.agent', '客户端', '系统配置/客户端/客户端', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3028, 'guide.visualization', 'zh', 'guide.visualization', '可视化', 'header/guide/可视化', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3030, 'guide.monitorTip', 'zh', 'guide.monitorTip', '帮助用户根据系统需求监控组件', 'header/guide/tip', '2022-07-25 03:35:03', 425); @@ -1915,54 +1915,52 @@ INSERT INTO `sys_i18n` VALUES (3070, 'validate.onlyWord', 'zh', 'validate.onlyWo INSERT INTO `sys_i18n` VALUES (3072, 'validate.email', 'zh', 'validate.email', '不合法的E-mail地址', '管理/用户/; 系统配置/个性化配置/;', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3073, 'validate.key', 'zh', 'validate.key', '不合法的值', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3074, '200', 'en', 'SUCCESS', 'success', '响应消息->请求成功', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3075, '121007', 'en', 'PANEL_NAME_ISNULL', 'Panel name can not be empty', '响应消息->panel新增/修改/导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3076, '121010', 'en', 'PANEL_ID_ISNULL', 'Panel ID can not be empty', '响应消息->panel修改/删除/复制/快照/顺序调整接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3077, '122009', 'en', 'PANEL_NAME_DUPLICATE', 'Panel name is duplicate', '响应消息->panel新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3078, '121002', 'en', 'PANEL_TYPE_ISNULL', 'Panel type can not be empty when link is not empty', '响应消息->panel新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3079, '124003', 'en', 'PANEL_TYPE_INVALIDE', 'Panel type must be dashboard, asset, project, module, endpoint or model', '响应消息->panel新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3081, '127014', 'en', 'PANEL_BUILDIN_CAN_NOT_REMOVE', 'This panel is built-in and cannot be deleted', '响应消息->panel删除接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3082, '121032', 'en', 'CHART_TITLE_ISNULL', 'Chart title can not be empty', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3083, '121035', 'en', 'CHART_SPAN_ISNULL', 'Chart span can not be empty', '响应消息->charts调整大小/新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3084, '121047', 'en', 'CHART_HEIGHT_ISNULL', 'Chart height can not be empty', '响应消息->charts调整大小/新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3085, '121030', 'en', 'CHART_TYPE_ISNULL', 'Chart type can not be empty', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3075, '121007', 'en', 'DASHBOARD_NAME_ISNULL', 'Dashboard name can not be empty', '响应消息->dashboard新增/修改/导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3076, '121010', 'en', 'DASHBOARD_ID_ISNULL', 'Dashboard ID can not be empty', '响应消息->dashboard修改/删除/复制/快照/顺序调整接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3077, '122009', 'en', 'DASHBOARD_NAME_DUPLICATE', 'Dashboard name is duplicate', '响应消息->dashboard新增/修改接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3078, '121002', 'en', 'DASHBOARD_TYPE_ISNULL', 'Dashboard type can not be empty when link is not empty', '响应消息->dashboard新增/修改接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3079, '124003', 'en', 'DASHBOARD_TYPE_INVALIDE', 'Dashboard type must be dashboard, asset, project, module, endpoint or template', '响应消息->dashboard新增/修改接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3081, '127014', 'en', 'DASHBOARD_BUILDIN_CAN_NOT_REMOVE', 'This dashboard is built-in and cannot be deleted', '响应消息->dashboard删除接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3082, '121032', 'en', 'CHART_TITLE_ISNULL', 'Chart title can not be empty', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3083, '121035', 'en', 'CHART_SPAN_ISNULL', 'Chart span can not be empty', '响应消息->charts调整大小/新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3084, '121047', 'en', 'CHART_HEIGHT_ISNULL', 'Chart height can not be empty', '响应消息->charts调整大小/新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3085, '121030', 'en', 'CHART_TYPE_ISNULL', 'Chart type can not be empty', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3087, '121052', 'en', 'CHART_ELEMENT_ISNULL', 'Chart element can not be empty', '响应消息->charts通过模板新增/新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3088, '123031', 'en', 'CHART_TYPE_INVALIDE', 'Chart type is invalide', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3089, '126042', 'en', 'CHART_PANEL_ISNULL', 'Panel is not exsits', '响应消息->charts调整顺序/新增/修改/复制、panel快照接口;上下文->定时发送快照邮件任务', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3090, '126043', 'en', 'CHART_NOTEXSITS', 'Chart is not exsits', '响应消息->module批量导入、asset model批量导入、panel快照接口;上下文->定时发送快照邮件任务', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3088, '123031', 'en', 'CHART_TYPE_INVALIDE', 'Chart type is invalide', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3090, '126043', 'en', 'CHART_NOTEXSITS', 'Chart is not exsits', '响应消息->module批量导入、asset model批量导入、dashboard快照接口;上下文->定时发送快照邮件任务', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3091, '121046', 'en', 'CHART_ID_ISNULL', 'Chart ID can not be empty', '响应消息->charts调整大小/修改/删除/顺序调整接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3098, '121028', 'en', 'CHART_URLPARAM_ISNULL', 'Chart param cannot be empty when type is url', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3099, '123038', 'en', 'CHART_PARAM_FORMAT', 'Chart param must be JSON format', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3101, '123039', 'en', 'CHART_PARAMURL_FORMAT', 'Chart param url value must be URL format', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3102, '121040', 'en', 'CHART_PARAMSINGLESTAT_ISNULL', 'Chart param statistics not found when type is singleStat', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3103, '124041', 'en', 'CHART_PARAMSINGLESTAT_INVALIDE', 'Chart param statistics must be min, max, average, total, first, last, range or different', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3104, '121036', 'en', 'CHART_SINGLESTATPARAM_ISNULL', 'Chart param cannot be empty when type is singleStat', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3105, '127056', 'en', 'CHART_BUILDIN_CAN_NOT_REMOVE', 'This chart is built-in and cannot be deleted', '响应消息->charts删除/模板同步、panel删除、asset修改/删除/取消导入、endpoint删除/取消导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3106, '121060', 'en', 'CHARTELEMENT_EXPRESSION_ISNULL', 'Chart element expression can not be empty', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3098, '121028', 'en', 'CHART_URLPARAM_ISNULL', 'Chart param cannot be empty when type is url', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3099, '123038', 'en', 'CHART_PARAM_FORMAT', 'Chart param must be JSON format', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3101, '123039', 'en', 'CHART_PARAMURL_FORMAT', 'Chart param url value must be URL format', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3102, '121040', 'en', 'CHART_PARAMSINGLESTAT_ISNULL', 'Chart param statistics not found when type is singleStat', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3103, '124041', 'en', 'CHART_PARAMSINGLESTAT_INVALIDE', 'Chart param statistics must be min, max, average, total, first, first*, last, last*, range or different', '响应消息->charts新增/修改、dashboard导入接口', '2023-02-16 08:39:53', 1); +INSERT INTO `sys_i18n` VALUES (3104, '121036', 'en', 'CHART_SINGLESTATPARAM_ISNULL', 'Chart param cannot be empty when type is singleStat', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3105, '127056', 'en', 'CHART_BUILDIN_CAN_NOT_REMOVE', 'This chart is built-in and cannot be deleted', '响应消息->charts删除/模板同步、dashboard删除、asset修改/删除/取消导入、endpoint删除/取消导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3106, '121060', 'en', 'CHARTELEMENT_EXPRESSION_ISNULL', 'Chart element expression can not be empty', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3107, '121057', 'en', 'CHARTELEMENT_TYPE_ISNULL', 'Chart element type can not be empty', '响应消息->charts新增/修改接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3108, '123058', 'en', 'CHARTELEMENT_TYPE_INVALIDE', 'Chart element type is invalide', '响应消息->charts新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3112, '126005', 'en', 'PANEL_NOT_EXIST', 'Panel does not exist', '响应消息->charts通过模板新增/新增/修改、panel修改/导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3122, '123022', 'en', 'CHART_WIDTH_FORMAT', 'Chart width format should be a integer', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3123, '123021', 'en', 'CHART_WIDTH_INVALIDE', 'Chart width should be between 1 and 12', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3124, '123049', 'en', 'CHART_HEIGHT_FORMAT', 'Chart height format should be a integer', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3125, '126029', 'en', 'CHART_UNIT_NOTFOUND', 'Chart unit not found', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3126, '123053', 'en', 'CHART_ELEMENTS_FORMAT', 'Chart elements must be JSON format', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3127, '123012', 'en', 'PANEL_CHART_TEMPLATE_TYPE_INCORRECT', 'Panel charts template type must be dashboard, asset, endpoint and template', '响应消息->panel导出/导入/模板下载接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3128, '121013', 'en', 'PANEL_CHART_IMPORT_LINKID_ISNULL', 'When the type is model or asset, link Id cannot be empty', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3129, '121011', 'en', 'PANEL_CHART_TEMPLATE_TYPE_ISNULL', 'Panel charts template type is null', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3130, '121033', 'en', 'CHART_TEXTPARAM_ISNULL', 'Chart param cannot be empty when type is text', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3112, '126005', 'en', 'DASHBOARD_NOT_EXIST', 'Dashboard does not exist', '响应消息->charts通过模板新增/新增/修改、dashboard修改/导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3122, '123022', 'en', 'CHART_WIDTH_FORMAT', 'Chart width format should be a integer', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3123, '123021', 'en', 'CHART_WIDTH_INVALIDE', 'Chart width should be between 1 and 12', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3124, '123049', 'en', 'CHART_HEIGHT_FORMAT', 'Chart height format should be a integer', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3125, '126029', 'en', 'CHART_UNIT_NOTFOUND', 'Chart unit not found', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3126, '123053', 'en', 'CHART_ELEMENTS_FORMAT', 'Chart elements must be JSON format', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3127, '123012', 'en', 'DASHBOARD_CHART_TEMPLATE_TYPE_INCORRECT', 'Dashboard charts template type must be dashboard, asset, endpoint and template', '响应消息->dashboard导出/导入/模板下载接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3129, '121011', 'en', 'DASHBOARD_CHART_TEMPLATE_TYPE_ISNULL', 'Dashboard import type is null', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3130, '121033', 'en', 'CHART_TEXTPARAM_ISNULL', 'Chart param cannot be empty when type is text', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3132, '121023', 'en', 'CHART_WEIGHT_ISNULL', 'Chart weight can not be empty', '响应消息->charts顺序调整接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3133, '121004', 'en', 'PANEL_PID_ISNULL', 'Panel pid can not be empty', '响应消息->panel顺序调整接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3134, '121001', 'en', 'PANEL_WEIGHT_ISNULL', 'Panel weight not be empty', '响应消息->panel顺序调整接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3135, '123008', 'en', 'PANEL_NAME_FORMAT_ERROR', 'Panel name format error, can not include \'/\'', '响应消息->panel新增/修改接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3133, '121004', 'en', 'DASHBOARD_PID_ISNULL', 'Dashboard pid can not be empty', '响应消息->dashboard顺序调整接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3134, '121001', 'en', 'DASHBOARD_WEIGHT_ISNULL', 'Dashboard weight not be empty', '响应消息->dashboard顺序调整接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3135, '123008', 'en', 'DASHBOARD_NAME_FORMAT_ERROR', 'Dashboard name format error, can not include \'/\'', '响应消息->dashboard新增/修改接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3136, '121051', 'en', 'CHART_GROUPID_ISNULL', 'Chart group id can not be empty', '响应消息->charts新增/修改接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3137, '121024', 'en', 'CHART_VARTYPE_ISNULL', 'Chart var type can not be empty when using templates', '响应消息->charts新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3137, '121024', 'en', 'CHART_VARTYPE_ISNULL', 'Chart var type can not be empty when using templates', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3138, '121037', 'en', 'CHART_PID_ISNULL', 'pid can not be empty', '响应消息->charts通过模板新增接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3139, '121026', 'en', 'CHART_VARID_ISNULL', 'varid can not be empty', '响应消息->charts通过模板新增接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3140, '121034', 'en', 'CHART_SYNCTMPL_ERROR', 'Chart sync param can not be null', '响应消息->charts模板同步接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3141, '121027', 'en', 'CHART_VARID_ERROR', 'varid param error', '响应消息->charts通过模板新增接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3142, '121050', 'en', 'CHART_GROUP_NAME_DUPLICATE', 'chart type is group name is duplicate', '响应消息->charts通过模板新增/新增/修改、panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3143, '123048', 'en', 'CHART_HEIGHT_INVALIDE', 'Chart height should be between 1 and 12', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3144, '123025', 'en', 'CHART_VARTYPE_ERROR', 'Chart var type must be Asset or Endpoint', '响应消息->panel导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3142, '121050', 'en', 'CHART_GROUP_NAME_DUPLICATE', 'chart type is group name is duplicate', '响应消息->charts通过模板新增/新增/修改、dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3143, '123048', 'en', 'CHART_HEIGHT_INVALIDE', 'Chart height should be between 1 and 12', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3144, '123025', 'en', 'CHART_VARTYPE_ERROR', 'Chart var type must be Asset or Endpoint', '响应消息->dashboard导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3145, '122045', 'en', 'CHART_NAME_DUPLICATE_NOTLINK', 'Chart name is duplicated and cannot be linked', '响应消息->module批量导入、asset model批量导入接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3146, '136008', 'en', 'EXPRETMPL_NOT_FOUND', 'Expression template not found', '响应消息->表达式模板详情接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3147, '131007', 'en', 'EXPRETMPL_NAME_ISNULL', 'Expression template name is null', '响应消息->表达式模板新增/修改/批量导入接口', '2021-11-02 00:00:00', 1); @@ -2258,7 +2256,7 @@ INSERT INTO `sys_i18n` VALUES (3572, '521011', 'en', 'AGENT_PARAM_MATCH_ISNULL', INSERT INTO `sys_i18n` VALUES (3573, '523012', 'en', 'AGENT_PORT_ERROR', 'Agent port is incorrect', '响应消息->agent新增/修改接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3574, '523013', 'en', 'AGENT_HOST_ERROR', 'Agent host is incorrect', '响应消息->agent新增/修改接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3575, '526014', 'en', 'AGENT_NOTEXSITS', 'Agent is not exsits', '响应消息->agent详情接口', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (3576, '526015', 'en', 'AGENT_EXIST_ERROR', 'Agent is exists : host,type,port repeat', '响应消息->agent新增/修改接口', '2021-11-02 00:00:00', 1); +INSERT INTO `sys_i18n` VALUES (3576, '526015', 'en', 'AGENT_EXIST_ERROR', 'Agent is exists : host,port repeat', '响应消息->agent新增/修改接口', '2023-03-02 02:31:07', 414); INSERT INTO `sys_i18n` VALUES (3577, '523016', 'en', 'AGENT_TYPE_INVALIDE', 'Agent type is incorrect', '响应消息->agent新增/修改接口', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3578, '526017', 'en', 'AGENT_UNAVAILABLE', 'No agent available', '响应消息->prometheus代理、loki代理接口;上下文->告警规则判断、资产ping状态更新、Endpoint状态更新任务', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3579, '521018', 'en', 'AGENT_TOKEN_ISNULL', 'Agent token info can not be empty', '响应消息->agent新增/修改接口', '2021-11-02 00:00:00', 1); @@ -2474,54 +2472,52 @@ INSERT INTO `sys_i18n` VALUES (3806, '715004', 'en', 'LICENSE_MAXIMUMASSETS_INVA INSERT INTO `sys_i18n` VALUES (3807, '715005', 'en', 'LICENSE_VERSION_INVALID', 'The version is not valid', '未在代码中使用', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3808, '999', 'en', 'ERROR', 'Error', '响应消息->请求发生错误', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (3810, '200', 'zh', 'SUCCESS', '成功', '响应消息->请求成功', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3811, '121007', 'zh', 'PANEL_NAME_ISNULL', '面板名称不能为空', '响应消息->panel新增/修改/导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3812, '121010', 'zh', 'PANEL_ID_ISNULL', '面板ID不能为空', '响应消息->panel修改/删除/复制/快照/顺序调整接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3813, '122009', 'zh', 'PANEL_NAME_DUPLICATE', '面板名称不能重复', '响应消息->panel新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3814, '121002', 'zh', 'PANEL_TYPE_ISNULL', '面板类型不能为空', '响应消息->panel新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3815, '124003', 'zh', 'PANEL_TYPE_INVALIDE', '面板类型不在允许范围内', '响应消息->panel新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3817, '127014', 'zh', 'PANEL_BUILDIN_CAN_NOT_REMOVE', '内置面板不能删除', '响应消息->panel删除接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3818, '121032', 'zh', 'CHART_TITLE_ISNULL', '图表标题不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3819, '121035', 'zh', 'CHART_SPAN_ISNULL', '图表宽度不能为空', '响应消息->charts调整大小/新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3820, '121047', 'zh', 'CHART_HEIGHT_ISNULL', '图表高度不能为空', '响应消息->charts调整大小/新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3821, '121030', 'zh', 'CHART_TYPE_ISNULL', '图表类型不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3811, '121007', 'zh', 'DASHBOARD_NAME_ISNULL', '面板名称不能为空', '响应消息->dashboard新增/修改/导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3812, '121010', 'zh', 'DASHBOARD_ID_ISNULL', '面板ID不能为空', '响应消息->dashboard修改/删除/复制/快照/顺序调整接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3813, '122009', 'zh', 'DASHBOARD_NAME_DUPLICATE', '面板名称不能重复', '响应消息->dashboard新增/修改接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3814, '121002', 'zh', 'DASHBOARD_TYPE_ISNULL', '面板类型不能为空', '响应消息->dashboard新增/修改接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3815, '124003', 'zh', 'DASHBOARD_TYPE_INVALIDE', '面板类型不在允许范围内', '响应消息->dashboard新增/修改接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3817, '127014', 'zh', 'DASHBOARD_BUILDIN_CAN_NOT_REMOVE', '内置面板不能删除', '响应消息->dashboard删除接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3818, '121032', 'zh', 'CHART_TITLE_ISNULL', '图表标题不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3819, '121035', 'zh', 'CHART_SPAN_ISNULL', '图表宽度不能为空', '响应消息->charts调整大小/新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3820, '121047', 'zh', 'CHART_HEIGHT_ISNULL', '图表高度不能为空', '响应消息->charts调整大小/新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3821, '121030', 'zh', 'CHART_TYPE_ISNULL', '图表类型不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3823, '121052', 'zh', 'CHART_ELEMENT_ISNULL', '图表查询表达式不能为空', '响应消息->charts通过模板新增/新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3824, '123031', 'zh', 'CHART_TYPE_INVALIDE', '图表类型不在允许范围内', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3825, '126042', 'zh', 'CHART_PANEL_ISNULL', '图表所关联面板属性不能为空', '响应消息->charts调整顺序/新增/修改/复制、panel快照接口;上下文->定时发送快照邮件任务', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3826, '126043', 'zh', 'CHART_NOTEXSITS', '图表不存在', '响应消息->module批量导入、asset model批量导入、panel快照接口;上下文->定时发送快照邮件任务', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3824, '123031', 'zh', 'CHART_TYPE_INVALIDE', '图表类型不在允许范围内', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3826, '126043', 'zh', 'CHART_NOTEXSITS', '图表不存在', '响应消息->module批量导入、asset model批量导入、dashboard快照接口;上下文->定时发送快照邮件任务', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3827, '121046', 'zh', 'CHART_ID_ISNULL', '图表ID不能为空', '响应消息->charts调整大小/修改/删除/顺序调整接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3834, '121028', 'zh', 'CHART_URLPARAM_ISNULL', '图表链接参数不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3835, '123038', 'zh', 'CHART_PARAM_FORMAT', '图表参数必须为json格式', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3837, '123039', 'zh', 'CHART_PARAMURL_FORMAT', '图表链接非正确网址', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3838, '121040', 'zh', 'CHART_PARAMSINGLESTAT_ISNULL', '图表类型为单值图时未找到图表参数统计信息', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3839, '124041', 'zh', 'CHART_PARAMSINGLESTAT_INVALIDE', '图表类型为单值图时,选择类型不在允许范围内', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3840, '121036', 'zh', 'CHART_SINGLESTATPARAM_ISNULL', '图表类型为单值图时,参数不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3841, '127056', 'zh', 'CHART_BUILDIN_CAN_NOT_REMOVE', '内置图表不能删除', '响应消息->charts删除/模板同步、panel删除、asset修改/删除/取消导入、endpoint删除/取消导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3842, '121060', 'zh', 'CHARTELEMENT_EXPRESSION_ISNULL', '图表查询表达式不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3834, '121028', 'zh', 'CHART_URLPARAM_ISNULL', '图表链接参数不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3835, '123038', 'zh', 'CHART_PARAM_FORMAT', '图表参数必须为json格式', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3837, '123039', 'zh', 'CHART_PARAMURL_FORMAT', '图表链接非正确网址', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3838, '121040', 'zh', 'CHART_PARAMSINGLESTAT_ISNULL', '图表类型为单值图时未找到图表参数统计信息', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3839, '124041', 'zh', 'CHART_PARAMSINGLESTAT_INVALIDE', '图表类型为单值图时,选择类型不在允许范围内', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3840, '121036', 'zh', 'CHART_SINGLESTATPARAM_ISNULL', '图表类型为单值图时,参数不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3841, '127056', 'zh', 'CHART_BUILDIN_CAN_NOT_REMOVE', '内置图表不能删除', '响应消息->charts删除/模板同步、dashboard删除、asset修改/删除/取消导入、endpoint删除/取消导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3842, '121060', 'zh', 'CHARTELEMENT_EXPRESSION_ISNULL', '图表查询表达式不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3843, '121057', 'zh', 'CHARTELEMENT_TYPE_ISNULL', '图表查询表达式类型不能为空', '响应消息->charts新增/修改接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3844, '123058', 'zh', 'CHARTELEMENT_TYPE_INVALIDE', '图表查询表达式类型不在允许范围内', '响应消息->charts新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3848, '126005', 'zh', 'PANEL_NOT_EXIST', '面板未创建', '响应消息->charts通过模板新增/新增/修改、panel修改/导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3858, '123022', 'zh', 'CHART_WIDTH_FORMAT', '图表宽度类型错误', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3859, '123021', 'zh', 'CHART_WIDTH_INVALIDE', '图表宽度应在1-12内', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3860, '123049', 'zh', 'CHART_HEIGHT_FORMAT', '图表高度类型错误', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3861, '126029', 'zh', 'CHART_UNIT_NOTFOUND', '图表单位不存在', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3862, '123053', 'zh', 'CHART_ELEMENTS_FORMAT', '图表查询表达式必须为json格式', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3863, '123012', 'zh', 'PANEL_CHART_TEMPLATE_TYPE_INCORRECT', '图表模板类型不在允许范围内', '响应消息->panel导出/导入/模板下载接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3864, '121013', 'zh', 'PANEL_CHART_IMPORT_LINKID_ISNULL', '图表模板类型为资产或型号时,链接不能为空', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3865, '121011', 'zh', 'PANEL_CHART_TEMPLATE_TYPE_ISNULL', '图表模板类型不能为空', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3866, '121033', 'zh', 'CHART_TEXTPARAM_ISNULL', '图表文本类型参数不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3848, '126005', 'zh', 'DASHBOARD_NOT_EXIST', '面板未创建', '响应消息->charts通过模板新增/新增/修改、dashboard修改/导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3858, '123022', 'zh', 'CHART_WIDTH_FORMAT', '图表宽度类型错误', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3859, '123021', 'zh', 'CHART_WIDTH_INVALIDE', '图表宽度应在1-12内', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3860, '123049', 'zh', 'CHART_HEIGHT_FORMAT', '图表高度类型错误', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3861, '126029', 'zh', 'CHART_UNIT_NOTFOUND', '图表单位不存在', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3862, '123053', 'zh', 'CHART_ELEMENTS_FORMAT', '图表查询表达式必须为json格式', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3863, '123012', 'zh', 'DASHBOARD_CHART_TEMPLATE_TYPE_INCORRECT', '图表模板类型不在允许范围内', '响应消息->dashboard导出/导入/模板下载接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3865, '121011', 'zh', 'DASHBOARD_CHART_TEMPLATE_TYPE_ISNULL', '面板导入类型不能为空', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3866, '121033', 'zh', 'CHART_TEXTPARAM_ISNULL', '图表文本类型参数不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3868, '121023', 'zh', 'CHART_WEIGHT_ISNULL', '图表排序权重不能为空', '响应消息->charts顺序调整接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3869, '121004', 'zh', 'PANEL_PID_ISNULL', '面板父面板ID不能为空', '响应消息->panel顺序调整接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3870, '121001', 'zh', 'PANEL_WEIGHT_ISNULL', '面板宽度不能为空', '响应消息->panel顺序调整接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3871, '123008', 'zh', 'PANEL_NAME_FORMAT_ERROR', '面板名称格式错误', '响应消息->panel新增/修改接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3869, '121004', 'zh', 'DASHBOARD_PID_ISNULL', '面板父面板ID不能为空', '响应消息->dashboard顺序调整接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3870, '121001', 'zh', 'DASHBOARD_WEIGHT_ISNULL', '面板宽度不能为空', '响应消息->dashboard顺序调整接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3871, '123008', 'zh', 'DASHBOARD_NAME_FORMAT_ERROR', '面板名称格式错误', '响应消息->dashboard新增/修改接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3872, '121051', 'zh', 'CHART_GROUPID_ISNULL', '图表组ID不能为空', '响应消息->charts新增/修改接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3873, '121024', 'zh', 'CHART_VARTYPE_ISNULL', '图表引用模板时,链接值不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3873, '121024', 'zh', 'CHART_VARTYPE_ISNULL', '图表引用模板时,链接值不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3874, '121037', 'zh', 'CHART_PID_ISNULL', '图表模板ID不能为空', '响应消息->charts通过模板新增接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3875, '121026', 'zh', 'CHART_VARID_ISNULL', '图表链接ID不能为空', '响应消息->charts通过模板新增接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3876, '121034', 'zh', 'CHART_SYNCTMPL_ERROR', '图表同步参数错误', '响应消息->charts模板同步接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3877, '121027', 'zh', 'CHART_VARID_ERROR', '图表链接ID错误', '响应消息->charts通过模板新增接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3878, '121050', 'zh', 'CHART_GROUP_NAME_DUPLICATE', '图表组名称重复', '响应消息->charts通过模板新增/新增/修改、panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3879, '123048', 'zh', 'CHART_HEIGHT_INVALIDE', '图表高度应在1-12内', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (3880, '123025', 'zh', 'CHART_VARTYPE_ERROR', '图表链接类型不在允许范围内', '响应消息->panel导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3878, '121050', 'zh', 'CHART_GROUP_NAME_DUPLICATE', '图表组名称重复', '响应消息->charts通过模板新增/新增/修改、dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3879, '123048', 'zh', 'CHART_HEIGHT_INVALIDE', '图表高度应在1-12内', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (3880, '123025', 'zh', 'CHART_VARTYPE_ERROR', '图表链接类型不在允许范围内', '响应消息->dashboard导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3881, '122045', 'zh', 'CHART_NAME_DUPLICATE_NOTLINK', '图表名称重复不能被链接', '响应消息->module批量导入、asset model批量导入接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3882, '136008', 'zh', 'EXPRETMPL_NOT_FOUND', '查询表达式模板不存在', '响应消息->表达式模板详情接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (3883, '131007', 'zh', 'EXPRETMPL_NAME_ISNULL', '查询表达式模板名称不能为空', '响应消息->表达式模板新增/修改/批量导入接口', '2021-11-03 16:28:05', 1); @@ -2817,7 +2813,7 @@ INSERT INTO `sys_i18n` VALUES (4308, '521011', 'zh', 'AGENT_PARAM_MATCH_ISNULL', INSERT INTO `sys_i18n` VALUES (4309, '523012', 'zh', 'AGENT_PORT_ERROR', '客户端端口错误', '响应消息->agent新增/修改接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (4310, '523013', 'zh', 'AGENT_HOST_ERROR', '客户端IP地址错误', '响应消息->agent新增/修改接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (4311, '526014', 'zh', 'AGENT_NOTEXSITS', '客户端不存在', '响应消息->agent详情接口', '2021-11-03 16:28:05', 1); -INSERT INTO `sys_i18n` VALUES (4312, '526015', 'zh', 'AGENT_EXIST_ERROR', '客户端已存在,类型 端口或IP重复', '响应消息->agent新增/修改接口', '2021-11-03 16:28:05', 1); +INSERT INTO `sys_i18n` VALUES (4312, '526015', 'zh', 'AGENT_EXIST_ERROR', '客户端已存在: IP ,端口重复', '响应消息->agent新增/修改接口', '2023-03-02 02:31:38', 414); INSERT INTO `sys_i18n` VALUES (4313, '523016', 'zh', 'AGENT_TYPE_INVALIDE', '客户端类型错误', '响应消息->agent新增/修改接口', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (4314, '526017', 'zh', 'AGENT_UNAVAILABLE', '客户端不可用', '响应消息->prometheus代理、loki代理接口;上下文->告警规则判断、资产ping状态更新、Endpoint状态更新任务', '2021-11-03 16:28:05', 1); INSERT INTO `sys_i18n` VALUES (4315, '521018', 'zh', 'AGENT_TOKEN_ISNULL', '客户端token不能为空', '响应消息->agent新增/修改接口', '2021-11-03 16:28:05', 1); @@ -3040,7 +3036,7 @@ INSERT INTO `sys_i18n` VALUES (4552, 'el.pagination.pageClassifier', 'en', 'el.p INSERT INTO `sys_i18n` VALUES (4553, 'el.upload.preview', 'en', 'el.upload.preview', 'Preview', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4554, 'el.upload.continue', 'en', 'el.upload.continue', 'Continue', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4556, 'el.upload.deleteTip', 'en', 'el.upload.deleteTip', 'press delete to remove', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (4560, 'el.datepicker.nextMonth', 'en', 'el.datepicker.nextMonth', 'Next Month', '时间组件/', '2022-07-25 07:42:38', 425); +INSERT INTO `sys_i18n` VALUES (4560, 'el.datepicker.nextMonth', 'en', 'el.datepicker.nextMonth', 'Next month', '时间组件/', '2022-12-14 09:13:00', 415); INSERT INTO `sys_i18n` VALUES (4561, 'el.datepicker.week', 'en', 'el.datepicker.week', 'week', ' \nel时间组件/', '2022-07-25 07:43:03', 425); INSERT INTO `sys_i18n` VALUES (4562, 'el.datepicker.weeks.thu', 'en', 'el.datepicker.weeks.thu', 'Thu', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4563, 'el.datepicker.weeks.tue', 'en', 'el.datepicker.weeks.tue', 'Tue', '', '2021-11-02 00:00:00', 1); @@ -3049,15 +3045,15 @@ INSERT INTO `sys_i18n` VALUES (4565, 'el.datepicker.weeks.sat', 'en', 'el.datepi INSERT INTO `sys_i18n` VALUES (4566, 'el.datepicker.weeks.fri', 'en', 'el.datepicker.weeks.fri', 'Fri', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4567, 'el.datepicker.weeks.sun', 'en', 'el.datepicker.weeks.sun', 'Sun', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4568, 'el.datepicker.weeks.mon', 'en', 'el.datepicker.weeks.mon', 'Mon', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (4569, 'el.datepicker.endDate', 'en', 'el.datepicker.endDate', 'End Date', 'el时间组件/', '2022-07-25 07:43:32', 425); +INSERT INTO `sys_i18n` VALUES (4569, 'el.datepicker.endDate', 'en', 'el.datepicker.endDate', 'End date', 'el时间组件/', '2022-12-14 09:13:10', 415); INSERT INTO `sys_i18n` VALUES (4570, 'el.datepicker.year', 'en', 'el.datepicker.year', '-', 'el时间组件/', '2022-07-25 07:44:46', 425); INSERT INTO `sys_i18n` VALUES (4571, 'el.datepicker.selectDate', 'en', 'el.datepicker.selectDate', 'Select date', ' \nel时间组件/', '2022-07-25 07:45:31', 425); INSERT INTO `sys_i18n` VALUES (4572, 'el.datepicker.month12', 'en', 'el.datepicker.month12', 'December', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (4573, 'el.datepicker.prevMonth', 'en', 'el.datepicker.prevMonth', 'Previous Month', 'el时间组件/\n与dashboard.panel.prevMonth 一样, 第二个字母大小写不同,这个value更改不了', '2022-07-25 07:46:20', 425); +INSERT INTO `sys_i18n` VALUES (4573, 'el.datepicker.prevMonth', 'en', 'el.datepicker.prevMonth', 'Previous month', 'el时间组件/\n与dashboard.dashboard.prevMonth 一样, 第二个字母大小写不同,这个value更改不了', '2022-12-14 09:12:30', 415); INSERT INTO `sys_i18n` VALUES (4574, 'el.datepicker.month11', 'en', 'el.datepicker.month11', 'November', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4575, 'el.datepicker.now', 'en', 'el.datepicker.now', 'Now', 'el时间组件/', '2022-07-25 07:47:02', 425); INSERT INTO `sys_i18n` VALUES (4576, 'el.datepicker.today', 'en', 'el.datepicker.today', 'Today', '', '2021-11-02 00:00:00', 1); -INSERT INTO `sys_i18n` VALUES (4578, 'el.datepicker.prevYear', 'en', 'el.datepicker.prevYear', 'Previous Year', 'el时间组件/', '2022-07-25 07:48:08', 425); +INSERT INTO `sys_i18n` VALUES (4578, 'el.datepicker.prevYear', 'en', 'el.datepicker.prevYear', 'Previous year', 'el时间组件/', '2022-12-14 09:12:39', 415); INSERT INTO `sys_i18n` VALUES (4579, 'el.datepicker.month1', 'en', 'el.datepicker.month1', 'January', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4580, 'el.datepicker.month2', 'en', 'el.datepicker.month2', 'February', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4581, 'el.datepicker.month3', 'en', 'el.datepicker.month3', 'March', '', '2021-11-02 00:00:00', 1); @@ -3080,8 +3076,8 @@ INSERT INTO `sys_i18n` VALUES (4600, 'el.datepicker.month8', 'en', 'el.datepicke INSERT INTO `sys_i18n` VALUES (4601, 'el.datepicker.month9', 'en', 'el.datepicker.month9', 'September', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4602, 'el.datepicker.month10', 'en', 'el.datepicker.month10', 'October', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4603, 'el.datepicker.confirm', 'en', 'el.datepicker.confirm', 'OK', ' \nel时间组件/', '2022-07-25 07:49:59', 425); -INSERT INTO `sys_i18n` VALUES (4604, 'el.datepicker.nextYear', 'en', 'el.datepicker.nextYear', 'Next Year', ' \nel时间组件/', '2022-07-25 07:50:50', 425); -INSERT INTO `sys_i18n` VALUES (4606, 'el.datepicker.startDate', 'en', 'el.datepicker.startDate', 'Start Date', ' \nel时间组件/', '2022-07-25 07:51:03', 425); +INSERT INTO `sys_i18n` VALUES (4604, 'el.datepicker.nextYear', 'en', 'el.datepicker.nextYear', 'Next year', 'el时间组件/', '2022-12-14 09:12:02', 415); +INSERT INTO `sys_i18n` VALUES (4606, 'el.datepicker.startDate', 'en', 'el.datepicker.startDate', 'Start date', 'el时间组件/', '2022-12-14 09:12:09', 415); INSERT INTO `sys_i18n` VALUES (4614, 'el.transfer.noCheckedFormat', 'en', 'el.transfer.noCheckedFormat', '{total} items', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4616, 'el.transfer.hasCheckedFormat', 'en', 'el.transfer.hasCheckedFormat', '{checked}/{total} checked', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4617, 'el.transfer.filterPlaceholder', 'en', 'el.transfer.filterPlaceholder', 'Enter keyword', '', '2021-11-02 00:00:00', 1); @@ -3092,8 +3088,8 @@ INSERT INTO `sys_i18n` VALUES (4628, 'el.table.sumText', 'en', 'el.table.sumText INSERT INTO `sys_i18n` VALUES (4631, 'el.table.confirmFilter', 'en', 'el.table.confirmFilter', 'Confirm', '', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (4721, 'config.menus.lang', 'en', 'config.menus.lang', 'Lang', '', '2021-11-04 05:59:15', 1); INSERT INTO `sys_i18n` VALUES (4722, 'config.menus.lang', 'zh', 'config.menus.lang', '语言', '', '2021-11-04 05:59:36', 1); -INSERT INTO `sys_i18n` VALUES (4725, 'config.menus.createI18n', 'en', 'config.menus.createI18n', 'New I18N', '系统配置/I18N/新增 按钮\n', '2022-07-25 08:23:04', 425); -INSERT INTO `sys_i18n` VALUES (4726, 'config.menus.editI18n', 'en', 'config.menus.editI18n', 'Edit I18N', ' \n系统配置/I18N/编辑 按钮', '2022-07-25 08:23:45', 425); +INSERT INTO `sys_i18n` VALUES (4725, 'config.menus.createI18n', 'en', 'config.menus.createI18n', 'New i18N', '系统配置/I18N/新增 按钮', '2022-12-14 09:09:13', 415); +INSERT INTO `sys_i18n` VALUES (4726, 'config.menus.editI18n', 'en', 'config.menus.editI18n', 'Edit i18N', '系统配置/I18N/编辑 按钮', '2022-12-14 09:11:32', 415); INSERT INTO `sys_i18n` VALUES (4727, 'config.menus.editI18n', 'zh', 'config.menus.editI18n', '编辑 I18N', '系统配置/I18N/编辑 按钮', '2022-07-25 08:23:41', 425); INSERT INTO `sys_i18n` VALUES (4728, 'config.menus.createI18n', 'zh', 'config.menus.createI18n', '新增 I18N', '系统配置/I18N/新增 按钮\n', '2022-07-25 08:23:01', 425); INSERT INTO `sys_i18n` VALUES (4729, 'overall.alertRuleEvalLog', 'en', 'overall.alertRuleEvalLog', 'Evaluation log', '告警/告警规则/prop name\n', '2022-07-25 08:25:32', 425); @@ -3103,12 +3099,12 @@ INSERT INTO `sys_i18n` VALUES (4732, 'alert.alertRuleMessage', 'zh', 'alert.aler INSERT INTO `sys_i18n` VALUES (4734, 'overall.active', 'en', 'overall.active', 'Active', '告警/告警信息/已激活;\n系统配置/模板/图表模板/;\n\n', '2022-07-25 08:30:18', 425); INSERT INTO `sys_i18n` VALUES (4735, 'overall.allData', 'en', 'overall.allData', 'All data', '告警/告警信息/所有数据; ', '2022-07-25 08:31:19', 425); INSERT INTO `sys_i18n` VALUES (4736, 'overall.selectRecords', 'en', 'overall.selectRecords', 'Select records', '告警/告警信息/选择记录;', '2022-07-25 08:32:35', 425); -INSERT INTO `sys_i18n` VALUES (4737, 'overall.current', 'en', 'overall.current', 'Current Page', ' \n告警/告警信息/导出/当前页;', '2022-07-25 08:33:27', 425); +INSERT INTO `sys_i18n` VALUES (4737, 'overall.current', 'en', 'overall.current', 'Current page', '告警/告警信息/导出/当前页;', '2022-12-13 02:56:34', 415); INSERT INTO `sys_i18n` VALUES (4738, 'overall.current', 'zh', 'overall.current', '当前页', ' \n告警/告警信息/导出/当前页;', '2022-07-25 08:33:21', 425); INSERT INTO `sys_i18n` VALUES (4739, 'overall.selectRecords', 'zh', 'overall.selectRecords', '选择记录', '告警/告警信息/选择记录;', '2022-07-25 08:32:29', 425); INSERT INTO `sys_i18n` VALUES (4740, 'overall.allData', 'zh', 'overall.allData', '所有数据', '告警/告警信息/所有数据; ', '2022-07-25 08:31:15', 425); -INSERT INTO `sys_i18n` VALUES (4743, 'overall.more', 'en', 'overall.more', 'More', 'panel/更多;\n资产/资产列表/更多;\n资产/数据中心/更多;\n资产/资产配置/型号/更多;\n资产/资产配置/属性/更多;\n\n监控/应用/更多;\n监控/应用实例/更多;\n告警/告警信息/更多;\n告警/告警规则/更多;\n系统配置/IPAM/更多;\n系统配置/模板/表达式模板/更多;\n系统配置/模板/图表模板/更多;\n\n\n\n\n\n\n\n\n\n\n', '2022-07-25 08:40:43', 425); -INSERT INTO `sys_i18n` VALUES (4744, 'overall.more', 'zh', 'overall.more', '更多', 'panel/更多;\n资产/资产列表/更多;\n资产/数据中心/更多;\n资产/资产配置/型号/更多;\n资产/资产配置/属性/更多;\n\n监控/应用/更多;\n监控/应用实例/更多;\n告警/告警信息/更多;\n告警/告警规则/更多;\n系统配置/IPAM/更多;\n系统配置/模板/表达式模板/更多;\n系统配置/模板/图表模板/更多;\n\n\n\n\n\n\n\n\n\n\n', '2022-07-25 08:40:38', 425); +INSERT INTO `sys_i18n` VALUES (4743, 'overall.more', 'en', 'overall.more', 'More', 'dashboard/更多;\n资产/资产列表/更多;\n资产/数据中心/更多;\n资产/资产配置/型号/更多;\n资产/资产配置/属性/更多;\n\n监控/应用/更多;\n监控/应用实例/更多;\n告警/告警信息/更多;\n告警/告警规则/更多;\n系统配置/IPAM/更多;\n系统配置/模板/表达式模板/更多;\n系统配置/模板/图表模板/更多;\n\n\n\n\n\n\n\n\n\n\n', '2022-07-25 08:40:43', 425); +INSERT INTO `sys_i18n` VALUES (4744, 'overall.more', 'zh', 'overall.more', '更多', 'dashboard/更多;\n资产/资产列表/更多;\n资产/数据中心/更多;\n资产/资产配置/型号/更多;\n资产/资产配置/属性/更多;\n\n监控/应用/更多;\n监控/应用实例/更多;\n告警/告警信息/更多;\n告警/告警规则/更多;\n系统配置/IPAM/更多;\n系统配置/模板/表达式模板/更多;\n系统配置/模板/图表模板/更多;\n\n\n\n\n\n\n\n\n\n\n', '2022-07-25 08:40:38', 425); INSERT INTO `sys_i18n` VALUES (4747, 'project.endpoint.item', 'en', 'project.endpoint.item', 'Item', '监控/应用实例/title;\n监控/应用/title;\n\n', '2022-07-25 08:42:10', 425); INSERT INTO `sys_i18n` VALUES (4748, 'project.endpoint.item', 'zh', 'project.endpoint.item', '项目', '监控/应用实例/title;\n监控/应用/title;\n\n', '2022-07-25 08:42:06', 425); INSERT INTO `sys_i18n` VALUES (4749, 'overall.addParameter', 'en', 'overall.addParameter', 'Add parameter', '监控/应用实例/修改应用实例/添加参数提示;\n', '2022-07-25 08:43:55', 425); @@ -3138,7 +3134,7 @@ INSERT INTO `sys_i18n` VALUES (4772, 'config.system.basic.num', 'zh', 'config.sy INSERT INTO `sys_i18n` VALUES (4773, 'config.system.basic.lower', 'en', 'config.system.basic.lower', 'Lower case letters', '系统配置/个性化配置/小写字母;', '2022-07-25 08:53:30', 425); INSERT INTO `sys_i18n` VALUES (4774, 'config.system.basic.lower', 'zh', 'config.system.basic.lower', '小写字母', '系统配置/个性化配置/小写字母;', '2022-07-25 08:53:24', 425); INSERT INTO `sys_i18n` VALUES (4775, 'config.system.basic.upper', 'zh', 'config.system.basic.upper', '大写字母', '系统配置/个性化配置/大写字母;', '2022-07-25 08:53:38', 425); -INSERT INTO `sys_i18n` VALUES (4776, 'config.system.basic.upper', 'en', 'config.system.basic.upper', 'Uppercase letter', '系统配置/个性化配置/大写字母;', '2022-07-25 08:53:42', 425); +INSERT INTO `sys_i18n` VALUES (4776, 'config.system.basic.upper', 'en', 'config.system.basic.upper', 'Uppercase letters', '系统配置/个性化配置/大写字母;', '2022-12-15 02:33:18', 415); INSERT INTO `sys_i18n` VALUES (4777, 'config.system.basic.spec', 'zh', 'config.system.basic.spec', '特殊字符', '系统配置/个性化配置/特殊字符;', '2022-07-25 08:53:50', 425); INSERT INTO `sys_i18n` VALUES (4778, 'config.system.basic.spec', 'en', 'config.system.basic.spec', 'Special characters', '系统配置/个性化配置/特殊字符;', '2022-07-25 08:53:54', 425); INSERT INTO `sys_i18n` VALUES (4779, 'config.system.basic.retry', 'en', 'config.system.basic.retry', 'Number of errors', '系统配置/个性化配置/错误次数;', '2022-07-25 08:54:09', 425); @@ -3168,54 +3164,54 @@ INSERT INTO `sys_i18n` VALUES (4802, 'validate.repeat', 'zh', 'validate.repeat', INSERT INTO `sys_i18n` VALUES (4803, 'config.assetType.vm', 'zh', 'config.assetType.vm', 'VM', '资产/资产列表/vm', '2022-07-25 09:05:27', 425); INSERT INTO `sys_i18n` VALUES (4804, 'config.assetType.vmh', 'zh', 'config.assetType.vmh', 'VMH', ' \n资产/资产列表/VMH', '2022-07-25 09:05:46', 425); INSERT INTO `sys_i18n` VALUES (4805, 'config.assetType.snmpEnable', 'zh', 'config.assetType.snmpEnable', '启用 SNMP', '\n资产/资产列表/ \n启用 SNMP', '2022-07-25 09:06:07', 425); -INSERT INTO `sys_i18n` VALUES (4806, '121054', 'en', 'CHART_DATASOURCE_ISNULL', 'Chart datasource can not be null', '响应消息->charts新增/修改、panel导入接口', '2021-11-29 15:03:27', 1); -INSERT INTO `sys_i18n` VALUES (4807, '121054', 'zh', 'CHART_DATASOURCE_ISNULL', '图表数据源不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-11-29 15:03:49', 1); -INSERT INTO `sys_i18n` VALUES (4808, '121055', 'en', 'CHART_DATASOURCE_INVALIDE', 'Chart datasource must be metrics,logs,system,misc', '响应消息->charts新增/修改、panel导入接口', '2021-11-29 15:05:45', 1); -INSERT INTO `sys_i18n` VALUES (4809, '121055', 'zh', 'CHART_DATASOURCE_INVALIDE', '图表数据源类型必须为指标,日志,系统或其它', '响应消息->charts新增/修改、panel导入接口', '2021-11-29 15:05:48', 1); -INSERT INTO `sys_i18n` VALUES (4810, 'dashboard.panel.chartForm.dataConfig', 'en', 'dashboard.panel.chartForm.dataConfig', 'Data configurations', 'panel/title', '2022-07-25 09:07:15', 425); -INSERT INTO `sys_i18n` VALUES (4811, 'dashboard.panel.chartForm.dataConfig', 'zh', 'dashboard.panel.chartForm.dataConfig', '数据配置', 'panel/title', '2022-07-25 09:07:12', 425); -INSERT INTO `sys_i18n` VALUES (4834, 'dashboard.panel.chartForm.displayConfig', 'en', 'dashboard.panel.chartForm.displayConfig', 'Display configurations', 'panel/title', '2022-07-25 09:08:49', 425); -INSERT INTO `sys_i18n` VALUES (4835, 'dashboard.panel.chartForm.displayConfig', 'zh', 'dashboard.panel.chartForm.displayConfig', '显示配置', ' \npanel/title', '2022-07-25 09:09:02', 425); -INSERT INTO `sys_i18n` VALUES (4836, 'dashboard.panel.chartForm.stack', 'en', 'dashboard.panel.chartForm.stack', 'Stack', 'panel/', '2022-07-25 09:11:21', 425); -INSERT INTO `sys_i18n` VALUES (4837, 'dashboard.panel.chartForm.stack', 'zh', 'dashboard.panel.chartForm.stack', '堆叠', 'panel/', '2022-07-25 09:11:25', 425); -INSERT INTO `sys_i18n` VALUES (4838, 'dashboard.panel.chartForm.legendPosition', 'en', 'dashboard.panel.chartForm.legendPosition', 'Placement', 'panel/', '2022-07-25 09:11:28', 425); -INSERT INTO `sys_i18n` VALUES (4839, 'dashboard.panel.chartForm.legendPosition', 'zh', 'dashboard.panel.chartForm.legendPosition', '布局', 'panel/', '2022-07-25 09:11:31', 425); -INSERT INTO `sys_i18n` VALUES (4840, 'dashboard.panel.chartForm.legendValues', 'en', 'dashboard.panel.chartForm.legendValues', 'Values', 'panel/', '2022-07-25 09:11:35', 425); -INSERT INTO `sys_i18n` VALUES (4841, 'dashboard.panel.chartForm.legendValues', 'zh', 'dashboard.panel.chartForm.legendValues', 'Values', 'panel/', '2022-07-25 09:11:38', 425); -INSERT INTO `sys_i18n` VALUES (4842, 'dashboard.panel.chartForm.valueMapping', 'en', 'dashboard.panel.chartForm.valueMapping', 'Value mappings', 'panel/', '2022-07-25 09:11:41', 425); -INSERT INTO `sys_i18n` VALUES (4843, 'dashboard.panel.chartForm.valueMapping', 'zh', 'dashboard.panel.chartForm.valueMapping', '映射值', 'panel/', '2022-07-25 09:11:45', 425); -INSERT INTO `sys_i18n` VALUES (4844, 'dashboard.panel.chartForm.typeVal.point.label', 'en', 'dashboard.panel.chartForm.typeVal.point.label', 'Point', 'panel/', '2022-07-25 09:11:48', 425); -INSERT INTO `sys_i18n` VALUES (4845, 'dashboard.panel.chartForm.typeVal.point.label', 'zh', 'dashboard.panel.chartForm.typeVal.point.label', '散点图', 'panel/', '2022-07-25 09:11:52', 425); -INSERT INTO `sys_i18n` VALUES (4846, 'dashboard.panel.chartForm.typeVal.gauge.label', 'en', 'dashboard.panel.chartForm.typeVal.gauge.label', 'Guage', 'panel/', '2022-07-25 09:11:56', 425); -INSERT INTO `sys_i18n` VALUES (4847, 'dashboard.panel.chartForm.typeVal.gauge.label', 'zh', 'dashboard.panel.chartForm.typeVal.gauge.label', 'Guage', 'panel/', '2022-07-25 09:12:00', 425); -INSERT INTO `sys_i18n` VALUES (4848, 'dashboard.panel.chartForm.typeVal.treemap.label', 'en', 'dashboard.panel.chartForm.typeVal.treemap.label', 'Treemap', 'panel/', '2022-07-25 09:12:04', 425); -INSERT INTO `sys_i18n` VALUES (4849, 'dashboard.panel.chartForm.typeVal.treemap.label', 'zh', 'dashboard.panel.chartForm.typeVal.treemap.label', 'Treemap', 'panel/', '2022-07-25 09:12:08', 425); -INSERT INTO `sys_i18n` VALUES (4850, 'dashboard.panel.chartForm.typeVal.log.label', 'en', 'dashboard.panel.chartForm.typeVal.log.label', 'Log', 'panel/', '2022-07-25 09:12:12', 425); -INSERT INTO `sys_i18n` VALUES (4851, 'dashboard.panel.chartForm.typeVal.log.label', 'zh', 'dashboard.panel.chartForm.typeVal.log.label', '日志', 'panel/', '2022-07-25 09:12:15', 425); -INSERT INTO `sys_i18n` VALUES (4852, 'dashboard.panel.chartForm.tableIndex', 'en', 'dashboard.panel.chartForm.tableIndex', 'Unique label', 'panel/', '2022-07-25 09:12:19', 425); -INSERT INTO `sys_i18n` VALUES (4853, 'dashboard.panel.chartForm.tableIndex', 'zh', 'dashboard.panel.chartForm.tableIndex', '独一无二的标签', 'panel/', '2022-07-25 09:12:30', 425); -INSERT INTO `sys_i18n` VALUES (4854, 'dashboard.panel.chartForm.sort', 'en', 'dashboard.panel.chartForm.sort', 'Sort', 'panel/', '2022-07-25 09:12:33', 425); -INSERT INTO `sys_i18n` VALUES (4855, 'dashboard.panel.chartForm.sort', 'zh', 'dashboard.panel.chartForm.sort', '排序', 'panel/', '2022-07-25 09:12:37', 425); -INSERT INTO `sys_i18n` VALUES (4856, 'dashboard.explore.ascending', 'en', 'dashboard.explore.ascending', 'Ascending', 'panel/', '2022-07-25 09:12:41', 425); -INSERT INTO `sys_i18n` VALUES (4857, 'dashboard.explore.ascending', 'zh', 'dashboard.explore.ascending', '升序', 'panel/', '2022-07-25 09:12:48', 425); -INSERT INTO `sys_i18n` VALUES (4874, 'dashboard.panel.chartForm.select', 'en', 'dashboard.panel.chartForm.select', 'Value', 'panel/', '2022-07-25 09:12:52', 425); -INSERT INTO `sys_i18n` VALUES (4875, 'dashboard.panel.chartForm.select', 'zh', 'dashboard.panel.chartForm.select', '统计值', 'panel/', '2022-07-25 09:12:58', 425); -INSERT INTO `sys_i18n` VALUES (4876, 'dashboard.panel.chartForm.result', 'en', 'dashboard.panel.chartForm.result', 'Result ', 'panel/', '2022-07-25 09:13:02', 425); -INSERT INTO `sys_i18n` VALUES (4877, 'dashboard.panel.chartForm.result', 'zh', 'dashboard.panel.chartForm.result', '结果', 'panel/', '2022-07-25 09:13:08', 425); -INSERT INTO `sys_i18n` VALUES (4878, 'placeholder.chart.threshold', 'en', 'placeholder.chart.threshold', 'Please input threshold. Click on the left color bar to adjust the threshold color', '监控/应用实例/提示;\npanel/\n', '2022-07-25 09:17:54', 425); -INSERT INTO `sys_i18n` VALUES (4879, 'placeholder.chart.threshold', 'zh', 'placeholder.chart.threshold', '请输入阈值。点击左侧色块调整阈值颜色', '监控/应用实例/提示;\npanel/\n\n', '2022-07-25 09:17:58', 425); +INSERT INTO `sys_i18n` VALUES (4806, '121054', 'en', 'CHART_DATASOURCE_ISNULL', 'Chart datasource can not be null', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-29 15:03:27', 1); +INSERT INTO `sys_i18n` VALUES (4807, '121054', 'zh', 'CHART_DATASOURCE_ISNULL', '图表数据源不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-29 15:03:49', 1); +INSERT INTO `sys_i18n` VALUES (4808, '121055', 'en', 'CHART_DATASOURCE_INVALIDE', 'Chart datasource must be metrics,logs,system,misc', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-29 15:05:45', 1); +INSERT INTO `sys_i18n` VALUES (4809, '121055', 'zh', 'CHART_DATASOURCE_INVALIDE', '图表数据源类型必须为指标,日志,系统或其它', '响应消息->charts新增/修改、dashboard导入接口', '2021-11-29 15:05:48', 1); +INSERT INTO `sys_i18n` VALUES (4810, 'dashboard.dashboard.chartForm.dataConfig', 'en', 'dashboard.dashboard.chartForm.dataConfig', 'Data configurations', 'dashboard/title', '2022-07-25 09:07:15', 425); +INSERT INTO `sys_i18n` VALUES (4811, 'dashboard.dashboard.chartForm.dataConfig', 'zh', 'dashboard.dashboard.chartForm.dataConfig', '数据配置', 'dashboard/title', '2022-07-25 09:07:12', 425); +INSERT INTO `sys_i18n` VALUES (4834, 'dashboard.dashboard.chartForm.displayConfig', 'en', 'dashboard.dashboard.chartForm.displayConfig', 'Display configurations', 'dashboard/title', '2022-07-25 09:08:49', 425); +INSERT INTO `sys_i18n` VALUES (4835, 'dashboard.dashboard.chartForm.displayConfig', 'zh', 'dashboard.dashboard.chartForm.displayConfig', '显示配置', ' \ndashboard/title', '2022-07-25 09:09:02', 425); +INSERT INTO `sys_i18n` VALUES (4836, 'dashboard.dashboard.chartForm.stack', 'en', 'dashboard.dashboard.chartForm.stack', 'Stack', 'dashboard/', '2022-07-25 09:11:21', 425); +INSERT INTO `sys_i18n` VALUES (4837, 'dashboard.dashboard.chartForm.stack', 'zh', 'dashboard.dashboard.chartForm.stack', '堆叠', 'dashboard/', '2022-07-25 09:11:25', 425); +INSERT INTO `sys_i18n` VALUES (4838, 'dashboard.dashboard.chartForm.legendPosition', 'en', 'dashboard.dashboard.chartForm.legendPosition', 'Placement', 'dashboard/', '2022-07-25 09:11:28', 425); +INSERT INTO `sys_i18n` VALUES (4839, 'dashboard.dashboard.chartForm.legendPosition', 'zh', 'dashboard.dashboard.chartForm.legendPosition', '布局', 'dashboard/', '2022-07-25 09:11:31', 425); +INSERT INTO `sys_i18n` VALUES (4840, 'dashboard.dashboard.chartForm.legendValues', 'en', 'dashboard.dashboard.chartForm.legendValues', 'Values', 'dashboard/', '2022-07-25 09:11:35', 425); +INSERT INTO `sys_i18n` VALUES (4841, 'dashboard.dashboard.chartForm.legendValues', 'zh', 'dashboard.dashboard.chartForm.legendValues', 'Values', 'dashboard/', '2022-07-25 09:11:38', 425); +INSERT INTO `sys_i18n` VALUES (4842, 'dashboard.dashboard.chartForm.valueMapping', 'en', 'dashboard.dashboard.chartForm.valueMapping', 'Value mappings', 'dashboard/', '2022-07-25 09:11:41', 425); +INSERT INTO `sys_i18n` VALUES (4843, 'dashboard.dashboard.chartForm.valueMapping', 'zh', 'dashboard.dashboard.chartForm.valueMapping', '映射值', 'dashboard/', '2022-07-25 09:11:45', 425); +INSERT INTO `sys_i18n` VALUES (4844, 'dashboard.dashboard.chartForm.typeVal.point.label', 'en', 'dashboard.dashboard.chartForm.typeVal.point.label', 'Point', 'dashboard/', '2022-07-25 09:11:48', 425); +INSERT INTO `sys_i18n` VALUES (4845, 'dashboard.dashboard.chartForm.typeVal.point.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.point.label', '散点图', 'dashboard/', '2022-07-25 09:11:52', 425); +INSERT INTO `sys_i18n` VALUES (4846, 'dashboard.dashboard.chartForm.typeVal.gauge.label', 'en', 'dashboard.dashboard.chartForm.typeVal.gauge.label', 'Guage', 'dashboard/', '2022-07-25 09:11:56', 425); +INSERT INTO `sys_i18n` VALUES (4847, 'dashboard.dashboard.chartForm.typeVal.gauge.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.gauge.label', 'Guage', 'dashboard/', '2022-07-25 09:12:00', 425); +INSERT INTO `sys_i18n` VALUES (4848, 'dashboard.dashboard.chartForm.typeVal.treemap.label', 'en', 'dashboard.dashboard.chartForm.typeVal.treemap.label', 'Treemap', 'dashboard/', '2022-07-25 09:12:04', 425); +INSERT INTO `sys_i18n` VALUES (4849, 'dashboard.dashboard.chartForm.typeVal.treemap.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.treemap.label', 'Treemap', 'dashboard/', '2022-07-25 09:12:08', 425); +INSERT INTO `sys_i18n` VALUES (4850, 'dashboard.dashboard.chartForm.typeVal.log.label', 'en', 'dashboard.dashboard.chartForm.typeVal.log.label', 'Log', 'dashboard/', '2022-07-25 09:12:12', 425); +INSERT INTO `sys_i18n` VALUES (4851, 'dashboard.dashboard.chartForm.typeVal.log.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.log.label', '日志', 'dashboard/', '2022-07-25 09:12:15', 425); +INSERT INTO `sys_i18n` VALUES (4852, 'dashboard.dashboard.chartForm.tableIndex', 'en', 'dashboard.dashboard.chartForm.tableIndex', 'Unique label', 'dashboard/', '2022-07-25 09:12:19', 425); +INSERT INTO `sys_i18n` VALUES (4853, 'dashboard.dashboard.chartForm.tableIndex', 'zh', 'dashboard.dashboard.chartForm.tableIndex', '独一无二的标签', 'dashboard/', '2022-07-25 09:12:30', 425); +INSERT INTO `sys_i18n` VALUES (4854, 'dashboard.dashboard.chartForm.sort', 'en', 'dashboard.dashboard.chartForm.sort', 'Sort', 'dashboard/', '2022-07-25 09:12:33', 425); +INSERT INTO `sys_i18n` VALUES (4855, 'dashboard.dashboard.chartForm.sort', 'zh', 'dashboard.dashboard.chartForm.sort', '排序', 'dashboard/', '2022-07-25 09:12:37', 425); +INSERT INTO `sys_i18n` VALUES (4856, 'dashboard.explore.ascending', 'en', 'dashboard.explore.ascending', 'Ascending', 'dashboard/', '2022-07-25 09:12:41', 425); +INSERT INTO `sys_i18n` VALUES (4857, 'dashboard.explore.ascending', 'zh', 'dashboard.explore.ascending', '升序', 'dashboard/', '2022-07-25 09:12:48', 425); +INSERT INTO `sys_i18n` VALUES (4874, 'dashboard.dashboard.chartForm.select', 'en', 'dashboard.dashboard.chartForm.select', 'Value', 'dashboard/', '2022-07-25 09:12:52', 425); +INSERT INTO `sys_i18n` VALUES (4875, 'dashboard.dashboard.chartForm.select', 'zh', 'dashboard.dashboard.chartForm.select', '统计值', 'dashboard/', '2022-07-25 09:12:58', 425); +INSERT INTO `sys_i18n` VALUES (4876, 'dashboard.dashboard.chartForm.result', 'en', 'dashboard.dashboard.chartForm.result', 'Result ', 'dashboard/', '2022-07-25 09:13:02', 425); +INSERT INTO `sys_i18n` VALUES (4877, 'dashboard.dashboard.chartForm.result', 'zh', 'dashboard.dashboard.chartForm.result', '结果', 'dashboard/', '2022-07-25 09:13:08', 425); +INSERT INTO `sys_i18n` VALUES (4878, 'placeholder.chart.threshold', 'en', 'placeholder.chart.threshold', 'Please input threshold. Click on the left color bar to adjust the threshold color', '监控/应用实例/提示;\ndashboard/\n', '2022-07-25 09:17:54', 425); +INSERT INTO `sys_i18n` VALUES (4879, 'placeholder.chart.threshold', 'zh', 'placeholder.chart.threshold', '请输入阈值。点击左侧色块调整阈值颜色', '监控/应用实例/提示;\ndashboard/\n\n', '2022-07-25 09:17:58', 425); INSERT INTO `sys_i18n` VALUES (4880, 'placeholder.log.limit', 'en', 'placeholder.log.limit', 'The first 100 entries are returned by default', '', '2021-12-03 03:21:05', 1); INSERT INTO `sys_i18n` VALUES (4881, 'placeholder.log.limit', 'zh', 'placeholder.log.limit', '默认返回前100条', '', '2021-12-03 03:21:15', 1); INSERT INTO `sys_i18n` VALUES (4882, 'placeholder.chart.display', 'zh', 'placeholder.chart.display', '可以使用变量 {{xxx}} 替换返回结果的内容。列如: {{value}}', '', '2021-12-03 03:31:17', 1); INSERT INTO `sys_i18n` VALUES (4883, 'placeholder.chart.display', 'en', 'placeholder.chart.display', 'You can replace the content with {{XXX}}. Such as: {{value}}', '', '2021-12-03 03:33:11', 1); INSERT INTO `sys_i18n` VALUES (4884, 'placeholder.system.limit', 'en', 'placeholder.system.limit', 'Default all', '系统配置/个性化配置/\n默认全部', '2022-07-25 09:19:14', 425); INSERT INTO `sys_i18n` VALUES (4885, 'placeholder.system.limit', 'zh', 'placeholder.system.limit', '默认全部', '系统配置/个性化配置/\n默认全部', '2022-07-25 09:19:04', 425); -INSERT INTO `sys_i18n` VALUES (4896, 'error.nameDuplicate', 'en', 'error.nameDuplicate', 'Name is duplicate', '系统配置/个性化配置/名字重复;\npanel/\n', '2022-07-25 09:19:50', 425); -INSERT INTO `sys_i18n` VALUES (4897, 'error.nameDuplicate', 'zh', 'error.nameDuplicate', '名字重复', '系统配置/个性化配置/名字重复;\npanel/\n', '2022-07-25 09:19:47', 425); -INSERT INTO `sys_i18n` VALUES (4898, 'dashboard.panel.chartForm.dimension', 'en', 'dashboard.panel.chartForm.dimension', 'Dimension', '系统配置/个性化配置/label\n\n', '2022-07-25 09:21:41', 425); -INSERT INTO `sys_i18n` VALUES (4899, 'dashboard.panel.chartForm.dimension', 'zh', 'dashboard.panel.chartForm.dimension', '维度', '系统配置/个性化配置/label\n', '2022-07-25 09:21:29', 425); -INSERT INTO `sys_i18n` VALUES (4900, 'dashboard.panel.chartForm.refer', 'en', 'dashboard.panel.chartForm.refer', 'Refer', ' \n系统配置/个性化配置/Refer/label', '2022-07-25 09:21:18', 425); -INSERT INTO `sys_i18n` VALUES (4901, 'dashboard.panel.chartForm.refer', 'zh', 'dashboard.panel.chartForm.refer', 'Refer', ' \n系统配置/个性化配置/Refer/label', '2022-07-25 09:21:23', 425); +INSERT INTO `sys_i18n` VALUES (4896, 'error.nameDuplicate', 'en', 'error.nameDuplicate', 'Name is duplicate', '系统配置/个性化配置/名字重复;\ndashboard/\n', '2022-07-25 09:19:50', 425); +INSERT INTO `sys_i18n` VALUES (4897, 'error.nameDuplicate', 'zh', 'error.nameDuplicate', '名字重复', '系统配置/个性化配置/名字重复;\ndashboard/\n', '2022-07-25 09:19:47', 425); +INSERT INTO `sys_i18n` VALUES (4898, 'dashboard.dashboard.chartForm.dimension', 'en', 'dashboard.dashboard.chartForm.dimension', 'Dimension', '系统配置/个性化配置/label\n\n', '2022-07-25 09:21:41', 425); +INSERT INTO `sys_i18n` VALUES (4899, 'dashboard.dashboard.chartForm.dimension', 'zh', 'dashboard.dashboard.chartForm.dimension', '维度', '系统配置/个性化配置/label\n', '2022-07-25 09:21:29', 425); +INSERT INTO `sys_i18n` VALUES (4900, 'dashboard.dashboard.chartForm.refer', 'en', 'dashboard.dashboard.chartForm.refer', 'Refer', ' \n系统配置/个性化配置/Refer/label', '2022-07-25 09:21:18', 425); +INSERT INTO `sys_i18n` VALUES (4901, 'dashboard.dashboard.chartForm.refer', 'zh', 'dashboard.dashboard.chartForm.refer', 'Refer', ' \n系统配置/个性化配置/Refer/label', '2022-07-25 09:21:23', 425); INSERT INTO `sys_i18n` VALUES (5320, 'config.dc.tel', 'en', 'config.dc.tel', 'Telephone', '表头->数据中心导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (5321, 'config.dc.tel', 'zh', 'config.dc.tel', '电话', '表头->数据中心导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (5322, 'config.dc.principal', 'en', 'config.dc.principal', 'Administrator', '表头->数据中心导入/导出/模板下载', '2022-07-21 06:18:50', 1); @@ -3398,34 +3394,34 @@ INSERT INTO `sys_i18n` VALUES (5514, 'asset.talon.port.comment', 'en', 'asset.ta INSERT INTO `sys_i18n` VALUES (5515, 'asset.talon.port.comment', 'zh', 'asset.talon.port.comment', 'TALON 服务端口 为空时默认:10092 示例: 10092', '表头->资产导入/导出/模板下载', '2022-07-21 06:18:50', 415); INSERT INTO `sys_i18n` VALUES (5516, 'asset.talon.enable.comment', 'en', 'asset.talon.enable.comment', 'TALON open status Default is 0, 1: Open 0: Close Example: 1', '表头->资产导入/导出/模板下载', '2022-07-21 06:18:50', 415); INSERT INTO `sys_i18n` VALUES (5517, 'asset.talon.enable.comment', 'zh', 'asset.talon.enable.comment', 'TALON 开启状态 为空时默认为0, 1: 开启 0: 关闭 示例: 1', '表头->资产导入/导出/模板下载', '2022-07-21 06:18:50', 415); -INSERT INTO `sys_i18n` VALUES (5518, 'dashboard.panel.chartForm.element', 'en', 'dashboard.panel.chartForm.element', 'Element', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5519, 'dashboard.panel.chartForm.element', 'zh', 'dashboard.panel.chartForm.element', '元素', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5520, 'dashboard.panel.panelForm.panelName.comment', 'en', 'dashboard.panel.panelForm.panelName.comment', 'Panel(Required) Example: System panel/Main panel (use / as a character separation to indicate the relationship between parent an', '表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5521, 'dashboard.panel.panelForm.panelName.comment', 'zh', 'dashboard.panel.panelForm.panelName.comment', '面板名称(必填) 示例: 系统面板/主面板 (使用 / 作为字符分隔,表示 父子节点关系)', '表头->dashboard panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5522, 'dashboard.panel.chartForm.group.comment', 'en', 'dashboard.panel.chartForm.group.comment', 'Group name Example: default', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5523, 'dashboard.panel.chartForm.group.comment', 'zh', 'dashboard.panel.chartForm.group.comment', '组名 示例: default', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5524, 'dashboard.panel.chartForm.name.comment', 'en', 'dashboard.panel.chartForm.name.comment', 'Chart title(Required) Example: CPU usage', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5525, 'dashboard.panel.chartForm.name.comment', 'zh', 'dashboard.panel.chartForm.name.comment', '图表名称(必填) 示例: CPU使用率', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5526, 'dashboard.panel.chartForm.type.comment', 'en', 'dashboard.panel.chartForm.type.comment', 'Chart type(Required) Optional: Line Chart,Histogram,Table,Stack Area,SingleStat,URL,Alert list,Text,Group,Diagram,Logs Example: ', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5527, 'dashboard.panel.chartForm.type.comment', 'zh', 'dashboard.panel.chartForm.type.comment', '图表类型(必填) 可选: 曲线图,柱状图,表格,堆叠区域图,SingleStat,URL,告警列表,文本,图表组,Diagram,Logs 示例: 曲线图', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5528, 'dashboard.panel.chartForm.width.comment', 'en', 'dashboard.panel.chartForm.width.comment', 'width(Required) Optional:1-12 Example: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5529, 'dashboard.panel.chartForm.width.comment', 'zh', 'dashboard.panel.chartForm.width.comment', '宽度(必填) 可选:1-12 示例: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5530, 'dashboard.panel.chartForm.high.comment', 'en', 'dashboard.panel.chartForm.high.comment', 'height(Required),Optional:1-12 Example: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5531, 'dashboard.panel.chartForm.high.comment', 'zh', 'dashboard.panel.chartForm.high.comment', '高度(必填),可选:1-12 示例: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5532, 'dashboard.panel.chartForm.unit.comment', 'en', 'dashboard.panel.chartForm.unit.comment', 'unit(Required) Optional: Misc: none,short,percent(0-100),percent(0.0-1.0),local formatData: bits,bytes,kilobytes,megabytes,gigab', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5533, 'dashboard.panel.chartForm.unit.comment', 'zh', 'dashboard.panel.chartForm.unit.comment', '单位(必填) 可选: Misc: none,short,percent(0-100),percent(0.0-1.0),local formatData: bits,bytes,kilobytes,megabytes,gigabytes,terabytes', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5534, 'dashboard.panel.chartForm.legendValue.comment', 'en', 'dashboard.panel.chartForm.legendValue.comment', 'Parameters match type,The format is JSON format ', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5535, 'dashboard.panel.chartForm.legendValue.comment', 'zh', 'dashboard.panel.chartForm.legendValue.comment', '参数 根据type不同,内容不同,格式为JSON格式 ', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5536, 'dashboard.panel.chartForm.element.comment', 'en', 'dashboard.panel.chartForm.element.comment', 'When the type is line, table, stackArea, singleStat, histogram, it contains elements key and the value is an object array', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5537, 'dashboard.panel.chartForm.element.comment', 'zh', 'dashboard.panel.chartForm.element.comment', '当type=line,bar,stackArea时,包含 elements key,值为对象数组。', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5538, 'dashboard.panel.chartForm.remark.comment', 'en', 'dashboard.panel.chartForm.remark.comment', 'The chart description', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5539, 'dashboard.panel.chartForm.remark.comment', 'zh', 'dashboard.panel.chartForm.remark.comment', '图表描述说明', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5540, 'dashboard.panel.chartForm.varType.comment', 'en', 'dashboard.panel.chartForm.varType.comment', 'Variable type Required when type is template, optional: Asset, Endpoint Example: Asset', '表头->资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5541, 'dashboard.panel.chartForm.varType.comment', 'zh', 'dashboard.panel.chartForm.varType.comment', '变量类型 当类型是 template 时必填,可选:Asset,端点 示例: Asset', '表头->资产panel导入/导出/模板下载', '2022-08-01 06:05:43', 415); -INSERT INTO `sys_i18n` VALUES (5542, 'dashboard.panel.chartForm.datasource', 'en', 'dashboard.panel.chartForm.datasource', 'Datasource', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5543, 'dashboard.panel.chartForm.datasource', 'zh', 'dashboard.panel.chartForm.datasource', '数据源', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5544, 'dashboard.panel.chartForm.datasource.comment', 'en', 'dashboard.panel.chartForm.datasource.comment', 'Datasource Example:metrics,logs,system,misc', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5545, 'dashboard.panel.chartForm.datasource.comment', 'zh', 'dashboard.panel.chartForm.datasource.comment', '数据源 示例 metrics,logs,system,misc', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5518, 'dashboard.dashboard.chartForm.element', 'en', 'dashboard.dashboard.chartForm.element', 'Element', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5519, 'dashboard.dashboard.chartForm.element', 'zh', 'dashboard.dashboard.chartForm.element', '元素', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5520, 'dashboard.dashboard.dashboardForm.dashboardName.comment', 'en', 'dashboard.dashboard.dashboardForm.dashboardName.comment', 'Dashboard(Required) Example: System dashboard/Main dashboard (use / as a character separation to indicate the relationship between parent an', '表头->dashboard dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5521, 'dashboard.dashboard.dashboardForm.dashboardName.comment', 'zh', 'dashboard.dashboard.dashboardForm.dashboardName.comment', '面板名称(必填) 示例: 系统面板/主面板 (使用 / 作为字符分隔,表示 父子节点关系)', '表头->dashboard dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5522, 'dashboard.dashboard.chartForm.group.comment', 'en', 'dashboard.dashboard.chartForm.group.comment', 'Group name Example: default', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5523, 'dashboard.dashboard.chartForm.group.comment', 'zh', 'dashboard.dashboard.chartForm.group.comment', '组名 示例: default', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5524, 'dashboard.dashboard.chartForm.name.comment', 'en', 'dashboard.dashboard.chartForm.name.comment', 'Chart title(Required) Example: CPU usage', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5525, 'dashboard.dashboard.chartForm.name.comment', 'zh', 'dashboard.dashboard.chartForm.name.comment', '图表名称(必填) 示例: CPU使用率', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5526, 'dashboard.dashboard.chartForm.type.comment', 'en', 'dashboard.dashboard.chartForm.type.comment', 'Chart type(Required) Optional: Line Chart,Histogram,Table,Stack Area,SingleStat,URL,Alert list,Text,Group,Diagram,Logs Example: ', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5527, 'dashboard.dashboard.chartForm.type.comment', 'zh', 'dashboard.dashboard.chartForm.type.comment', '图表类型(必填) 可选: 曲线图,柱状图,表格,堆叠区域图,SingleStat,URL,告警列表,文本,图表组,Diagram,Logs 示例: 曲线图', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5528, 'dashboard.dashboard.chartForm.width.comment', 'en', 'dashboard.dashboard.chartForm.width.comment', 'width(Required) Optional:1-12 Example: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5529, 'dashboard.dashboard.chartForm.width.comment', 'zh', 'dashboard.dashboard.chartForm.width.comment', '宽度(必填) 可选:1-12 示例: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5530, 'dashboard.dashboard.chartForm.high.comment', 'en', 'dashboard.dashboard.chartForm.high.comment', 'height(Required),Optional:1-12 Example: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5531, 'dashboard.dashboard.chartForm.high.comment', 'zh', 'dashboard.dashboard.chartForm.high.comment', '高度(必填),可选:1-12 示例: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5532, 'dashboard.dashboard.chartForm.unit.comment', 'en', 'dashboard.dashboard.chartForm.unit.comment', 'unit(Required) Optional: Misc: none,short,percent(0-100),percent(0.0-1.0),local formatData: bits,bytes,kilobytes,megabytes,gigab', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5533, 'dashboard.dashboard.chartForm.unit.comment', 'zh', 'dashboard.dashboard.chartForm.unit.comment', '单位(必填) 可选: Misc: none,short,percent(0-100),percent(0.0-1.0),local formatData: bits,bytes,kilobytes,megabytes,gigabytes,terabytes', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5534, 'dashboard.dashboard.chartForm.legendValue.comment', 'en', 'dashboard.dashboard.chartForm.legendValue.comment', 'Parameters match type,The format is JSON format ', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5535, 'dashboard.dashboard.chartForm.legendValue.comment', 'zh', 'dashboard.dashboard.chartForm.legendValue.comment', '参数 根据type不同,内容不同,格式为JSON格式 ', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5536, 'dashboard.dashboard.chartForm.element.comment', 'en', 'dashboard.dashboard.chartForm.element.comment', 'When the type is line, table, stackArea, singleStat, histogram, it contains elements key and the value is an object array', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5537, 'dashboard.dashboard.chartForm.element.comment', 'zh', 'dashboard.dashboard.chartForm.element.comment', '当type=line,bar,stackArea时,包含 elements key,值为对象数组。', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5538, 'dashboard.dashboard.chartForm.remark.comment', 'en', 'dashboard.dashboard.chartForm.remark.comment', 'The chart description', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5539, 'dashboard.dashboard.chartForm.remark.comment', 'zh', 'dashboard.dashboard.chartForm.remark.comment', '图表描述说明', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5540, 'dashboard.dashboard.chartForm.varType.comment', 'en', 'dashboard.dashboard.chartForm.varType.comment', 'Variable type Required when type is template, optional: Asset, Endpoint Example: Asset', '表头->资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5541, 'dashboard.dashboard.chartForm.varType.comment', 'zh', 'dashboard.dashboard.chartForm.varType.comment', '变量类型 当类型是 template 时必填,可选:Asset,端点 示例: Asset', '表头->资产dashboard导入/导出/模板下载', '2022-08-01 06:05:43', 415); +INSERT INTO `sys_i18n` VALUES (5542, 'dashboard.dashboard.chartForm.datasource', 'en', 'dashboard.dashboard.chartForm.datasource', 'Data Source', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2023-02-01 09:42:07', 407); +INSERT INTO `sys_i18n` VALUES (5543, 'dashboard.dashboard.chartForm.datasource', 'zh', 'dashboard.dashboard.chartForm.datasource', '数据源', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5544, 'dashboard.dashboard.chartForm.datasource.comment', 'en', 'dashboard.dashboard.chartForm.datasource.comment', 'Datasource Example:metrics,logs,system,misc', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5545, 'dashboard.dashboard.chartForm.datasource.comment', 'zh', 'dashboard.dashboard.chartForm.datasource.comment', '数据源 示例 metrics,logs,system,misc', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (5546, 'config.system.license.license', 'en', 'config.system.license.license', 'License', '系统配置/个性化配置/证书\n', '2022-07-25 09:22:24', 425); INSERT INTO `sys_i18n` VALUES (5547, 'config.system.license.license', 'zh', 'config.system.license.license', '证书', '系统配置/个性化配置/证书\n', '2022-07-25 09:22:20', 425); INSERT INTO `sys_i18n` VALUES (5550, 'license.devices', 'en', 'license.devices', 'Licensed Servers', 'license/授权主机', '2022-09-29 07:05:03', 409); @@ -3442,38 +3438,38 @@ INSERT INTO `sys_i18n` VALUES (5564, 'license.uploadLicense', 'en', 'license.upl INSERT INTO `sys_i18n` VALUES (5565, 'license.uploadLicense', 'zh', 'license.uploadLicense', '上传许可证', ' \nlicense/上传许可证', '2022-07-25 09:29:58', 425); INSERT INTO `sys_i18n` VALUES (5566, 'license.nzTitleValue', 'en', 'license.nzTitleValue', 'Network Zodiac One-Stop Monitoring System', ' \nlicense/哪吒一站式监控系统', '2022-07-25 09:30:15', 425); INSERT INTO `sys_i18n` VALUES (5567, 'license.nzTitleValue', 'zh', 'license.nzTitleValue', '哪吒一站式监控系统', ' \nlicense/哪吒一站式监控系统', '2022-07-25 09:30:11', 425); -INSERT INTO `sys_i18n` VALUES (5568, 'dashboard.panel.chartForm.columns', 'en', 'dashboard.panel.chartForm.columns', 'Columns', '\n系统配置/个性化配置/ table column\n', '2022-07-25 09:31:07', 425); -INSERT INTO `sys_i18n` VALUES (5569, 'dashboard.panel.chartForm.columns', 'zh', 'dashboard.panel.chartForm.columns', '列', '\n系统配置/个性化配置/ table column\n', '2022-07-25 09:31:02', 425); +INSERT INTO `sys_i18n` VALUES (5568, 'dashboard.dashboard.chartForm.columns', 'en', 'dashboard.dashboard.chartForm.columns', 'Columns', '\n系统配置/个性化配置/ table column\n', '2022-07-25 09:31:07', 425); +INSERT INTO `sys_i18n` VALUES (5569, 'dashboard.dashboard.chartForm.columns', 'zh', 'dashboard.dashboard.chartForm.columns', '列', '\n系统配置/个性化配置/ table column\n', '2022-07-25 09:31:02', 425); INSERT INTO `sys_i18n` VALUES (5570, 'license.inactive', 'en', 'license.inactive', 'Inactive', 'license/是否激活', '2022-07-25 09:31:44', 425); INSERT INTO `sys_i18n` VALUES (5571, 'license.inactive', 'zh', 'license.inactive', 'Inactive', 'license/是否激活', '2022-07-25 09:31:40', 425); INSERT INTO `sys_i18n` VALUES (5572, 'login.download', 'en', 'login.download', 'Download license', '', '2021-12-17 08:53:08', 1); INSERT INTO `sys_i18n` VALUES (5573, 'login.download', 'zh', 'login.download', '下载许可', '', '2021-12-17 08:53:13', 1); -INSERT INTO `sys_i18n` VALUES (5574, '121059', 'en', 'CHARTELEMENT_NAME_ISNULL', 'Chart element name can not be empty', '响应消息->charts新增/修改、panel导入接口', '2021-12-18 09:32:35', 1); -INSERT INTO `sys_i18n` VALUES (5575, '121059', 'zh', 'CHARTELEMENT_NAME_ISNULL', '图表元素名称不能为空', '响应消息->charts新增/修改、panel导入接口', '2021-12-18 09:32:58', 1); -INSERT INTO `sys_i18n` VALUES (5576, 'dashboard.panel.chartForm.nullType', 'en', 'dashboard.panel.chartForm.nullType', 'Null value', 'panel/', '2022-07-25 09:32:52', 425); -INSERT INTO `sys_i18n` VALUES (5577, 'dashboard.panel.chartForm.nullType', 'zh', 'dashboard.panel.chartForm.nullType', 'Null value', 'panel/', '2022-07-25 09:32:56', 425); -INSERT INTO `sys_i18n` VALUES (5580, 'dashboard.panel.chartForm.typeVal.map.label', 'en', 'dashboard.panel.chartForm.typeVal.map.label', 'Map', 'panel/', '2022-07-25 09:33:01', 425); -INSERT INTO `sys_i18n` VALUES (5581, 'dashboard.panel.chartForm.typeVal.map.label', 'zh', 'dashboard.panel.chartForm.typeVal.map.label', '地图', 'panel/', '2022-07-25 09:33:07', 425); -INSERT INTO `sys_i18n` VALUES (5582, 'dashboard.panel.chartForm.typeVal.topology.label', 'en', 'dashboard.panel.chartForm.typeVal.topology.label', 'Project topology', 'panel/', '2022-07-25 09:33:27', 425); -INSERT INTO `sys_i18n` VALUES (5583, 'dashboard.panel.chartForm.typeVal.topology.label', 'zh', 'dashboard.panel.chartForm.typeVal.topology.label', '轮播图', 'panel/', '2022-07-25 09:33:31', 425); -INSERT INTO `sys_i18n` VALUES (5584, 'dashboard.panel.chartForm.typeVal.hexagonFigure.label', 'en', 'dashboard.panel.chartForm.typeVal.hexagonFigure.label', 'Hexagon', 'panel/', '2022-07-25 09:33:34', 425); -INSERT INTO `sys_i18n` VALUES (5585, 'dashboard.panel.chartForm.typeVal.hexagonFigure.label', 'zh', 'dashboard.panel.chartForm.typeVal.hexagonFigure.label', '蜂窝图', 'panel/', '2022-07-25 09:33:37', 425); -INSERT INTO `sys_i18n` VALUES (5588, 'license.organization', 'zh', 'license.organization', '组织', 'panel/', '2022-07-25 09:33:40', 425); -INSERT INTO `sys_i18n` VALUES (5589, 'license.organization', 'en', 'license.organization', 'Organization', 'panel/', '2022-07-25 09:33:43', 425); -INSERT INTO `sys_i18n` VALUES (5590, 'overall.link', 'en', 'overall.link', 'Link', 'panel/', '2022-07-25 09:33:48', 425); -INSERT INTO `sys_i18n` VALUES (5591, 'overall.link', 'zh', 'overall.link', '链接', 'panel/', '2022-07-25 09:33:51', 425); -INSERT INTO `sys_i18n` VALUES (5592, 'dashboard.panel.chartForm.min', 'en', 'dashboard.panel.chartForm.min', 'Min', 'panel/', '2022-07-25 09:33:55', 425); -INSERT INTO `sys_i18n` VALUES (5593, 'dashboard.panel.chartForm.min', 'zh', 'dashboard.panel.chartForm.min', '最小值', 'panel/', '2022-07-25 09:33:58', 425); -INSERT INTO `sys_i18n` VALUES (5594, 'dashboard.panel.chartForm.max', 'en', 'dashboard.panel.chartForm.max', 'Max', 'panel/', '2022-07-25 09:34:01', 425); -INSERT INTO `sys_i18n` VALUES (5595, 'dashboard.panel.chartForm.max', 'zh', 'dashboard.panel.chartForm.max', '最大值', 'panel/', '2022-07-25 09:34:05', 425); -INSERT INTO `sys_i18n` VALUES (5596, 'dashboard.panel.chartForm.typeVal.clock.label', 'en', 'dashboard.panel.chartForm.typeVal.clock.label', 'Clock', 'panel/', '2022-07-25 09:34:08', 425); -INSERT INTO `sys_i18n` VALUES (5597, 'dashboard.panel.chartForm.typeVal.clock.label', 'zh', 'dashboard.panel.chartForm.typeVal.clock.label', '时钟', 'panel/', '2022-07-25 09:34:12', 425); -INSERT INTO `sys_i18n` VALUES (5598, 'dashboard.panel.chartForm.typeVal.local', 'en', 'dashboard.panel.chartForm.typeVal.local', 'Local time', 'panel/', '2022-07-25 09:34:16', 425); -INSERT INTO `sys_i18n` VALUES (5599, 'dashboard.panel.chartForm.typeVal.local', 'zh', 'dashboard.panel.chartForm.typeVal.local', '本地时间', 'panel/', '2022-07-25 09:34:19', 425); -INSERT INTO `sys_i18n` VALUES (5600, 'dashboard.panel.chartForm.typeVal.server', 'en', 'dashboard.panel.chartForm.typeVal.server', 'Server time', 'panel/', '2022-07-25 09:34:22', 425); -INSERT INTO `sys_i18n` VALUES (5601, 'dashboard.panel.chartForm.typeVal.server', 'zh', 'dashboard.panel.chartForm.typeVal.server', '服务器时间', 'panel/', '2022-07-25 09:34:26', 425); -INSERT INTO `sys_i18n` VALUES (5602, 'dashboard.panel.chartForm.timeType', 'en', 'dashboard.panel.chartForm.timeType', 'Time type', 'panel/', '2022-07-25 09:34:29', 425); -INSERT INTO `sys_i18n` VALUES (5603, 'dashboard.panel.chartForm.timeType', 'zh', 'dashboard.panel.chartForm.timeType', '时间类型', 'panel/', '2022-07-25 09:34:39', 425); +INSERT INTO `sys_i18n` VALUES (5574, '121059', 'en', 'CHARTELEMENT_NAME_ISNULL', 'Chart element name can not be empty', '响应消息->charts新增/修改、dashboard导入接口', '2021-12-18 09:32:35', 1); +INSERT INTO `sys_i18n` VALUES (5575, '121059', 'zh', 'CHARTELEMENT_NAME_ISNULL', '图表元素名称不能为空', '响应消息->charts新增/修改、dashboard导入接口', '2021-12-18 09:32:58', 1); +INSERT INTO `sys_i18n` VALUES (5576, 'dashboard.dashboard.chartForm.nullType', 'en', 'dashboard.dashboard.chartForm.nullType', 'Null value', 'dashboard/', '2022-07-25 09:32:52', 425); +INSERT INTO `sys_i18n` VALUES (5577, 'dashboard.dashboard.chartForm.nullType', 'zh', 'dashboard.dashboard.chartForm.nullType', 'Null value', 'dashboard/', '2022-07-25 09:32:56', 425); +INSERT INTO `sys_i18n` VALUES (5580, 'dashboard.dashboard.chartForm.typeVal.map.label', 'en', 'dashboard.dashboard.chartForm.typeVal.map.label', 'Map', 'dashboard/', '2022-07-25 09:33:01', 425); +INSERT INTO `sys_i18n` VALUES (5581, 'dashboard.dashboard.chartForm.typeVal.map.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.map.label', '地图', 'dashboard/', '2022-07-25 09:33:07', 425); +INSERT INTO `sys_i18n` VALUES (5582, 'dashboard.dashboard.chartForm.typeVal.topology.label', 'en', 'dashboard.dashboard.chartForm.typeVal.topology.label', 'Project topology', 'dashboard/', '2022-07-25 09:33:27', 425); +INSERT INTO `sys_i18n` VALUES (5583, 'dashboard.dashboard.chartForm.typeVal.topology.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.topology.label', '轮播图', 'dashboard/', '2022-07-25 09:33:31', 425); +INSERT INTO `sys_i18n` VALUES (5584, 'dashboard.dashboard.chartForm.typeVal.hexagonFigure.label', 'en', 'dashboard.dashboard.chartForm.typeVal.hexagonFigure.label', 'Hexagon', 'dashboard/', '2022-07-25 09:33:34', 425); +INSERT INTO `sys_i18n` VALUES (5585, 'dashboard.dashboard.chartForm.typeVal.hexagonFigure.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.hexagonFigure.label', '蜂窝图', 'dashboard/', '2022-07-25 09:33:37', 425); +INSERT INTO `sys_i18n` VALUES (5588, 'license.organization', 'zh', 'license.organization', '组织', 'dashboard/', '2022-07-25 09:33:40', 425); +INSERT INTO `sys_i18n` VALUES (5589, 'license.organization', 'en', 'license.organization', 'Organization', 'dashboard/', '2022-07-25 09:33:43', 425); +INSERT INTO `sys_i18n` VALUES (5590, 'overall.link', 'en', 'overall.link', 'Link', 'dashboard/', '2022-07-25 09:33:48', 425); +INSERT INTO `sys_i18n` VALUES (5591, 'overall.link', 'zh', 'overall.link', '链接', 'dashboard/', '2022-07-25 09:33:51', 425); +INSERT INTO `sys_i18n` VALUES (5592, 'dashboard.dashboard.chartForm.min', 'en', 'dashboard.dashboard.chartForm.min', 'Min', 'dashboard/', '2022-07-25 09:33:55', 425); +INSERT INTO `sys_i18n` VALUES (5593, 'dashboard.dashboard.chartForm.min', 'zh', 'dashboard.dashboard.chartForm.min', '最小值', 'dashboard/', '2022-07-25 09:33:58', 425); +INSERT INTO `sys_i18n` VALUES (5594, 'dashboard.dashboard.chartForm.max', 'en', 'dashboard.dashboard.chartForm.max', 'Max', 'dashboard/', '2022-07-25 09:34:01', 425); +INSERT INTO `sys_i18n` VALUES (5595, 'dashboard.dashboard.chartForm.max', 'zh', 'dashboard.dashboard.chartForm.max', '最大值', 'dashboard/', '2022-07-25 09:34:05', 425); +INSERT INTO `sys_i18n` VALUES (5596, 'dashboard.dashboard.chartForm.typeVal.clock.label', 'en', 'dashboard.dashboard.chartForm.typeVal.clock.label', 'Clock', 'dashboard/', '2022-07-25 09:34:08', 425); +INSERT INTO `sys_i18n` VALUES (5597, 'dashboard.dashboard.chartForm.typeVal.clock.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.clock.label', '时钟', 'dashboard/', '2022-07-25 09:34:12', 425); +INSERT INTO `sys_i18n` VALUES (5598, 'dashboard.dashboard.chartForm.typeVal.local', 'en', 'dashboard.dashboard.chartForm.typeVal.local', 'Local time', 'dashboard/', '2022-07-25 09:34:16', 425); +INSERT INTO `sys_i18n` VALUES (5599, 'dashboard.dashboard.chartForm.typeVal.local', 'zh', 'dashboard.dashboard.chartForm.typeVal.local', '本地时间', 'dashboard/', '2022-07-25 09:34:19', 425); +INSERT INTO `sys_i18n` VALUES (5600, 'dashboard.dashboard.chartForm.typeVal.server', 'en', 'dashboard.dashboard.chartForm.typeVal.server', 'Server time', 'dashboard/', '2022-07-25 09:34:22', 425); +INSERT INTO `sys_i18n` VALUES (5601, 'dashboard.dashboard.chartForm.typeVal.server', 'zh', 'dashboard.dashboard.chartForm.typeVal.server', '服务器时间', 'dashboard/', '2022-07-25 09:34:26', 425); +INSERT INTO `sys_i18n` VALUES (5602, 'dashboard.dashboard.chartForm.timeType', 'en', 'dashboard.dashboard.chartForm.timeType', 'Time type', 'dashboard/', '2022-07-25 09:34:29', 425); +INSERT INTO `sys_i18n` VALUES (5603, 'dashboard.dashboard.chartForm.timeType', 'zh', 'dashboard.dashboard.chartForm.timeType', '时间类型', 'dashboard/', '2022-07-25 09:34:39', 425); INSERT INTO `sys_i18n` VALUES (5604, 'license.permanent', 'en', 'license.permanent', 'Permanent', 'license/永久有效', '2022-07-25 09:35:06', 425); INSERT INTO `sys_i18n` VALUES (5605, 'license.permanent', 'zh', 'license.permanent', '永久有效', 'license/永久有效', '2022-07-25 09:35:02', 425); INSERT INTO `sys_i18n` VALUES (5606, 'overall.chartTemplate', 'zh', 'overall.chartTemplate', '图表模板', '', '2022-07-11 09:39:11', 415); @@ -3550,8 +3546,8 @@ INSERT INTO `sys_i18n` VALUES (5690, 'asset.password', 'en', 'asset.password', ' INSERT INTO `sys_i18n` VALUES (5691, 'asset.password', 'zh', 'asset.password', '用户名密码', '表头->资产导入/导出/模板下载', '2022-07-21 06:18:50', 98); INSERT INTO `sys_i18n` VALUES (5692, 'asset.publicKey', 'en', 'asset.publicKey', 'Public key', '', '2022-02-17 09:19:04', 98); INSERT INTO `sys_i18n` VALUES (5693, 'asset.publicKey', 'zh', 'asset.publicKey', '公钥', '', '2022-02-17 09:19:54', 98); -INSERT INTO `sys_i18n` VALUES (5694, 'dashboard.panel.chartForm.filter', 'en', 'dashboard.panel.chartForm.filter', 'Filter', '', '2022-02-22 06:28:51', 1); -INSERT INTO `sys_i18n` VALUES (5695, 'dashboard.panel.chartForm.filter', 'zh', 'dashboard.panel.chartForm.filter', '过滤', '', '2022-02-22 06:29:56', 1); +INSERT INTO `sys_i18n` VALUES (5694, 'dashboard.dashboard.chartForm.filter', 'en', 'dashboard.dashboard.chartForm.filter', 'Filter', '', '2022-02-22 06:28:51', 1); +INSERT INTO `sys_i18n` VALUES (5695, 'dashboard.dashboard.chartForm.filter', 'zh', 'dashboard.dashboard.chartForm.filter', '过滤', '', '2022-02-22 06:29:56', 1); INSERT INTO `sys_i18n` VALUES (5696, '721001', 'en', 'IPAM_SUBNET_ID_ISNULL', 'Ipamsubnet id can not be null', '响应消息->ipam subnet新增/修改接口', '2022-02-08 06:13:08', 1); INSERT INTO `sys_i18n` VALUES (5697, '721001', 'zh', 'IPAM_SUBNET_ID_ISNULL', '子网id不能为空', '响应消息->ipam subnet新增/修改接口', '2022-02-08 06:13:29', 1); INSERT INTO `sys_i18n` VALUES (5698, '721002', 'en', 'IPAM_SUBNET_NAME_ISNULL', 'Ipamsubnet name can not be null', '响应消息->ipam subnet新增/修改/导入接口', '2022-02-08 06:13:08', 1); @@ -3601,30 +3597,30 @@ INSERT INTO `sys_i18n` VALUES (5766, 'alert.lastAt', 'en', 'alert.lastAt', 'Last INSERT INTO `sys_i18n` VALUES (5767, 'alert.lastAt', 'zh', 'alert.lastAt', '最近一次', '', '2022-03-02 08:42:46', 1); INSERT INTO `sys_i18n` VALUES (5768, 'validate.address', 'en', 'validate.address', 'invalid IP address', '', '2022-03-07 06:29:27', 382); INSERT INTO `sys_i18n` VALUES (5769, 'validate.address', 'zh', 'validate.address', '不合法的 IP 地址', '', '2022-03-07 06:29:16', 382); -INSERT INTO `sys_i18n` VALUES (5770, 'dashboard.panel.chartForm.x', 'en', 'dashboard.panel.chartForm.x', 'X', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5771, 'dashboard.panel.chartForm.x', 'zh', 'dashboard.panel.chartForm.x', 'X', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5772, 'dashboard.panel.chartForm.y', 'en', 'dashboard.panel.chartForm.y', 'Y', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5773, 'dashboard.panel.chartForm.y', 'zh', 'dashboard.panel.chartForm.y', 'Y', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5774, 'overall.address', 'en', 'overall.address', 'address', '', '2022-03-07 06:54:25', 382); +INSERT INTO `sys_i18n` VALUES (5770, 'dashboard.dashboard.chartForm.x', 'en', 'dashboard.dashboard.chartForm.x', 'X', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5771, 'dashboard.dashboard.chartForm.x', 'zh', 'dashboard.dashboard.chartForm.x', 'X', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5772, 'dashboard.dashboard.chartForm.y', 'en', 'dashboard.dashboard.chartForm.y', 'Y', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5773, 'dashboard.dashboard.chartForm.y', 'zh', 'dashboard.dashboard.chartForm.y', 'Y', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载、机柜导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5774, 'overall.address', 'en', 'overall.address', 'Address', '', '2023-01-09 09:30:59', 415); INSERT INTO `sys_i18n` VALUES (5775, 'overall.address', 'zh', 'overall.address', '地址', '', '2022-03-07 06:54:37', 382); -INSERT INTO `sys_i18n` VALUES (5776, 'dashboard.panel.chartForm.x.comment', 'en', 'dashboard.panel.chartForm.x.comment', 'x(Required),Optional:1-12 sum with width can not be greater than 12 Example: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5777, 'dashboard.panel.chartForm.x.comment', 'zh', 'dashboard.panel.chartForm.x.comment', 'x轴(必填),可选:1-12 与宽度的和不能超过12 示例: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5778, 'dashboard.panel.chartForm.y.comment', 'en', 'dashboard.panel.chartForm.y.comment', 'y(Required),Optional:1-12 Example: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5779, 'dashboard.panel.chartForm.y.comment', 'zh', 'dashboard.panel.chartForm.y.comment', 'y轴(必填),可选:1-12 示例: 10', '表头->dashboard panel导入/导出/模板下载、资产panel导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (5780, '121044', 'en', 'CHART_NAME_TOO_LONG', 'Chart name too long than 64', '响应消息->panel导入接口', '2022-03-08 01:48:06', 1); -INSERT INTO `sys_i18n` VALUES (5781, '121044', 'zh', 'CHART_NAME_TOO_LONG', '图表名称过长超过64', '响应消息->panel导入接口', '2022-03-08 01:48:31', 1); -INSERT INTO `sys_i18n` VALUES (5782, '121018', 'zh', 'CHART_X_ISNULL', '图表x轴不能为空', '响应消息->panel导入接口', '2022-03-08 01:48:52', 1); -INSERT INTO `sys_i18n` VALUES (5783, '121018', 'en', 'CHART_X_ISNULL', 'Chart x can not be empty', '响应消息->panel导入接口', '2022-03-08 01:49:07', 1); -INSERT INTO `sys_i18n` VALUES (5784, '123020', 'en', 'CHART_X_FORMAT', 'Chart x format should be a integer', '响应消息->panel导入接口', '2022-03-08 01:49:23', 1); -INSERT INTO `sys_i18n` VALUES (5785, '123020', 'zh', 'CHART_X_FORMAT', '图表x轴数据格式错误', '响应消息->panel导入接口', '2022-03-08 01:49:38', 1); -INSERT INTO `sys_i18n` VALUES (5786, '123019', 'en', 'CHART_X_INVALIDE', 'Chart x should be between 0 and 12', '响应消息->panel导入接口', '2022-03-08 01:49:53', 1); -INSERT INTO `sys_i18n` VALUES (5787, '123019', 'zh', 'CHART_X_INVALIDE', '图表x轴长度应在0~12之内', '响应消息->panel导入接口', '2022-03-08 01:50:19', 1); -INSERT INTO `sys_i18n` VALUES (5788, '121015', 'en', 'CHART_Y_ISNULL', 'Chart y can not be empty', '响应消息->panel导入接口', '2022-03-08 01:50:36', 1); -INSERT INTO `sys_i18n` VALUES (5789, '121015', 'zh', 'CHART_Y_ISNULL', '图表Y轴不能为空', '响应消息->panel导入接口', '2022-03-08 01:50:50', 1); -INSERT INTO `sys_i18n` VALUES (5790, '123016', 'en', 'CHART_Y_FORMAT', 'Chart y format should be a integer', '响应消息->panel导入接口', '2022-03-08 01:51:02', 1); -INSERT INTO `sys_i18n` VALUES (5791, '123016', 'zh', 'CHART_Y_FORMAT', '图表y轴数据格式错误', '响应消息->panel导入接口', '2022-03-08 01:51:22', 1); -INSERT INTO `sys_i18n` VALUES (5792, '123017', 'en', 'CHART_X_WIDTH_INVALIDE', 'Chart x and width sum cannot be greater than 12 ', '响应消息->panel导入接口', '2022-03-08 01:51:35', 1); -INSERT INTO `sys_i18n` VALUES (5793, '123017', 'zh', 'CHART_X_WIDTH_INVALIDE', '图表x轴和宽度之和不能超过12', '响应消息->panel导入接口', '2022-03-08 01:51:54', 1); +INSERT INTO `sys_i18n` VALUES (5776, 'dashboard.dashboard.chartForm.x.comment', 'en', 'dashboard.dashboard.chartForm.x.comment', 'x(Required),Optional:1-12 sum with width can not be greater than 12 Example: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5777, 'dashboard.dashboard.chartForm.x.comment', 'zh', 'dashboard.dashboard.chartForm.x.comment', 'x轴(必填),可选:1-12 与宽度的和不能超过12 示例: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5778, 'dashboard.dashboard.chartForm.y.comment', 'en', 'dashboard.dashboard.chartForm.y.comment', 'y(Required),Optional:1-12 Example: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5779, 'dashboard.dashboard.chartForm.y.comment', 'zh', 'dashboard.dashboard.chartForm.y.comment', 'y轴(必填),可选:1-12 示例: 10', '表头->dashboard dashboard导入/导出/模板下载、资产dashboard导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (5780, '121044', 'en', 'CHART_NAME_TOO_LONG', 'Chart name too long than 64', '响应消息->dashboard导入接口', '2022-03-08 01:48:06', 1); +INSERT INTO `sys_i18n` VALUES (5781, '121044', 'zh', 'CHART_NAME_TOO_LONG', '图表名称过长超过64', '响应消息->dashboard导入接口', '2022-03-08 01:48:31', 1); +INSERT INTO `sys_i18n` VALUES (5782, '121018', 'zh', 'CHART_X_ISNULL', '图表x轴不能为空', '响应消息->dashboard导入接口', '2022-03-08 01:48:52', 1); +INSERT INTO `sys_i18n` VALUES (5783, '121018', 'en', 'CHART_X_ISNULL', 'Chart x can not be empty', '响应消息->dashboard导入接口', '2022-03-08 01:49:07', 1); +INSERT INTO `sys_i18n` VALUES (5784, '123020', 'en', 'CHART_X_FORMAT', 'Chart x format should be a integer', '响应消息->dashboard导入接口', '2022-03-08 01:49:23', 1); +INSERT INTO `sys_i18n` VALUES (5785, '123020', 'zh', 'CHART_X_FORMAT', '图表x轴数据格式错误', '响应消息->dashboard导入接口', '2022-03-08 01:49:38', 1); +INSERT INTO `sys_i18n` VALUES (5786, '123019', 'en', 'CHART_X_INVALIDE', 'Chart x should be between 0 and 12', '响应消息->dashboard导入接口', '2022-03-08 01:49:53', 1); +INSERT INTO `sys_i18n` VALUES (5787, '123019', 'zh', 'CHART_X_INVALIDE', '图表x轴长度应在0~12之内', '响应消息->dashboard导入接口', '2022-03-08 01:50:19', 1); +INSERT INTO `sys_i18n` VALUES (5788, '121015', 'en', 'CHART_Y_ISNULL', 'Chart y can not be empty', '响应消息->dashboard导入接口', '2022-03-08 01:50:36', 1); +INSERT INTO `sys_i18n` VALUES (5789, '121015', 'zh', 'CHART_Y_ISNULL', '图表Y轴不能为空', '响应消息->dashboard导入接口', '2022-03-08 01:50:50', 1); +INSERT INTO `sys_i18n` VALUES (5790, '123016', 'en', 'CHART_Y_FORMAT', 'Chart y format should be a integer', '响应消息->dashboard导入接口', '2022-03-08 01:51:02', 1); +INSERT INTO `sys_i18n` VALUES (5791, '123016', 'zh', 'CHART_Y_FORMAT', '图表y轴数据格式错误', '响应消息->dashboard导入接口', '2022-03-08 01:51:22', 1); +INSERT INTO `sys_i18n` VALUES (5792, '123017', 'en', 'CHART_X_WIDTH_INVALIDE', 'Chart x and width sum cannot be greater than 12 ', '响应消息->dashboard导入接口', '2022-03-08 01:51:35', 1); +INSERT INTO `sys_i18n` VALUES (5793, '123017', 'zh', 'CHART_X_WIDTH_INVALIDE', '图表x轴和宽度之和不能超过12', '响应消息->dashboard导入接口', '2022-03-08 01:51:54', 1); INSERT INTO `sys_i18n` VALUES (5796, 'config.ipamip.ipamsubnet', 'en', 'config.ipamip.ipamsubnet', 'Ipamsubnet', '表头->ipam导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (5797, 'config.ipamip.ipamsubnet', 'zh', 'config.ipamip.ipamsubnet', '子网信息', '表头->ipam导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (5800, 'config.ipamip.mac', 'en', 'config.ipamip.mac', 'Mac', '表头->ipam导入/导出/模板下载', '2022-07-21 06:18:50', 1); @@ -3671,8 +3667,8 @@ INSERT INTO `sys_i18n` VALUES (5862, 'overall.addColumns', 'en', 'overall.addCol INSERT INTO `sys_i18n` VALUES (5863, 'overall.addColumns', 'zh', 'overall.addColumns', '添加列', '', '2022-03-24 07:38:56', 1); INSERT INTO `sys_i18n` VALUES (5864, 'overall.addMapping', 'en', 'overall.addMapping', 'Add value mapping', '', '2022-07-08 13:19:10', 415); INSERT INTO `sys_i18n` VALUES (5865, 'overall.addMapping', 'zh', 'overall.addMapping', '添加映射值', '', '2022-07-11 09:53:06', 415); -INSERT INTO `sys_i18n` VALUES (5866, 'dashboard.panel.chartForm.valMapping.regx', 'en', 'dashboard.panel.chartForm.valMapping.regx', 'Regx', '', '2022-03-24 07:46:00', 1); -INSERT INTO `sys_i18n` VALUES (5867, 'dashboard.panel.chartForm.valMapping.regx', 'zh', 'dashboard.panel.chartForm.valMapping.regx', '正则', '', '2022-03-24 07:46:09', 1); +INSERT INTO `sys_i18n` VALUES (5866, 'dashboard.dashboard.chartForm.valMapping.regx', 'en', 'dashboard.dashboard.chartForm.valMapping.regx', 'Regx', '', '2022-03-24 07:46:00', 1); +INSERT INTO `sys_i18n` VALUES (5867, 'dashboard.dashboard.chartForm.valMapping.regx', 'zh', 'dashboard.dashboard.chartForm.valMapping.regx', '正则', '', '2022-03-24 07:46:09', 1); INSERT INTO `sys_i18n` VALUES (5868, 'overall.global', 'en', 'overall.global', 'Global', '搜索框组件/promServer类型', '2022-07-25 09:52:14', 425); INSERT INTO `sys_i18n` VALUES (5869, 'overall.global', 'zh', 'overall.global', 'Global', '搜索框组件/promServer类型', '2022-07-25 09:52:10', 425); INSERT INTO `sys_i18n` VALUES (5870, 'overall.perDatacenter', 'en', 'overall.perDatacenter', 'Per-Datacenter', '', '2022-03-24 07:53:06', 1); @@ -3699,10 +3695,10 @@ INSERT INTO `sys_i18n` VALUES (5890, 'overall.left', 'en', 'overall.left', 'Left INSERT INTO `sys_i18n` VALUES (5891, 'overall.left', 'zh', 'overall.left', '左', '', '2022-07-26 01:20:52', 425); INSERT INTO `sys_i18n` VALUES (5892, 'overall.right', 'en', 'overall.right', 'Right', '', '2022-03-25 05:46:11', 1); INSERT INTO `sys_i18n` VALUES (5893, 'overall.right', 'zh', 'overall.right', '右', '', '2022-03-25 05:46:21', 1); -INSERT INTO `sys_i18n` VALUES (5894, 'panel.assetOk', 'en', 'panel.assetOk', 'Asset ok', 'panel/', '2022-07-26 01:29:55', 425); -INSERT INTO `sys_i18n` VALUES (5895, 'panel.assetOk', 'zh', 'panel.assetOk', '资产正常', 'panel/', '2022-07-26 01:29:45', 425); -INSERT INTO `sys_i18n` VALUES (5896, 'panel.assetAlarm', 'en', 'panel.assetAlarm', 'Asset alarm', 'panel/', '2022-07-26 01:29:49', 425); -INSERT INTO `sys_i18n` VALUES (5897, 'panel.assetAlarm', 'zh', 'panel.assetAlarm', '资产告警', 'panel/', '2022-07-26 01:29:52', 425); +INSERT INTO `sys_i18n` VALUES (5894, 'dashboard.assetOk', 'en', 'dashboard.assetOk', 'Asset ok', 'dashboard/', '2022-07-26 01:29:55', 425); +INSERT INTO `sys_i18n` VALUES (5895, 'dashboard.assetOk', 'zh', 'dashboard.assetOk', '资产正常', 'dashboard/', '2022-07-26 01:29:45', 425); +INSERT INTO `sys_i18n` VALUES (5896, 'dashboard.assetAlarm', 'en', 'dashboard.assetAlarm', 'Asset alarm', 'dashboard/', '2022-07-26 01:29:49', 425); +INSERT INTO `sys_i18n` VALUES (5897, 'dashboard.assetAlarm', 'zh', 'dashboard.assetAlarm', '资产告警', 'dashboard/', '2022-07-26 01:29:52', 425); INSERT INTO `sys_i18n` VALUES (5898, 'overall.topology', 'zh', 'overall.topology', '关系图', ' \n资产/数据中心/更多操作/关系图; 资产/资产列表/更多操作/关系图; 资产/资产配置/属性/更多操作/关系图; 资产/资产配置/型号/更多操作/关系图; 监控/应用组/更多操作/关系图; 监控/应用/更多操作/关系图; 监控/应用实例/更多操作/关系图;', '2022-07-20 09:41:44', 425); INSERT INTO `sys_i18n` VALUES (5899, 'overall.topology', 'en', 'overall.topology', 'Graph', '资产/数据中心/更多操作/关系图;\n资产/资产列表/更多操作/关系图;\n资产/资产配置/属性/更多操作/关系图;\n资产/资产配置/型号/更多操作/关系图;\n监控/应用组/更多操作/关系图;\n监控/应用/更多操作/关系图;\n监控/应用实例/更多操作/关系图;\n\n', '2022-07-20 09:41:38', 425); INSERT INTO `sys_i18n` VALUES (5900, '372010', 'en', 'ASSET_FIELD_META_KEY_NAME_DUPLICATE', 'Asset field key value or name duplicate', '响应消息->asset属性元数据新增/属性元数据修改接口', '2022-03-30 06:11:23', 1); @@ -3717,10 +3713,10 @@ INSERT INTO `sys_i18n` VALUES (5908, '513027', 'en', 'SYS_USER_PIN_NOT_CONTAIN_U INSERT INTO `sys_i18n` VALUES (5909, '513027', 'zh', 'SYS_USER_PIN_NOT_CONTAIN_UPPERCASE_LETTERS', '系统用户密码必须包含大写字母', '响应消息->user新增/修改/修改密码、登录接口', '2022-03-30 06:20:06', 1); INSERT INTO `sys_i18n` VALUES (5910, '513028', 'en', 'SYS_USER_PIN_NOT_CONTAIN_SPECIAL_LETTERS', 'System user pin must contain special letters', '响应消息->user新增/修改/修改密码、登录接口', '2022-03-30 06:20:39', 1); INSERT INTO `sys_i18n` VALUES (5911, '513028', 'zh', 'SYS_USER_PIN_NOT_CONTAIN_SPECIAL_LETTERS', '系统用户密码必须包含特殊字母', '响应消息->user新增/修改/修改密码、登录接口', '2022-03-30 06:20:58', 1); -INSERT INTO `sys_i18n` VALUES (5912, '513029', 'en', 'SYS_USER_PIN_LONGTIME_NO_MODIFY', 'System user pin has not been modified for a long time more than {0}', '响应消息->user新增/修改/修改密码、登录接口', '2022-06-20 06:21:48', 1); +INSERT INTO `sys_i18n` VALUES (5912, '513029', 'en', 'SYS_USER_PIN_LONGTIME_NO_MODIFY', 'System user pin has not been modified for a long time more than {0} days', '响应消息->user新增/修改/修改密码、登录接口', '2022-06-20 06:21:48', 1); INSERT INTO `sys_i18n` VALUES (5913, '513029', 'zh', 'SYS_USER_PIN_LONGTIME_NO_MODIFY', '系统用户密码超过 {0} 天未修改', '响应消息->user新增/修改/修改密码、登录接口', '2022-06-20 06:25:44', 1); -INSERT INTO `sys_i18n` VALUES (5914, '513030', 'en', 'SYS_USER_PIN_RETRY_ERROR', 'System user pin too many errors more than {0} , please try again after {1} minutes', '响应消息->user新增/修改/修改密码、登录接口', '2022-03-30 06:26:49', 1); -INSERT INTO `sys_i18n` VALUES (5915, '513030', 'zh', 'SYS_USER_PIN_RETRY_ERROR', '重试次数大于 {0},请在 {1} 分钟后重试', '响应消息->user新增/修改/修改密码、登录接口', '2022-06-20 06:25:32', 1); +INSERT INTO `sys_i18n` VALUES (5914, '513030', 'en', 'SYS_USER_PIN_RETRY_ERROR', 'System user pin too many errors more than {0} times, please try again after {1} minutes', '响应消息->user新增/修改/修改密码、登录接口', '2022-03-30 06:26:49', 1); +INSERT INTO `sys_i18n` VALUES (5915, '513030', 'zh', 'SYS_USER_PIN_RETRY_ERROR', '重试次数大于 {0} 次,请在 {1} 分钟后重试', '响应消息->user新增/修改/修改密码、登录接口', '2022-06-20 06:25:32', 1); INSERT INTO `sys_i18n` VALUES (5916, '521019', 'en', 'AGENT_NAME_ISNULL', 'Agent name can not be empty', '响应消息->agent新增/修改接口', '2022-03-30 06:29:30', 1); INSERT INTO `sys_i18n` VALUES (5917, '521019', 'zh', 'AGENT_NAME_ISNULL', '客户端名称不能为空', '响应消息->agent新增/修改接口', '2022-03-30 06:29:19', 1); INSERT INTO `sys_i18n` VALUES (5918, '521020', 'en', 'AGENT_NAME_EXISTED', 'Agent name existed', '响应消息->agent新增/修改接口', '2022-03-30 06:30:07', 1); @@ -3793,22 +3789,22 @@ INSERT INTO `sys_i18n` VALUES (5994, 'backup.backupNow', 'en', 'backup.backupNow INSERT INTO `sys_i18n` VALUES (5995, 'backup.backupNow', 'zh', 'backup.backupNow', '立即备份成功', 'backup/msg提示语句', '2022-07-20 09:24:07', 425); INSERT INTO `sys_i18n` VALUES (5996, 'backup.Restore', 'en', 'backup.Restore', 'Restore success', 'backup/按钮提示语句', '2022-07-20 09:23:46', 425); INSERT INTO `sys_i18n` VALUES (5997, 'backup.Restore', 'zh', 'backup.Restore', '恢复成功', 'backup/按钮提示语句', '2022-07-20 09:23:42', 425); -INSERT INTO `sys_i18n` VALUES (5998, 'backup.schedule', 'en', 'backup.schedule', 'Schedule', ' \npanel/; ', '2022-07-20 09:23:04', 425); -INSERT INTO `sys_i18n` VALUES (5999, 'backup.schedule', 'zh', 'backup.schedule', '时间表', ' \npanel/; ', '2022-07-20 09:23:08', 425); -INSERT INTO `sys_i18n` VALUES (6000, 'backup.only', 'en', 'backup.only', 'One time only', ' \npanel/; backuop/;', '2022-07-20 09:22:41', 425); -INSERT INTO `sys_i18n` VALUES (6001, 'backup.only', 'zh', 'backup.only', '仅一次', ' \npanel/; backuop/;', '2022-07-20 09:22:37', 425); -INSERT INTO `sys_i18n` VALUES (6002, 'backup.Daily', 'en', 'backup.Daily', 'Daily', 'panel/每日; backuop/每日;', '2022-07-20 09:22:13', 425); -INSERT INTO `sys_i18n` VALUES (6003, 'backup.Daily', 'zh', 'backup.Daily', '每日', 'panel/每日; backuop/每日;', '2022-07-20 09:22:09', 425); -INSERT INTO `sys_i18n` VALUES (6004, 'backup.Weekly', 'en', 'backup.Weekly', 'Weekly', ' \npanel/每周; backuop/每周;', '2022-07-20 09:21:35', 425); -INSERT INTO `sys_i18n` VALUES (6005, 'backup.Weekly', 'zh', 'backup.Weekly', '每周', ' \npanel/每周; backuop/每周;', '2022-07-20 09:21:31', 425); -INSERT INTO `sys_i18n` VALUES (6006, 'backup.Monthly', 'en', 'backup.Monthly', 'Monthly', 'panel/每月; backuop/每月;', '2022-07-20 09:21:12', 425); -INSERT INTO `sys_i18n` VALUES (6007, 'backup.Monthly', 'zh', 'backup.Monthly', '每月', 'panel/每月; backuop/每月;', '2022-07-20 09:21:08', 425); +INSERT INTO `sys_i18n` VALUES (5998, 'backup.schedule', 'en', 'backup.schedule', 'Schedule', ' \ndashboard/; ', '2022-07-20 09:23:04', 425); +INSERT INTO `sys_i18n` VALUES (5999, 'backup.schedule', 'zh', 'backup.schedule', '时间表', ' \ndashboard/; ', '2022-07-20 09:23:08', 425); +INSERT INTO `sys_i18n` VALUES (6000, 'backup.only', 'en', 'backup.only', 'One time only', ' \ndashboard/; backuop/;', '2022-07-20 09:22:41', 425); +INSERT INTO `sys_i18n` VALUES (6001, 'backup.only', 'zh', 'backup.only', '仅一次', ' \ndashboard/; backuop/;', '2022-07-20 09:22:37', 425); +INSERT INTO `sys_i18n` VALUES (6002, 'backup.Daily', 'en', 'backup.Daily', 'Daily', 'dashboard/每日; backuop/每日;', '2022-07-20 09:22:13', 425); +INSERT INTO `sys_i18n` VALUES (6003, 'backup.Daily', 'zh', 'backup.Daily', '每日', 'dashboard/每日; backuop/每日;', '2022-07-20 09:22:09', 425); +INSERT INTO `sys_i18n` VALUES (6004, 'backup.Weekly', 'en', 'backup.Weekly', 'Weekly', ' \ndashboard/每周; backuop/每周;', '2022-07-20 09:21:35', 425); +INSERT INTO `sys_i18n` VALUES (6005, 'backup.Weekly', 'zh', 'backup.Weekly', '每周', ' \ndashboard/每周; backuop/每周;', '2022-07-20 09:21:31', 425); +INSERT INTO `sys_i18n` VALUES (6006, 'backup.Monthly', 'en', 'backup.Monthly', 'Monthly', 'dashboard/每月; backuop/每月;', '2022-07-20 09:21:12', 425); +INSERT INTO `sys_i18n` VALUES (6007, 'backup.Monthly', 'zh', 'backup.Monthly', '每月', 'dashboard/每月; backuop/每月;', '2022-07-20 09:21:08', 425); INSERT INTO `sys_i18n` VALUES (6014, 'backup.day', 'en', 'backup.day', 'days', '', '2022-04-08 09:24:56', 1); INSERT INTO `sys_i18n` VALUES (6015, 'backup.day', 'zh', 'backup.day', '日', '', '2022-04-08 09:25:05', 1); -INSERT INTO `sys_i18n` VALUES (6018, 'backup.DayOfMonth', 'en', 'backup.DayOfMonth', 'Every day of the months', 'panel/;\nbackuop/;', '2022-07-20 09:20:21', 425); -INSERT INTO `sys_i18n` VALUES (6019, 'backup.DayOfMonth', 'zh', 'backup.DayOfMonth', '月里的每一天', 'panel/;\nbackuop/;', '2022-07-20 09:20:17', 425); -INSERT INTO `sys_i18n` VALUES (6020, 'backup.WeekOn', 'en', 'backup.WeekOn', 'Week on', 'backup/一周;\npanel/周;', '2022-07-20 09:19:41', 425); -INSERT INTO `sys_i18n` VALUES (6021, 'backup.WeekOn', 'zh', 'backup.WeekOn', '一周', 'backup/一周;\npanel/周;', '2022-07-20 09:19:37', 425); +INSERT INTO `sys_i18n` VALUES (6018, 'backup.DayOfMonth', 'en', 'backup.DayOfMonth', 'Every day of the months', 'dashboard/;\nbackuop/;', '2022-07-20 09:20:21', 425); +INSERT INTO `sys_i18n` VALUES (6019, 'backup.DayOfMonth', 'zh', 'backup.DayOfMonth', '月里的每一天', 'dashboard/;\nbackuop/;', '2022-07-20 09:20:17', 425); +INSERT INTO `sys_i18n` VALUES (6020, 'backup.WeekOn', 'en', 'backup.WeekOn', 'Week on', 'backup/一周;\ndashboard/周;', '2022-07-20 09:19:41', 425); +INSERT INTO `sys_i18n` VALUES (6021, 'backup.WeekOn', 'zh', 'backup.WeekOn', '一周', 'backup/一周;\ndashboard/周;', '2022-07-20 09:19:37', 425); INSERT INTO `sys_i18n` VALUES (6022, 'backup.RepeatEvery', 'en', 'backup.RepeatEvery', 'Repeat every', 'backup/循环间隔', '2022-07-20 09:19:00', 425); INSERT INTO `sys_i18n` VALUES (6023, 'backup.RepeatEvery', 'zh', 'backup.RepeatEvery', '循环间隔', 'backup/循环间隔', '2022-07-20 09:18:56', 425); INSERT INTO `sys_i18n` VALUES (6024, 'config.backup.backup', 'en', 'config.backup.backup', 'Backup', '', '2022-07-11 08:22:42', 415); @@ -3817,22 +3813,22 @@ INSERT INTO `sys_i18n` VALUES (6026, 'trace.maximumHops', 'en', 'trace.maxHops', INSERT INTO `sys_i18n` VALUES (6027, 'trace.maximumHops', 'zh', 'trace.maxHops', '最大跃点数', '工具箱/路由跟踪/原table列/数据', '2022-07-20 09:17:53', 425); INSERT INTO `sys_i18n` VALUES (6028, 'trace.totalTime', 'en', 'trace.totalTime', 'Total time', '工具箱/路由跟踪/原table列/数据', '2022-07-20 09:17:34', 425); INSERT INTO `sys_i18n` VALUES (6029, 'trace.totalTime', 'zh', 'trace.totalTime', '总时间', '工具箱/路由跟踪/原table列/数据', '2022-07-20 09:17:29', 425); -INSERT INTO `sys_i18n` VALUES (6030, 'timepicker.timerange', 'en', 'timepicker.timerange', 'Absolute time range', '告警/告警信息/绝对时间范围;\npanel/绝对时间范围;', '2022-07-21 01:32:26', 425); -INSERT INTO `sys_i18n` VALUES (6031, 'timepicker.timerange', 'zh', 'timepicker.timerange', '绝对时间范围', '告警/告警信息/绝对时间范围;\n panel/绝对时间范围;', '2022-07-21 01:32:35', 425); +INSERT INTO `sys_i18n` VALUES (6030, 'timepicker.timerange', 'en', 'timepicker.timerange', 'Absolute time range', '告警/告警信息/绝对时间范围;\ndashboard/绝对时间范围;', '2022-07-21 01:32:26', 425); +INSERT INTO `sys_i18n` VALUES (6031, 'timepicker.timerange', 'zh', 'timepicker.timerange', '绝对时间范围', '告警/告警信息/绝对时间范围;\n dashboard/绝对时间范围;', '2022-07-21 01:32:35', 425); INSERT INTO `sys_i18n` VALUES (6032, 'timepicker.applytimerange', 'en', 'timepicker.applytimerange', 'Apply time range', ' \n告警/告警信息/应用时间范围;', '2022-07-20 09:16:06', 425); INSERT INTO `sys_i18n` VALUES (6033, 'timepicker.applytimerange', 'zh', 'timepicker.applytimerange', '应用时间范围', ' \n告警/告警信息/应用时间范围;', '2022-07-20 09:16:02', 425); -INSERT INTO `sys_i18n` VALUES (6034, 'timepicker.recentlyUsed', 'en', 'timepicker.recentlyUsed', 'Recently used absolute ranges', '告警/告警信息/最近使用的时间范围;\n panel/最近使用的时间范围;', '2022-07-21 01:32:50', 425); -INSERT INTO `sys_i18n` VALUES (6035, 'timepicker.recentlyUsed', 'zh', 'timepicker.recentlyUsed', '最近使用的时间范围', ' \n告警/告警信息/最近使用的时间范围; panel/最近使用的时间范围;', '2022-07-21 01:32:58', 425); -INSERT INTO `sys_i18n` VALUES (6036, 'timepicker.relatime', 'en', 'timepicker.relatime', 'Relatime time ranges', '告警/告警信息/时间范围;\npanel/时间范围;', '2022-07-21 01:33:11', 425); -INSERT INTO `sys_i18n` VALUES (6037, 'timepicker.relatime', 'zh', 'timepicker.relatime', '时间范围', '告警/告警信息/时间范围;\npanel/时间范围;', '2022-07-21 01:33:16', 425); +INSERT INTO `sys_i18n` VALUES (6034, 'timepicker.recentlyUsed', 'en', 'timepicker.recentlyUsed', 'Recently used absolute ranges', '告警/告警信息/最近使用的时间范围;\n dashboard/最近使用的时间范围;', '2022-07-21 01:32:50', 425); +INSERT INTO `sys_i18n` VALUES (6035, 'timepicker.recentlyUsed', 'zh', 'timepicker.recentlyUsed', '最近使用的时间范围', ' \n告警/告警信息/最近使用的时间范围; dashboard/最近使用的时间范围;', '2022-07-21 01:32:58', 425); +INSERT INTO `sys_i18n` VALUES (6036, 'timepicker.relatime', 'en', 'timepicker.relatime', 'Relatime time ranges', '告警/告警信息/时间范围;\ndashboard/时间范围;', '2022-07-21 01:33:11', 425); +INSERT INTO `sys_i18n` VALUES (6037, 'timepicker.relatime', 'zh', 'timepicker.relatime', '时间范围', '告警/告警信息/时间范围;\ndashboard/时间范围;', '2022-07-21 01:33:16', 425); INSERT INTO `sys_i18n` VALUES (6038, 'ping.duplicate', 'en', 'ping.duplicate', 'Repeated', '工具箱/Ping/msg提示\n', '2022-07-20 09:13:05', 425); INSERT INTO `sys_i18n` VALUES (6039, 'ping.duplicate', 'zh', 'ping.duplicate', '重复的', '工具箱/Ping/msg提示\n', '2022-07-20 09:13:00', 425); INSERT INTO `sys_i18n` VALUES (6040, '751000', 'en', 'TOOL_PING_IP_ISNULL', 'Ping ip can not be empty', '响应消息->tool ping接口', '2022-04-17 14:34:22', 1); INSERT INTO `sys_i18n` VALUES (6041, '751000', 'zh', 'TOOL_PING_IP_ISNULL', 'Ping ip不能为空', '响应消息->tool ping接口', '2022-04-17 14:35:05', 1); INSERT INTO `sys_i18n` VALUES (6042, '751001', 'en', 'TOOL_TRACEROUTE_IP_ISNULL', 'Traceroute ip can not be empty', '响应消息->tool traceroute接口', '2022-04-17 14:35:18', 1); INSERT INTO `sys_i18n` VALUES (6043, '751001', 'zh', 'TOOL_TRACEROUTE_IP_ISNULL', 'Traceroute ip不能为空', '响应消息->tool traceroute接口', '2022-04-17 14:35:46', 1); -INSERT INTO `sys_i18n` VALUES (6044, '123006', 'en', 'PANEL_NAME_TOO_LONG', 'Panel name too long than 64', '响应消息->panel复制接口', '2022-04-15 16:40:06', 1); -INSERT INTO `sys_i18n` VALUES (6045, '123006', 'zh', 'PANEL_NAME_TOO_LONG', '面板名称过长超过64', '响应消息->panel复制接口', '2022-04-15 16:40:31', 1); +INSERT INTO `sys_i18n` VALUES (6044, '123006', 'en', 'DASHBOARD_NAME_TOO_LONG', 'Dashboard name too long than 64', '响应消息->dashboard复制接口', '2022-04-15 16:40:06', 1); +INSERT INTO `sys_i18n` VALUES (6045, '123006', 'zh', 'DASHBOARD_NAME_TOO_LONG', '面板名称过长超过64', '响应消息->dashboard复制接口', '2022-04-15 16:40:31', 1); INSERT INTO `sys_i18n` VALUES (6046, '354024', 'en', 'TYPECONF_AUTHPROTOCOL_INCORRECT', 'Asset type config auth protocol must be 0 ,1 or 2', '响应消息->asset类型配置新增/类型配置修改接口', '2022-04-20 11:00:00', 1); INSERT INTO `sys_i18n` VALUES (6047, '354025', 'en', 'TYPECONF_SNMPENABLE_INCORRECT', 'Asset type config snmp enable must be 0 or 1', '响应消息->asset类型配置新增/类型配置修改接口', '2022-04-20 11:00:00', 1); INSERT INTO `sys_i18n` VALUES (6048, '354026', 'en', 'TYPECONF_SNMPCOLLECT_INCORRECT', 'Asset type config snmp collect must be 0 or 1', '响应消息->asset类型配置新增/类型配置修改接口', '2022-04-20 11:00:00', 1); @@ -3855,10 +3851,10 @@ INSERT INTO `sys_i18n` VALUES (6064, 'overall.acknowledge', 'en', 'overall.ackno INSERT INTO `sys_i18n` VALUES (6065, 'overall.acknowledge', 'zh', 'overall.acknowledge', '确认', '告警/告警信息/给搜索框子组件传递的信息', '2022-07-20 09:10:31', 425); INSERT INTO `sys_i18n` VALUES (6066, 'overall.batchAck', 'en', 'overall.batchAck', 'Batches acknowledge', '', '2022-05-05 03:40:34', 1); INSERT INTO `sys_i18n` VALUES (6067, 'overall.batchAck', 'zh', 'overall.batchAck', '批量确认', '', '2022-05-05 03:40:59', 1); -INSERT INTO `sys_i18n` VALUES (6068, 'tip.ackSuccess', 'en', 'tip.ackSuccess', 'Acknowledge Success', '告警/告警信息/提示语句', '2022-07-20 09:09:36', 425); +INSERT INTO `sys_i18n` VALUES (6068, 'tip.ackSuccess', 'en', 'tip.ackSuccess', 'Acknowledge success', '告警/告警信息/提示语句', '2022-12-14 08:41:32', 415); INSERT INTO `sys_i18n` VALUES (6069, 'tip.ackSuccess', 'zh', 'tip.ackSuccess', '确认成功', '告警/告警信息/提示语句', '2022-07-20 09:09:30', 425); -INSERT INTO `sys_i18n` VALUES (6070, 'tip.SelectAlertMessage', 'en', 'tip.SelectAlertMessage', 'Select Alert Message', '', '2022-05-06 01:36:08', 1); -INSERT INTO `sys_i18n` VALUES (6071, 'tip.SelectAlertMessages', 'en', 'tip.SelectAlertMessages', 'Select Alert Messages', '', '2022-05-06 01:39:47', 1); +INSERT INTO `sys_i18n` VALUES (6070, 'tip.SelectAlertMessage', 'en', 'tip.SelectAlertMessage', 'Select alert message', '', '2022-12-14 08:41:44', 415); +INSERT INTO `sys_i18n` VALUES (6071, 'tip.SelectAlertMessages', 'en', 'tip.SelectAlertMessages', 'Select alert messages', '', '2022-12-14 08:41:56', 415); INSERT INTO `sys_i18n` VALUES (6072, 'tip.SelectAlertMessages', 'zh', 'tip.SelectAlertMessages', '请选择相应的告警信息', '', '2022-05-06 01:40:53', 1); INSERT INTO `sys_i18n` VALUES (6073, 'tip.confirmBatchAck', 'en', 'tip.confirmBatchAck', 'Are you sure to acknowledge these {0} pieces of data', '告警/告警信息/提示语句', '2022-07-20 09:08:58', 425); INSERT INTO `sys_i18n` VALUES (6074, 'tip.confirmBatchAck', 'zh', 'tip.confirmBatchAck', '确定确认这{0}条数据吗?', '告警/告警信息/提示语句', '2022-07-20 09:09:02', 425); @@ -3870,9 +3866,9 @@ INSERT INTO `sys_i18n` VALUES (6079, 'date.fromGreaterTo', 'en', 'date.fromGreat INSERT INTO `sys_i18n` VALUES (6080, 'date.fromGreaterTo', 'zh', 'date.fromGreaterTo', '开始时间大于结束', '告警/告警信息/属性', '2022-07-20 09:06:53', 425); INSERT INTO `sys_i18n` VALUES (6081, 'ping.trace', 'en', 'ping.trace', 'Trace route ', '工具箱/路由跟踪/\n', '2022-07-20 09:04:59', 425); INSERT INTO `sys_i18n` VALUES (6082, 'ping.trace', 'zh', 'ping.trace', 'Trace route ', '工具箱/路由跟踪/\n', '2022-07-20 09:04:55', 425); -INSERT INTO `sys_i18n` VALUES (6083, 'overall.snapshoot', 'en', 'overall.snapshoot', 'Snapshot', 'panel/', '2022-07-20 09:03:55', 425); -INSERT INTO `sys_i18n` VALUES (6084, 'overall.snapshoot', 'zh', 'overall.snapshoot', '快照', 'panel/', '2022-07-20 09:03:49', 425); -INSERT INTO `sys_i18n` VALUES (6085, 'tip.addFavorites', 'en', 'tip.addFavorites', 'Add to Favorites', '', '2022-05-27 02:28:36', 1); +INSERT INTO `sys_i18n` VALUES (6083, 'overall.snapshoot', 'en', 'overall.snapshoot', 'Snapshot', 'dashboard/', '2022-07-20 09:03:55', 425); +INSERT INTO `sys_i18n` VALUES (6084, 'overall.snapshoot', 'zh', 'overall.snapshoot', '快照', 'dashboard/', '2022-07-20 09:03:49', 425); +INSERT INTO `sys_i18n` VALUES (6085, 'tip.addFavorites', 'en', 'tip.addFavorites', 'Add to favorites', '', '2022-12-14 08:42:18', 415); INSERT INTO `sys_i18n` VALUES (6086, 'tip.addFavorites', 'zh', 'tip.addFavorites', '添加到收藏夹', '', '2022-05-27 02:28:59', 1); INSERT INTO `sys_i18n` VALUES (6087, 'explore.graph', 'en', 'explore.graph', 'Graph', '监控/探索/metric/提示文字\n', '2022-07-20 09:02:50', 425); INSERT INTO `sys_i18n` VALUES (6088, 'explore.graph', 'zh', 'explore.graph', '图表', '监控/探索/metric/提示文字\n', '2022-07-20 09:02:45', 425); @@ -3890,8 +3886,8 @@ INSERT INTO `sys_i18n` VALUES (6099, 'endpoint.logEnable', 'en', 'endpoint.logEn INSERT INTO `sys_i18n` VALUES (6100, 'endpoint.logEnable', 'zh', 'endpoint.logEnable', '日志状态', '', '2022-06-02 06:51:35', 1); INSERT INTO `sys_i18n` VALUES (6101, 'overall.addDashboard', 'en', 'overall.addDashboard', 'Add dashboard', '仪表盘/新建仪表盘', '2022-07-20 09:01:27', 425); INSERT INTO `sys_i18n` VALUES (6102, 'overall.addDashboard', 'zh', 'overall.addDashboard', '新建仪表盘', ' \n仪表盘/新建仪表盘', '2022-07-20 09:01:22', 425); -INSERT INTO `sys_i18n` VALUES (6103, 'endpoint.labelKey', 'en', 'endpoint.labelKey', 'Label Key', '监控/应用实例/value', '2022-07-20 09:01:05', 425); -INSERT INTO `sys_i18n` VALUES (6104, 'endpoint.labelKey', 'zh', 'endpoint.labelKey', 'Llabel key', '监控/应用实例/value', '2022-07-20 09:01:01', 425); +INSERT INTO `sys_i18n` VALUES (6103, 'endpoint.labelKey', 'en', 'endpoint.labelKey', 'Label key', '监控/应用实例/value', '2022-12-14 08:40:29', 415); +INSERT INTO `sys_i18n` VALUES (6104, 'endpoint.labelKey', 'zh', 'endpoint.labelKey', 'Label key', '监控/应用实例/value', '2022-12-14 08:40:44', 415); INSERT INTO `sys_i18n` VALUES (6105, 'endpoint.labelValue', 'en', 'endpoint.labelValue', 'Label value', '监控/应用实例/value\n', '2022-07-20 09:00:37', 425); INSERT INTO `sys_i18n` VALUES (6106, 'endpoint.labelValue', 'zh', 'endpoint.labelValue', 'Label value', '监控/应用实例/value\n', '2022-07-20 09:00:31', 425); INSERT INTO `sys_i18n` VALUES (6111, '231004', 'en', 'ENDPOINT_EDITTYPE_ISNULL', 'Endpoint edit type can not be empty', '响应消息->endpoint修改接口', '2022-06-06 16:47:06', 1); @@ -3906,70 +3902,70 @@ INSERT INTO `sys_i18n` VALUES (6119, '234008', 'en', 'ENDPOINT_LABELS_ACTION_INV INSERT INTO `sys_i18n` VALUES (6120, '234008', 'zh', 'ENDPOINT_LABELS_ACTION_INVALIDE', '端点标签动作参数必须为0或1', '响应消息->endpoint批量修改接口', '2022-06-06 16:47:06', 1); INSERT INTO `sys_i18n` VALUES (6121, 'dashboard.allDashboards', 'en', 'dashboard.allDashboards', 'All dashboards', '仪表盘/全部', '2022-07-20 08:56:08', 425); INSERT INTO `sys_i18n` VALUES (6122, 'dashboard.allDashboards', 'zh', 'dashboard.allDashboards', '全部仪表盘', '仪表盘/全部', '2022-07-20 08:56:04', 425); -INSERT INTO `sys_i18n` VALUES (6123, 'dashboard.starredDashboards', 'en', 'dashboard.starredDashboards', 'Starred dashboards', ' \npanel/value', '2022-07-21 05:42:32', 415); -INSERT INTO `sys_i18n` VALUES (6124, 'dashboard.starredDashboards', 'zh', 'dashboard.starredDashboards', '我的收藏', 'panel/value', '2022-07-20 08:58:56', 425); -INSERT INTO `sys_i18n` VALUES (6125, 'dashboard.createdByYou', 'en', 'dashboard.createdByYou', 'Created by you', 'panel/value', '2022-07-20 08:58:49', 425); -INSERT INTO `sys_i18n` VALUES (6126, 'dashboard.createdByYou', 'zh', 'dashboard.createdByYou', '我的创建', 'panel/value', '2022-07-20 08:58:33', 425); -INSERT INTO `sys_i18n` VALUES (6127, 'dashboard.recentlyViewed', 'en', 'dashboard.recentlyViewed', 'Recently viewed', 'panel/value', '2022-07-20 08:58:37', 425); -INSERT INTO `sys_i18n` VALUES (6128, 'dashboard.recentlyViewed', 'zh', 'dashboard.recentlyViewed', '最近浏览', ' \npanel/value', '2022-07-20 08:59:05', 425); +INSERT INTO `sys_i18n` VALUES (6123, 'dashboard.starredDashboards', 'en', 'dashboard.starredDashboards', 'Starred dashboards', ' \ndashboard/value', '2022-07-21 05:42:32', 415); +INSERT INTO `sys_i18n` VALUES (6124, 'dashboard.starredDashboards', 'zh', 'dashboard.starredDashboards', '我的收藏', 'dashboard/value', '2022-07-20 08:58:56', 425); +INSERT INTO `sys_i18n` VALUES (6125, 'dashboard.createdByYou', 'en', 'dashboard.createdByYou', 'Created by you', 'dashboard/value', '2022-07-20 08:58:49', 425); +INSERT INTO `sys_i18n` VALUES (6126, 'dashboard.createdByYou', 'zh', 'dashboard.createdByYou', '我的创建', 'dashboard/value', '2022-07-20 08:58:33', 425); +INSERT INTO `sys_i18n` VALUES (6127, 'dashboard.recentlyViewed', 'en', 'dashboard.recentlyViewed', 'Recently viewed', 'dashboard/value', '2022-07-20 08:58:37', 425); +INSERT INTO `sys_i18n` VALUES (6128, 'dashboard.recentlyViewed', 'zh', 'dashboard.recentlyViewed', '最近浏览', ' \ndashboard/value', '2022-07-20 08:59:05', 425); INSERT INTO `sys_i18n` VALUES (6129, '376012', 'zh', 'ASSET_FIELD_META_REFERENCED', '属性被资产引用', '响应消息->asset属性元数据删除接口', '2022-06-09 03:04:46', 1); INSERT INTO `sys_i18n` VALUES (6130, '376012', 'en', 'ASSET_FIELD_META_REFERENCED', 'Asset field meta referenced', '响应消息->asset属性元数据删除接口', '2022-06-09 03:04:46', 1); -INSERT INTO `sys_i18n` VALUES (6131, 'dashboard.panel.report', 'en', 'dashboard.panel.report', 'Report', 'panel/Report/', '2022-07-20 08:55:29', 425); -INSERT INTO `sys_i18n` VALUES (6134, 'dashboard.panel.report', 'zh', 'dashboard.panel.report', '报表', 'panel/Report/', '2022-07-20 08:55:25', 425); -INSERT INTO `sys_i18n` VALUES (6135, 'dashboard.panel.period', 'en', 'dashboard.panel.period', 'Period', ' \npanel/周期', '2022-07-20 08:54:54', 425); -INSERT INTO `sys_i18n` VALUES (6136, 'dashboard.panel.period', 'zh', 'dashboard.panel.period', '周期', ' \npanel/周期', '2022-07-20 08:54:50', 425); -INSERT INTO `sys_i18n` VALUES (6139, 'dashboard.panel.prevDay', 'en', 'dashboard.panel.prevDay', 'Previous day', 'panel/前一天', '2022-07-20 08:54:18', 425); -INSERT INTO `sys_i18n` VALUES (6140, 'dashboard.panel.prevDay', 'zh', 'dashboard.panel.prevDay', '前一天', 'panel/前一天', '2022-07-20 08:54:23', 425); -INSERT INTO `sys_i18n` VALUES (6141, 'dashboard.panel.prevWeek', 'en', 'dashboard.panel.prevWeek', 'Previous week', 'panel/前一周', '2022-07-20 08:53:59', 425); -INSERT INTO `sys_i18n` VALUES (6142, 'dashboard.panel.prevWeek', 'zh', 'dashboard.panel.prevWeek', '前一周', 'panel/前一周', '2022-07-20 08:54:09', 425); -INSERT INTO `sys_i18n` VALUES (6143, 'dashboard.panel.receivers', 'en', 'dashboard.panel.receivers', 'Receivers', '', '2022-06-13 07:14:16', 1); -INSERT INTO `sys_i18n` VALUES (6144, 'dashboard.panel.receivers', 'zh', 'dashboard.panel.receivers', '接收人', 'panel/', '2022-07-20 08:53:00', 425); +INSERT INTO `sys_i18n` VALUES (6131, 'dashboard.dashboard.report', 'en', 'dashboard.dashboard.report', 'Report', 'dashboard/Report/', '2022-07-20 08:55:29', 425); +INSERT INTO `sys_i18n` VALUES (6134, 'dashboard.dashboard.report', 'zh', 'dashboard.dashboard.report', '报表', 'dashboard/Report/', '2022-07-20 08:55:25', 425); +INSERT INTO `sys_i18n` VALUES (6135, 'dashboard.dashboard.period', 'en', 'dashboard.dashboard.period', 'Period', ' \ndashboard/周期', '2022-07-20 08:54:54', 425); +INSERT INTO `sys_i18n` VALUES (6136, 'dashboard.dashboard.period', 'zh', 'dashboard.dashboard.period', '周期', ' \ndashboard/周期', '2022-07-20 08:54:50', 425); +INSERT INTO `sys_i18n` VALUES (6139, 'dashboard.dashboard.prevDay', 'en', 'dashboard.dashboard.prevDay', 'Previous day', 'dashboard/前一天', '2022-07-20 08:54:18', 425); +INSERT INTO `sys_i18n` VALUES (6140, 'dashboard.dashboard.prevDay', 'zh', 'dashboard.dashboard.prevDay', '前一天', 'dashboard/前一天', '2022-07-20 08:54:23', 425); +INSERT INTO `sys_i18n` VALUES (6141, 'dashboard.dashboard.prevWeek', 'en', 'dashboard.dashboard.prevWeek', 'Previous week', 'dashboard/前一周', '2022-07-20 08:53:59', 425); +INSERT INTO `sys_i18n` VALUES (6142, 'dashboard.dashboard.prevWeek', 'zh', 'dashboard.dashboard.prevWeek', '前一周', 'dashboard/前一周', '2022-07-20 08:54:09', 425); +INSERT INTO `sys_i18n` VALUES (6143, 'dashboard.dashboard.receivers', 'en', 'dashboard.dashboard.receivers', 'Receivers', '', '2022-06-13 07:14:16', 1); +INSERT INTO `sys_i18n` VALUES (6144, 'dashboard.dashboard.receivers', 'zh', 'dashboard.dashboard.receivers', '接收人', 'dashboard/', '2022-07-20 08:53:00', 425); INSERT INTO `sys_i18n` VALUES (6145, 'alert.relatedAlerts', 'en', 'alert.relatedAlerts', 'Related alerts', '', '2022-06-13 08:54:09', 1); INSERT INTO `sys_i18n` VALUES (6146, 'alert.relatedAlerts', 'zh', 'alert.relatedAlerts', '相关告警', '', '2022-06-13 08:54:48', 1); -INSERT INTO `sys_i18n` VALUES (6147, '121082', 'en', 'PANEL_PARAM_REPORTRANGE_ISNULL', 'Panel param report range can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6148, '121082', 'zh', 'PANEL_PARAM_REPORTRANGE_ISNULL', '面板参数报告范围不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6149, '121083', 'en', 'PANEL_PARAM_RANGETYPE_ISNULL', 'Panel param range type can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6150, '121083', 'zh', 'PANEL_PARAM_RANGETYPE_ISNULL', '面板参数范围类型不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6151, '123084', 'en', 'PANEL_PARAM_RANGETYPE_INVALIDE', 'Panel param range type must be previous or last', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6152, '123084', 'zh', 'PANEL_PARAM_RANGETYPE_INVALIDE', '面板参数范围类型必须为 previous 或 last', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6153, '121085', 'en', 'PANEL_PARAM_RANGEINTERVAL_ISNULL', 'Panel param range interval can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6154, '121085', 'zh', 'PANEL_PARAM_RANGEINTERVAL_ISNULL', '面板参数范围间隔不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6155, '121086', 'en', 'PANEL_PARAM_RANGEUNIT_ISNULL', 'Panel param range unit can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6156, '121086', 'zh', 'PANEL_PARAM_RANGEUNIT_ISNULL', '面板参数范围单元不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6157, '123087', 'en', 'PANEL_PARAM_RANGEUNIT_INVALIDE', 'Panel param range unit must be hour, day, week or month', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6158, '123087', 'zh', 'PANEL_PARAM_RANGEUNIT_INVALIDE', '面板参数范围单元必须为 hour, day, week 或 month', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6159, '121088', 'en', 'PANEL_PARAM_REPORTSCHEDULE_ISNULL', 'Panel param report schedule can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6160, '121088', 'zh', 'PANEL_PARAM_REPORTSCHEDULE_ISNULL', '面板参数报告日程不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6161, '121089', 'en', 'PANEL_PARAM_SCHEDULETYPE_ISNULL', 'Panel param schedule type can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6162, '121089', 'zh', 'PANEL_PARAM_SCHEDULETYPE_ISNULL', '面板参数日程类型不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6163, '123090', 'en', 'PANEL_PARAM_SCHEDULETYPE_INVALIDE', 'Panel param schedule type must be 1, 2, 3 or 4', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6164, '123090', 'zh', 'PANEL_PARAM_SCHEDULETYPE_INVALIDE', '面板参数日程类型必须为 1, 2, 3 或 4', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6165, '121091', 'en', 'PANEL_PARAM_SCHEDULEREPEAT_ISNULL', 'Panel param schedule repeat can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6166, '121091', 'zh', 'PANEL_PARAM_SCHEDULEREPEAT_ISNULL', '面板参数日程重复次数不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6167, '121092', 'en', 'PANEL_PARAM_SCHEDULESTIME_ISNULL', 'Panel param schedule stime can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6168, '121092', 'zh', 'PANEL_PARAM_SCHEDULESTIME_ISNULL', '面板参数日程开始时间不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6169, '121093', 'en', 'PANEL_PARAM_SCHEDULENUMS_ISNULL', 'Panel param schedule nums can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6170, '121093', 'zh', 'PANEL_PARAM_SCHEDULENUMS_ISNULL', '面板参数日程日期不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6171, '123094', 'en', 'PANEL_PARAM_SCHEDULENUMS_INVALIDE', 'Panel param schedule nums is invalide', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6172, '123094', 'zh', 'PANEL_PARAM_SCHEDULENUMS_INVALIDE', '面板参数日程日期不在允许范围内', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6173, '121095', 'en', 'PANEL_PARAM_REPORTRECEIVERS_ISNULL', 'Panel param report receivers can not be empty', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6174, '121095', 'zh', 'PANEL_PARAM_REPORTRECEIVERS_ISNULL', '面板参数报告接收人不能为空', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6175, '123096', 'en', 'PANEL_PARAM_REPORTCHARTSHARE_INVALIDE', 'Panel param report tooltip must be none, crosshair or tooltip', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); -INSERT INTO `sys_i18n` VALUES (6176, '123096', 'zh', 'PANEL_PARAM_REPORTCHARTSHARE_INVALIDE', '面板参数报告图表工具提示必须为 none, crosshair 或 tooltip', '响应消息->panel新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6147, '121082', 'en', 'DASHBOARD_PARAM_REPORTRANGE_ISNULL', 'Dashboard param report range can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6148, '121082', 'zh', 'DASHBOARD_PARAM_REPORTRANGE_ISNULL', '面板参数报告范围不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6149, '121083', 'en', 'DASHBOARD_PARAM_RANGETYPE_ISNULL', 'Dashboard param range type can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6150, '121083', 'zh', 'DASHBOARD_PARAM_RANGETYPE_ISNULL', '面板参数范围类型不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6151, '123084', 'en', 'DASHBOARD_PARAM_RANGETYPE_INVALIDE', 'Dashboard param range type must be previous or last', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6152, '123084', 'zh', 'DASHBOARD_PARAM_RANGETYPE_INVALIDE', '面板参数范围类型必须为 previous 或 last', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6153, '121085', 'en', 'DASHBOARD_PARAM_RANGEINTERVAL_ISNULL', 'Dashboard param range interval can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6154, '121085', 'zh', 'DASHBOARD_PARAM_RANGEINTERVAL_ISNULL', '面板参数范围间隔不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6155, '121086', 'en', 'DASHBOARD_PARAM_RANGEUNIT_ISNULL', 'Dashboard param range unit can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6156, '121086', 'zh', 'DASHBOARD_PARAM_RANGEUNIT_ISNULL', '面板参数范围单元不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6157, '123087', 'en', 'DASHBOARD_PARAM_RANGEUNIT_INVALIDE', 'Dashboard param range unit must be hour, day, week or month', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6158, '123087', 'zh', 'DASHBOARD_PARAM_RANGEUNIT_INVALIDE', '面板参数范围单元必须为 hour, day, week 或 month', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6159, '121088', 'en', 'DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL', 'Dashboard param report schedule can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6160, '121088', 'zh', 'DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL', '面板参数报告日程不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6161, '121089', 'en', 'DASHBOARD_PARAM_SCHEDULETYPE_ISNULL', 'Dashboard param schedule type can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6162, '121089', 'zh', 'DASHBOARD_PARAM_SCHEDULETYPE_ISNULL', '面板参数日程类型不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6163, '123090', 'en', 'DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE', 'Dashboard param schedule type must be 1, 2, 3 or 4', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6164, '123090', 'zh', 'DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE', '面板参数日程类型必须为 1, 2, 3 或 4', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6165, '121091', 'en', 'DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL', 'Dashboard param schedule repeat can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6166, '121091', 'zh', 'DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL', '面板参数日程重复次数不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6167, '121092', 'en', 'DASHBOARD_PARAM_SCHEDULESTIME_ISNULL', 'Dashboard param schedule stime can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6168, '121092', 'zh', 'DASHBOARD_PARAM_SCHEDULESTIME_ISNULL', '面板参数日程开始时间不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6169, '121093', 'en', 'DASHBOARD_PARAM_SCHEDULENUMS_ISNULL', 'Dashboard param schedule nums can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6170, '121093', 'zh', 'DASHBOARD_PARAM_SCHEDULENUMS_ISNULL', '面板参数日程日期不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6171, '123094', 'en', 'DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE', 'Dashboard param schedule nums is invalide', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6172, '123094', 'zh', 'DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE', '面板参数日程日期不在允许范围内', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6173, '121095', 'en', 'DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL', 'Dashboard param report receivers can not be empty', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6174, '121095', 'zh', 'DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL', '面板参数报告接收人不能为空', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6175, '123096', 'en', 'DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE', 'Dashboard param report tooltip must be none, crosshair or tooltip', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); +INSERT INTO `sys_i18n` VALUES (6176, '123096', 'zh', 'DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE', '面板参数报告图表工具提示必须为 none, crosshair 或 tooltip', '响应消息->dashboard新增/修改接口', '2022-06-15 10:47:06', 1); INSERT INTO `sys_i18n` VALUES (6177, 'overall.online', 'en', 'overall.online', 'Online', '\n管理/用户/在线;\n', '2022-07-20 08:10:36', 425); INSERT INTO `sys_i18n` VALUES (6178, 'overall.online', 'zh', 'overall.online', '在线', '\n管理/用户/在线;\n', '2022-07-20 08:10:33', 425); -INSERT INTO `sys_i18n` VALUES (6179, 'dashboard.panel.crosshair', 'en', 'dashboard.panel.crosshair', 'Share crosshair', ' \npanel/chartShare/', '2022-07-20 08:09:41', 425); -INSERT INTO `sys_i18n` VALUES (6180, 'dashboard.panel.crosshair', 'zh', 'dashboard.panel.crosshair', '分享光标', ' \npanel/chartShare/', '2022-07-20 08:09:37', 425); -INSERT INTO `sys_i18n` VALUES (6181, 'dashboard.panel.shareTooltip', 'en', 'dashboard.panel.shareTooltip', 'Share tooltip', ' \npanel/chartShare/', '2022-07-20 08:09:15', 425); -INSERT INTO `sys_i18n` VALUES (6182, 'dashboard.panel.shareTooltip', 'zh', 'dashboard.panel.shareTooltip', '分享提示框', ' \npanel/chartShare/', '2022-07-20 08:09:11', 425); -INSERT INTO `sys_i18n` VALUES (6183, 'dashboard.panel.chartTooltip', 'en', 'dashboard.panel.chartTooltip', 'Chart tooltip', 'panel/chartShare/', '2022-07-20 08:08:58', 425); -INSERT INTO `sys_i18n` VALUES (6184, 'dashboard.panel.chartTooltip', 'zh', 'dashboard.panel.chartTooltip', '图表提示框', 'panel/chartShare/', '2022-07-20 08:08:54', 425); -INSERT INTO `sys_i18n` VALUES (6185, 'dashboard.panel.chartTooltipText', 'en', 'dashboard.panel.chartTooltipText', 'Controls tooltip and hover highlight behavior across different charts', 'panel/chartShare/', '2022-07-20 08:08:39', 425); -INSERT INTO `sys_i18n` VALUES (6186, 'dashboard.panel.chartTooltipText', 'zh', 'dashboard.panel.chartTooltipText', '控制不同图表上的提示框和光标行为', 'panel/chartShare/', '2022-07-20 08:08:32', 425); +INSERT INTO `sys_i18n` VALUES (6179, 'dashboard.dashboard.crosshair', 'en', 'dashboard.dashboard.crosshair', 'Share crosshair', ' \ndashboard/chartShare/', '2022-07-20 08:09:41', 425); +INSERT INTO `sys_i18n` VALUES (6180, 'dashboard.dashboard.crosshair', 'zh', 'dashboard.dashboard.crosshair', '分享光标', ' \ndashboard/chartShare/', '2022-07-20 08:09:37', 425); +INSERT INTO `sys_i18n` VALUES (6181, 'dashboard.dashboard.shareTooltip', 'en', 'dashboard.dashboard.shareTooltip', 'Share tooltip', ' \ndashboard/chartShare/', '2022-07-20 08:09:15', 425); +INSERT INTO `sys_i18n` VALUES (6182, 'dashboard.dashboard.shareTooltip', 'zh', 'dashboard.dashboard.shareTooltip', '分享提示框', ' \ndashboard/chartShare/', '2022-07-20 08:09:11', 425); +INSERT INTO `sys_i18n` VALUES (6183, 'dashboard.dashboard.chartTooltip', 'en', 'dashboard.dashboard.chartTooltip', 'Chart tooltip', 'dashboard/chartShare/', '2022-07-20 08:08:58', 425); +INSERT INTO `sys_i18n` VALUES (6184, 'dashboard.dashboard.chartTooltip', 'zh', 'dashboard.dashboard.chartTooltip', '图表提示框', 'dashboard/chartShare/', '2022-07-20 08:08:54', 425); +INSERT INTO `sys_i18n` VALUES (6185, 'dashboard.dashboard.chartTooltipText', 'en', 'dashboard.dashboard.chartTooltipText', 'Controls tooltip and hover highlight behavior across different charts', 'dashboard/chartShare/', '2022-07-20 08:08:39', 425); +INSERT INTO `sys_i18n` VALUES (6186, 'dashboard.dashboard.chartTooltipText', 'zh', 'dashboard.dashboard.chartTooltipText', '控制不同图表上的提示框和光标行为', 'dashboard/chartShare/', '2022-07-20 08:08:32', 425); INSERT INTO `sys_i18n` VALUES (6187, '999', 'zh', 'ERROR', '错误', '响应消息->请求发生错误', '2021-11-02 00:00:00', 1); INSERT INTO `sys_i18n` VALUES (6188, 'tip.SelectAlertMessage', 'zh', 'tip.SelectAlertMessage', '选择告警', '资产/数据中心/名称; 资产/资产列表/名称; 资产/资产配置/属性/名称; 监控/应用组/名称; 监控/应用/名称; 监控/应用实例/名称; 告警/告警静默/名称;', '2022-07-20 08:07:47', 425); -INSERT INTO `sys_i18n` VALUES (6189, 'overall.name', 'en', 'overall.name', 'Name', '资产/数据中心/名称;\n资产/资产列表/名称;\n资产/资产配置/属性/名称;\n\n监控/应用组/名称;\n监控/应用/名称;\n监控/应用实例/名称;\n告警/告警静默/名称;\n\n\n\n\n\n\n\n表头->数据中心导入/导出/模板下载、endpoint导入/导出/模板下载、告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、资产导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 381); -INSERT INTO `sys_i18n` VALUES (6190, 'overall.name', 'zh', 'overall.name', '名称', '资产/数据中心/名称;\n资产/资产列表/名称;\n资产/资产配置/属性/名称;\n\n监控/应用组/名称;\n监控/应用/名称;\n监控/应用实例/名称;\n告警/告警静默/名称;\n\n\n\n\n\n\n\n表头->数据中心导入/导出/模板下载、endpoint导入/导出/模板下载、告警规则导入/导出/模板下载、资产panel导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、资产导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (6189, 'overall.name', 'en', 'overall.name', 'Name', '资产/数据中心/名称;\n资产/资产列表/名称;\n资产/资产配置/属性/名称;\n\n监控/应用组/名称;\n监控/应用/名称;\n监控/应用实例/名称;\n告警/告警静默/名称;\n\n\n\n\n\n\n\n表头->数据中心导入/导出/模板下载、endpoint导入/导出/模板下载、告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、资产导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 381); +INSERT INTO `sys_i18n` VALUES (6190, 'overall.name', 'zh', 'overall.name', '名称', '资产/数据中心/名称;\n资产/资产列表/名称;\n资产/资产配置/属性/名称;\n\n监控/应用组/名称;\n监控/应用/名称;\n监控/应用实例/名称;\n告警/告警静默/名称;\n\n\n\n\n\n\n\n表头->数据中心导入/导出/模板下载、endpoint导入/导出/模板下载、告警规则导入/导出/模板下载、资产dashboard导入/导出/模板下载、ipam子网导入/导出/模板下载、ipam导入/导出/模板下载、资产导入/导出/模板下载、机柜导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); INSERT INTO `sys_i18n` VALUES (6191, 'overall.save', 'en', 'overall.save', 'Save', '\n监控/应用实例/底部按钮;\n系统配置/客户端/底部按钮; \n资产/数据中心/底部按钮;\n', '2022-07-20 08:03:50', 425); INSERT INTO `sys_i18n` VALUES (6192, 'overall.save', 'zh', 'overall.save', '保存', '\n监控/应用实例/底部按钮;\n系统配置/客户端/底部按钮; \n资产/数据中心/底部按钮;\n', '2022-07-20 08:03:46', 425); INSERT INTO `sys_i18n` VALUES (6193, 'overall.state', 'en', 'overall.state', 'State', '监控/应用实例/状态; 监控/应用/状态; 监控/应用组/状态; 告警/告警信息/状态; 告警/告警静默/状态;\n表头->数据中心导入/导出/模板下载、告警规则导入/导出/模板下载、ipam导出、资产导入/导出/模板下载、告警信息导出', '2022-07-21 06:18:50', 425); @@ -4006,8 +4002,8 @@ INSERT INTO `sys_i18n` VALUES (6230, '731006', 'en', 'IPAM_IP_INTERVAL_ERROR', ' INSERT INTO `sys_i18n` VALUES (6231, '731006', 'zh', 'IPAM_IP_INTERVAL_ERROR', 'ip地址已存在', '响应消息->ipam新增/修改/导入接口', '2022-06-20 15:54:48', 1); INSERT INTO `sys_i18n` VALUES (6232, '731007', 'en', 'IPAM_IP_ASSET_ISNULL', 'Ipamip asset can not be null', '响应消息->ipam导入接口', '2022-06-20 15:54:48', 1); INSERT INTO `sys_i18n` VALUES (6233, '731007', 'zh', 'IPAM_IP_ASSET_ISNULL', 'ip资产不存在', '响应消息->ipam导入接口', '2022-06-20 15:54:48', 1); -INSERT INTO `sys_i18n` VALUES (6234, '731008', 'en', 'IPAM_IP_SUBNET_ISNULL', 'Ipamip subnet can not be null', '响应消息->ipam新增/修改/导入接口', '2022-06-20 15:54:48', 1); -INSERT INTO `sys_i18n` VALUES (6235, '731008', 'zh', 'IPAM_IP_SUBNET_ISNULL', 'ip子网不存在', '响应消息->ipam新增/修改/导入接口', '2022-06-20 15:54:48', 1); +INSERT INTO `sys_i18n` VALUES (6234, '731008', 'en', 'IPAM_IP_SUBNET_NOT_EXISTS', 'Ipamip subnet not exists', '响应消息->ipam新增/修改/导入接口', '2022-06-20 15:54:48', 1); +INSERT INTO `sys_i18n` VALUES (6235, '731008', 'zh', 'IPAM_IP_SUBNET_NOT_EXISTS', 'ip子网不存在', '响应消息->ipam新增/修改/导入接口', '2022-06-20 15:54:48', 1); INSERT INTO `sys_i18n` VALUES (6236, '731009', 'en', 'IPAM_IP_MAC_ERROR', 'Ipamip mac error, mac repeat', '响应消息->ipam导入接口', '2022-06-20 15:54:48', 1); INSERT INTO `sys_i18n` VALUES (6237, '731009', 'zh', 'IPAM_IP_MAC_ERROR', 'ip mac地址重复', '响应消息->ipam导入接口', '2022-06-20 15:54:48', 1); INSERT INTO `sys_i18n` VALUES (6238, '731010', 'en', 'IPAM_IP_SUBNET_ADDR_ERROR', 'Ipamip addr error, ip addr different subnet addr', '响应消息->ipam导入接口', '2022-06-20 15:54:48', 1); @@ -4048,28 +4044,28 @@ INSERT INTO `sys_i18n` VALUES (6274, 'config.alert.id.comment', 'en', 'config.al INSERT INTO `sys_i18n` VALUES (6275, 'config.alert.id.comment', 'zh', 'config.alert.id.comment', 'ID 示例:220623020000138', '表头->告警信息导出', '2022-07-21 06:18:50', 414); INSERT INTO `sys_i18n` VALUES (6276, 'config.alert.labels.comment', 'en', 'config.alert.labels.comment', 'Label Exampel : {\"instance\":\"192.168.40.126:9100\",\"module\":\"node_exporter\"}', '表头->告警信息导出', '2022-07-21 06:18:50', 414); INSERT INTO `sys_i18n` VALUES (6277, 'config.alert.labels.comment', 'zh', 'config.alert.labels.comment', '标签 示例:{\"instance\":\"192.168.40.126:9100\",\"module\":\"node_exporter\"}', '表头->告警信息导出', '2022-07-21 06:18:50', 414); -INSERT INTO `sys_i18n` VALUES (6278, 'dashboard.panel.queryExpression', 'en', 'dashboard.panel.queryExpression', 'Query expression', 'panel/Query expression/', '2022-07-20 07:43:28', 425); -INSERT INTO `sys_i18n` VALUES (6279, 'dashboard.panel.queryExpression', 'zh', 'dashboard.panel.queryExpression', '查询表达式', 'panel/Query expression/', '2022-07-20 07:43:23', 425); -INSERT INTO `sys_i18n` VALUES (6280, 'dashboard.panel.customValues', 'en', 'dashboard.panel.customValues', 'Custom values', 'panel/Custom values/', '2022-07-20 07:42:49', 425); -INSERT INTO `sys_i18n` VALUES (6281, 'dashboard.panel.customValues', 'zh', 'dashboard.panel.customValues', '自定义值', 'panel/Custom values/', '2022-07-20 07:42:45', 425); -INSERT INTO `sys_i18n` VALUES (6282, 'dashboard.panel.regex', 'en', 'dashboard.panel.regex', 'Regex', ' \npanel/Regex/', '2022-07-20 07:38:55', 425); -INSERT INTO `sys_i18n` VALUES (6283, 'dashboard.panel.regex', 'zh', 'dashboard.panel.regex', '正则表达式', 'panel/Regex/', '2022-07-20 07:38:44', 425); +INSERT INTO `sys_i18n` VALUES (6278, 'dashboard.dashboard.queryExpression', 'en', 'dashboard.dashboard.queryExpression', 'Query expression', 'dashboard/Query expression/', '2022-07-20 07:43:28', 425); +INSERT INTO `sys_i18n` VALUES (6279, 'dashboard.dashboard.queryExpression', 'zh', 'dashboard.dashboard.queryExpression', '查询表达式', 'dashboard/Query expression/', '2022-07-20 07:43:23', 425); +INSERT INTO `sys_i18n` VALUES (6280, 'dashboard.dashboard.customValues', 'en', 'dashboard.dashboard.customValues', 'Custom values', 'dashboard/Custom values/', '2022-07-20 07:42:49', 425); +INSERT INTO `sys_i18n` VALUES (6281, 'dashboard.dashboard.customValues', 'zh', 'dashboard.dashboard.customValues', '自定义值', 'dashboard/Custom values/', '2022-07-20 07:42:45', 425); +INSERT INTO `sys_i18n` VALUES (6282, 'dashboard.dashboard.regex', 'en', 'dashboard.dashboard.regex', 'Regex', ' \ndashboard/Regex/', '2022-07-20 07:38:55', 425); +INSERT INTO `sys_i18n` VALUES (6283, 'dashboard.dashboard.regex', 'zh', 'dashboard.dashboard.regex', '正则表达式', 'dashboard/Regex/', '2022-07-20 07:38:44', 425); INSERT INTO `sys_i18n` VALUES (6284, 'validate.variable', 'en', 'validate.variable', 'Only word and digit characters are allowed', '', '2022-06-28 09:07:55', 407); INSERT INTO `sys_i18n` VALUES (6285, 'validate.variable', 'zh', 'validate.variable', '只允许单词和数字字符', '', '2022-06-28 09:08:12', 407); -INSERT INTO `sys_i18n` VALUES (6286, 'dashboard.panel.multi', 'en', 'dashboard.panel.multi', 'Multi-value', 'panel/Multi-value/', '2022-07-20 07:38:08', 425); -INSERT INTO `sys_i18n` VALUES (6287, 'dashboard.panel.multi', 'zh', 'dashboard.panel.multi', '多值', 'panel/Multi-value/', '2022-07-20 07:38:01', 425); -INSERT INTO `sys_i18n` VALUES (6288, 'dashboard.panel.allOption', 'en', 'dashboard.panel.allOption', 'All option', 'panel/Multi-value/', '2022-07-20 07:37:08', 425); -INSERT INTO `sys_i18n` VALUES (6289, 'dashboard.panel.allOption', 'zh', 'dashboard.panel.allOption', '所有选项', 'panel/Multi-value/', '2022-07-20 07:37:12', 425); -INSERT INTO `sys_i18n` VALUES (6290, 'dashboard.panel.multiTip', 'en', 'dashboard.panel.multiTip', 'Enables multiple values to be selected at the same time', ' \npanel/Multi-value/', '2022-07-20 07:36:48', 425); -INSERT INTO `sys_i18n` VALUES (6291, 'dashboard.panel.multiTip', 'zh', 'dashboard.panel.multiTip', '允许同时选择多个值', 'panel/Multi-value/', '2022-07-20 07:36:42', 425); -INSERT INTO `sys_i18n` VALUES (6292, 'dashboard.panel.allOptionTip', 'en', 'dashboard.panel.allOptionTip', 'Enables an option to include all variables', ' \npanel/All option/', '2022-07-20 07:36:12', 425); -INSERT INTO `sys_i18n` VALUES (6293, 'dashboard.panel.allOptionTip', 'zh', 'dashboard.panel.allOptionTip', '启用包含所有变量的选项', ' \npanel/All option/', '2022-07-20 07:36:07', 425); -INSERT INTO `sys_i18n` VALUES (6294, 'dashboard.panel.variables', 'en', 'dashboard.panel.variables', 'Variables', ' \npanel/variable/', '2022-07-20 07:35:31', 425); -INSERT INTO `sys_i18n` VALUES (6295, 'dashboard.panel.variables', 'zh', 'dashboard.panel.variables', '变量', 'panel/variable/', '2022-07-20 07:35:26', 425); -INSERT INTO `sys_i18n` VALUES (6296, 'dashboard.panel.addVariable', 'en', 'dashboard.panel.addVariable', 'Add variable', ' \npanel/按钮提示文字', '2022-07-20 07:34:59', 425); -INSERT INTO `sys_i18n` VALUES (6297, 'dashboard.panel.addVariable', 'zh', 'dashboard.panel.addVariable', '添加变量', 'panel/按钮提示文字', '2022-07-20 07:34:50', 425); -INSERT INTO `sys_i18n` VALUES (6298, 'dashboard.panel.matchRegex', 'en', 'dashboard.panel.matchRegex', 'Must match the regex [a-zA-Z_][a-zA-Z0-9_]*', 'panel/Name/', '2022-07-20 07:31:52', 425); -INSERT INTO `sys_i18n` VALUES (6299, 'dashboard.panel.matchRegex', 'zh', 'dashboard.panel.matchRegex', '必须匹配正则表达式[a-zA-Z_][a-zA-Z0-9_]*', 'panel/Name/', '2022-07-20 07:31:48', 425); +INSERT INTO `sys_i18n` VALUES (6286, 'dashboard.dashboard.multi', 'en', 'dashboard.dashboard.multi', 'Multi-value', 'dashboard/Multi-value/', '2022-07-20 07:38:08', 425); +INSERT INTO `sys_i18n` VALUES (6287, 'dashboard.dashboard.multi', 'zh', 'dashboard.dashboard.multi', '多值', 'dashboard/Multi-value/', '2022-07-20 07:38:01', 425); +INSERT INTO `sys_i18n` VALUES (6288, 'dashboard.dashboard.allOption', 'en', 'dashboard.dashboard.allOption', 'All option', 'dashboard/Multi-value/', '2022-07-20 07:37:08', 425); +INSERT INTO `sys_i18n` VALUES (6289, 'dashboard.dashboard.allOption', 'zh', 'dashboard.dashboard.allOption', '所有选项', 'dashboard/Multi-value/', '2022-07-20 07:37:12', 425); +INSERT INTO `sys_i18n` VALUES (6290, 'dashboard.dashboard.multiTip', 'en', 'dashboard.dashboard.multiTip', 'Enables multiple values to be selected at the same time', ' \ndashboard/Multi-value/', '2022-07-20 07:36:48', 425); +INSERT INTO `sys_i18n` VALUES (6291, 'dashboard.dashboard.multiTip', 'zh', 'dashboard.dashboard.multiTip', '允许同时选择多个值', 'dashboard/Multi-value/', '2022-07-20 07:36:42', 425); +INSERT INTO `sys_i18n` VALUES (6292, 'dashboard.dashboard.allOptionTip', 'en', 'dashboard.dashboard.allOptionTip', 'Enables an option to include all variables', ' \ndashboard/All option/', '2022-07-20 07:36:12', 425); +INSERT INTO `sys_i18n` VALUES (6293, 'dashboard.dashboard.allOptionTip', 'zh', 'dashboard.dashboard.allOptionTip', '启用包含所有变量的选项', ' \ndashboard/All option/', '2022-07-20 07:36:07', 425); +INSERT INTO `sys_i18n` VALUES (6294, 'dashboard.dashboard.variables', 'en', 'dashboard.dashboard.variables', 'Variables', ' \ndashboard/variable/', '2022-07-20 07:35:31', 425); +INSERT INTO `sys_i18n` VALUES (6295, 'dashboard.dashboard.variables', 'zh', 'dashboard.dashboard.variables', '变量', 'dashboard/variable/', '2022-07-20 07:35:26', 425); +INSERT INTO `sys_i18n` VALUES (6296, 'dashboard.dashboard.addVariable', 'en', 'dashboard.dashboard.addVariable', 'Add variable', ' \ndashboard/按钮提示文字', '2022-07-20 07:34:59', 425); +INSERT INTO `sys_i18n` VALUES (6297, 'dashboard.dashboard.addVariable', 'zh', 'dashboard.dashboard.addVariable', '添加变量', 'dashboard/按钮提示文字', '2022-07-20 07:34:50', 425); +INSERT INTO `sys_i18n` VALUES (6298, 'dashboard.dashboard.matchRegex', 'en', 'dashboard.dashboard.matchRegex', 'Must match the regex [a-zA-Z_][a-zA-Z0-9_]*', 'dashboard/Name/', '2022-07-20 07:31:52', 425); +INSERT INTO `sys_i18n` VALUES (6299, 'dashboard.dashboard.matchRegex', 'zh', 'dashboard.dashboard.matchRegex', '必须匹配正则表达式[a-zA-Z_][a-zA-Z0-9_]*', 'dashboard/Name/', '2022-07-20 07:31:48', 425); INSERT INTO `sys_i18n` VALUES (6300, '221028', 'en', 'MODULE_CONFIG_JOURNALUNIT_ISNULL', 'Module config journal unit is null', '响应消息->module新增/修改/批量修改接口', '2022-06-28 17:36:13', 1); INSERT INTO `sys_i18n` VALUES (6301, '221028', 'zh', 'MODULE_CONFIG_JOURNALUNIT_ISNULL', '模块配置日志单位为空', '响应消息->module新增/修改/批量修改接口', '2022-06-28 17:36:13', 1); INSERT INTO `sys_i18n` VALUES (6302, '221029', 'en', 'MODULE_CONFIG_SYSLOG_APPNAME_ISNULL', 'Module config syslog appName is null', '响应消息->module新增/修改/批量修改接口', '2022-06-28 17:36:13', 1); @@ -4153,14 +4149,14 @@ INSERT INTO `sys_i18n` VALUES (6386, 'overall.enlargement', 'en', 'overall.enlar INSERT INTO `sys_i18n` VALUES (6387, 'overall.enlargement', 'zh', 'overall.enlargement', '放大', ' \nendpoint/提示文字', '2022-07-20 07:08:03', 425); INSERT INTO `sys_i18n` VALUES (6388, 'overall.shrink', 'en', 'overall.shrink', 'Shrink', ' \nendpoint/提示文字', '2022-07-20 07:07:59', 425); INSERT INTO `sys_i18n` VALUES (6389, 'overall.shrink', 'zh', 'overall.shrink', '缩小', 'endpoint/提示文字', '2022-07-20 07:07:52', 425); -INSERT INTO `sys_i18n` VALUES (6390, 'overall.visible', 'en', 'overall.visible', 'Visible', 'panel/提示文字', '2022-07-20 07:06:49', 425); -INSERT INTO `sys_i18n` VALUES (6391, 'overall.visible', 'zh', 'overall.visible', '可见', 'panel/提示文字', '2022-07-20 07:06:45', 425); -INSERT INTO `sys_i18n` VALUES (6392, 'overall.invisible', 'en', 'overall.invisible', 'Invisible', 'panel/提示文字', '2022-07-20 07:06:41', 425); -INSERT INTO `sys_i18n` VALUES (6393, 'overall.invisible', 'zh', 'overall.invisible', '不可见', ' \npanel/提示文字', '2022-07-20 07:02:10', 425); -INSERT INTO `sys_i18n` VALUES (6394, 'overall.starred', 'en', 'overall.starred', 'Starred', ' \npanel/提示文字', '2022-07-20 07:01:58', 425); -INSERT INTO `sys_i18n` VALUES (6395, 'overall.starred', 'zh', 'overall.starred', '收藏', ' \npanel/提示文字', '2022-07-20 07:02:14', 425); -INSERT INTO `sys_i18n` VALUES (6396, 'overall.unstarred', 'en', 'overall.unstarred', 'Unstarred', ' \npanel/提示文字', '2022-07-20 07:02:07', 425); -INSERT INTO `sys_i18n` VALUES (6397, 'overall.unstarred', 'zh', 'overall.unstarred', '未收藏', ' \npanel/提示文字', '2022-07-20 07:02:18', 425); +INSERT INTO `sys_i18n` VALUES (6390, 'overall.visible', 'en', 'overall.visible', 'Visible', 'dashboard/提示文字', '2022-07-20 07:06:49', 425); +INSERT INTO `sys_i18n` VALUES (6391, 'overall.visible', 'zh', 'overall.visible', '可见', 'dashboard/提示文字', '2022-07-20 07:06:45', 425); +INSERT INTO `sys_i18n` VALUES (6392, 'overall.invisible', 'en', 'overall.invisible', 'Invisible', 'dashboard/提示文字', '2022-07-20 07:06:41', 425); +INSERT INTO `sys_i18n` VALUES (6393, 'overall.invisible', 'zh', 'overall.invisible', '不可见', ' \ndashboard/提示文字', '2022-07-20 07:02:10', 425); +INSERT INTO `sys_i18n` VALUES (6394, 'overall.starred', 'en', 'overall.starred', 'Starred', ' \ndashboard/提示文字', '2022-07-20 07:01:58', 425); +INSERT INTO `sys_i18n` VALUES (6395, 'overall.starred', 'zh', 'overall.starred', '收藏', ' \ndashboard/提示文字', '2022-07-20 07:02:14', 425); +INSERT INTO `sys_i18n` VALUES (6396, 'overall.unstarred', 'en', 'overall.unstarred', 'Unstarred', ' \ndashboard/提示文字', '2022-07-20 07:02:07', 425); +INSERT INTO `sys_i18n` VALUES (6397, 'overall.unstarred', 'zh', 'overall.unstarred', '未收藏', ' \ndashboard/提示文字', '2022-07-20 07:02:18', 425); INSERT INTO `sys_i18n` VALUES (6398, 'overall.leftShift', 'en', 'overall.leftShift', 'Left shift ', '资产/资产列表/按钮提示文字', '2022-07-20 07:02:29', 425); INSERT INTO `sys_i18n` VALUES (6399, 'overall.leftShift', 'zh', 'overall.leftShift', '向左移', '资产/资产列表/按钮提示文字', '2022-07-20 07:02:33', 425); INSERT INTO `sys_i18n` VALUES (6400, 'overall.rightShift', 'en', 'overall.rightShift', 'Right shift', '资产/资产列表/按钮提示文字', '2022-07-20 07:02:37', 425); @@ -4215,8 +4211,8 @@ INSERT INTO `sys_i18n` VALUES (6475, 'buttons.expired', 'en', 'buttons.expired', INSERT INTO `sys_i18n` VALUES (6477, 'buttons.expired', 'zh', 'buttons.expired', '失效', '', '2022-07-08 07:31:43', 1); INSERT INTO `sys_i18n` VALUES (6479, 'buttons.basic', 'en', 'buttons.basic', 'Basic', '', '2022-07-08 07:32:56', 1); INSERT INTO `sys_i18n` VALUES (6481, 'buttons.basic', 'zh', 'buttons.basic', '基础', '', '2022-07-08 07:33:49', 1); -INSERT INTO `sys_i18n` VALUES (6483, 'overall.chartTemp', 'en', 'overall.chartTemp', 'Chart templates', 'panel/;资产/资产配置/型号/;\n表头->资产model导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); -INSERT INTO `sys_i18n` VALUES (6485, 'overall.chartTemp', 'zh', 'overall.chartTemp', '图表模板', 'panel/;资产/资产配置/型号/;\n表头->资产model导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (6483, 'overall.chartTemp', 'en', 'overall.chartTemp', 'Chart templates', 'dashboard/;资产/资产配置/型号/;\n表头->资产model导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); +INSERT INTO `sys_i18n` VALUES (6485, 'overall.chartTemp', 'zh', 'overall.chartTemp', '图表模板', 'dashboard/;资产/资产配置/型号/;\n表头->资产model导入/导出/模板下载、module导入/导出/模板下载', '2022-07-21 06:18:50', 425); INSERT INTO `sys_i18n` VALUES (6487, 'overall.dashboard', 'en', 'overall.dashboard', 'Dashboard', '', '2022-07-08 09:53:56', 1); INSERT INTO `sys_i18n` VALUES (6489, 'overall.dashboard', 'zh', 'overall.dashboard', '仪表盘', '', '2022-07-08 09:54:43', 1); INSERT INTO `sys_i18n` VALUES (6491, 'overall.models', 'en', 'overall.models', 'Models', '', '2022-07-08 10:06:53', 415); @@ -4341,12 +4337,12 @@ INSERT INTO `sys_i18n` VALUES (6731, 'export.records', 'en', 'export.records', ' INSERT INTO `sys_i18n` VALUES (6733, 'export.records', 'zh', 'export.records', '记录', '', '2022-07-12 09:43:17', 415); INSERT INTO `sys_i18n` VALUES (6735, 'export.fileFormat', 'en', 'export.fileFormat', 'File format', '', '2022-07-12 09:44:42', 415); INSERT INTO `sys_i18n` VALUES (6737, 'export.fileFormat', 'zh', 'export.fileFormat', '文件格式', '', '2022-07-12 09:44:56', 415); -INSERT INTO `sys_i18n` VALUES (6739, 'dashboard.panel.prevMonth', 'en', 'dashboard.panel.prevMonth', 'Previous month', '', '2022-07-13 03:04:39', 415); -INSERT INTO `sys_i18n` VALUES (6741, 'dashboard.panel.prevMonth', 'zh', 'dashboard.panel.prevMonth', '前一月', '', '2022-07-13 03:03:52', 415); -INSERT INTO `sys_i18n` VALUES (6743, 'dashboard.panel.variableName', 'en', 'dashboard.panel.variableName', 'Variable name', '', '2022-07-13 08:15:16', 407); -INSERT INTO `sys_i18n` VALUES (6745, 'dashboard.panel.variableName', 'zh', 'dashboard.panel.variableName', '变量名', '', '2022-07-13 08:15:38', 407); -INSERT INTO `sys_i18n` VALUES (6747, 'dashboard.panel.showHidden', 'en', 'dashboard.panel.showHidden', 'Show/Hidden', '', '2022-07-13 08:42:07', 407); -INSERT INTO `sys_i18n` VALUES (6749, 'dashboard.panel.showHidden', 'zh', 'dashboard.panel.showHidden', '显示/隐藏', '', '2022-07-13 08:42:35', 407); +INSERT INTO `sys_i18n` VALUES (6739, 'dashboard.dashboard.prevMonth', 'en', 'dashboard.dashboard.prevMonth', 'Previous month', '', '2022-07-13 03:04:39', 415); +INSERT INTO `sys_i18n` VALUES (6741, 'dashboard.dashboard.prevMonth', 'zh', 'dashboard.dashboard.prevMonth', '前一月', '', '2022-07-13 03:03:52', 415); +INSERT INTO `sys_i18n` VALUES (6743, 'dashboard.dashboard.variableName', 'en', 'dashboard.dashboard.variableName', 'Variable name', '', '2022-07-13 08:15:16', 407); +INSERT INTO `sys_i18n` VALUES (6745, 'dashboard.dashboard.variableName', 'zh', 'dashboard.dashboard.variableName', '变量名', '', '2022-07-13 08:15:38', 407); +INSERT INTO `sys_i18n` VALUES (6747, 'dashboard.dashboard.showHidden', 'en', 'dashboard.dashboard.showHidden', 'Show/Hidden', '', '2022-07-13 08:42:07', 407); +INSERT INTO `sys_i18n` VALUES (6749, 'dashboard.dashboard.showHidden', 'zh', 'dashboard.dashboard.showHidden', '显示/隐藏', '', '2022-07-13 08:42:35', 407); INSERT INTO `sys_i18n` VALUES (6751, 'placeholder.chart.column', 'en', 'placeholder.chart.column', 'Column', '系统配置/模板/图表模板/; 系统配置/个性化配置/; 监控/应用实例/;', '2022-07-20 03:46:12', 425); INSERT INTO `sys_i18n` VALUES (6753, 'placeholder.chart.column', 'zh', 'placeholder.chart.column', '列', '系统配置/模板/图表模板/;\n系统配置/个性化配置/;\n\n监控/应用实例/;\n\n', '2022-07-20 03:45:54', 425); INSERT INTO `sys_i18n` VALUES (6755, 'mertic_firewall_msg', 'zh', 'mertic_firewall_msg', 'Mertic:请求被防火墙阻止', '响应消息->endpoint错误诊断接口', '2022-07-11 16:28:48', 416); @@ -4365,8 +4361,8 @@ INSERT INTO `sys_i18n` VALUES (6779, 'tip.expressionLabel', 'en', 'tip.expressio INSERT INTO `sys_i18n` VALUES (6781, 'tip.expressionLabel', 'zh', 'tip.expressionLabel', '从表达式查询结果的标签组中,获取指定label对应的值。例如:', '', '2022-07-18 02:16:35', 407); INSERT INTO `sys_i18n` VALUES (6783, 'tip.expressionValue', 'en', 'tip.expressionValue', 'Get the value of the expression query result. For example:', '', '2022-07-18 02:18:10', 407); INSERT INTO `sys_i18n` VALUES (6785, 'tip.expressionValue', 'zh', 'tip.expressionValue', '获取表达式查询结果的值。例如:', '', '2022-07-18 02:18:51', 407); -INSERT INTO `sys_i18n` VALUES (6787, 'dashboard.panel.chartForm.typeVal.bubble.label', 'en', 'dashboard.panel.chartForm.typeVal.bubble.label', 'Bubble', '', '2022-07-19 10:26:05', 407); -INSERT INTO `sys_i18n` VALUES (6789, 'dashboard.panel.chartForm.typeVal.bubble.label', 'zh', 'dashboard.panel.chartForm.typeVal.bubble.label', '气泡图', '', '2022-07-19 10:25:05', 407); +INSERT INTO `sys_i18n` VALUES (6787, 'dashboard.dashboard.chartForm.typeVal.bubble.label', 'en', 'dashboard.dashboard.chartForm.typeVal.bubble.label', 'Bubble', '', '2022-07-19 10:26:05', 407); +INSERT INTO `sys_i18n` VALUES (6789, 'dashboard.dashboard.chartForm.typeVal.bubble.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.bubble.label', '气泡图', '', '2022-07-19 10:25:05', 407); INSERT INTO `sys_i18n` VALUES (6791, 'about.releaseNotes', 'en', 'about.releaseNotes', 'Release notes', '', '2022-07-20 10:51:56', 1); INSERT INTO `sys_i18n` VALUES (6792, 'about.releaseNotes', 'zh', 'about.releaseNotes', '发行说明', '', '2022-07-20 10:51:56', 1); INSERT INTO `sys_i18n` VALUES (6793, 'overall.show', 'en', 'overall.show', 'Show', '', '2022-07-20 11:00:09', 1); @@ -4375,7 +4371,7 @@ INSERT INTO `sys_i18n` VALUES (6795, 'overall.hidden', 'en', 'overall.hidden', ' INSERT INTO `sys_i18n` VALUES (6796, 'overall.hidden', 'zh', 'overall.hidden', '隐藏', '', '2022-07-20 11:00:53', 1); INSERT INTO `sys_i18n` VALUES (6797, 'config.exprTemp.name', 'en', 'config.exprTemp.name', 'Template name', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (6798, 'config.exprTemp.name', 'zh', 'config.exprTemp.name', '模板名称', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); -INSERT INTO `sys_i18n` VALUES (6799, 'config.exprTemp.gname', 'en', 'config.exprTemp.gname', 'Group Name', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); +INSERT INTO `sys_i18n` VALUES (6799, 'config.exprTemp.gname', 'en', 'config.exprTemp.gname', 'Group name', '表头->表达式模板导入/导出/模板下载', '2022-12-14 08:17:44', 415); INSERT INTO `sys_i18n` VALUES (6800, 'config.exprTemp.gname', 'zh', 'config.exprTemp.gname', '组名', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (6801, 'config.exprTemp.remark', 'en', 'config.exprTemp.remark', 'Remark', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); INSERT INTO `sys_i18n` VALUES (6802, 'config.exprTemp.remark', 'zh', 'config.exprTemp.remark', '描述', '表头->表达式模板导入/导出/模板下载', '2022-07-21 06:18:50', 1); @@ -4385,16 +4381,16 @@ INSERT INTO `sys_i18n` VALUES (6807, 'ping.packageSize', 'en', 'ping.packageSize INSERT INTO `sys_i18n` VALUES (6809, 'ping.packageSize', 'zh', 'ping.packageSize', '包大小', '', '2022-07-26 09:55:22', 407); INSERT INTO `sys_i18n` VALUES (6811, 'ping.bytes', 'en', 'ping.bytes', 'bytes', '', '2022-07-26 09:59:36', 407); INSERT INTO `sys_i18n` VALUES (6813, 'ping.bytes', 'zh', 'ping.bytes', '字节', '', '2022-07-26 09:59:46', 407); -INSERT INTO `sys_i18n` VALUES (6815, 'dashboard.panel.label_names()', 'en', 'dashboard.panel.label_names()', 'Returns a list of metric label names.', '', '2022-07-27 05:37:19', 407); -INSERT INTO `sys_i18n` VALUES (6817, 'dashboard.panel.label_names()', 'zh', 'dashboard.panel.label_names()', 'Returns a list of metric label names.', '', '2022-07-27 05:37:38', 407); -INSERT INTO `sys_i18n` VALUES (6819, 'dashboard.panel.label_values(label)', 'en', 'dashboard.panel.label_values(label)', 'Returns a list of label values for the label in every metric.', '', '2022-07-27 05:38:29', 407); -INSERT INTO `sys_i18n` VALUES (6821, 'dashboard.panel.label_values(label)', 'zh', 'dashboard.panel.label_values(label)', 'Returns a list of label values for the label in every metric.', '', '2022-07-27 05:38:42', 407); -INSERT INTO `sys_i18n` VALUES (6823, 'dashboard.panel.label_values(metric, label)', 'en', 'dashboard.panel.label_values(metric, label)', 'Returns a list of label values for the label in the specified metric.', '', '2022-07-27 05:39:19', 407); -INSERT INTO `sys_i18n` VALUES (6825, 'dashboard.panel.label_values(metric, label)', 'zh', 'dashboard.panel.label_values(metric, label)', 'Returns a list of label values for the label in the specified metric.', '', '2022-07-27 05:39:27', 407); -INSERT INTO `sys_i18n` VALUES (6827, 'dashboard.panel.metrics(metric)', 'en', 'dashboard.panel.metrics(metric)', 'Returns a list of metrics matching the specified metric regex.', '', '2022-07-27 05:40:06', 407); -INSERT INTO `sys_i18n` VALUES (6829, 'dashboard.panel.metrics(metric)', 'zh', 'dashboard.panel.metrics(metric)', 'Returns a list of metrics matching the specified metric regex.', '', '2022-07-27 05:40:26', 407); -INSERT INTO `sys_i18n` VALUES (6831, 'dashboard.panel.query_result(query)', 'en', 'dashboard.panel.query_result(query)', 'Returns a list of metric query result for the query.', '', '2022-07-27 05:40:50', 407); -INSERT INTO `sys_i18n` VALUES (6833, 'dashboard.panel.query_result(query)', 'zh', 'dashboard.panel.query_result(query)', 'Returns a list of metric query result for the query.', '', '2022-07-27 05:41:02', 407); +INSERT INTO `sys_i18n` VALUES (6815, 'dashboard.dashboard.label_names()', 'en', 'dashboard.dashboard.label_names()', 'Returns a list of metric label names.', '', '2022-07-27 05:37:19', 407); +INSERT INTO `sys_i18n` VALUES (6817, 'dashboard.dashboard.label_names()', 'zh', 'dashboard.dashboard.label_names()', 'Returns a list of metric label names.', '', '2022-07-27 05:37:38', 407); +INSERT INTO `sys_i18n` VALUES (6819, 'dashboard.dashboard.label_values(label)', 'en', 'dashboard.dashboard.label_values(label)', 'Returns a list of label values for the label in every metric.', '', '2022-07-27 05:38:29', 407); +INSERT INTO `sys_i18n` VALUES (6821, 'dashboard.dashboard.label_values(label)', 'zh', 'dashboard.dashboard.label_values(label)', 'Returns a list of label values for the label in every metric.', '', '2022-07-27 05:38:42', 407); +INSERT INTO `sys_i18n` VALUES (6823, 'dashboard.dashboard.label_values(metric, label)', 'en', 'dashboard.dashboard.label_values(metric, label)', 'Returns a list of label values for the label in the specified metric.', '', '2022-07-27 05:39:19', 407); +INSERT INTO `sys_i18n` VALUES (6825, 'dashboard.dashboard.label_values(metric, label)', 'zh', 'dashboard.dashboard.label_values(metric, label)', 'Returns a list of label values for the label in the specified metric.', '', '2022-07-27 05:39:27', 407); +INSERT INTO `sys_i18n` VALUES (6827, 'dashboard.dashboard.metrics(metric)', 'en', 'dashboard.dashboard.metrics(metric)', 'Returns a list of metrics matching the specified metric regex.', '', '2022-07-27 05:40:06', 407); +INSERT INTO `sys_i18n` VALUES (6829, 'dashboard.dashboard.metrics(metric)', 'zh', 'dashboard.dashboard.metrics(metric)', 'Returns a list of metrics matching the specified metric regex.', '', '2022-07-27 05:40:26', 407); +INSERT INTO `sys_i18n` VALUES (6831, 'dashboard.dashboard.query_result(query)', 'en', 'dashboard.dashboard.query_result(query)', 'Returns a list of metric query result for the query.', '', '2022-07-27 05:40:50', 407); +INSERT INTO `sys_i18n` VALUES (6833, 'dashboard.dashboard.query_result(query)', 'zh', 'dashboard.dashboard.query_result(query)', 'Returns a list of metric query result for the query.', '', '2022-07-27 05:41:02', 407); INSERT INTO `sys_i18n` VALUES (6835, 'overall.ipam.available', 'en', 'overall.ipam.available', 'Available', '', '2022-07-28 08:34:27', 407); INSERT INTO `sys_i18n` VALUES (6837, 'overall.ipam.available', 'zh', 'overall.ipam.available', '可用的', '', '2022-07-28 08:34:42', 407); INSERT INTO `sys_i18n` VALUES (6839, 'overall.ipam.transient', 'en', 'overall.ipam.transient', 'Transient', '', '2022-07-28 08:35:43', 407); @@ -4420,7 +4416,7 @@ INSERT INTO `sys_i18n` VALUES (6877, 'record_rule', 'zh', 'record_rule', '记录 INSERT INTO `sys_i18n` VALUES (6879, 'overall.recordRule.edit', 'en', 'overall.recordRule.edit', 'Edit record rule', '', '2022-08-04 08:27:47', 415); INSERT INTO `sys_i18n` VALUES (6881, 'overall.recordRule.edit', 'zh', 'overall.recordRule.edit', '修改记录规则', '', '2022-08-04 08:28:09', 415); INSERT INTO `sys_i18n` VALUES (6883, 'overall.importSupport', 'en', 'overall.importSupport', 'Support xlsx / xls / csv / json files', '', '2022-08-05 08:22:47', 407); -INSERT INTO `sys_i18n` VALUES (6885, 'overall.importSupport', 'zh', 'overall.importSupport', '支持 xlsx / xls / csv / json files', '', '2022-08-05 08:23:07', 407); +INSERT INTO `sys_i18n` VALUES (6885, 'overall.importSupport', 'zh', 'overall.importSupport', '支持 xlsx / xls / csv / json 文件', '', '2022-11-28 07:43:36', 407); INSERT INTO `sys_i18n` VALUES (6887, 'overall.importResult', 'en', 'overall.importResult', 'Import result', '', '2022-08-05 08:24:48', 407); INSERT INTO `sys_i18n` VALUES (6889, 'overall.importResult', 'zh', 'overall.importResult', '导入结果', '', '2022-08-05 08:25:01', 407); INSERT INTO `sys_i18n` VALUES (6891, 'overall.selectTemplate', 'en', 'overall.selectTemplate', 'Select template format', '', '2022-08-08 01:55:08', 407); @@ -4515,12 +4511,12 @@ INSERT INTO `sys_i18n` VALUES (7087, '815', 'en', 'IMPORT_NOT_WITHIN_REASON', '{ INSERT INTO `sys_i18n` VALUES (7089, '815', 'zh', 'IMPORT_NOT_WITHIN_REASON', '{0} 不在合理范围内', '', '2022-08-15 03:22:35', 1); INSERT INTO `sys_i18n` VALUES (7091, '816', 'en', 'IMPORT_NOT_MATCH', '{0} does not match {1} configuration', '', '2022-08-15 03:22:48', 1); INSERT INTO `sys_i18n` VALUES (7093, '816', 'zh', 'IMPORT_NOT_MATCH', '{0} 和 {1} 配置不相符', '', '2022-08-15 03:24:05', 1); -INSERT INTO `sys_i18n` VALUES (7095, 'dashboard.panel.chartForm.typeVal.sankey.label', 'en', 'dashboard.panel.chartForm.typeVal.sankey.label', 'Sankey', '', '2022-08-16 02:45:01', 407); -INSERT INTO `sys_i18n` VALUES (7097, 'dashboard.panel.chartForm.typeVal.sankey.label', 'zh', 'dashboard.panel.chartForm.typeVal.sankey.label', '桑基图', '', '2022-08-16 02:43:58', 407); -INSERT INTO `sys_i18n` VALUES (7099, 'dashboard.panel.chartForm.sourceLabel', 'en', 'dashboard.panel.chartForm.sourceLabel', 'Source label', '', '2022-08-16 03:15:56', 407); -INSERT INTO `sys_i18n` VALUES (7101, 'dashboard.panel.chartForm.sourceLabel', 'zh', 'dashboard.panel.chartForm.sourceLabel', '来源标签', '', '2022-08-16 03:16:38', 407); -INSERT INTO `sys_i18n` VALUES (7103, 'dashboard.panel.chartForm.targetLabel', 'en', 'dashboard.panel.chartForm.targetLabel', 'Target label', '', '2022-08-16 03:20:06', 407); -INSERT INTO `sys_i18n` VALUES (7105, 'dashboard.panel.chartForm.targetLabel', 'zh', 'dashboard.panel.chartForm.targetLabel', '目标标签', '', '2022-08-16 03:20:17', 407); +INSERT INTO `sys_i18n` VALUES (7095, 'dashboard.dashboard.chartForm.typeVal.sankey.label', 'en', 'dashboard.dashboard.chartForm.typeVal.sankey.label', 'Sankey', '', '2022-08-16 02:45:01', 407); +INSERT INTO `sys_i18n` VALUES (7097, 'dashboard.dashboard.chartForm.typeVal.sankey.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.sankey.label', '桑基图', '', '2022-08-16 02:43:58', 407); +INSERT INTO `sys_i18n` VALUES (7099, 'dashboard.dashboard.chartForm.sourceLabel', 'en', 'dashboard.dashboard.chartForm.sourceLabel', 'Source label', '', '2022-08-16 03:15:56', 407); +INSERT INTO `sys_i18n` VALUES (7101, 'dashboard.dashboard.chartForm.sourceLabel', 'zh', 'dashboard.dashboard.chartForm.sourceLabel', '来源标签', '', '2022-08-16 03:16:38', 407); +INSERT INTO `sys_i18n` VALUES (7103, 'dashboard.dashboard.chartForm.targetLabel', 'en', 'dashboard.dashboard.chartForm.targetLabel', 'Target label', '', '2022-08-16 03:20:06', 407); +INSERT INTO `sys_i18n` VALUES (7105, 'dashboard.dashboard.chartForm.targetLabel', 'zh', 'dashboard.dashboard.chartForm.targetLabel', '目标标签', '', '2022-08-16 03:20:17', 407); INSERT INTO `sys_i18n` VALUES (7107, 'error.labelEqual', 'en', 'error.labelEqual', 'Source label cannot be equal to Target label', '', '2022-08-16 06:18:32', 407); INSERT INTO `sys_i18n` VALUES (7109, 'error.labelEqual', 'zh', 'error.labelEqual', '来源标签不能等于目标标签', '', '2022-08-16 06:18:27', 407); INSERT INTO `sys_i18n` VALUES (7111, '217018', 'en', 'PROJECT_RELOBJ_CAN_NOT_REMOVE', 'Project have associated data and cannot be deleted', '', '2022-08-19 07:11:06', 1); @@ -4607,11 +4603,11 @@ INSERT INTO `sys_i18n` VALUES (7257, 'issueTab.whole', 'en', 'issueTab.whole', ' INSERT INTO `sys_i18n` VALUES (7259, 'issueTab.whole', 'zh', 'issueTab.whole', '全部', '', '2022-09-05 01:15:56', 425); INSERT INTO `sys_i18n` VALUES (7261, 'issueTab.comment', 'en', 'issueTab.comment', 'comment', '', '2022-09-05 01:16:20', 425); INSERT INTO `sys_i18n` VALUES (7263, 'issueTab.comment', 'zh', 'issueTab.comment', '评论', '', '2022-09-05 01:16:39', 425); -INSERT INTO `sys_i18n` VALUES (7265, 'issueTab.changeRecord', 'en', 'issueTab.changeRecord', 'change record', '', '2022-09-05 01:17:22', 425); +INSERT INTO `sys_i18n` VALUES (7265, 'issueTab.changeRecord', 'en', 'issueTab.changeRecord', 'Change record', '', '2022-12-14 08:05:23', 415); INSERT INTO `sys_i18n` VALUES (7267, 'issueTab.changeRecord', 'zh', 'issueTab.changeRecord', '变更记录', '', '2022-09-05 01:17:47', 425); -INSERT INTO `sys_i18n` VALUES (7269, 'issueTab.addComment', 'en', 'issueTab.addComment', 'add comment', '', '2022-09-05 01:18:47', 425); +INSERT INTO `sys_i18n` VALUES (7269, 'issueTab.addComment', 'en', 'issueTab.addComment', 'Add comment', '', '2022-12-14 08:05:14', 415); INSERT INTO `sys_i18n` VALUES (7271, 'issueTab.addComment', 'zh', 'issueTab.addComment', '添加评论', '', '2022-09-05 01:19:03', 425); -INSERT INTO `sys_i18n` VALUES (7273, 'issueTab.Add', 'en', 'issueTab.Add', 'add', '', '2022-09-05 01:19:16', 425); +INSERT INTO `sys_i18n` VALUES (7273, 'issueTab.Add', 'en', 'issueTab.Add', 'Add', '', '2022-12-14 08:05:05', 415); INSERT INTO `sys_i18n` VALUES (7275, 'issueTab.Add', 'zh', 'issueTab.Add', '添加', '', '2022-09-05 01:19:26', 425); INSERT INTO `sys_i18n` VALUES (7285, 'overall.process', 'en', 'overall.process', 'Process', '', '2022-09-06 03:43:10', 415); INSERT INTO `sys_i18n` VALUES (7287, 'overall.process', 'zh', 'overall.process', '进程', '', '2022-09-06 03:43:51', 415); @@ -4619,8 +4615,8 @@ INSERT INTO `sys_i18n` VALUES (7289, 'asset.process.threadCount', 'en', 'asset.p INSERT INTO `sys_i18n` VALUES (7291, 'asset.process.threadCount', 'zh', 'asset.process.threadCount', '线程数', '', '2022-09-08 02:00:21', 415); INSERT INTO `sys_i18n` VALUES (7293, 'asset.process.PID', 'en', 'asset.process.PID', 'PID', '', '2022-09-06 06:03:06', 415); INSERT INTO `sys_i18n` VALUES (7295, 'asset.process.PID', 'zh', 'asset.process.PID', '进程号', '', '2022-09-06 06:03:23', 415); -INSERT INTO `sys_i18n` VALUES (7297, 'dashboard.panel.chartForm.typeVal.rank.label', 'en', 'dashboard.panel.chartForm.typeVal.rank.label', 'Rank', '', '2022-09-06 06:26:08', 407); -INSERT INTO `sys_i18n` VALUES (7299, 'dashboard.panel.chartForm.typeVal.rank.label', 'zh', 'dashboard.panel.chartForm.typeVal.rank.label', '排行榜', '', '2022-09-06 06:26:20', 407); +INSERT INTO `sys_i18n` VALUES (7297, 'dashboard.dashboard.chartForm.typeVal.rank.label', 'en', 'dashboard.dashboard.chartForm.typeVal.rank.label', 'Rank', '', '2022-09-06 06:26:08', 407); +INSERT INTO `sys_i18n` VALUES (7299, 'dashboard.dashboard.chartForm.typeVal.rank.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.rank.label', '排行榜', '', '2022-09-06 06:26:20', 407); INSERT INTO `sys_i18n` VALUES (7300, '401000', 'en', 'ASSET_COMMENT_ID_ISNULL', 'Asset comment id can not be empty', '响应消息->资产评论修改/删除', '2022-09-06 15:34:12', 416); INSERT INTO `sys_i18n` VALUES (7301, '401000', 'zh', 'ASSET_COMMENT_ID_ISNULL', '资产评论ID不能为空', '响应消息->资产评论修改/删除', '2022-09-06 15:34:12', 416); INSERT INTO `sys_i18n` VALUES (7302, '401001', 'en', 'ASSET_COMMENT_CONTENT_ISNULL', 'Asset comment content can not be empty', '响应消息->资产评论修改/新增', '2022-09-06 15:34:12', 416); @@ -4631,21 +4627,21 @@ INSERT INTO `sys_i18n` VALUES (7307, 'asset.process.cpu', 'en', 'asset.process.c INSERT INTO `sys_i18n` VALUES (7309, 'asset.process.cpu', 'zh', 'asset.process.cpu', 'CPU 使用率', '', '2022-09-08 03:22:36', 415); INSERT INTO `sys_i18n` VALUES (7311, 'asset.process.mem', 'en', 'asset.process.mem', 'Memory usage', '', '2022-09-13 07:05:53', 415); INSERT INTO `sys_i18n` VALUES (7313, 'asset.process.mem', 'zh', 'asset.process.mem', '内存使用率', '', '2022-09-13 07:06:18', 415); -INSERT INTO `sys_i18n` VALUES (7319, 'silence.expired', 'en', 'silence.expired', 'expired', 'silence -》 state', '2022-09-08 08:48:23', 381); -INSERT INTO `sys_i18n` VALUES (7321, 'silence.expired', 'zh', 'silence.expired', 'expired', 'silence-》 state', '2022-09-08 08:48:39', 381); -INSERT INTO `sys_i18n` VALUES (7323, 'silence.pending', 'en', 'silence.pending', 'pending', 'silence -》 state', '2022-09-08 08:49:09', 381); -INSERT INTO `sys_i18n` VALUES (7325, 'silence.pending', 'zh', 'silence.pending', 'pending', 'silence -》 state', '2022-09-08 08:49:32', 381); -INSERT INTO `sys_i18n` VALUES (7327, 'silence.active', 'en', 'silence.active', 'active', 'silence =》 state', '2022-09-08 08:50:26', 381); -INSERT INTO `sys_i18n` VALUES (7329, 'silence.active', 'zh', 'silence.active', 'active', 'silence =》 state', '2022-09-08 08:50:43', 381); +INSERT INTO `sys_i18n` VALUES (7319, 'silence.expired', 'en', 'silence.expired', 'Expired', 'silence -》 state', '2022-12-14 07:59:21', 415); +INSERT INTO `sys_i18n` VALUES (7321, 'silence.expired', 'zh', 'silence.expired', 'Expired', 'silence-》 state', '2022-12-14 07:59:34', 415); +INSERT INTO `sys_i18n` VALUES (7323, 'silence.pending', 'en', 'silence.pending', 'Pending', 'silence -》 state', '2022-12-14 07:58:29', 415); +INSERT INTO `sys_i18n` VALUES (7325, 'silence.pending', 'zh', 'silence.pending', 'Pending', 'silence -》 state', '2022-12-14 07:58:37', 415); +INSERT INTO `sys_i18n` VALUES (7327, 'silence.active', 'en', 'silence.active', 'Active', 'silence =》 state', '2022-12-14 07:58:44', 415); +INSERT INTO `sys_i18n` VALUES (7329, 'silence.active', 'zh', 'silence.active', 'Active', 'silence =》 state', '2022-12-14 07:58:51', 415); INSERT INTO `sys_i18n` VALUES (7331, 'overall.network', 'en', 'overall.network', 'Network', '', '2022-09-13 07:38:23', 415); INSERT INTO `sys_i18n` VALUES (7333, 'overall.network', 'zh', 'overall.network', '网络', '', '2022-09-13 07:38:48', 415); INSERT INTO `sys_i18n` VALUES (7339, 'asset.network.localAddress', 'en', 'asset.network.localAddress', 'Local address', '', '2022-09-13 08:14:58', 415); INSERT INTO `sys_i18n` VALUES (7341, 'asset.network.localAddress', 'zh', 'asset.network.localAddress', '本地地址', '', '2022-09-13 08:15:22', 415); INSERT INTO `sys_i18n` VALUES (7343, 'asset.network.foreignAddress', 'zh', 'asset.network.foreignAddress', '外部地址', '', '2022-09-13 08:29:19', 415); INSERT INTO `sys_i18n` VALUES (7345, 'asset.network.foreignAddress', 'en', 'asset.network.foreignAddress', 'Foreign address', '', '2022-09-13 08:29:43', 415); -INSERT INTO `sys_i18n` VALUES (7347, 'asset.network.transmitQueue', 'en', 'asset.network.transmitQueue', 'TransmitQueue', '', '2022-09-13 08:31:26', 415); +INSERT INTO `sys_i18n` VALUES (7347, 'asset.network.transmitQueue', 'en', 'asset.network.transmitQueue', 'Transmit queue', '', '2022-12-14 08:04:14', 415); INSERT INTO `sys_i18n` VALUES (7349, 'asset.network.transmitQueue', 'zh', 'asset.network.transmitQueue', '发送队列', '', '2022-09-13 08:31:47', 415); -INSERT INTO `sys_i18n` VALUES (7351, 'asset.network.receiveQueue', 'en', 'asset.network.receiveQueue', 'ReceiveQueue', '', '2022-09-13 08:32:23', 415); +INSERT INTO `sys_i18n` VALUES (7351, 'asset.network.receiveQueue', 'en', 'asset.network.receiveQueue', 'Receive queue', '', '2022-12-14 08:04:25', 415); INSERT INTO `sys_i18n` VALUES (7353, 'asset.network.receiveQueue', 'zh', 'asset.network.receiveQueue', '接收队列', '', '2022-09-13 08:32:40', 415); INSERT INTO `sys_i18n` VALUES (7357, '641000', 'en', 'VSYS_TASK_ISNULL', 'Vsys task can not be empty', '', '2022-09-14 06:09:14', 1); INSERT INTO `sys_i18n` VALUES (7359, '641001', 'en', 'VSYS_TASK_ID_ISNULL', 'Vsys task id can not be empty', '', '2022-09-14 06:09:14', 1); @@ -4715,9 +4711,9 @@ INSERT INTO `sys_i18n` VALUES (7473, 'overall.result.successful', 'en', 'overall INSERT INTO `sys_i18n` VALUES (7474, 'overall.result.successful', 'zh', 'overall.result.successful', '导入成功数量', '', '2022-10-21 06:24:23', 407); INSERT INTO `sys_i18n` VALUES (7475, 'overall.result.fail', 'en', 'overall.result.fail', 'Import failed count', '', '2022-10-21 02:58:57', 407); INSERT INTO `sys_i18n` VALUES (7476, 'overall.result.fail', 'zh', 'overall.result.fail', '导入失败数量', '', '2022-10-21 06:24:17', 407); -INSERT INTO `sys_i18n` VALUES (7477, 'overall.result.newQuantity', 'en', 'overall.result.newQuantity', 'new quantity', '', '2022-10-21 03:27:21', 407); +INSERT INTO `sys_i18n` VALUES (7477, 'overall.result.newQuantity', 'en', 'overall.result.newQuantity', 'New quantity', '', '2022-12-14 07:54:00', 415); INSERT INTO `sys_i18n` VALUES (7478, 'overall.result.newQuantity', 'zh', 'overall.result.newQuantity', '新增数量', '', '2022-10-21 03:27:29', 407); -INSERT INTO `sys_i18n` VALUES (7479, 'overall.result.updates', 'en', 'overall.result.updates', 'number of updates', '', '2022-10-21 03:02:01', 407); +INSERT INTO `sys_i18n` VALUES (7479, 'overall.result.updates', 'en', 'overall.result.updates', 'Number of updates', '', '2022-12-14 07:54:11', 415); INSERT INTO `sys_i18n` VALUES (7480, 'overall.result.updates', 'zh', 'overall.result.updates', '更新数量', '', '2022-10-21 03:02:10', 407); INSERT INTO `sys_i18n` VALUES (7481, 'overall.result.downloadFail', 'en', 'overall.result.downloadFail', 'Download failed records', '', '2022-10-21 06:23:50', 407); INSERT INTO `sys_i18n` VALUES (7482, 'overall.result.downloadFail', 'zh', 'overall.result.downloadFail', '下载失败记录', '', '2022-10-21 06:24:09', 407); @@ -4751,5 +4747,433 @@ INSERT INTO `sys_i18n` VALUES (7512, 'dashboard.snapshotTip2', 'en', 'dashboard. INSERT INTO `sys_i18n` VALUES (7513, 'dashboard.snapshotTip2', 'zh', 'dashboard.snapshotTip2', '快照将以文件的形式下载到您的计算机上 ,您可以用浏览器查看它。', '', '2022-11-08 01:12:06', 407); INSERT INTO `sys_i18n` VALUES (7514, 'dashboard.elapsedTime', 'en', 'dashboard.elapsedTime', 'Elapsed time', '', '2022-11-04 09:20:31', 407); INSERT INTO `sys_i18n` VALUES (7515, 'dashboard.elapsedTime', 'zh', 'dashboard.elapsedTime', '运行时间', '', '2022-11-04 09:20:45', 407); +INSERT INTO `sys_i18n` VALUES (7516, 'config.system.monitor.interface_name', 'en', 'config.system.monitor.interface_name', 'Interface names', '', '2022-12-14 02:04:43', 415); +INSERT INTO `sys_i18n` VALUES (7517, 'config.system.monitor.interface_name', 'zh', 'config.system.monitor.interface_name', '接口名称', '', '2022-11-11 03:49:46', 415); +INSERT INTO `sys_i18n` VALUES (7518, 'overall.add.interface_name', 'en', 'overall.add.interface_name', 'Add interface name', '', '2022-11-11 14:13:57', 415); +INSERT INTO `sys_i18n` VALUES (7519, 'overall.add.interface_name', 'zh', 'overall.add.interface_name', '添加接口名称', '', '2022-11-11 14:14:59', 415); +INSERT INTO `sys_i18n` VALUES (7520, 'dashboard.repeat', 'en', 'dashboard.repeat', 'Repeat', '', '2022-11-14 07:56:45', 407); +INSERT INTO `sys_i18n` VALUES (7521, 'dashboard.repeat', 'zh', 'dashboard.repeat', '重复', '', '2022-11-14 07:57:00', 407); +INSERT INTO `sys_i18n` VALUES (7522, '611007', 'en', 'TERMINAL_CONNECTION_HOST_ISNULL', 'Terminal connection host can not be null', '', '2022-11-14 08:25:20', 1); +INSERT INTO `sys_i18n` VALUES (7523, '611007', 'zh', 'TERMINAL_CONNECTION_HOST_ISNULL', '终端连接主机不能为空', '', '2022-11-14 08:25:44', 1); +INSERT INTO `sys_i18n` VALUES (7524, '611008', 'en', 'TERMINAL_CONNECTION_PORT_ISNULL', 'Terminal connection port can not be null', '', '2022-11-14 08:25:58', 1); +INSERT INTO `sys_i18n` VALUES (7525, '611008', 'zh', 'TERMINAL_CONNECTION_PORT_ISNULL', '终端连接端口不能为空', '', '2022-11-14 08:26:14', 1); +INSERT INTO `sys_i18n` VALUES (7526, '614009', 'en', 'TERMINAL_CONNECTION_AUTHPROTOCOL_INVALIDED', 'Terminal connection authProtocol is not in the range of enumeration', '', '2022-11-14 08:26:38', 1); +INSERT INTO `sys_i18n` VALUES (7527, '614009', 'zh', 'TERMINAL_CONNECTION_AUTHPROTOCOL_INVALIDED', '终端连接协议不在枚举范围内', '', '2022-11-14 08:26:56', 1); +INSERT INTO `sys_i18n` VALUES (7528, '614010', 'en', 'TERMINAL_CONNECTION_AUTHTYPE_INVALIDED', 'Terminal connection authType is not in the range of enumeration', '', '2022-11-14 08:27:10', 1); +INSERT INTO `sys_i18n` VALUES (7529, '614010', 'zh', 'TERMINAL_CONNECTION_AUTHTYPE_INVALIDED', '终端连接认证类型不在枚举范围内', '', '2022-11-14 08:27:32', 1); +INSERT INTO `sys_i18n` VALUES (7530, '611011', 'en', 'TERMINAL_CONNECTION_AUTHUSERNAME_ISNULL', 'Terminal connection authUsername can not be null', '', '2022-11-14 08:27:48', 1); +INSERT INTO `sys_i18n` VALUES (7531, '611011', 'zh', 'TERMINAL_CONNECTION_AUTHUSERNAME_ISNULL', '终端连接用户名不能为空', '', '2022-11-14 08:28:24', 1); +INSERT INTO `sys_i18n` VALUES (7532, '611012', 'en', 'TERMINAL_CONNECTION_AUTHPIN_ISNULL', 'Terminal connection authPin can not be null', '', '2022-11-14 08:28:40', 1); +INSERT INTO `sys_i18n` VALUES (7533, '611012', 'zh', 'TERMINAL_CONNECTION_AUTHPIN_ISNULL', '终端连接密码不能为空', '', '2022-11-14 08:28:56', 1); +INSERT INTO `sys_i18n` VALUES (7534, '611013', 'en', 'TERMINAL_CONNECTION_AUTHPRIKEY_ISNULL', 'Terminal connection authPriKey can not be null', '', '2022-11-14 08:29:10', 1); +INSERT INTO `sys_i18n` VALUES (7535, '611013', 'zh', 'TERMINAL_CONNECTION_AUTHPRIKEY_ISNULL', '终端连接私钥不能为空', '', '2022-11-14 08:29:29', 1); +INSERT INTO `sys_i18n` VALUES (7536, '618014', 'en', 'TERMINAL_ASSET_NOT_SUPPORT', 'The asset does not support remote terminal', '', '2022-11-14 08:29:44', 1); +INSERT INTO `sys_i18n` VALUES (7537, '618014', 'zh', 'TERMINAL_ASSET_NOT_SUPPORT', '资产不支持远程终端', '', '2022-11-14 08:29:56', 1); +INSERT INTO `sys_i18n` VALUES (7538, '616015', 'en', 'TERMINAL_SESSION_NOT_FOUND', 'Terminal session not found, expired or does not exist, please login again.', '', '2022-11-14 08:30:09', 1); +INSERT INTO `sys_i18n` VALUES (7539, '616015', 'zh', 'TERMINAL_SESSION_NOT_FOUND', '终端会话未找到,过期或不存在,请再次登录', '', '2022-11-14 08:30:46', 1); +INSERT INTO `sys_i18n` VALUES (7540, '617016', 'en', 'TERMINAL_CANNOT_DELETE_DIR', 'Do not delete directories', '', '2022-11-14 08:31:02', 1); +INSERT INTO `sys_i18n` VALUES (7541, '617016', 'zh', 'TERMINAL_CANNOT_DELETE_DIR', '不能删除目录', '', '2022-11-14 08:31:19', 1); +INSERT INTO `sys_i18n` VALUES (7542, '617017', 'en', 'TERMINAL_UPLOAD_DIRECTORY_ERROR', 'The upload path can only be a directory', '', '2022-11-14 08:31:33', 1); +INSERT INTO `sys_i18n` VALUES (7543, '617017', 'zh', 'TERMINAL_UPLOAD_DIRECTORY_ERROR', '上传路径只能是目录', '', '2022-11-14 08:31:45', 1); +INSERT INTO `sys_i18n` VALUES (7544, '616018', 'en', 'TERMINAL_DOWNLOAD_NO_SUCH_FILE', 'No such file', '', '2022-11-14 08:31:56', 1); +INSERT INTO `sys_i18n` VALUES (7545, '616018', 'zh', 'TERMINAL_DOWNLOAD_NO_SUCH_FILE', '没有这样的文件', '', '2022-11-14 08:32:07', 1); +INSERT INTO `sys_i18n` VALUES (7546, '617019', 'en', 'TERMINAL_DOWNLOAD_NOT_SUPPORTED_DIRECTORY', 'Not supported to get directory', '', '2022-11-14 08:32:19', 1); +INSERT INTO `sys_i18n` VALUES (7547, '617019', 'zh', 'TERMINAL_DOWNLOAD_NOT_SUPPORTED_DIRECTORY', '不支持下载目录', '', '2022-11-14 08:32:36', 1); +INSERT INTO `sys_i18n` VALUES (7548, '616020', 'en', 'TERMINAL_UPLOAD_PROGRESS_NOT_FOUND', 'Terminal upload progress information not found, expired or does not exist.', '', '2022-11-14 08:32:48', 1); +INSERT INTO `sys_i18n` VALUES (7549, '616020', 'zh', 'TERMINAL_UPLOAD_PROGRESS_NOT_FOUND', '终端上传进度信息未找到,过期或不存在', '', '2022-11-14 08:33:02', 1); +INSERT INTO `sys_i18n` VALUES (7550, '121098', 'en', 'DASHBOARD_VARTYPE_ISNULL', 'Dashboard varType can not be empty when type be template', '响应消息->dashboard新增/修改接口', '2022-11-14 14:14:59', 416); +INSERT INTO `sys_i18n` VALUES (7551, '121098', 'zh', 'DASHBOARD_VARTYPE_ISNULL', '面板变量类型不能为空', '响应消息->dashboard新增/修改接口', '2022-11-14 14:14:59', 416); +INSERT INTO `sys_i18n` VALUES (7552, '124099', 'en', 'DASHBOARD_VARTYPE_INVALIDE', 'Dashboard varType must be 0, 1 or 2', '响应消息->dashboard新增/修改接口', '2022-11-14 14:14:59', 416); +INSERT INTO `sys_i18n` VALUES (7553, '124099', 'zh', 'DASHBOARD_VARTYPE_INVALIDE', '面板变量类型不在允许范围内', '响应消息->dashboard新增/修改接口', '2022-11-14 14:14:59', 416); +INSERT INTO `sys_i18n` VALUES (7554, 'overall.dashboardTemplate', 'en', 'overall.dashboardTemplate', 'Dashboard templates', '', '2022-12-13 09:48:12', 415); +INSERT INTO `sys_i18n` VALUES (7555, 'overall.dashboardTemplate', 'zh', 'overall.dashboardTemplate', '仪表盘模板', '', '2022-11-18 09:07:24', 414); +INSERT INTO `sys_i18n` VALUES (7560, 'dashboard.dashboard.createDashboardTempTitle', 'en', 'dashboard.dashboard.createDashboardTempTitle', 'New dashboard template', '', '2022-12-14 07:47:55', 415); +INSERT INTO `sys_i18n` VALUES (7561, 'dashboard.dashboard.createDashboardTempTitle', 'zh', 'dashboard.dashboard.createDashboardTempTitle', '新增仪表盘模板', '', '2022-11-21 07:11:01', 407); +INSERT INTO `sys_i18n` VALUES (7562, 'dashboard.dashboard.editDashboardTempTitle', 'en', 'dashboard.dashboard.editDashboardTempTitle', 'Edit dashboard template', '', '2022-12-14 07:48:05', 415); +INSERT INTO `sys_i18n` VALUES (7563, 'dashboard.dashboard.editDashboardTempTitle', 'zh', 'dashboard.dashboard.editDashboardTempTitle', '修改仪表盘模板', '', '2022-11-21 07:11:35', 407); +INSERT INTO `sys_i18n` VALUES (7564, 'overall.uploadFiles', 'en', 'overall.uploadFiles', 'Upload files', '', '2022-11-21 07:47:36', 415); +INSERT INTO `sys_i18n` VALUES (7565, 'overall.uploadFiles', 'zh', 'overall.uploadFiles', '上传文件', '', '2022-11-21 07:49:20', 415); +INSERT INTO `sys_i18n` VALUES (7566, 'overall.downloadFile', 'en', 'overall.downloadFile', 'Download file', '', '2022-11-21 07:50:17', 415); +INSERT INTO `sys_i18n` VALUES (7567, 'overall.downloadFile', 'zh', 'overall.downloadFile', '下载文件', '', '2022-11-21 07:50:39', 415); +INSERT INTO `sys_i18n` VALUES (7568, 'overall.newFolder', 'en', 'overall.newFolder', 'New folder', '', '2022-11-21 07:51:59', 415); +INSERT INTO `sys_i18n` VALUES (7569, 'overall.newFolder', 'zh', 'overall.newFolder', '新建文件夹', '', '2022-11-21 07:52:21', 415); +INSERT INTO `sys_i18n` VALUES (7570, 'overall.deleteFiles', 'en', 'overall.deleteFiles', 'Delete files', '', '2022-11-21 07:53:36', 415); +INSERT INTO `sys_i18n` VALUES (7571, 'overall.deleteFiles', 'zh', 'overall.deleteFiles', '删除文件', '', '2022-11-21 07:54:01', 415); +INSERT INTO `sys_i18n` VALUES (7572, 'terminal.filetransfer', 'en', 'terminal.filetransfer', 'File transfer', 'terminal 文件传输', '2022-12-14 07:48:21', 415); +INSERT INTO `sys_i18n` VALUES (7573, 'terminal.filetransfer', 'zh', 'terminal.filetransfer', '文件传输', 'terminal 文件传输', '2022-11-22 01:31:13', 381); +INSERT INTO `sys_i18n` VALUES (7574, 'terminal.sftp', 'en', 'terminal.sftp', 'SFTP', 'terminal sftp', '2022-11-22 01:34:43', 381); +INSERT INTO `sys_i18n` VALUES (7575, 'terminal.sftp', 'zh', 'terminal.sftp', 'SFTP', 'terminal sftp', '2022-11-22 01:34:51', 381); +INSERT INTO `sys_i18n` VALUES (7576, 'terminal.back', 'zh', 'terminal.back', '上一级', 'terminal 返回上一级', '2022-11-22 01:35:55', 381); +INSERT INTO `sys_i18n` VALUES (7577, 'terminal.back', 'en', 'terminal.back', 'Go up', 'terminal 返回上一级', '2022-11-22 01:37:57', 381); +INSERT INTO `sys_i18n` VALUES (7578, 'overall.create', 'en', 'overall.create', 'Create', '', '2022-11-22 01:41:02', 381); +INSERT INTO `sys_i18n` VALUES (7579, 'overall.create', 'zh', 'overall.create', '创建', '', '2022-11-22 01:41:16', 381); +INSERT INTO `sys_i18n` VALUES (7580, 'overall.folderName', 'en', 'overall.folderName', 'Folder name', '', '2022-12-14 07:47:35', 415); +INSERT INTO `sys_i18n` VALUES (7581, 'overall.folderName', 'zh', 'overall.folderName', '文件夹名称', 'termail 创建文件夹', '2022-11-22 01:53:08', 381); +INSERT INTO `sys_i18n` VALUES (7582, '121100', 'en', 'DASHBOARD_LINK_ISNULL', 'Dashboard link can not be empty when type be asset, project, module or endpoint', '响应消息->Dashboard新增/修改', '2022-11-22 01:53:08', 416); +INSERT INTO `sys_i18n` VALUES (7583, '121100', 'zh', 'DASHBOARD_LINK_ISNULL', '面板关联项不能为空', '响应消息->Dashboard新增/修改', '2022-11-22 01:53:08', 416); +INSERT INTO `sys_i18n` VALUES (7584, 'overall.dashboardTemp', 'en', 'overall.dashboardTemp', 'DashboardTemp preview', '', '2022-11-22 02:03:49', 407); +INSERT INTO `sys_i18n` VALUES (7585, 'overall.dashboardTemp', 'zh', 'overall.dashboardTemp', '仪表盘预览', '', '2022-11-22 02:04:13', 407); +INSERT INTO `sys_i18n` VALUES (7586, 'model.dashboardtemplate', 'en', 'model.dashboardtemplate', 'Dashboard template', '', '2022-11-22 06:02:39', 415); +INSERT INTO `sys_i18n` VALUES (7587, 'model.dashboardtemplate', 'zh', 'model.dashboardtemplate', '仪表盘模板', '', '2022-11-22 06:03:31', 415); +INSERT INTO `sys_i18n` VALUES (7588, 'tip.confirmDuplicateDashboard', 'en', 'tip.confirmDuplicateDashboard', 'Are you sure to duplicate this dashboard?', '', '2022-11-23 08:51:42', 407); +INSERT INTO `sys_i18n` VALUES (7589, 'tip.confirmDuplicateDashboard', 'zh', 'tip.confirmDuplicateDashboard', '确认复制吗?', '', '2022-11-23 08:52:06', 407); +INSERT INTO `sys_i18n` VALUES (7590, 'dashboard.dashboard.chartForm.charts', 'en', 'dashboard.dashboard.chartForm.charts', 'Charts', 'dashboard 导入/导出/模板下载', '2022-11-25 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7591, 'dashboard.dashboard.chartForm.charts', 'zh', 'dashboard.dashboard.chartForm.charts', '图表', 'dashboard 导入/导出/模板下载;', '2022-11-25 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7592, 'overall.supportJson', 'en', 'overall.supportJson', 'Support json files', '', '2022-11-28 07:42:32', 407); +INSERT INTO `sys_i18n` VALUES (7593, 'overall.supportJson', 'zh', 'overall.supportJson', '支持 json 文件', '', '2022-11-28 07:43:45', 407); +INSERT INTO `sys_i18n` VALUES (7594, 'dashboard.dashboard.chartForm.weight', 'en', 'dashboard.dashboard.chartForm.weight', 'Order', 'dashboard 导入/导出/模板下载', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7595, 'dashboard.dashboard.chartForm.weight', 'zh', 'dashboard.dashboard.chartForm.weight', '图表顺序', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7596, 'dashboard.dashboard.chartForm.children', 'en', 'dashboard.dashboard.chartForm.children', 'Chart children', 'dashboard 导入/导出/模板下载', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7597, 'dashboard.dashboard.chartForm.children', 'zh', 'dashboard.dashboard.chartForm.children', '组内图表', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7598, 'dashboard.dashboard.chartForm.name', 'en', 'dashboard.dashboard.chartForm.name', 'Chart name', 'dashboard 导入/导出/模板下载', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7599, 'dashboard.dashboard.chartForm.name', 'zh', 'dashboard.dashboard.chartForm.name', '图表名称', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7600, '123101', 'en', 'DASHBOARD_IMPORT_TYPE_INCORRECT', 'Dashboard import type must be dashboard or template', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7601, '123101', 'zh', 'DASHBOARD_IMPORT_TYPE_INCORRECT', '面板导入类型不在允许范围内', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7602, 'dashboard.dashboard.children', 'en', 'dashboard.dashboard.children', 'Dashboard children', 'dashboard 导入/导出/模板下载', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7603, 'dashboard.dashboard.children', 'zh', 'dashboard.dashboard.children', '子面板', 'dashboard 导入/导出/模板下载;', '2022-11-29 06:18:50', 416); +INSERT INTO `sys_i18n` VALUES (7604, 'dashboard.dashboard.addByTemplate', 'en', 'dashboard.dashboard.addByTemplate', 'From template', '', '2022-12-13 05:58:52', 415); +INSERT INTO `sys_i18n` VALUES (7605, 'dashboard.dashboard.addByTemplate', 'zh', 'dashboard.dashboard.addByTemplate', '通过模板添加', '', '2022-12-02 08:34:39', 407); +INSERT INTO `sys_i18n` VALUES (7606, '121102', 'en', 'DASHBOARD_TEMPLATE_SYNC_PARAM_ISNULL', 'Dashboard template synchronization parameter is null', '', '2022-12-07 08:26:43', 1); +INSERT INTO `sys_i18n` VALUES (7607, '121102', 'zh', 'DASHBOARD_TEMPLATE_SYNC_PARAM_ISNULL', '仪表盘模板同步参数为空', '', '2022-12-07 08:27:39', 1); +INSERT INTO `sys_i18n` VALUES (7608, '127103', 'en', 'DASHBOARD_TEMPLATE_SYNC_FAILED_GET_LOCK', 'Dashboard template synchronization is in progress please try again later', '', '2022-12-07 08:28:03', 1); +INSERT INTO `sys_i18n` VALUES (7609, '127103', 'zh', 'DASHBOARD_TEMPLATE_SYNC_FAILED_GET_LOCK', '仪表盘模板同步正在进行,请稍后重试', '', '2022-12-07 08:28:17', 1); +INSERT INTO `sys_i18n` VALUES (7610, 'config.model.dashboardtemplate.comment', 'en', 'config.model.dashboardtemplate.comment', 'Asset dashboard template Example: Basic Dashboard Template', '', '2022-12-07 09:26:41', 1); +INSERT INTO `sys_i18n` VALUES (7611, 'config.model.dashboardtemplate.comment', 'zh', 'config.model.dashboardtemplate.comment', '资产仪表盘模板 示例:基本仪表盘模板', '', '2022-12-07 09:27:13', 1); +INSERT INTO `sys_i18n` VALUES (7612, 'terminal.reconnect', 'en', 'terminal.reconnect', 'Reconnect', '', '2022-12-14 07:45:20', 415); +INSERT INTO `sys_i18n` VALUES (7613, 'terminal.reconnect', 'zh', 'terminal.reconnect', '重新连接', 'terminal 重新连接', '2022-12-08 08:06:40', 1); +INSERT INTO `sys_i18n` VALUES (7614, 'terminal.changeTime', 'en', 'terminal.changeTime', 'Change the time', 'terminal changeTime', '2022-12-14 07:45:10', 415); +INSERT INTO `sys_i18n` VALUES (7615, 'terminal.changeTime', 'zh', 'terminal.changeTime', '变更时间', 'terminal changeTime', '2022-12-08 11:17:28', 1); +INSERT INTO `sys_i18n` VALUES (7616, 'terminal.rename', 'en', 'terminal.rename', 'Rename', 'terminal rename', '2022-12-14 07:45:01', 415); +INSERT INTO `sys_i18n` VALUES (7617, 'terminal.rename', 'zh', 'terminal.rename', '变更名称', 'terminal rename', '2022-12-08 12:03:33', 1); +INSERT INTO `sys_i18n` VALUES (7618, 'terminal.delinfo', 'en', 'terminal.delinfo', 'Are you sure you want to delete“{fileName}”?', '', '2022-12-08 13:17:17', 1); +INSERT INTO `sys_i18n` VALUES (7619, 'terminal.delinfo', 'zh', 'terminal.delinfo', '确定删除“{fileName}”这个文件吗?', '', '2022-12-08 13:21:32', 1); +INSERT INTO `sys_i18n` VALUES (7620, 'terminal.modifyTime', 'en', 'terminal.modifyTime', 'Modify time', 'terminal fileInfo', '2022-12-14 07:44:31', 415); +INSERT INTO `sys_i18n` VALUES (7621, 'terminal.modifyTime', 'zh', 'terminal.modifyTime', '更改时间', 'terminal fileInfo', '2022-12-08 13:43:44', 1); +INSERT INTO `sys_i18n` VALUES (7622, 'terminal.owner', 'zh', 'terminal.owner', '上传者', 'terminal fileInfo', '2022-12-08 13:45:03', 1); +INSERT INTO `sys_i18n` VALUES (7623, 'terminal.owner', 'en', 'terminal.owner', 'Owner', 'terminal fileInfo', '2022-12-14 07:44:21', 415); +INSERT INTO `sys_i18n` VALUES (7624, 'terminal.catalogueFile', 'zh', 'terminal.catalogueFile', '目录文件', 'terminal fileInfo', '2022-12-08 13:51:35', 1); +INSERT INTO `sys_i18n` VALUES (7625, 'terminal.catalogueFile', 'en', 'terminal.catalogueFile', 'Catalogue file', 'terminal fileInfo', '2022-12-08 14:10:10', 1); +INSERT INTO `sys_i18n` VALUES (7626, 'project.module.dashboardtemplate.comment', 'en', 'project.module.dashboardtemplate.comment', 'Endpoint dashboard template Example: Basic Dashboard Template', '', '2022-12-09 08:45:02', 1); +INSERT INTO `sys_i18n` VALUES (7627, 'project.module.dashboardtemplate.comment', 'zh', 'project.module.dashboardtemplate.comment', '端点仪表盘 模板示例:基本仪表盘模板', '', '2022-12-09 08:45:30', 1); +INSERT INTO `sys_i18n` VALUES (7628, 'terminal.confirm', 'en', 'terminal.confirm', 'Enter to confirm', 'terminal path confirm', '2022-12-14 08:49:45', 1); +INSERT INTO `sys_i18n` VALUES (7629, 'terminal.confirm', 'zh', 'terminal.confirm', '按回车键确认', 'terminal path confirm', '2022-12-14 08:50:13', 1); +INSERT INTO `sys_i18n` VALUES (7630, 'tools.cmd', 'en', 'tools.cmd', 'command', '', '2022-12-15 02:51:41', 415); +INSERT INTO `sys_i18n` VALUES (7631, 'tools.cmd', 'zh', 'tools.cmd', '命令', '', '2022-12-15 02:52:02', 415); +INSERT INTO `sys_i18n` VALUES (7634, '611021', 'en', 'TERMINAL_NEW_PATH_ISNULL', 'File new path cannot be empty', '', '2022-12-16 09:21:38', 1); +INSERT INTO `sys_i18n` VALUES (7635, '611021', 'zh', 'TERMINAL_NEW_PATH_ISNULL', '文件新建路径不能为空', '', '2022-12-16 09:22:13', 1); +INSERT INTO `sys_i18n` VALUES (7636, 'endpoints.metricTarget', 'en', 'endpoints.metricTarget', 'Metric target', '', '2022-12-19 06:46:46', 415); +INSERT INTO `sys_i18n` VALUES (7637, 'endpoints.metricTarget', 'zh', 'endpoints.metricTarget', '度量目标', '', '2022-12-19 06:47:05', 415); +INSERT INTO `sys_i18n` VALUES (7638, 'terminal.showFile', 'en', 'terminal.showFile', 'Show hide file', 'terminal fileDirectory showFile', '2023-01-04 02:09:59', 1); +INSERT INTO `sys_i18n` VALUES (7639, 'terminal.showFile', 'zh', 'terminal.showFile', '显示隐藏文件', 'terminal fileDirectory showFile', '2022-12-22 02:53:05', 1); +INSERT INTO `sys_i18n` VALUES (7640, 'terminal.title', 'en', 'terminal.title', 'Web terminal', 'terminal title', '2023-01-04 02:09:43', 1); +INSERT INTO `sys_i18n` VALUES (7641, 'terminal.title', 'zh', 'terminal.title', 'Web terminal', 'terminal title', '2022-12-22 02:56:00', 1); +INSERT INTO `sys_i18n` VALUES (7642, '607003', 'en', 'SYS_BACKUP_IN_PROGRESS', 'System data backup is in progress please try again later', '', '2022-12-22 03:15:35', 1); +INSERT INTO `sys_i18n` VALUES (7643, '607003', 'zh', 'SYS_BACKUP_IN_PROGRESS', '正在备份系统数据,请稍后再试', '', '2022-12-22 03:15:47', 1); +INSERT INTO `sys_i18n` VALUES (7644, 'overall.terminallog', 'en', 'overall.terminallog', 'Web terminal log', '', '2023-01-04 02:00:56', 1); +INSERT INTO `sys_i18n` VALUES (7645, 'overall.terminallog', 'zh', 'overall.terminallog', '终端日志', '', '2022-12-27 05:42:00', 415); +INSERT INTO `sys_i18n` VALUES (7646, 'terminal.placeholder', 'zh', 'terminal.placeholder', '发送文本到所有SSH终端', 'terminal 发送文本到所有SSH终端的placeholder', '2022-12-28 03:04:13', 1); +INSERT INTO `sys_i18n` VALUES (7647, 'terminal.placeholder', 'en', 'terminal.placeholder', 'Send text to all SSH terminals', 'terminal 发送文本到所有SSH终端的placeholder', '2022-12-28 03:04:54', 1); +INSERT INTO `sys_i18n` VALUES (7648, 'diagnose.asset.item.reachable', 'en', 'diagnose.asset.item.reachable', 'Reachability Information', '', '2023-01-04 07:56:22', 1); +INSERT INTO `sys_i18n` VALUES (7649, 'diagnose.asset.item.reachable', 'zh', 'diagnose.asset.item.reachable', '可达性信息', '', '2023-01-03 09:57:42', 1); +INSERT INTO `sys_i18n` VALUES (7650, 'diagnose.asset.item.agent.status', 'en', 'diagnose.asset.item.agent.status', 'Agent Status', '', '2023-01-04 07:56:27', 1); +INSERT INTO `sys_i18n` VALUES (7651, 'diagnose.asset.item.agent.status', 'zh', 'diagnose.asset.item.agent.status', '客户端状态', '', '2023-01-04 01:29:30', 1); +INSERT INTO `sys_i18n` VALUES (7652, 'diagnose.asset.resolution.reachable', 'en', 'diagnose.asset.resolution.reachable', '## Check items\n+ Shutdown/IP does not exist\n+ Network configuration\n+ Firewall settings\n+ Faulty network cable', '', '2023-01-04 03:34:32', 1); +INSERT INTO `sys_i18n` VALUES (7653, 'diagnose.asset.resolution.reachable', 'zh', 'diagnose.asset.resolution.reachable', '## 检查项\n+ 关机/IP不存在\n+ 网络配置\n+ 防火墙设置\n+ 网线故障', '', '2023-01-04 03:34:48', 1); +INSERT INTO `sys_i18n` VALUES (7654, 'diagnose.asset.resolution.agent.status', 'en', 'diagnose.asset.resolution.agent.status', '## Check items\n+ Agent status', '', '2023-01-04 03:35:27', 1); +INSERT INTO `sys_i18n` VALUES (7655, 'diagnose.asset.resolution.agent.status', 'zh', 'diagnose.asset.resolution.agent.status', '## 检查项\n+ 客户端状态', '', '2023-01-04 03:35:37', 1); +INSERT INTO `sys_i18n` VALUES (7656, 'diagnose.asset.resolution.agent.config', 'en', 'diagnose.asset.resolution.agent.config', '## Configuration items\n+ Agent data', '', '2023-01-04 03:35:46', 1); +INSERT INTO `sys_i18n` VALUES (7657, 'diagnose.asset.resolution.agent.config', 'zh', 'diagnose.asset.resolution.agent.config', '## 配置项\n+ 客户端数据', '', '2023-01-17 03:16:55', 1); +INSERT INTO `sys_i18n` VALUES (7658, 'diagnose.asset.item.stateconf', 'zh', 'diagnose.asset.item.stateconf', '资产状态配置', '', '2023-01-04 07:55:44', 1); +INSERT INTO `sys_i18n` VALUES (7659, 'diagnose.asset.item.stateconf', 'en', 'diagnose.asset.item.stateconf', 'Asset State Configuration', '', '2023-01-04 07:56:13', 1); +INSERT INTO `sys_i18n` VALUES (7660, 'diagnose.asset.resolution.stateconf', 'en', 'diagnose.asset.resolution.stateconf', '## Check items\n+ Asset state configuration items', '', '2023-01-04 07:58:01', 1); +INSERT INTO `sys_i18n` VALUES (7661, 'diagnose.asset.resolution.stateconf', 'zh', 'diagnose.asset.resolution.stateconf', '## 检查项\n+ 资产状态配置项', '', '2023-01-04 07:58:14', 1); +INSERT INTO `sys_i18n` VALUES (7662, 'diagnose.asset.item.blackbox', 'en', 'diagnose.asset.item.blackbox', 'Monitoring Configuration', '', '2023-01-04 07:59:47', 1); +INSERT INTO `sys_i18n` VALUES (7663, 'diagnose.asset.item.blackbox', 'zh', 'diagnose.asset.item.blackbox', '监控配置', '', '2023-01-04 07:59:56', 1); +INSERT INTO `sys_i18n` VALUES (7664, 'diagnose.asset.resolution.blackbox', 'zh', 'diagnose.asset.resolution.blackbox', '## 配置项\n+ 编辑资产触发配置下发流程', '', '2023-01-04 08:01:42', 1); +INSERT INTO `sys_i18n` VALUES (7665, 'diagnose.asset.resolution.blackbox', 'en', 'diagnose.asset.resolution.blackbox', '## Configuration items\n+ Editing asset triggers the configuration delivery process', '', '2023-01-04 08:02:34', 1); +INSERT INTO `sys_i18n` VALUES (7666, 'terminal.noHistoricalRecord', 'en', 'terminal.noHistoricalRecord', 'No historical record', '', '2023-01-04 08:26:36', 407); +INSERT INTO `sys_i18n` VALUES (7667, 'terminal.noHistoricalRecord', 'zh', 'terminal.noHistoricalRecord', '没有历史记录', '', '2023-01-04 08:26:59', 407); +INSERT INTO `sys_i18n` VALUES (7668, 'terminal.history', 'en', 'terminal.history', 'History', '', '2023-01-05 08:40:59', 407); +INSERT INTO `sys_i18n` VALUES (7669, 'terminal.history', 'zh', 'terminal.history', '历史记录', '', '2023-01-05 08:41:11', 407); +INSERT INTO `sys_i18n` VALUES (7670, 'diagnose.agent.item.reachable', 'zh', 'diagnose.agent.item.reachable', '可达性信息', '', '2023-01-06 03:34:07', 1); +INSERT INTO `sys_i18n` VALUES (7671, 'diagnose.agent.item.reachable', 'en', 'diagnose.agent.item.reachable', 'Reachability Information', '', '2023-01-06 03:34:20', 1); +INSERT INTO `sys_i18n` VALUES (7672, 'diagnose.agent.resolution.reachable', 'en', 'diagnose.agent.resolution.reachable', '## Check items\n+ Shutdown/IP does not exist\n+ Network configuration\n+ Firewall settings\n+ Faulty network cable', '', '2023-01-06 03:34:47', 1); +INSERT INTO `sys_i18n` VALUES (7673, 'diagnose.agent.resolution.reachable', 'zh', 'diagnose.agent.resolution.reachable', '## 检查项\n+ 关机/IP不存在\n+ 网络配置\n+ 防火墙设置\n+ 网线故障', '', '2023-01-06 03:34:58', 1); +INSERT INTO `sys_i18n` VALUES (7674, 'diagnose.agent.item.connectable', 'en', 'diagnose.agent.item.connectable', 'Agent Port Connectable Infomation', '', '2023-01-06 03:46:02', 1); +INSERT INTO `sys_i18n` VALUES (7675, 'diagnose.agent.item.connectable', 'zh', 'diagnose.agent.item.connectable', '客户端服务端口连接信息', '', '2023-01-06 03:46:23', 1); +INSERT INTO `sys_i18n` VALUES (7676, 'diagnose.agent.resolution.connectable', 'en', 'diagnose.agent.resolution.connectable', '## Check items\n+ Agent service status\n+ Agent port & protocol configuration\n+ Firewall settings', '', '2023-01-06 06:16:28', 1); +INSERT INTO `sys_i18n` VALUES (7677, 'diagnose.agent.resolution.connectable', 'zh', 'diagnose.agent.resolution.connectable', '## 检查项 \n+ 客户端服务状态\n+ 客户端端口&协议配置\n+ 防火墙设置', '', '2023-01-06 06:16:42', 1); +INSERT INTO `sys_i18n` VALUES (7678, 'diagnose.agent.item.components', 'en', 'diagnose.agent.item.components', 'Agent State', '', '2023-01-06 06:28:07', 1); +INSERT INTO `sys_i18n` VALUES (7679, 'diagnose.agent.item.components', 'zh', 'diagnose.agent.item.components', '客户端状态', '', '2023-01-06 06:28:03', 1); +INSERT INTO `sys_i18n` VALUES (7680, 'diagnose.agent.item.nzagent', 'en', 'diagnose.agent.item.nzagent', 'Agent Service Status', '', '2023-01-06 06:33:36', 1); +INSERT INTO `sys_i18n` VALUES (7681, 'diagnose.agent.item.nzagent', 'zh', 'diagnose.agent.item.nzagent', '客户端服务状态', '', '2023-01-06 06:33:52', 1); +INSERT INTO `sys_i18n` VALUES (7682, 'diagnose.agent.resolution.nzagent', 'en', 'diagnose.agent.resolution.nzagent', '## Check items\n+ Agent service running status', '', '2023-01-06 06:35:43', 1); +INSERT INTO `sys_i18n` VALUES (7683, 'diagnose.agent.resolution.nzagent', 'zh', 'diagnose.agent.resolution.nzagent', '## 检查项 \n+ 客户端程序运行状态', '', '2023-01-06 06:36:09', 1); +INSERT INTO `sys_i18n` VALUES (7684, 'diagnose.agent.item.auth', 'en', 'diagnose.agent.item.auth', 'Token Invalid', '', '2023-01-06 06:38:07', 1); +INSERT INTO `sys_i18n` VALUES (7685, 'diagnose.agent.item.auth', 'zh', 'diagnose.agent.item.auth', '令牌无效', '', '2023-01-06 06:38:40', 1); +INSERT INTO `sys_i18n` VALUES (7686, 'diagnose.agent.resolution.auth', 'en', 'diagnose.agent.resolution.auth', '## Check items\n+ Token Configuration', '', '2023-01-06 06:39:36', 1); +INSERT INTO `sys_i18n` VALUES (7687, 'diagnose.agent.resolution.auth', 'zh', 'diagnose.agent.resolution.auth', '## 检查项 \n+ 令牌配置', '', '2023-01-06 06:39:55', 1); +INSERT INTO `sys_i18n` VALUES (7688, 'diagnose.agent.item.cortex', 'en', 'diagnose.agent.item.cortex', 'Cortex Component State', '', '2023-01-06 06:41:58', 1); +INSERT INTO `sys_i18n` VALUES (7689, 'diagnose.agent.item.cortex', 'zh', 'diagnose.agent.item.cortex', 'Cortex 组件状态', '', '2023-01-06 06:42:34', 1); +INSERT INTO `sys_i18n` VALUES (7690, 'diagnose.agent.resolution.cortex', 'en', 'diagnose.agent.resolution.cortex', '## Check items\n+ Cortex component running status', '', '2023-01-06 06:43:58', 1); +INSERT INTO `sys_i18n` VALUES (7691, 'diagnose.agent.resolution.cortex', 'zh', 'diagnose.agent.resolution.cortex', '## 检查项 \n+ Cortex 组件运行状态', '', '2023-01-06 06:44:22', 1); +INSERT INTO `sys_i18n` VALUES (7692, 'diagnose.agent.item.loki', 'en', 'diagnose.agent.item.loki', 'Loki Component State', '', '2023-01-06 06:45:14', 1); +INSERT INTO `sys_i18n` VALUES (7693, 'diagnose.agent.item.loki', 'zh', 'diagnose.agent.item.loki', 'Loki 组件状态', '', '2023-01-06 06:45:25', 1); +INSERT INTO `sys_i18n` VALUES (7694, 'diagnose.agent.resolution.loki', 'en', 'diagnose.agent.resolution.loki', '## Check items\n+ Loki component running status', '', '2023-01-06 06:45:42', 1); +INSERT INTO `sys_i18n` VALUES (7695, 'diagnose.agent.resolution.loki', 'zh', 'diagnose.agent.resolution.loki', '## 检查项 \n+ Loki 组件运行状态', '', '2023-01-06 06:45:54', 1); +INSERT INTO `sys_i18n` VALUES (7696, 'diagnose.agent.item.snmpExporter', 'en', 'diagnose.agent.item.snmpExporter', 'SNMP Exporter Component State', '', '2023-01-06 06:51:11', 1); +INSERT INTO `sys_i18n` VALUES (7697, 'diagnose.agent.item.snmpExporter', 'zh', 'diagnose.agent.item.snmpExporter', 'SNMP Exporter 组件状态', '', '2023-01-06 06:51:22', 1); +INSERT INTO `sys_i18n` VALUES (7698, 'diagnose.agent.resolution.snmpExporter', 'en', 'diagnose.agent.resolution.snmpExporter', '## Check items\n+ SNMP Exporter component running status', '', '2023-01-06 06:51:49', 1); +INSERT INTO `sys_i18n` VALUES (7699, 'diagnose.agent.resolution.snmpExporter', 'zh', 'diagnose.agent.resolution.snmpExporter', '## 检查项 \n+ SNMP Exporter 组件运行状态', '', '2023-01-06 06:52:26', 1); +INSERT INTO `sys_i18n` VALUES (7700, 'diagnose.agent.item.blackboxExporter', 'en', 'diagnose.agent.item.blackboxExporter', 'Blackbox Exporter Component State', '', '2023-01-06 06:54:41', 1); +INSERT INTO `sys_i18n` VALUES (7701, 'diagnose.agent.item.blackboxExporter', 'zh', 'diagnose.agent.item.blackboxExporter', 'Blackbox Exporter 组件状态', '', '2023-01-06 06:54:56', 1); +INSERT INTO `sys_i18n` VALUES (7702, 'diagnose.agent.resolution.blackboxExporter', 'en', 'diagnose.agent.resolution.blackboxExporter', '## Check items\n+ Blackbox Exporter component running status', '', '2023-01-06 06:55:10', 1); +INSERT INTO `sys_i18n` VALUES (7703, 'diagnose.agent.resolution.blackboxExporter', 'zh', 'diagnose.agent.resolution.blackboxExporter', '## 检查项 \n+ Blackbox Exporter 组件运行状态', '', '2023-01-06 06:55:26', 1); +INSERT INTO `sys_i18n` VALUES (7704, 'diagnose.agent.item.prometheus', 'en', 'diagnose.agent.item.prometheus', 'Prometheus Component State', '', '2023-01-06 06:55:47', 1); +INSERT INTO `sys_i18n` VALUES (7705, 'diagnose.agent.item.prometheus', 'zh', 'diagnose.agent.item.prometheus', 'Prometheus 组件状态', '', '2023-01-06 06:56:04', 1); +INSERT INTO `sys_i18n` VALUES (7706, 'diagnose.agent.resolution.prometheus', 'en', 'diagnose.agent.resolution.prometheus', '## Check items\n+ Prometheus component running status', '', '2023-01-06 06:56:21', 1); +INSERT INTO `sys_i18n` VALUES (7707, 'diagnose.agent.resolution.prometheus', 'zh', 'diagnose.agent.resolution.prometheus', '## 检查项 \n+ Prometheus 组件运行状态', '', '2023-01-06 06:56:35', 1); +INSERT INTO `sys_i18n` VALUES (7708, 'config.agent.cortexDetail', 'en', 'config.agent.cortexDetail', 'Cortex status', '', '2023-01-31 10:07:04', 415); +INSERT INTO `sys_i18n` VALUES (7709, 'config.agent.cortexDetail', 'zh', 'config.agent.cortexDetail', 'Cortex 状态', '', '2023-02-01 01:24:18', 415); +INSERT INTO `sys_i18n` VALUES (7710, 'cortex.availabilityZone', 'en', 'cortex.availabilityZone', 'Availability zone', '', '2023-01-09 09:29:40', 415); +INSERT INTO `sys_i18n` VALUES (7711, 'cortex.availabilityZone', 'zh', 'cortex.availabilityZone', '可用性区域', '', '2023-01-09 09:30:21', 415); +INSERT INTO `sys_i18n` VALUES (7712, 'cortex.registeredAt', 'en', 'cortex.registeredAt', 'Registered at', '', '2023-01-09 09:32:52', 415); +INSERT INTO `sys_i18n` VALUES (7713, 'cortex.registeredAt', 'zh', 'cortex.registeredAt', '注册', '', '2023-01-09 09:33:04', 415); +INSERT INTO `sys_i18n` VALUES (7714, 'cortex.lastHeartbeat', 'en', 'cortex.lastHeartbeat', 'Last heartbeat', '', '2023-01-09 09:37:41', 415); +INSERT INTO `sys_i18n` VALUES (7715, 'cortex.lastHeartbeat', 'zh', 'cortex.lastHeartbeat', '最后一次讯号', '', '2023-01-09 09:37:55', 415); +INSERT INTO `sys_i18n` VALUES (7716, 'cortex.ownership', 'en', 'cortex.ownership', 'Ownership', '', '2023-01-09 09:40:16', 415); +INSERT INTO `sys_i18n` VALUES (7717, 'cortex.ownership', 'zh', 'cortex.ownership', '所有权', '', '2023-01-09 09:40:34', 415); +INSERT INTO `sys_i18n` VALUES (7718, 'cortex.ready', 'en', 'cortex.ready', 'Ready', '', '2023-01-10 06:49:15', 415); +INSERT INTO `sys_i18n` VALUES (7719, 'cortex.distributorService', 'en', 'cortex.distributorService', 'Distributor service', '', '2023-01-10 07:00:34', 415); +INSERT INTO `sys_i18n` VALUES (7720, 'cortex.distributorService', 'zh', 'cortex.distributorService', '经销商服务', '', '2023-01-10 08:38:29', 415); +INSERT INTO `sys_i18n` VALUES (7721, 'cortex.ingesterService', 'en', 'cortex.ingesterService', 'Ingester service', '', '2023-01-10 08:40:16', 415); +INSERT INTO `sys_i18n` VALUES (7722, 'cortex.ingesterService', 'zh', 'cortex.ingesterService', '接待服务', '', '2023-01-10 08:40:34', 415); +INSERT INTO `sys_i18n` VALUES (7723, 'cortex.ringStatus', 'en', 'cortex.ringStatus', 'Ring status', '', '2023-01-10 08:54:31', 415); +INSERT INTO `sys_i18n` VALUES (7724, 'cortex.ringStatus', 'zh', 'cortex.ringStatus', '运行状态', '', '2023-01-10 08:54:55', 415); +INSERT INTO `sys_i18n` VALUES (7725, 'cortex.serviceStatus', 'en', 'cortex.serviceStatus', 'Service status', '', '2023-01-10 08:55:50', 415); +INSERT INTO `sys_i18n` VALUES (7726, 'cortex.serviceStatus', 'zh', 'cortex.serviceStatus', '服务状态', '', '2023-01-10 08:56:07', 415); +INSERT INTO `sys_i18n` VALUES (7727, 'cortex.ready', 'zh', 'cortex.ready', '就绪', '', '2023-01-10 09:42:23', 415); +INSERT INTO `sys_i18n` VALUES (7728, 'cortex.includeDefaultValues', 'en', 'cortex.includeDefaultValues', 'Include default values', '', '2023-01-12 02:43:09', 415); +INSERT INTO `sys_i18n` VALUES (7729, 'cortex.includeDefaultValues', 'zh', 'cortex.includeDefaultValues', '包含默认值', '', '2023-01-12 02:43:26', 415); +INSERT INTO `sys_i18n` VALUES (7730, 'cortex.querier', 'en', 'cortex.querier', 'Querier', '', '2023-01-12 02:45:10', 415); +INSERT INTO `sys_i18n` VALUES (7731, 'cortex.querier', 'zh', 'cortex.querier', '查询器', '', '2023-01-12 02:45:28', 415); +INSERT INTO `sys_i18n` VALUES (7732, 'cortex.ring', 'en', 'cortex.ring', 'Ring', '', '2023-01-12 02:47:22', 415); +INSERT INTO `sys_i18n` VALUES (7733, 'cortex.ring', 'zh', 'cortex.ring', '振铃', '', '2023-01-12 02:47:36', 415); +INSERT INTO `sys_i18n` VALUES (7734, 'cortex.storeGateway', 'en', 'cortex.storeGateway', 'Store gateway', '', '2023-01-12 02:54:54', 415); +INSERT INTO `sys_i18n` VALUES (7735, 'cortex.storeGateway', 'zh', 'cortex.storeGateway', '存储网关', '', '2023-01-12 02:56:22', 415); +INSERT INTO `sys_i18n` VALUES (7736, 'cortex.storeQueryable', 'en', 'cortex.storeQueryable', 'Store queryable', '', '2023-01-12 03:07:19', 415); +INSERT INTO `sys_i18n` VALUES (7737, 'cortex.storeQueryable', 'zh', 'cortex.storeQueryable', '存储可查询', '', '2023-01-12 03:07:35', 415); +INSERT INTO `sys_i18n` VALUES (7738, 'cortex.queryFrontend', 'en', 'cortex.queryFrontend', 'Query frontend', '', '2023-01-12 03:12:11', 415); +INSERT INTO `sys_i18n` VALUES (7739, 'cortex.queryFrontend', 'zh', 'cortex.queryFrontend', '查询前端', '', '2023-01-12 03:12:25', 415); +INSERT INTO `sys_i18n` VALUES (7740, '316039', 'en', 'ASSET_TERMINAL_ACCOUNT_INFO_NOTFOUND', 'Account information for asset terminal login is not configured', '', '2023-01-12 08:23:04', 1); +INSERT INTO `sys_i18n` VALUES (7741, '316039', 'zh', 'ASSET_TERMINAL_ACCOUNT_INFO_NOTFOUND', '资产终端登录账号信息未配置', '', '2023-01-12 08:23:15', 1); +INSERT INTO `sys_i18n` VALUES (7742, 'cortex.ingester', 'en', 'cortex.ingester', 'Ingester', '', '2023-01-12 07:49:44', 415); +INSERT INTO `sys_i18n` VALUES (7743, 'cortex.ingester', 'zh', 'cortex.ingester', '投资者', '', '2023-01-12 07:50:04', 415); +INSERT INTO `sys_i18n` VALUES (7744, 'cortex.memberlist', 'en', 'cortex.memberlist', 'Member list KV', '', '2023-01-13 03:44:13', 415); +INSERT INTO `sys_i18n` VALUES (7745, 'cortex.memberlist', 'zh', 'cortex.memberlist', '成员列表', '', '2023-01-13 03:44:19', 415); +INSERT INTO `sys_i18n` VALUES (7746, 'cortex.queryFrontendTripperware', 'en', 'cortex.queryFrontendTripperware', 'Query frontend tripperware', '', '2023-01-13 03:43:16', 415); +INSERT INTO `sys_i18n` VALUES (7747, 'cortex.queryFrontendTripperware', 'zh', 'cortex.queryFrontendTripperware', '查询前端用品', '', '2023-01-13 03:42:43', 415); +INSERT INTO `sys_i18n` VALUES (7748, 'cortex.IncludeDefault', 'en', 'cortex.IncludeDefault', 'Include default values', '', '2023-01-13 03:46:27', 415); +INSERT INTO `sys_i18n` VALUES (7749, 'cortex.IncludeDefault', 'zh', 'cortex.IncludeDefault', '包括默认值', '', '2023-01-13 03:46:43', 415); +INSERT INTO `sys_i18n` VALUES (7750, 'metric.diagnose.endpoint.item.agent.status', 'en', 'metric.diagnose.endpoint.item.agent.status', 'Agent Status', '', '2023-01-17 06:39:09', 1); +INSERT INTO `sys_i18n` VALUES (7751, 'metric.diagnose.endpoint.item.agent.status', 'zh', 'metric.diagnose.endpoint.item.agent.status', '客户端状态', '', '2023-01-17 06:39:01', 1); +INSERT INTO `sys_i18n` VALUES (7752, 'diagnose.endpoint.resolution.agent.status', 'en', 'diagnose.endpoint.resolution.agent.status', '## Check items\n+ Agent status', '', '2023-01-17 03:16:03', 1); +INSERT INTO `sys_i18n` VALUES (7753, 'diagnose.endpoint.resolution.agent.status', 'zh', 'diagnose.endpoint.resolution.agent.status', '## 检查项\n+ 客户端状态', '', '2023-01-17 03:16:14', 1); +INSERT INTO `sys_i18n` VALUES (7754, 'diagnose.endpoint.resolution.agent.config', 'en', 'diagnose.endpoint.resolution.agent.config', '## Configuration items\n+ Agent data', '', '2023-01-17 03:16:45', 1); +INSERT INTO `sys_i18n` VALUES (7755, 'diagnose.endpoint.resolution.agent.config', 'zh', 'diagnose.endpoint.resolution.agent.config', '## 配置项\n+ 客户端数据', '', '2023-01-17 03:16:58', 1); +INSERT INTO `sys_i18n` VALUES (7756, 'metric.diagnose.endpoint.item.monitor.status', 'zh', 'metric.diagnose.endpoint.item.monitor.status', '指标端点监控状态', '', '2023-01-17 06:39:21', 1); +INSERT INTO `sys_i18n` VALUES (7757, 'metric.diagnose.endpoint.item.monitor.status', 'en', 'metric.diagnose.endpoint.item.monitor.status', 'Metric Endpoint Monitor Status', '', '2023-01-17 06:39:35', 1); +INSERT INTO `sys_i18n` VALUES (7758, 'metric.diagnose.endpoint.item.monitor.dc', 'en', 'metric.diagnose.endpoint.item.monitor.dc', 'Data Center State', '', '2023-01-17 03:44:39', 1); +INSERT INTO `sys_i18n` VALUES (7759, 'metric.diagnose.endpoint.item.monitor.dc', 'zh', 'metric.diagnose.endpoint.item.monitor.dc', '数据中心状态', '', '2023-01-17 03:45:05', 1); +INSERT INTO `sys_i18n` VALUES (7760, 'diagnose.endpoint.resolution.monitor.dc', 'en', 'diagnose.endpoint.resolution.monitor.dc', '## Configuration items\n+ Enable data center', '', '2023-01-17 05:47:20', 1); +INSERT INTO `sys_i18n` VALUES (7761, 'diagnose.endpoint.resolution.monitor.dc', 'zh', 'diagnose.endpoint.resolution.monitor.dc', '## 配置项\n+ 启用数据中心', '', '2023-01-17 05:47:28', 1); +INSERT INTO `sys_i18n` VALUES (7762, 'metric.diagnose.endpoint.item.monitor.asset', 'en', 'metric.diagnose.endpoint.item.monitor.asset', 'Asset State', '', '2023-01-17 05:50:59', 1); +INSERT INTO `sys_i18n` VALUES (7763, 'metric.diagnose.endpoint.item.monitor.asset', 'zh', 'metric.diagnose.endpoint.item.monitor.asset', '资产状态', '', '2023-01-17 05:51:09', 1); +INSERT INTO `sys_i18n` VALUES (7764, 'diagnose.endpoint.resolution.monitor.asset', 'en', 'diagnose.endpoint.resolution.monitor.asset', '## Configuration items\n+ Modify the asset state to a configuration that supports monitor', '', '2023-01-17 06:02:45', 1); +INSERT INTO `sys_i18n` VALUES (7765, 'diagnose.endpoint.resolution.monitor.asset', 'zh', 'diagnose.endpoint.resolution.monitor.asset', '## 配置项\n+ 修改资产状态为支持监控的配置', '', '2023-01-17 06:02:54', 1); +INSERT INTO `sys_i18n` VALUES (7766, 'metric.diagnose.endpoint.item.monitor.config', 'en', 'metric.diagnose.endpoint.item.monitor.config', 'Metric Endpoint State', '', '2023-01-17 06:05:38', 1); +INSERT INTO `sys_i18n` VALUES (7767, 'metric.diagnose.endpoint.item.monitor.config', 'zh', 'metric.diagnose.endpoint.item.monitor.config', '指标端点状态', '', '2023-01-17 06:05:51', 1); +INSERT INTO `sys_i18n` VALUES (7768, 'diagnose.endpoint.resolution.monitor.config', 'en', 'diagnose.endpoint.resolution.monitor.config', '## Configuration items\n+ Enable Endpoint Monitor Status', '', '2023-01-17 06:08:02', 1); +INSERT INTO `sys_i18n` VALUES (7769, 'diagnose.endpoint.resolution.monitor.config', 'zh', 'diagnose.endpoint.resolution.monitor.config', '## 配置项\n+ 启用端点监控状态', '', '2023-01-17 06:08:13', 1); +INSERT INTO `sys_i18n` VALUES (7770, 'metric.diagnose.endpoint.item.scrape.config', 'en', 'metric.diagnose.endpoint.item.scrape.config', 'Metric Endpoint Monitor Profile', '', '2023-01-17 06:41:08', 1); +INSERT INTO `sys_i18n` VALUES (7771, 'metric.diagnose.endpoint.item.scrape.config', 'zh', 'metric.diagnose.endpoint.item.scrape.config', '指标端点监控配置文件', '', '2023-01-17 06:40:25', 1); +INSERT INTO `sys_i18n` VALUES (7772, 'diagnose.endpoint.resolution.scrape.config', 'zh', 'diagnose.endpoint.resolution.scrape.config', '## 配置项\n+ 编辑端点以触发重新配置流程', '', '2023-01-17 06:26:31', 1); +INSERT INTO `sys_i18n` VALUES (7773, 'diagnose.endpoint.resolution.scrape.config', 'en', 'diagnose.endpoint.resolution.scrape.config', '## Configuration items\n+ Edit the endpoint to trigger the reconfiguration process', '', '2023-01-17 06:26:53', 1); +INSERT INTO `sys_i18n` VALUES (7774, 'metric.diagnose.endpoint.item.reachable', 'en', 'metric.diagnose.endpoint.item.reachable', 'Metric Endpoint Reachability Information', '', '2023-01-17 06:40:45', 1); +INSERT INTO `sys_i18n` VALUES (7775, 'metric.diagnose.endpoint.item.reachable', 'zh', 'metric.diagnose.endpoint.item.reachable', '指标端点可达性信息', '', '2023-01-17 06:40:56', 1); +INSERT INTO `sys_i18n` VALUES (7776, 'diagnose.endpoint.resolution.reachable', 'en', 'diagnose.endpoint.resolution.reachable', '## Check items\n+ Shutdown/IP does not exist\n+ Network configuration\n+ Firewall settings\n+ Faulty network cable', '', '2023-01-17 06:32:46', 1); +INSERT INTO `sys_i18n` VALUES (7777, 'diagnose.endpoint.resolution.reachable', 'zh', 'diagnose.endpoint.resolution.reachable', '## 检查项\n+ 关机/IP不存在\n+ 网络配置\n+ 防火墙设置\n+ 网线故障', '', '2023-01-17 06:32:55', 1); +INSERT INTO `sys_i18n` VALUES (7778, 'metric.diagnose.endpoint.item.connectable', 'en', 'metric.diagnose.endpoint.item.connectable', 'Metric Endpoint Port Connectable Infomation', '', '2023-01-17 06:36:51', 1); +INSERT INTO `sys_i18n` VALUES (7779, 'metric.diagnose.endpoint.item.connectable', 'zh', 'metric.diagnose.endpoint.item.connectable', '指标端点服务端口连接信息', '', '2023-01-17 06:37:21', 1); +INSERT INTO `sys_i18n` VALUES (7780, 'diagnose.endpoint.resolution.connectable', 'en', 'diagnose.endpoint.resolution.connectable', '## Check items\n+ Metric endpoint service status\n+ Metric endpoint port & protocol configuration\n+ Firewall settings', '', '2023-01-17 06:53:12', 1); +INSERT INTO `sys_i18n` VALUES (7781, 'diagnose.endpoint.resolution.connectable', 'zh', 'diagnose.endpoint.resolution.connectable', '## 检查项 \n+ 指标端点服务状态\n+ 指标端点端口&协议配置\n+ 防火墙设置', '', '2023-01-17 06:53:47', 1); +INSERT INTO `sys_i18n` VALUES (7782, 'metric.diagnose.endpoint.item.timeout', 'en', 'metric.diagnose.endpoint.item.timeout', 'Metric Endpoint Timeout Check', '', '2023-01-17 07:04:01', 1); +INSERT INTO `sys_i18n` VALUES (7783, 'metric.diagnose.endpoint.item.timeout', 'zh', 'metric.diagnose.endpoint.item.timeout', '指标端点超时检查', '', '2023-01-17 07:04:13', 1); +INSERT INTO `sys_i18n` VALUES (7784, 'diagnose.endpoint.resolution.timeout', 'en', 'diagnose.endpoint.resolution.timeout', '## Check items\n+ Increase scrape timeout', '', '2023-01-17 07:17:56', 1); +INSERT INTO `sys_i18n` VALUES (7785, 'diagnose.endpoint.resolution.timeout', 'zh', 'diagnose.endpoint.resolution.timeout', '## 检查项 \n+ 增大超时时间', '', '2023-01-17 07:18:16', 1); +INSERT INTO `sys_i18n` VALUES (7786, 'metric.diagnose.endpoint.item.scrape.status', 'en', 'metric.diagnose.endpoint.item.scrape.status', 'Metric Endpoint Scrape Status', '', '2023-01-17 07:30:07', 1); +INSERT INTO `sys_i18n` VALUES (7787, 'metric.diagnose.endpoint.item.scrape.status', 'zh', 'metric.diagnose.endpoint.item.scrape.status', '指标端点采集状态', '', '2023-01-17 07:30:39', 1); +INSERT INTO `sys_i18n` VALUES (7788, 'diagnose.endpoint.resolution.firewall', 'en', 'diagnose.endpoint.resolution.firewall', '## Check items\n+ Firewall settings', '', '2023-01-17 07:40:20', 1); +INSERT INTO `sys_i18n` VALUES (7789, 'diagnose.endpoint.resolution.firewall', 'zh', 'diagnose.endpoint.resolution.firewall', '## 检查项 \n+ 防火墙设置', '', '2023-01-17 07:40:42', 1); +INSERT INTO `sys_i18n` VALUES (7790, 'diagnose.endpoint.resolution.auth', 'zh', 'diagnose.endpoint.resolution.auth', '## 检查项 \n+ 端点认证配置', '', '2023-01-17 07:45:29', 1); +INSERT INTO `sys_i18n` VALUES (7791, 'diagnose.endpoint.resolution.auth', 'en', 'diagnose.endpoint.resolution.auth', '## Check items\n+ Endpoint authentication configuration', '', '2023-01-17 07:46:15', 1); +INSERT INTO `sys_i18n` VALUES (7792, 'diagnose.endpoint.resolution.error', 'zh', 'diagnose.endpoint.resolution.error', '未知错误', '', '2023-01-17 07:52:03', 1); +INSERT INTO `sys_i18n` VALUES (7793, 'diagnose.endpoint.resolution.error', 'en', 'diagnose.endpoint.resolution.error', 'Unknown error', '', '2023-01-17 07:52:51', 1); +INSERT INTO `sys_i18n` VALUES (7794, 'metric.diagnose.endpoint.item.snmp.agent', 'en', 'metric.diagnose.endpoint.item.snmp.agent', 'Metric Endpoint SNMP Service Status', '', '2023-01-17 07:59:19', 1); +INSERT INTO `sys_i18n` VALUES (7795, 'metric.diagnose.endpoint.item.snmp.agent', 'zh', 'metric.diagnose.endpoint.item.snmp.agent', '指标端点SNMP服务状态', '', '2023-01-17 07:59:28', 1); +INSERT INTO `sys_i18n` VALUES (7796, 'diagnose.endpoint.resolution.snmp.agent', 'en', 'diagnose.endpoint.resolution.snmp.agent', '## Check items\n+ SNMP service status\n+ SNMP credential configuration\n+ OID configuration', '', '2023-01-17 08:02:01', 1); +INSERT INTO `sys_i18n` VALUES (7797, 'diagnose.endpoint.resolution.snmp.agent', 'zh', 'diagnose.endpoint.resolution.snmp.agent', '## 检查项 \n+ SNMP 服务状态\n+ SNMP 凭证配置\n+ OID 配置', '', '2023-01-17 08:02:10', 1); +INSERT INTO `sys_i18n` VALUES (7798, 'logs.diagnose.endpoint.item.agent.status', 'en', 'logs.diagnose.endpoint.item.agent.status', 'Agent Status', '', '2023-01-17 09:47:55', 1); +INSERT INTO `sys_i18n` VALUES (7799, 'logs.diagnose.endpoint.item.agent.status', 'zh', 'logs.diagnose.endpoint.item.agent.status', '客户端状态', '', '2023-01-17 09:48:02', 1); +INSERT INTO `sys_i18n` VALUES (7800, 'logs.diagnose.endpoint.item.monitor.status', 'en', 'logs.diagnose.endpoint.item.monitor.status', 'Log Monitor Status', '', '2023-01-17 09:49:53', 1); +INSERT INTO `sys_i18n` VALUES (7801, 'logs.diagnose.endpoint.item.monitor.status', 'zh', 'logs.diagnose.endpoint.item.monitor.status', '日志监控状态', '', '2023-01-17 09:50:02', 1); +INSERT INTO `sys_i18n` VALUES (7802, 'logs.diagnose.endpoint.item.monitor.dc', 'en', 'logs.diagnose.endpoint.item.monitor.dc', 'Data Center State', '', '2023-01-17 09:50:38', 1); +INSERT INTO `sys_i18n` VALUES (7803, 'logs.diagnose.endpoint.item.monitor.dc', 'zh', 'logs.diagnose.endpoint.item.monitor.dc', '数据中心状态', '', '2023-01-17 09:50:44', 1); +INSERT INTO `sys_i18n` VALUES (7804, 'logs.diagnose.endpoint.item.monitor.asset', 'en', 'logs.diagnose.endpoint.item.monitor.asset', 'Asset State', '', '2023-01-17 09:51:12', 1); +INSERT INTO `sys_i18n` VALUES (7805, 'logs.diagnose.endpoint.item.monitor.asset', 'zh', 'logs.diagnose.endpoint.item.monitor.asset', '资产状态', '', '2023-01-17 09:51:18', 1); +INSERT INTO `sys_i18n` VALUES (7806, 'diagnose.endpoint.resolution.client.asset', 'en', 'diagnose.endpoint.resolution.client.asset', '## Configuration items\n+ Open TALON configuration', '', '2023-01-17 09:53:26', 1); +INSERT INTO `sys_i18n` VALUES (7807, 'diagnose.endpoint.resolution.client.asset', 'zh', 'diagnose.endpoint.resolution.client.asset', '## 配置项\n+ 开启 TALON 配置', '', '2023-01-17 09:53:38', 1); +INSERT INTO `sys_i18n` VALUES (7808, 'logs.diagnose.endpoint.item.monitor.config', 'en', 'logs.diagnose.endpoint.item.monitor.config', 'Log Endpoint State', '', '2023-01-17 09:54:03', 1); +INSERT INTO `sys_i18n` VALUES (7809, 'logs.diagnose.endpoint.item.monitor.config', 'zh', 'logs.diagnose.endpoint.item.monitor.config', '日志端点状态', '', '2023-01-17 09:54:14', 1); +INSERT INTO `sys_i18n` VALUES (7810, 'logs.diagnose.endpoint.item.reachable', 'zh', 'logs.diagnose.endpoint.item.reachable', '日志端点可达性信息', '', '2023-01-17 09:56:27', 1); +INSERT INTO `sys_i18n` VALUES (7811, 'logs.diagnose.endpoint.item.reachable', 'en', 'logs.diagnose.endpoint.item.reachable', 'Log Endpoint Reachability Information', '', '2023-01-17 09:56:48', 1); +INSERT INTO `sys_i18n` VALUES (7812, 'logs.diagnose.endpoint.item.talon', 'en', 'logs.diagnose.endpoint.item.talon', 'Talon Status', '', '2023-01-17 09:57:48', 1); +INSERT INTO `sys_i18n` VALUES (7813, 'logs.diagnose.endpoint.item.talon', 'zh', 'logs.diagnose.endpoint.item.talon', 'Talon 状态', '', '2023-01-17 09:58:42', 1); +INSERT INTO `sys_i18n` VALUES (7814, 'diagnose.endpoint.resolution.talon', 'en', 'diagnose.endpoint.resolution.talon', '## Check items\n+ Talon service running status', '', '2023-01-17 09:59:44', 1); +INSERT INTO `sys_i18n` VALUES (7815, 'diagnose.endpoint.resolution.talon', 'zh', 'diagnose.endpoint.resolution.talon', '## 检查项 \n+ TALON程序运行状态', '', '2023-01-17 10:00:23', 1); +INSERT INTO `sys_i18n` VALUES (7818, 'diagnose.endpoint.item.talon.auth', 'en', 'diagnose.endpoint.item.talon.auth', 'Token Invalid', '', '2023-01-17 10:01:45', 1); +INSERT INTO `sys_i18n` VALUES (7819, 'diagnose.endpoint.item.talon.auth', 'zh', 'diagnose.endpoint.item.talon.auth', '令牌无效', '', '2023-01-17 10:01:55', 1); +INSERT INTO `sys_i18n` VALUES (7820, 'diagnose.endpoint.resolution.talon.auth', 'en', 'diagnose.endpoint.resolution.talon.auth', '## Check items\n+ Token Configuration', '', '2023-01-17 10:02:13', 1); +INSERT INTO `sys_i18n` VALUES (7821, 'diagnose.endpoint.resolution.talon.auth', 'zh', 'diagnose.endpoint.resolution.talon.auth', '## 检查项 \n+ 令牌配置', '', '2023-01-17 10:02:18', 1); +INSERT INTO `sys_i18n` VALUES (7822, 'diagnose.endpoint.item.talon.promtail', 'en', 'diagnose.endpoint.item.talon.promtail', 'Promtail Component State', '', '2023-01-17 10:02:40', 1); +INSERT INTO `sys_i18n` VALUES (7823, 'diagnose.endpoint.item.talon.promtail', 'zh', 'diagnose.endpoint.item.talon.promtail', 'Promtail 组件状态', '', '2023-01-17 10:02:50', 1); +INSERT INTO `sys_i18n` VALUES (7824, 'diagnose.endpoint.resolution.talon.promtail', 'en', 'diagnose.endpoint.resolution.talon.promtail', '## Check items\n+ Promtail component running status', '', '2023-01-17 10:03:10', 1); +INSERT INTO `sys_i18n` VALUES (7825, 'diagnose.endpoint.resolution.talon.promtail', 'zh', 'diagnose.endpoint.resolution.talon.promtail', '## 检查项 \n+ Promtail 组件运行状态', '', '2023-01-17 10:03:20', 1); +INSERT INTO `sys_i18n` VALUES (7826, 'dashboard.dashboard.chartForm.typeVal.funnel.label', 'en', 'dashboard.dashboard.chartForm.typeVal.funnel.label', 'Funnel', '', '2023-01-31 06:38:45', 407); +INSERT INTO `sys_i18n` VALUES (7827, 'dashboard.dashboard.chartForm.typeVal.funnel.label', 'zh', 'dashboard.dashboard.chartForm.typeVal.funnel.label', '漏斗图', '', '2023-01-31 06:39:02', 407); +INSERT INTO `sys_i18n` VALUES (7828, 'config.agent.lokiStatus', 'en', 'config.agent.lokiStatus', 'Loki status', '', '2023-02-01 01:22:35', 415); +INSERT INTO `sys_i18n` VALUES (7829, 'config.agent.lokiStatus', 'zh', 'config.agent.lokiStatus', 'Loki 状态', '', '2023-02-01 01:23:41', 415); +INSERT INTO `sys_i18n` VALUES (7830, 'loki.store', 'en', 'loki.store', 'Store', '', '2023-02-01 03:11:13', 415); +INSERT INTO `sys_i18n` VALUES (7831, 'loki.store', 'zh', 'loki.store', '存储', '', '2023-02-01 03:12:34', 415); +INSERT INTO `sys_i18n` VALUES (7832, 'loki.distributor', 'en', 'loki.distributor', 'Distributor', '', '2023-02-01 03:14:11', 415); +INSERT INTO `sys_i18n` VALUES (7833, 'loki.distributor', 'zh', 'loki.distributor', '经销商', '', '2023-02-01 03:14:33', 415); +INSERT INTO `sys_i18n` VALUES (7834, 'loki.queryScheduler', 'en', 'loki.queryScheduler', 'Query scheduler', '', '2023-02-01 03:26:20', 415); +INSERT INTO `sys_i18n` VALUES (7835, 'loki.queryScheduler', 'zh', 'loki.queryScheduler', '查询调度程序', '', '2023-02-01 03:26:37', 415); +INSERT INTO `sys_i18n` VALUES (7836, 'loki.ingesterQuerier', 'en', 'loki.ingesterQuerier', 'Ingester querier', '', '2023-02-01 03:37:45', 415); +INSERT INTO `sys_i18n` VALUES (7837, 'loki.ingesterQuerier', 'zh', 'loki.ingesterQuerier', '摄取查询器', '', '2023-02-01 03:38:10', 415); +INSERT INTO `sys_i18n` VALUES (7838, 'dashboard.dashboard.chartForm.rightYAxis', 'en', 'dashboard.dashboard.chartForm.rightYAxis', 'Right Y Axis', '', '2023-02-01 08:06:55', 407); +INSERT INTO `sys_i18n` VALUES (7839, 'dashboard.dashboard.chartForm.rightYAxis', 'zh', 'dashboard.dashboard.chartForm.rightYAxis', '右Y轴', '', '2023-02-01 08:07:11', 407); +INSERT INTO `sys_i18n` VALUES (7840, 'cortex.compactor', 'en', 'cortex.compactor', 'Compactor', '', '2023-02-02 08:11:39', 415); +INSERT INTO `sys_i18n` VALUES (7841, 'cortex.compactor', 'zh', 'cortex.compactor', '紧密器', '', '2023-02-02 08:11:59', 415); +INSERT INTO `sys_i18n` VALUES (7842, 'dashboard.dashboard.chartForm.sparklineMode', 'en', 'dashboard.dashboard.chartForm.sparklineMode', 'Sparkline mode', '', '2023-02-08 09:59:39', 407); +INSERT INTO `sys_i18n` VALUES (7843, 'dashboard.dashboard.chartForm.sparklineMode', 'zh', 'dashboard.dashboard.chartForm.sparklineMode', '趋势图模式', '', '2023-02-10 06:04:25', 407); +INSERT INTO `sys_i18n` VALUES (7844, 'overall.diagnosis', 'en', 'overall.diagnosis', 'Diagnosis', '', '2023-02-09 08:03:29', 415); +INSERT INTO `sys_i18n` VALUES (7845, 'overall.diagnosis', 'zh', 'overall.diagnosis', '诊断', '', '2023-02-09 08:03:50', 415); +INSERT INTO `sys_i18n` VALUES (7846, 'overall.serviceTime', 'en', 'overall.serviceTime', 'Service time', '', '2023-02-13 07:04:35', 415); +INSERT INTO `sys_i18n` VALUES (7847, 'overall.serviceTime', 'zh', 'overall.serviceTime', '用时', '', '2023-02-13 07:04:51', 415); +INSERT INTO `sys_i18n` VALUES (7848, '612022', 'en', 'TERMINAL_MKDIR_DIR_ALREADY_EXISTS', 'The specified file name already exists, please enter another name.', '', '2023-02-15 07:37:08', 1); +INSERT INTO `sys_i18n` VALUES (7849, '612022', 'zh', 'TERMINAL_MKDIR_DIR_ALREADY_EXISTS', '指定的文件名已存在,请输入其他名称。', '', '2023-02-15 07:37:19', 1); +INSERT INTO `sys_i18n` VALUES (7850, '616023', 'en', 'TERMINAL_LS_FOLDER_ERROR', 'Cannot display remote folder', '', '2023-02-15 08:36:34', 1); +INSERT INTO `sys_i18n` VALUES (7851, '616023', 'zh', 'TERMINAL_LS_FOLDER_ERROR', '无法显示远程文件夹', '', '2023-02-15 08:36:47', 1); +INSERT INTO `sys_i18n` VALUES (7852, 'dashboard.dashboard.chartForm.statisticsVal.first*', 'en', 'dashboard.dashboard.chartForm.statisticsVal.first*', 'First *', '', '2023-02-16 06:22:13', 407); +INSERT INTO `sys_i18n` VALUES (7853, 'dashboard.dashboard.chartForm.statisticsVal.first*', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.first*', '第一个非空值', '', '2023-02-16 06:22:32', 407); +INSERT INTO `sys_i18n` VALUES (7854, 'dashboard.dashboard.chartForm.statisticsVal.last*', 'en', 'dashboard.dashboard.chartForm.statisticsVal.last*', 'Last *', '', '2023-02-16 06:23:29', 407); +INSERT INTO `sys_i18n` VALUES (7855, 'dashboard.dashboard.chartForm.statisticsVal.last*', 'zh', 'dashboard.dashboard.chartForm.statisticsVal.last*', '最后一个非空值', '', '2023-02-16 06:23:20', 407); +INSERT INTO `sys_i18n` VALUES (7856, '618024', 'en', 'TERMINAL_DUPLICATE_SESSION_FAILED', 'Duplicate session failed.', '', '2023-02-16 09:00:19', 1); +INSERT INTO `sys_i18n` VALUES (7857, '618024', 'zh', 'TERMINAL_DUPLICATE_SESSION_FAILED', '重复会话失败', '', '2023-02-16 09:00:33', 1); +INSERT INTO `sys_i18n` VALUES (7858, '618025', 'en', 'TERMINAL_STOP_SESSION_FAILED', 'Failed to stop session', '', '2023-02-17 02:04:52', 1); +INSERT INTO `sys_i18n` VALUES (7859, '618025', 'zh', 'TERMINAL_STOP_SESSION_FAILED', '停止会话失败', '', '2023-02-17 02:05:13', 1); +INSERT INTO `sys_i18n` VALUES (7860, '761000', 'en', 'INT_MODULE_ID_ISNULL', 'integration module id can not be null', '', '2023-02-17 08:16:10', 414); +INSERT INTO `sys_i18n` VALUES (7861, '761000', 'zh', 'INT_MODULE_ID_ISNULL', '集成模块 id 不能为空', '', '2023-02-17 08:16:14', 414); +INSERT INTO `sys_i18n` VALUES (7862, '761001', 'en', 'INT_MODULE_NOT_FOUNT', 'integration module not fount', '', '2023-02-17 08:16:22', 414); +INSERT INTO `sys_i18n` VALUES (7863, '761001', 'zh', 'INT_MODULE_NOT_FOUNT', '集成模块不存在', '', '2023-02-17 08:16:25', 414); +INSERT INTO `sys_i18n` VALUES (7864, 'integration', 'en', 'integration', 'Integration', '', '2023-02-20 07:32:45', 1); +INSERT INTO `sys_i18n` VALUES (7865, 'integration', 'zh', 'integration', '集成', '', '2023-02-20 07:32:50', 1); +INSERT INTO `sys_i18n` VALUES (7866, 'integration.internal', 'en', 'integration.internal', 'internal', '', '2023-02-20 07:33:05', 1); +INSERT INTO `sys_i18n` VALUES (7867, 'integration.internal', 'zh', 'integration.internal', '内置', '', '2023-02-20 07:33:15', 1); +INSERT INTO `sys_i18n` VALUES (7868, 'integration.availableIntegration', 'en', 'integration.availableIntegration', 'Available Integration', '', '2023-02-20 07:35:11', 1); +INSERT INTO `sys_i18n` VALUES (7869, 'integration.availableIntegration', 'zh', 'integration.availableIntegration', '可用的集成', '', '2023-02-20 07:35:30', 1); +INSERT INTO `sys_i18n` VALUES (7870, 'project.topology.addNode', 'en', 'project.topology.addNode', 'Add elements', 'project 编辑 添加 node title', '2023-03-07 08:40:53', 1); +INSERT INTO `sys_i18n` VALUES (7871, 'project.topology.addNode', 'zh', 'project.topology.addNode', '添加节点', '', '2023-02-23 08:44:25', 403); +INSERT INTO `sys_i18n` VALUES (7872, 'project.topology.thumbnail', 'en', 'project.topology.thumbnail', 'Thumbnail', 'projet topo 编辑 小地图', '2023-02-23 08:53:48', 403); +INSERT INTO `sys_i18n` VALUES (7873, 'project.topology.thumbnail', 'zh', 'project.topology.thumbnail', '缩略图', 'projet topo 编辑 小地图', '2023-02-23 08:54:43', 403); +INSERT INTO `sys_i18n` VALUES (7874, 'project.topology.element', 'zh', 'project.topology.element', '元素', 'projet topo 编辑 元素选项', '2023-02-23 09:02:19', 403); +INSERT INTO `sys_i18n` VALUES (7875, 'project.topology.element', 'en', 'project.topology.element', 'Element', 'projet topo 编辑 元素选项', '2023-02-23 09:02:25', 403); +INSERT INTO `sys_i18n` VALUES (7876, 'project.topology.canvas', 'en', 'project.topology.canvas', 'Canvas', 'projet topo 编辑 画布选项', '2023-02-23 09:00:28', 403); +INSERT INTO `sys_i18n` VALUES (7877, 'project.topology.canvas', 'zh', 'project.topology.canvas', '画布', 'projet topo 编辑 画布选项', '2023-02-23 09:00:38', 403); +INSERT INTO `sys_i18n` VALUES (7878, 'project.topology.elements', 'en', 'project.topology.elements', 'Elements', 'projetc topo 编辑 画布 所有元素', '2023-02-23 09:03:20', 403); +INSERT INTO `sys_i18n` VALUES (7879, 'project.topology.image', 'en', 'project.topology.image', 'Image', '', '2023-02-23 09:07:24', 403); +INSERT INTO `sys_i18n` VALUES (7880, 'project.topology.image', 'zh', 'project.topology.image', '图片', '', '2023-02-23 09:07:36', 403); +INSERT INTO `sys_i18n` VALUES (7881, 'project.topology.elements', 'zh', 'project.topology.elements', '所有元素', 'projetc topo 编辑 画布 所有元素', '2023-02-23 09:11:40', 403); +INSERT INTO `sys_i18n` VALUES (7882, 'project.topology.timeRange', 'zh', 'project.topology.timeRange', '时间范围', 'projetc topo 编辑 数据 timeRange', '2023-02-23 09:12:06', 403); +INSERT INTO `sys_i18n` VALUES (7883, 'project.topology.timeRange', 'en', 'project.topology.timeRange', 'Time range', 'projetc topo 编辑 数据 timeRange', '2023-02-23 09:12:21', 403); +INSERT INTO `sys_i18n` VALUES (7884, 'project.topology.position', 'en', 'project.topology.position', 'Position', '监控/应用组/画布属性位置', '2023-02-23 09:13:04', 403); +INSERT INTO `sys_i18n` VALUES (7885, 'project.topology.position', 'zh', 'project.topology.position', '位置', '监控/应用组/画布属性位置', '2023-02-23 09:16:53', 403); +INSERT INTO `sys_i18n` VALUES (7886, 'project.topology.lockRatio', 'en', 'project.topology.lockRatio', 'Lock aspect ratio', '监控/应用组/画布属性 锁定比例', '2023-02-28 06:05:10', 403); +INSERT INTO `sys_i18n` VALUES (7887, 'project.topology.lockRatio', 'zh', 'project.topology.lockRatio', '锁定比例', '监控/应用组/画布属性 锁定比例', '2023-02-28 06:05:14', 403); +INSERT INTO `sys_i18n` VALUES (7888, 'project.topology.border', 'en', 'project.topology.border', 'Border', '', '2023-02-23 09:21:14', 403); +INSERT INTO `sys_i18n` VALUES (7889, 'project.topology.border', 'zh', 'project.topology.border', '边框', '监控/应用组/画布属性 边框', '2023-02-23 09:21:43', 403); +INSERT INTO `sys_i18n` VALUES (7890, 'project.topology.radius', 'en', 'project.topology.radius', 'Radius', '', '2023-02-23 09:23:18', 403); +INSERT INTO `sys_i18n` VALUES (7891, 'project.topology.radius', 'zh', 'project.topology.radius', '边框圆角', '监控/应用组/画布属性 边框圆角', '2023-02-23 09:23:52', 403); +INSERT INTO `sys_i18n` VALUES (7892, 'project.topology.opacity', 'en', 'project.topology.opacity', 'Opacity', '', '2023-02-23 09:34:02', 403); +INSERT INTO `sys_i18n` VALUES (7893, 'project.topology.opacity', 'zh', 'project.topology.opacity', '透明度', 'project topo 编辑 节点属性', '2023-02-23 09:34:22', 403); +INSERT INTO `sys_i18n` VALUES (7894, 'project.topology.imageRatio', 'en', 'project.topology.imageRatio', 'Image ratio', '', '2023-02-23 09:36:46', 403); +INSERT INTO `sys_i18n` VALUES (7895, 'project.topology.imageRatio', 'zh', 'project.topology.imageRatio', '图片保留长宽比', 'project topo 编辑 节点属性', '2023-02-23 09:37:09', 403); +INSERT INTO `sys_i18n` VALUES (7896, 'project.topology.borderColor', 'en', 'project.topology.borderColor', 'Border color', '', '2023-02-23 09:45:43', 403); +INSERT INTO `sys_i18n` VALUES (7897, 'project.topology.borderColor', 'zh', 'project.topology.borderColor', '边框颜色', 'project topo 编辑 节点属性', '2023-02-23 09:46:09', 403); +INSERT INTO `sys_i18n` VALUES (7898, 'project.topology.borderWidth', 'en', 'project.topology.borderWidth', 'Border width', '', '2023-02-23 09:46:35', 403); +INSERT INTO `sys_i18n` VALUES (7899, 'project.topology.borderWidth', 'zh', 'project.topology.borderWidth', '边框宽度', 'project topo 编辑 节点属性', '2023-02-23 09:46:47', 403); +INSERT INTO `sys_i18n` VALUES (7900, 'project.topology.animate', 'zh', 'project.topology.animate', '动画', '监控/应用组/画布属性', '2023-02-23 09:47:45', 403); +INSERT INTO `sys_i18n` VALUES (7901, 'project.topology.animate', 'en', 'project.topology.animate', 'Animate', '监控/应用组/画布属性', '2023-02-23 09:48:00', 403); +INSERT INTO `sys_i18n` VALUES (7902, 'project.topology.speed', 'en', 'project.topology.speed', 'Speed', '监控/应用组/画布属性', '2023-02-23 09:48:58', 403); +INSERT INTO `sys_i18n` VALUES (7903, 'project.topology.speed', 'zh', 'project.topology.speed', '速度', '监控/应用组/画布属性', '2023-02-23 09:49:08', 403); +INSERT INTO `sys_i18n` VALUES (7904, 'project.topology.reverse', 'en', 'project.topology.reverse', 'Reverse', '监控/应用组/画布属性', '2023-02-23 09:50:08', 403); +INSERT INTO `sys_i18n` VALUES (7905, 'project.topology.reverse', 'zh', 'project.topology.reverse', '反向流动', '监控/应用组/画布属性', '2023-02-23 09:50:49', 403); +INSERT INTO `sys_i18n` VALUES (7906, 'project.topology.tooltip', 'en', 'project.topology.tooltip', 'Tooltip', '监控/应用组/画布属性', '2023-02-23 09:53:12', 403); +INSERT INTO `sys_i18n` VALUES (7907, 'project.topology.tooltip', 'zh', 'project.topology.tooltip', '提示气泡', '监控/应用组/画布属性', '2023-02-23 09:53:45', 403); +INSERT INTO `sys_i18n` VALUES (7908, 'project.topology.legends', 'en', 'project.topology.legends', 'Legends', '监控/应用组/画布属性', '2023-02-23 09:55:27', 403); +INSERT INTO `sys_i18n` VALUES (7909, 'project.topology.legends', 'zh', 'project.topology.legends', '图例', '监控/应用组/画布属性', '2023-02-23 09:56:22', 403); +INSERT INTO `sys_i18n` VALUES (7910, 'overall.undo', 'en', 'overall.undo', 'Undo', '', '2023-02-27 05:59:28', 403); +INSERT INTO `sys_i18n` VALUES (7911, 'overall.undo', 'zh', 'overall.undo', '撤销', '', '2023-02-27 05:59:47', 403); +INSERT INTO `sys_i18n` VALUES (7912, 'integration.talonRemark', 'zh', 'integration.talonRemark', '官方提供标准的采集器,用来从你的系统和应用程序中收集各种指标和日志类集成数据', '', '2023-02-27 09:02:16', 407); +INSERT INTO `sys_i18n` VALUES (7913, 'integration.talonRemark', 'en', 'integration.talonRemark', 'The official provided standard collector,used to collect to collect metrics and log class integration data from your system and applications', '', '2023-02-27 09:25:01', 407); +INSERT INTO `sys_i18n` VALUES (7914, 'integration.manualInstallation', 'en', 'integration.manualInstallation', 'Manual installation', '', '2023-02-28 02:01:33', 407); +INSERT INTO `sys_i18n` VALUES (7915, 'integration.manualInstallation', 'zh', 'integration.manualInstallation', '手动安装', '', '2023-02-27 09:25:56', 407); +INSERT INTO `sys_i18n` VALUES (7916, 'integration.automaticInstallation', 'en', 'integration.automaticInstallation', 'Automatic installation', '', '2023-02-28 02:01:27', 407); +INSERT INTO `sys_i18n` VALUES (7917, 'integration.automaticInstallation', 'zh', 'integration.automaticInstallation', '自动安装', '', '2023-02-27 09:27:31', 407); +INSERT INTO `sys_i18n` VALUES (7918, 'integration.downloadTalon', 'en', 'integration.downloadTalon', 'Download NZ-TALON installation package', '', '2023-02-27 09:29:37', 407); +INSERT INTO `sys_i18n` VALUES (7919, 'integration.downloadTalon', 'zh', 'integration.downloadTalon', '下载NZ-TALON安装包', '', '2023-02-27 09:29:58', 407); +INSERT INTO `sys_i18n` VALUES (7920, 'integration.uploadTalon', 'en', 'integration.uploadTalon', 'To upload the installation package to the target asset, run the following command', '', '2023-02-27 09:33:47', 407); +INSERT INTO `sys_i18n` VALUES (7921, 'integration.uploadTalon', 'zh', 'integration.uploadTalon', '将安装包上传到目标资产,执行以下命令', '', '2023-02-27 09:34:52', 407); +INSERT INTO `sys_i18n` VALUES (7922, 'integration.installed', 'en', 'integration.installed', 'After the installation is complete, run the following command to obtain the NZ-TALON token', '', '2023-02-27 09:36:55', 407); +INSERT INTO `sys_i18n` VALUES (7923, 'integration.installed', 'zh', 'integration.installed', '成功安装后通过以下命令获取NZ-TALON token', '', '2023-02-27 09:37:22', 407); +INSERT INTO `sys_i18n` VALUES (7924, 'integration.editAsset', 'en', 'integration.editAsset', 'Edit assets The NZ-TALON configuration is complete', '', '2023-02-27 09:39:07', 407); +INSERT INTO `sys_i18n` VALUES (7925, 'integration.editAsset', 'zh', 'integration.editAsset', '编辑资产完成NZ-TALON配置', '', '2023-02-27 09:39:24', 407); +INSERT INTO `sys_i18n` VALUES (7926, 'integration.enableTalon', 'en', 'integration.enableTalon', 'Enable NZ-TALON', '', '2023-02-27 09:40:32', 407); +INSERT INTO `sys_i18n` VALUES (7927, 'integration.enableTalon', 'zh', 'integration.enableTalon', '开启NZ-TALON', '', '2023-02-27 09:46:10', 407); +INSERT INTO `sys_i18n` VALUES (7928, 'integration.enterToken', 'en', 'integration.enterToken', 'Enter the token obtained in the previous step', '', '2023-02-27 09:41:38', 407); +INSERT INTO `sys_i18n` VALUES (7929, 'integration.enterToken', 'zh', 'integration.enterToken', '输入上一步获取的token', '', '2023-02-27 09:41:57', 407); +INSERT INTO `sys_i18n` VALUES (7930, 'integration.enterPort', 'en', 'integration.enterPort', 'Enter port(default:10092)', '', '2023-02-27 09:44:45', 407); +INSERT INTO `sys_i18n` VALUES (7931, 'integration.enterPort', 'zh', 'integration.enterPort', '输入端口(默认:10092)', '', '2023-02-27 09:44:11', 407); +INSERT INTO `sys_i18n` VALUES (7932, 'integration.newInstallation', 'en', 'integration.newInstallation', 'New installation', '', '2023-02-27 09:48:45', 407); +INSERT INTO `sys_i18n` VALUES (7933, 'integration.newInstallation', 'zh', 'integration.newInstallation', '新安装', '', '2023-02-27 09:49:07', 407); +INSERT INTO `sys_i18n` VALUES (7934, 'integration.upgradeInstallation', 'en', 'integration.upgradeInstallation', 'Upgrade installation', '', '2023-02-27 09:50:00', 407); +INSERT INTO `sys_i18n` VALUES (7935, 'integration.upgradeInstallation', 'zh', 'integration.upgradeInstallation', '升级安装', '', '2023-02-27 09:50:26', 407); +INSERT INTO `sys_i18n` VALUES (7936, 'integration.newUpgrade', 'en', 'integration.newUpgrade', 'New/Upgrade installation', '', '2023-02-28 02:01:53', 407); +INSERT INTO `sys_i18n` VALUES (7937, 'integration.newUpgrade', 'zh', 'integration.newUpgrade', '新/升级 安装', '', '2023-02-27 09:54:33', 407); +INSERT INTO `sys_i18n` VALUES (7938, 'integration.selectAsset', 'en', 'integration.selectAsset', 'Select target asset', '', '2023-02-27 09:56:01', 407); +INSERT INTO `sys_i18n` VALUES (7939, 'integration.selectAsset', 'zh', 'integration.selectAsset', '选择目标资产', '', '2023-02-27 09:56:25', 407); +INSERT INTO `sys_i18n` VALUES (7940, 'integration.loginAsset', 'en', 'integration.loginAsset', 'Log in to the target asset and run the following command', '', '2023-03-01 01:23:11', 407); +INSERT INTO `sys_i18n` VALUES (7941, 'integration.loginAsset', 'zh', 'integration.loginAsset', '登录目标资产,执行以下命令', '', '2023-03-01 01:23:29', 407); +INSERT INTO `sys_i18n` VALUES (7942, 'integration.autoRemark', 'en', 'integration.autoRemark', 'Command to automatically download installation files and install software. During the initial installation, NZ-TALON information is automatically registered', '', '2023-02-27 10:00:42', 407); +INSERT INTO `sys_i18n` VALUES (7943, 'integration.autoRemark', 'zh', 'integration.autoRemark', '命令实现自动下载安装文件和软件安装,初次安装时会自动完成NZ-TALON信息注册', '', '2023-02-27 10:01:17', 407); +INSERT INTO `sys_i18n` VALUES (7944, 'project.topology.up', 'zh', 'project.topology.up', '上一层', '监控/应用组/画布属性', '2023-02-28 02:27:12', 403); +INSERT INTO `sys_i18n` VALUES (7945, 'project.topology.up', 'en', 'project.topology.up', 'Up', '监控/应用组/画布属性', '2023-02-28 02:27:22', 403); +INSERT INTO `sys_i18n` VALUES (7946, 'project.topology.down', 'en', 'project.topology.down', 'Down', '监控/应用组/画布属性', '2023-02-28 02:27:37', 403); +INSERT INTO `sys_i18n` VALUES (7947, 'project.topology.down', 'zh', 'project.topology.down', '下一层', '监控/应用组/画布属性', '2023-02-28 02:27:48', 403); +INSERT INTO `sys_i18n` VALUES (7948, 'overall.addTooltipLegend', 'en', 'overall.addTooltipLegend', 'Add legend', '', '2023-02-28 02:32:50', 403); +INSERT INTO `sys_i18n` VALUES (7949, 'overall.addTooltipLegend', 'zh', 'overall.addTooltipLegend', '添加图例', 'project topo element 添加图例', '2023-02-28 02:33:21', 403); +INSERT INTO `sys_i18n` VALUES (7950, 'overall.tempImport', 'en', 'overall.tempImport', 'Template import', '', '2023-03-06 03:44:58', 407); +INSERT INTO `sys_i18n` VALUES (7951, 'overall.tempImport', 'zh', 'overall.tempImport', '模板导入', '', '2023-03-06 03:45:07', 407); SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/R__AZ_sys_menu.sql b/nz-admin/src/main/resources/db/R__AZ_sys_menu.sql index d61a2be4..0d4ad39e 100644 --- a/nz-admin/src/main/resources/db/R__AZ_sys_menu.sql +++ b/nz-admin/src/main/resources/db/R__AZ_sys_menu.sql @@ -6,7 +6,7 @@ delete from sys_menu; -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (1, 'dashboard', 'dashboard', 'dashboard.title', 0, '', 1, '/panel', 1, 'nz-icon nz-icon-menu-dashboard', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (1, 'dashboard', 'dashboard', 'dashboard.title', 0, '', 1, '/dashboard', 1, 'nz-icon nz-icon-menu-dashboard', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (4, 'explore', 'explore', 'dashboard.metricPreview.title', 6, '', 1, '/explore', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (5, 'asset', 'asset', 'overall.assetList', 2147, '', 1, '/asset', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (6, 'monitor', 'monitor', 'overall.monitor', 0, '', 1, '', 3, 'nz-icon nz-icon-menu-project', '', 1); @@ -24,11 +24,11 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (18, 'Terminal log', 'terminalLog', 'config.terminallog.terminallog', 2229, '', 1, '/terminalLog', 12, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (19, 'operationLog', 'operationLog', 'config.operationlog.operationlog', 2229, '', 1, '/operationLog', 9, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (20, 'about', 'about', 'overall.about', 0, '', 1, '/about', 99, 'nz-icon nz-icon-about', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (21, 'Backup', 'backup', 'Backup', 2149, '', 1, '/backup', 7, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (301, 'Main Add ', 'main_add', 'buttons.add', 1, 'visual:panel:save,visual:chart:save', 2, '', 10, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (302, 'Main Edit ', 'main_edit', 'buttons.edit', 1, 'visual:panel:update,visual:chart:update', 2, '', 15, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (303, 'Main Delete', 'main_delete', 'buttons.delete', 1, 'visual:panel:delete,visual:chart:delete', 2, '', 20, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (312, 'Main View', 'panel_view', 'buttons.view', 1, '', 2, '', 5, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (21, 'Backup', 'backup', 'Backup', 2149, '', 1, '/backup', 7, '', '', 0); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (301, 'Main Add ', 'main_add', 'buttons.add', 1, 'visual:dashboard:save,visual:chart:save', 2, '', 10, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (302, 'Main Edit ', 'main_edit', 'buttons.edit', 1, 'visual:dashboard:update,visual:chart:update', 2, '', 15, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (303, 'Main Delete', 'main_delete', 'buttons.delete', 1, 'visual:dashboard:delete,visual:chart:delete', 2, '', 20, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (312, 'Main View', 'dashboard_view', 'buttons.view', 1, '', 2, '', 5, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (501, 'Add asset', 'asset_add', 'buttons.add', 5, 'asset:save', 2, '', 10, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (502, 'Edit asset', 'asset_edit', 'buttons.edit', 5, 'asset:update', 2, '', 15, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (504, 'asset_delete', 'asset_delete', 'buttons.delete', 5, 'asset:delete', 2, '', 25, '', '', 1); @@ -44,6 +44,7 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (622, 'monitor_module_add', 'monitor_module_add', 'buttons.add', 2145, 'module:save', 2, '', 10, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (623, 'project_view', 'project_view', 'buttons.view', 2144, '', 2, '', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (801, 'Expire message', 'alertMessage_expired', 'buttons.expired', 8, '', 2, '', 10, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (802, 'Delete message', 'alertMessage_delete', 'buttons.delete', 8, 'alert:message:delete', 2, '', 6, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (803, 'View message', 'alertMessage_view', 'buttons.view', 8, '', 2, '', 5, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (901, 'Add rule', 'alertRule_add', 'buttons.add', 9, 'alert:rule:save', 2, '', 10, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (902, 'Edit rule', 'alertRule_edit', 'buttons.edit', 9, 'alert:rule:update', 2, '', 15, '', '', 1); @@ -89,7 +90,7 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2115, 'View alert silence', 'alertSilence_view', 'buttons.view', 2114, '', 2, '', 3, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2116, 'Add alert silence', 'alertSilence_add', 'buttons.add', 2114, 'alert:silence:save', 2, '', 5, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2117, 'Edit alert silence', 'alertSilence_edit', 'buttons.edit', 2114, 'alert:silence:update', 2, '', 6, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2118, 'expressionTemplate', 'exprTemp', 'overall.exprTemp', 2180, '', 1, '/exprTemp', 2, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2118, 'expressionTemplate', 'exprTemp', 'overall.exprTemp', 2180, '', 1, '/exprTemp', 3, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2120, 'Edit expression template', 'expressionTemplate_edit', 'buttons.edit', 2118, 'expression:tmpl:update', 2, '', 15, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2121, 'Delete expression template', 'expressionTemplate_delete', 'buttons.delete', 2118, 'expression:tmpl:delete', 2, '', 20, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2122, 'View expression template', 'expressionTemplate_view', 'buttons.view', 2118, '', 2, '', 1, '', '', 1); @@ -119,7 +120,7 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2166, 'Credentials', 'snmp_mib_credentials', 'config.mib.credentials', 16, '', 1, '/credentials', 2, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2176, 'endpointList', 'endpoint_list', 'buttons.view', 2146, '', 2, '', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2180, 'template', 'template', 'overall.template', 10, '', 1, '/template', 4, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2181, 'chartTemp', 'config_chart_temp', 'overall.chartTemp', 2180, '', 1, '/chartTemp', 1, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2181, 'chartTemp', 'config_chart_temp', 'overall.chartTemp', 2180, '', 1, '/chartTemp', 2, '', '', 0); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2182, 'bbuttons.system.reset', 'system_reset_reset', 'system.reset.reset', 2214, 'sys:config:reset', 2, '', 0, '', '', 0); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2187, 'apiKey', 'apiKey', 'system.apikey.apiKey', 2149, '', 1, '/apiKey', 5, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2188, 'buttons.system.apikey.add', 'system_apiKey_add', 'buttons.add', 2187, 'sys:apiKey:save', 2, '', 2, '', '', 1); @@ -139,7 +140,7 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2209, 'basic', 'basic', 'buttons.basic', 17, '', 3, '', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2210, 'monitor', 'system_monitor', 'buttons.system.monitor', 10, '', 1, '/monitor', 6, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2211, 'email', 'email', 'buttons.system.email', 2230, '', 1, '/email', 1, '', '', 1); -INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2212, 'terminal', 'terminal', 'buttons.system.terminal', 10, '', 1, '/terminal', 8, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2212, 'terminal', 'terminal', 'buttons.system.terminal', 10, '', 1, '/terminalSetting', 8, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2213, 'LDAP', 'LDAP', 'buttons.system.ldap', 2149, '', 1, '/ldap', 4, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2214, 'reset', 'reset', 'system.reset.reset', 17, '', 3, '', 9, '', '', 0); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2215, 'license', 'license', 'config.system.license.license', 2149, '', 1, '/license', 6, '', '', 1); @@ -172,3 +173,11 @@ INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2266, 'Issue record Edit', 'issue_record_edit', 'buttons.edit', 2264, '', 2, '', 3, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2267, 'Issue record View', 'issue_record_view', 'buttons.view', 2264, '', 2, '', 1, '', '', 1); INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2268, 'Issue record Delete', 'issue_record_delete', 'buttons.delete', 2264, '', 2, '', 4, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2270, 'backup_download', 'backup_download', 'overall.download', 21, '', 2, '', 1, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2271, 'backup_restore', 'backup_restore', 'backup.RestoreNow', 21, '', 2, '', 2, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2272, 'backup_del', 'backup_del', 'buttons.delete', 21, '', 2, '', 3, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2273, 'dashboardTemplate', 'dashboard_template', 'overall.dashboardTemplate', 2180, '', 1, '/dashboardTemp', 1, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2274, 'Dashboard Temp Add', 'dashboard_temp_add', 'buttons.add', 2273, '', 2, '', 2, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2275, 'Dashboard Temp Edit', 'dashboard_temp_edit', 'buttons.edit', 2273, '', 2, '', 3, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2276, 'Dashboard Temp View', 'dashboard_temp_view', 'buttons.view', 2273, '', 2, '', 1, '', '', 1); +INSERT INTO `sys_menu`(`id`, `name`, `code`, `i18n`, `parent_id`, `perms`, `type`, `route`, `order_num`, `icon`, `required`, `state`) VALUES (2277, 'Dashboard Temp Delete', 'dashboard_temp_delete', 'buttons.delete', 2273, '', 2, '', 4, '', '', 1); diff --git a/nz-admin/src/main/resources/db/R__AZ_sys_role_menu.sql b/nz-admin/src/main/resources/db/R__AZ_sys_role_menu.sql index 1be9a1cc..bd1403f3 100644 --- a/nz-admin/src/main/resources/db/R__AZ_sys_role_menu.sql +++ b/nz-admin/src/main/resources/db/R__AZ_sys_role_menu.sql @@ -45,6 +45,7 @@ INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 609); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 610); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 611); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 803); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 802); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 801); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 910); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 901); @@ -130,6 +131,13 @@ INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2265); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2266); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2267); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2268); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2274); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2275); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2276); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2277); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2270); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2271); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 1, 2272); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 312); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 4); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 529); @@ -160,3 +168,4 @@ INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 2246); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 2253); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 2261); INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 2267); +INSERT INTO `sys_role_menu`(`id`, `role_id`, `menu_id`) VALUES (null, 2, 2276); diff --git a/nz-admin/src/main/resources/db/V2022.11.04__modify_asset_asset_ipmi.sql b/nz-admin/src/main/resources/db/V2022.11.04__modify_asset_asset_ipmi.sql new file mode 100644 index 00000000..bdc9c12b --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.04__modify_asset_asset_ipmi.sql @@ -0,0 +1,13 @@ +/** + 1. asset_asset add column ipmi_ip + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + + +ALTER TABLE `asset_asset` + ADD COLUMN IF NOT EXISTS `ipmi_ip` VARCHAR(64) NOT NULL DEFAULT ''; + + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.11.14__create_table_terminal_sftp_log.sql b/nz-admin/src/main/resources/db/V2022.11.14__create_table_terminal_sftp_log.sql new file mode 100644 index 00000000..7bcd3f52 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.14__create_table_terminal_sftp_log.sql @@ -0,0 +1,21 @@ +/** + 1.create table terminal_sftp_log + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for terminal_sftp_log +-- ---------------------------- +DROP TABLE IF EXISTS `terminal_sftp_log`; +CREATE TABLE `terminal_sftp_log` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `uuid` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'session uuid', + `type` int(10) NOT NULL COMMENT '1: 上传文件 2:下载文件 3:新建文件夹 4:删除文件', + `name` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '文件名', + `ts` bigint(20) NOT NULL COMMENT '单位:ms', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.11.15__modify_visual_panel_vartype.sql b/nz-admin/src/main/resources/db/V2022.11.15__modify_visual_panel_vartype.sql new file mode 100644 index 00000000..539eb41f --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.15__modify_visual_panel_vartype.sql @@ -0,0 +1,14 @@ +/** + 1. visual_panel add column var_type, tmpl_id + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + + +ALTER TABLE `visual_panel` + ADD COLUMN IF NOT EXISTS `var_type` INT(10) NOT NULL DEFAULT '0' COMMENT '模板或使用模板创建有效\r\n0: none\r\n1: asset\r\n2: endpoint', + ADD COLUMN IF NOT EXISTS `tmpl_id` INT(10) NOT NULL DEFAULT '-1' COMMENT '默认:-1\r\n模板创建有效,关联 visual_panel.id'; + + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.11.16__table_vsys_result_add_req_param_col.sql b/nz-admin/src/main/resources/db/V2022.11.16__table_vsys_result_add_req_param_col.sql new file mode 100644 index 00000000..511fb1f6 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.16__table_vsys_result_add_req_param_col.sql @@ -0,0 +1,17 @@ +/** + + 1. vsys_result 新增 req_param 列, 该内容包含 sf ruleSet chain 三个接口请求参数记录 + 2. vsys_task device_tag 字段调整长度 + + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +ALTER TABLE `vsys_result` +ADD COLUMN IF NOT EXISTS `req_param` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '接口请求参数'; + +ALTER TABLE `vsys_task` +MODIFY COLUMN `device_tag` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '设备组'; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.11.18__modify_asset_model_panelid.sql b/nz-admin/src/main/resources/db/V2022.11.18__modify_asset_model_panelid.sql new file mode 100644 index 00000000..740e2ef6 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.18__modify_asset_model_panelid.sql @@ -0,0 +1,16 @@ +/** + 1. asset_model add column panel_id + 2. monitor_module add column panel_id + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + + +ALTER TABLE `asset_model` + ADD COLUMN IF NOT EXISTS `panel_id` INT(10) COMMENT 'panel 模板id'; + +ALTER TABLE `monitor_module` + ADD COLUMN IF NOT EXISTS `panel_id` INT(10) COMMENT 'panel 模板id'; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.11.26__backup and modify asset_model table.sql b/nz-admin/src/main/resources/db/V2022.11.26__backup and modify asset_model table.sql new file mode 100644 index 00000000..7a8155db --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.11.26__backup and modify asset_model table.sql @@ -0,0 +1,20 @@ +/** + * 1. 备份并更新 asset_model + */ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- asset model +DROP TABLE IF EXISTS asset_model_V3_6; + +-- 复制表结构 +CREATE TABLE asset_model_V3_6 like asset_model; + +-- 复制表数据 +INSERT INTO asset_model_V3_6 select * from asset_model; + +-- 删除原来数据 +DELETE FROM asset_model; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/nz-admin/src/main/resources/db/V2022.12.07__table visual_panel data supplement default value.sql b/nz-admin/src/main/resources/db/V2022.12.07__table visual_panel data supplement default value.sql new file mode 100644 index 00000000..8032c083 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.12.07__table visual_panel data supplement default value.sql @@ -0,0 +1,6 @@ +/** + 1. supplement var_type default value + */ + +update visual_panel set var_type = 1 where type = 'asset'; +update visual_panel set var_type = 2 where type = 'endpoint'; diff --git a/nz-admin/src/main/resources/db/V2022.12.26__modify_terminal_record_structure.sql b/nz-admin/src/main/resources/db/V2022.12.26__modify_terminal_record_structure.sql new file mode 100644 index 00000000..4bef91a4 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2022.12.26__modify_terminal_record_structure.sql @@ -0,0 +1,11 @@ + +/** + 1. terminal_record add column storage_type & path + 2. terminal_record modify column content + */ + +ALTER TABLE `terminal_record` +ADD COLUMN IF NOT EXISTS `storage_type` int(1) NOT NULL DEFAULT 1 COMMENT '存储模式,1: 本地存储,2:S3对象存储', +ADD COLUMN IF NOT EXISTS `path` varchar(4096) DEFAULT NULL COMMENT 'S3对象存储时有效', +MODIFY COLUMN `content` MEDIUMBLOB NULL COMMENT '记录的是 session开始后的时间偏移量\r\n\r\n最大储存 65K,超过部分再新增一条记录'; + diff --git a/nz-admin/src/main/resources/db/V2023.01.11__modify_monitor_endpoint_state_structure.sql b/nz-admin/src/main/resources/db/V2023.01.11__modify_monitor_endpoint_state_structure.sql new file mode 100644 index 00000000..e835e116 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2023.01.11__modify_monitor_endpoint_state_structure.sql @@ -0,0 +1,8 @@ + +/** + 1. monitor_endpoint_state add column msg + */ + +ALTER TABLE `monitor_endpoint_state` +ADD COLUMN IF NOT EXISTS `msg` varchar(512) NOT NULL DEFAULT '' COMMENT '错误信息'; + diff --git a/nz-admin/src/main/resources/db/V2023.01.12__update assetInfo and endpointInfo chart name.sql b/nz-admin/src/main/resources/db/V2023.01.12__update assetInfo and endpointInfo chart name.sql new file mode 100644 index 00000000..9ddeee78 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2023.01.12__update assetInfo and endpointInfo chart name.sql @@ -0,0 +1,8 @@ + +/** + 1. update assetInfo and endpointInfo chart name + */ + +UPDATE visual_chart SET name = "Asset information" WHERE type = "assetInfo"; +UPDATE visual_chart SET name = "Endpoint information" WHERE type = "endpointInfo"; + diff --git a/nz-admin/src/main/resources/db/V2023.01.13__modify dashboard names for asset and endpoint types.sql b/nz-admin/src/main/resources/db/V2023.01.13__modify dashboard names for asset and endpoint types.sql new file mode 100644 index 00000000..8c651942 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2023.01.13__modify dashboard names for asset and endpoint types.sql @@ -0,0 +1,20 @@ + +/** + 1. modify dashboard names for asset and endpoint types + */ + +UPDATE visual_panel panel +LEFT JOIN asset_asset asset ON panel.link = asset.id +SET panel.name = asset.name +WHERE + panel.type = "asset" + AND asset.name IS NOT NULL; + + +UPDATE visual_panel panel +LEFT JOIN monitor_endpoint endpoint ON panel.link = endpoint.id +SET panel.name = endpoint.name +WHERE + panel.type = "endpoint" + AND endpoint.name IS NOT NULL; + diff --git a/nz-admin/src/main/resources/db/V2023.01.14__visual_panel renamed visual_dashboard.sql b/nz-admin/src/main/resources/db/V2023.01.14__visual_panel renamed visual_dashboard.sql new file mode 100644 index 00000000..60b3f817 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2023.01.14__visual_panel renamed visual_dashboard.sql @@ -0,0 +1,45 @@ + +/** + 1. visual_panel renamed visual_dashboard + 2. asset_model + 3. monitor_module + 4. visual_chart col and index + 5. sys_log + 6. sys_user_starred + 7. 对 V3_0 -> V3_2 Chart 升级表进行字段更改 table_name = visual_chart_v3_2 + */ + +DROP TABLE IF EXISTS visual_dashboard; + +-- 复制表结构 +CREATE TABLE visual_dashboard like visual_panel; + +-- 复制表数据 +INSERT INTO visual_dashboard SELECT * FROM visual_panel; + +-- 删除原来的表 +DROP TABLE IF EXISTS visual_panel; + + +-- 重命名字段 +ALTER TABLE `asset_model` CHANGE IF EXISTS `panel_id` `dashboard_id` INT(10) COMMENT 'dashboard 模板id'; + +ALTER TABLE `monitor_module` CHANGE IF EXISTS `panel_id` `dashboard_id` INT(10) COMMENT 'dashboard 模板id'; + +ALTER TABLE `visual_chart` CHANGE IF EXISTS `panel_id` `dashboard_id` int(10) NOT NULL COMMENT '图表 id,关联 dashboard 表 当 dashboard_id = 0 代表为模板'; + +-- 更新 visual_chart 索引 +DROP index IF EXISTS `idx_panel_id` ON `visual_chart`; +ALTER TABLE `visual_chart` ADD index IF NOT EXISTS `idx_dashboard_id` (`dashboard_id`); + + +-- sys_log & sys_user_starred +ALTER TABLE `sys_log` +MODIFY COLUMN `type` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '可选值\r\nasset\r\nendpoint\r\nproject\r\nmodule\r\nalert rule\r\nalert message\r\ndashboard\r\nchart\r\ndatacenter\r\ncabinet'; + +UPDATE `sys_log` SET type = "dashboard" WHERE type = "visual panel"; + +ALTER TABLE `sys_user_starred` +MODIFY COLUMN `type` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '可选值:datacenter,project,module,endpoint,alertRule,asset,dashboard,chart'; + +UPDATE `sys_user_starred` SET type = "dashboard" WHERE type = "panel"; diff --git a/nz-admin/src/main/resources/db/V2023.01.15__modify the device_tag column length of vsys_info table.sql b/nz-admin/src/main/resources/db/V2023.01.15__modify the device_tag column length of vsys_info table.sql new file mode 100644 index 00000000..53e6c738 --- /dev/null +++ b/nz-admin/src/main/resources/db/V2023.01.15__modify the device_tag column length of vsys_info table.sql @@ -0,0 +1,9 @@ +/** + + 1. modify the device_tag column length of vsys_info table + + */ + +ALTER TABLE `vsys_info` +MODIFY COLUMN `device_tag` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '设备组'; + diff --git a/nz-admin/src/main/resources/mapper/alert/AlertMessageHistoryPartitionManagementDao.xml b/nz-admin/src/main/resources/mapper/alert/AlertMessageHistoryPartitionManagementDao.xml index 6c478594..e4e7aa80 100644 --- a/nz-admin/src/main/resources/mapper/alert/AlertMessageHistoryPartitionManagementDao.xml +++ b/nz-admin/src/main/resources/mapper/alert/AlertMessageHistoryPartitionManagementDao.xml @@ -10,7 +10,7 @@ FROM INFORMATION_SCHEMA.PARTITIONS WHERE - TABLE_NAME = #{tableName} AND PARTITION_NAME != "" + TABLE_NAME = #{tableName} AND PARTITION_NAME != "" AND TABLE_SCHEMA = database() <if test="partitionNames != null and partitionNames.length > 0"> AND PARTITION_NAME IN <foreach item="item" collection="partitionNames" separator="," open="(" close=")" index=""> diff --git a/nz-admin/src/main/resources/mapper/asset/AssetAssetDao.xml b/nz-admin/src/main/resources/mapper/asset/AssetAssetDao.xml index 9ce2ce93..a418c058 100644 --- a/nz-admin/src/main/resources/mapper/asset/AssetAssetDao.xml +++ b/nz-admin/src/main/resources/mapper/asset/AssetAssetDao.xml @@ -12,6 +12,7 @@ <result property="cabinetStart" column="cabinet_start"/> <result property="cabinetEnd" column="cabinet_end"/> <result property="manageIp" column="manage_ip"/> + <result property="ipmiIp" column="ipmi_ip"/> <result property="purchaseDate" column="purchase_date"/> <result property="createAt" column="create_at"/> <result property="updateAt" column="update_at"/> @@ -75,7 +76,7 @@ </resultMap> - <resultMap type="com.nis.modules.panel.entity.VisualChart" id="chartIdWithAssetEntity"> + <resultMap type="com.nis.modules.dashboard.entity.VisualChart" id="chartIdWithAssetEntity"> <id property="id" column="chartId"/> <association property="asset" javaType="com.nis.modules.asset.entity.AssetAsset"> @@ -144,6 +145,10 @@ AND locate(#{params.manageIp} , asset.manage_ip) </if> + <if test="params.ipmiIp != null and params.ipmiIp != ''"> + AND locate(#{params.ipmiIp} , asset.ipmi_ip) + </if> + <if test="params.brandIds != null and params.brandIds.size > 0"> AND asset.brand_id IN <foreach collection="params.brandIds" item="brandId" index="no" open="(" separator="," close=")"> @@ -249,6 +254,9 @@ #{tmplId} </foreach> </if> + <if test="params.snmpEnable != null and params.snmpEnable != ''"> + AND type.snmp_enable = #{params.snmpEnable} + </if> </where> <if test="params.orderBy == null or params.orderBy == ''"> @@ -285,6 +293,9 @@ <if test="params.manageIp != null and params.manageIp != ''"> AND locate(#{params.manageIp} , asset.manage_ip) </if> + <if test="params.ipmiIp != null and params.ipmiIp != ''"> + AND locate(#{params.ipmiIp} , asset.ipmi_ip) + </if> <if test="params.brandIds != null and params.brandIds.size > 0"> AND asset.brand_id IN <foreach collection="params.brandIds" item="brandId" index="no" open="(" separator="," close=")"> @@ -412,33 +423,6 @@ </foreach> </update> - <select id="getAssetsByChartIds" resultMap="chartIdWithAssetEntity"> - SELECT - cha.id as chartId, - ass.id, - ass.name, - ass.sn, - ass.manage_ip, - ass.number - FROM - visual_chart cha - LEFT JOIN visual_panel pan ON cha.panel_id = pan.id - LEFT JOIN asset_asset ass ON pan.link = ass.id - WHERE - cha.id IN - <foreach collection="ids" item="id" index="no" open="(" separator="," close=")"> - #{id} - </foreach> - </select> - - <update id="updateBrandIdByModelId"> - UPDATE asset_asset - SET brand_id = #{brandId} - WHERE - model_id = #{modelId} - </update> - - <select id="getTsgAssetListbyModel" resultType="com.nis.modules.asset.entity.AssetAsset"> SELECT ass.* diff --git a/nz-admin/src/main/resources/mapper/asset/AssetModelDao.xml b/nz-admin/src/main/resources/mapper/asset/AssetModelDao.xml index 345a630a..3212ee2e 100644 --- a/nz-admin/src/main/resources/mapper/asset/AssetModelDao.xml +++ b/nz-admin/src/main/resources/mapper/asset/AssetModelDao.xml @@ -12,6 +12,7 @@ <result property="typeId" column="type_id"/> <result property="sysObjectId" column="sys_object_id"/> <result property="chartIds" column="chart_ids"/> + <result property="dashboardId" column="dashboard_id"/> <result property="assetNum" column="assetNum"/> <result property="starred" column="starred"/> <result property="tsgAppliance" column="tsg_appliance"/> diff --git a/nz-admin/src/main/resources/mapper/asset/V3_2_AssetModelDao.xml b/nz-admin/src/main/resources/mapper/asset/V3_2_AssetModelDao.xml deleted file mode 100644 index 784af7e2..00000000 --- a/nz-admin/src/main/resources/mapper/asset/V3_2_AssetModelDao.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - -<mapper namespace="com.nis.common.update.v3_2_to_3_3.dao.V3_2_AssetModelDao"> - - <resultMap type="com.nis.modules.asset.entity.AssetModel" id="modelView"> - <result property="id" column="id"/> - <result property="name" column="name"/> - <result property="brandId" column="brand_id"/> - <result property="remark" column="remark"/> - <result property="seq" column="seq"/> - <result property="chartIds" column="chart_ids"/> - <result property="usize" column="usize"/> - </resultMap> - - <select id="checkTableExists" resultType="java.util.Map"> - SHOW TABLES LIKE #{tableName}; - </select> - - <update id="dropTable"> - DROP TABLE ${tableName}; - </update> - - <select id="queryAssetModelIdAndTypesMapping" resultType="java.util.Map"> - SELECT - model_id AS modelId, - GROUP_CONCAT( DISTINCT type_id ) AS typeId - FROM - asset_asset - GROUP BY - model_id; - </select> - - <select id="queryList" resultMap="modelView"> - SELECT - * - FROM - asset_model_v3_2; - </select> - -</mapper> diff --git a/nz-admin/src/main/resources/mapper/panel/VisualChartDao.xml b/nz-admin/src/main/resources/mapper/dashboard/VisualChartDao.xml index 793d6bd8..2c6dab42 100644 --- a/nz-admin/src/main/resources/mapper/panel/VisualChartDao.xml +++ b/nz-admin/src/main/resources/mapper/dashboard/VisualChartDao.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> -<mapper namespace="com.nis.modules.panel.dao.VisualChartDao"> +<mapper namespace="com.nis.modules.dashboard.dao.VisualChartDao"> - <resultMap id="visualChartResult" type="com.nis.modules.panel.entity.VisualChart"> + <resultMap id="visualChartResult" type="com.nis.modules.dashboard.entity.VisualChart"> <result property="id" column="id"></result> <result property="name" column="name"></result> - <result property="panelId" column="panel_id"></result> + <result property="dashboardId" column="dashboard_id"></result> <result property="groupId" column="group_id"></result> <result property="span" column="span"></result> <result property="height" column="height"></result> @@ -26,16 +26,17 @@ <result property="varName" column="var_name"/> <result property="chartNums" column="chartNums"></result> <result property="datasource" column="datasource"/> - <association property="panel" javaType="com.nis.modules.panel.entity.VisualPanel" columnPrefix="panel_"> - <id property="id" column="id"/> + <association property="dashboard" javaType="com.nis.modules.dashboard.entity.VisualDashboard" columnPrefix="dashboard_"> + <id property="id" column="id"/> <result property="name" column="name"/> <result property="link" column="link"/> + <result property="varType" column="var_type"/> </association> - <association property="group" javaType="com.nis.modules.panel.entity.VisualChart" columnPrefix="group_"> + <association property="group" javaType="com.nis.modules.dashboard.entity.VisualChart" columnPrefix="group_"> <id property="id" column="id"/> <result property="name" column="name"/> </association> - <collection property="elements" ofType="com.nis.modules.panel.entity.VisualChartElement" columnPrefix="vce_"> + <collection property="elements" ofType="com.nis.modules.dashboard.entity.VisualChartElement" columnPrefix="vce_"> <id property="id" column="id"/> <result property="expression" column="expression"></result> <result property="type" column="type"></result> @@ -56,12 +57,14 @@ vce.legend AS vce_legend, vce.name AS vce_name, vce.state AS vce_state, - vp.id as panel_id, - vp.name as panel_name, + vp.id as dashboard_id, + vp.name as dashboard_name, + vp.var_type as dashboard_var_type, + vp.link as dashboard_link, case when vch.var_type=1 then aa.name when vch.var_type=2 then me.name end as var_name FROM visual_chart vch LEFT JOIN visual_chart_element vce ON vch.id = vce.chart_id - left join visual_panel vp on vch.panel_id = vp.id + left join visual_dashboard vp on vch.dashboard_id = vp.id left join visual_chart gvch on vch.group_id = gvch.id left join asset_asset aa on vch.var_id = aa.id left join monitor_endpoint me on vch.var_id = me.id @@ -79,13 +82,14 @@ vce.legend AS vce_legend, vce.name AS vce_name, vce.state AS vce_state, - vp.id as panel_id, - vp.name as panel_name, - vp.link as panel_link, + vp.id as dashboard_id, + vp.name as dashboard_name, + vp.var_type as dashboard_var_type, + vp.link as dashboard_link, case when vch.var_type=1 then aa.name when vch.var_type=2 then me.name end as var_name FROM visual_chart vch LEFT JOIN visual_chart_element vce ON vch.id = vce.chart_id - left join visual_panel vp on vch.panel_id = vp.id + left join visual_dashboard vp on vch.dashboard_id = vp.id left join visual_chart gvch on vch.group_id = gvch.id left join asset_asset aa on vch.var_id = aa.id left join monitor_endpoint me on vch.var_id = me.id @@ -100,13 +104,13 @@ vch.*, vcg.id as group_id, vcg.name as group_name, - vp.id as panel_id, - vp.name as panel_name, - vp.link as panel_link, + vp.id as dashboard_id, + vp.name as dashboard_name, + vp.link as dashboard_link, case when vch.var_type=1 then aa.name when vch.var_type=2 then me.name end as var_name FROM visual_chart vch left join visual_chart vcg on vch.group_id = vcg.id - left join visual_panel vp on vch.panel_id = vp.id + left join visual_dashboard vp on vch.dashboard_id = vp.id left join asset_asset aa on vch.var_id = aa.id left join monitor_endpoint me on vch.var_id = me.id WHERE 1=1 @@ -117,8 +121,8 @@ </foreach> </if> - <if test="params.panelId != null"> - AND vch.panel_id = #{params.panelId} + <if test="params.dashboardId != null"> + AND vch.dashboard_id = #{params.dashboardId} </if> <if test="params.name != null and params.name != ''"> @@ -151,8 +155,8 @@ </foreach> </if> - <if test="params.panelType!=null and params.panelType!=''"> - AND vp.type = #{params.panelType} + <if test="params.dashboardType!=null and params.dashboardType!=''"> + AND vp.type = #{params.dashboardType} </if> /* 如果排序字段为null , 按照 weight 排序 */ @@ -185,42 +189,12 @@ <if test="chart.y !=null"> y = #{chart.y}, </if> - panel_id = #{panelId} + dashboard_id = #{dashboardId} WHERE id = #{chart.id} </foreach> </update> - <select id="selectChartNum" resultMap="visualChartResult"> - select panel_id id,count(*) chartNums - from visual_chart group by panel_id - </select> - - - <select id="selectTmplCharts" resultMap="visualChartResult"> - select vch.* - from visual_chart vch - <if test="params.models != null and (params.models).size > 0"> - left join asset_asset aa on vch.var_id = aa.id - </if> - <if test="params.modules != null and (params.modules).size > 0"> - left join monitor_endpoint me on vch.var_id = me.id - </if> - where vch.pid is not null - <if test="params.panelId != null"> - and vch.panel_id = #{params.panelId} - </if> - <if test="params.pid != null"> - and vch.pid = #{params.pid} - </if> - <if test="params.ids != null and params.size > 0 "> - and vch.id in - <foreach item="id" collection="params.ids" separator="," open="(" close=")" index=""> - #{id} - </foreach> - </if> - </select> - <select id="selectInstanceChart" resultMap="visualChartResult"> select vc.* from visual_chart vc @@ -239,38 +213,15 @@ </if> </select> - <select id="queryChartWithElementByIds" resultMap="visualChartResult"> - SELECT - vch.*, - vce.id AS vce_id, - vce.expression AS vce_expression, - vce.type AS vce_type, - vce.legend AS vce_legend, - vce.name AS vce_name, - vce.state AS vce_state - FROM - visual_chart vch - LEFT JOIN visual_chart_element vce ON vch.id = vce.chart_id - <where> - <if test="list != null"> - vch.id in - <foreach item="id" collection="list" separator="," open="(" close=")" index=""> - #{id} - </foreach> - </if> - </where> - </select> - - <insert id="insertBatchChart"> insert into visual_chart - (`id`, `name`, `panel_id`, `group_id`, `span`, `height`, `update_by`, `update_at`, `type`, `unit`, `weight`, `param`, `pid`, `build_in`, `remark`, `seq`, `var_type`, `var_id`, `x`, `y`, `datasource`) + (`id`, `name`, `dashboard_id`, `group_id`, `span`, `height`, `update_by`, `update_at`, `type`, `unit`, `weight`, `param`, `pid`, `build_in`, `remark`, `seq`, `var_type`, `var_id`, `x`, `y`, `datasource`) VALUES <foreach collection="list" item="item" separator="," > ( #{item.id}, #{item.name}, - #{item.panelId}, + #{item.dashboardId}, #{item.groupId}, #{item.span}, #{item.height}, @@ -292,4 +243,20 @@ ) </foreach> </insert> + + <select id="queryChartsIncludeElementInfo" resultMap="visualChartResult"> + SELECT + chart.*, + vce.id AS vce_id, + vce.expression AS vce_expression, + vce.type AS vce_type, + vce.legend AS vce_legend, + vce.name AS vce_name, + vce.state AS vce_state + FROM + visual_chart chart + LEFT JOIN visual_chart_element vce ON chart.id = vce.chart_id + WHERE + chart.dashboard_id = #{dashboardId} + </select> </mapper> diff --git a/nz-admin/src/main/resources/mapper/panel/VisualChartElementDao.xml b/nz-admin/src/main/resources/mapper/dashboard/VisualChartElementDao.xml index 3c7ecd54..ac5d6194 100644 --- a/nz-admin/src/main/resources/mapper/panel/VisualChartElementDao.xml +++ b/nz-admin/src/main/resources/mapper/dashboard/VisualChartElementDao.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> -<mapper namespace="com.nis.modules.panel.dao.VisualChartElementDao"> +<mapper namespace="com.nis.modules.dashboard.dao.VisualChartElementDao"> <update id="updateNameBatch"> update visual_chart_element diff --git a/nz-admin/src/main/resources/mapper/panel/VisualPanelDao.xml b/nz-admin/src/main/resources/mapper/dashboard/VisualDashboardDao.xml index 62c87663..06d9d6d5 100644 --- a/nz-admin/src/main/resources/mapper/panel/VisualPanelDao.xml +++ b/nz-admin/src/main/resources/mapper/dashboard/VisualDashboardDao.xml @@ -1,11 +1,13 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> -<mapper namespace="com.nis.modules.panel.dao.VisualPanelDao"> +<mapper namespace="com.nis.modules.dashboard.dao.VisualDashboardDao"> - <resultMap id="visualPanelResult" type="com.nis.modules.panel.entity.VisualPanel"> + <resultMap id="dashboardResult" type="com.nis.modules.dashboard.entity.VisualDashboard"> <result property="id" column="id"></result> <result property="name" column="name"></result> <result property="type" column="type"></result> + <result property="varType" column="var_type"></result> + <result property="tmplId" column="tmpl_id"></result> <result property="link" column="link"></result> <result property="buildIn" column="build_in"></result> <result property="createBy" column="create_by"></result> @@ -17,40 +19,39 @@ <result property="uts" column="uts"></result> <result property="chartNum" column="chart_num"></result> <result property="starred" column="starred"></result> - <association property="parent" columnPrefix="parent_" javaType="com.nis.modules.panel.entity.VisualPanel"> + <association property="parent" columnPrefix="parent_" javaType="com.nis.modules.dashboard.entity.VisualDashboard"> <result property="id" column="id" /> <result property="name" column="name"></result> </association> </resultMap> - - <select id="queryInfo" resultMap="visualPanelResult"> + + <select id="queryInfo" resultMap="dashboardResult"> SELECT - childPanel.*, - fatherPanel.id AS parent_id, - fatherPanel.NAME AS parent_name, + childDashboard.*, + fatherDashboard.id AS parent_id, + fatherDashboard.NAME AS parent_name, IFNULL( chart.chartNum, 0 ) AS chart_num FROM - visual_panel childPanel - LEFT JOIN visual_panel fatherPanel ON childPanel.pid = fatherPanel.id - LEFT JOIN ( SELECT panel_id, count( 1 ) AS chartNum FROM visual_chart GROUP BY panel_id ) chart ON childPanel.id = chart.panel_id + visual_dashboard childDashboard + LEFT JOIN visual_dashboard fatherDashboard ON childDashboard.pid = fatherDashboard.id + LEFT JOIN ( SELECT dashboard_id, count( 1 ) AS chartNum FROM visual_chart GROUP BY dashboard_id ) chart ON childDashboard.id = chart.dashboard_id WHERE - childPanel.id = #{id} + childDashboard.id = #{id} </select> - <select id="queryList" resultMap="visualPanelResult"> + <select id="queryList" resultMap="dashboardResult"> SELECT pan.*, - fatherPanel.id AS parent_id, - fatherPanel.NAME AS parent_name, - childrenPanel.*, + fatherDashboard.id AS parent_id, + fatherDashboard.NAME AS parent_name, IFNULL( chart.chartNum, 0 ) AS chart_num , - IFNULL( sta.starred, 0 ) AS starred + IFNULL( sta.starred, 0 ) AS starred, + pan.var_type as varType FROM - visual_panel pan - LEFT JOIN visual_panel fatherPanel ON pan.pid = fatherPanel.id - LEFT JOIN visual_panel childrenPanel ON pan.id = childrenPanel.pid - LEFT JOIN ( SELECT panel_id, count( 1 ) AS chartNum FROM visual_chart GROUP BY panel_id ) chart ON pan.id = chart.panel_id - LEFT JOIN ( SELECT IF(COUNT(1) > 0, 1, 0) AS starred,tid FROM sys_user_starred WHERE TYPE = "panel" AND uid = #{params.currentLoginUserID} GROUP BY tid) sta ON pan.id = sta.tid + visual_dashboard pan + LEFT JOIN visual_dashboard fatherDashboard ON pan.pid = fatherDashboard.id + LEFT JOIN ( SELECT dashboard_id, count( 1 ) AS chartNum FROM visual_chart GROUP BY dashboard_id ) chart ON pan.id = chart.dashboard_id + LEFT JOIN ( SELECT IF(COUNT(1) > 0, 1, 0) AS starred,tid FROM sys_user_starred WHERE TYPE = "dashboard" AND uid = #{params.currentLoginUserID} GROUP BY tid) sta ON pan.id = sta.tid <where> <if test="params.ids != null"> and pan.id in @@ -63,9 +64,25 @@ and pan.type=#{params.type} </if> + <if test="params.name != null and params.name != ''"> + AND locate(#{params.name} , pan.name) + </if> + + <if test="params.createBy != null and params.createBy != ''"> + and pan.create_by=#{params.createBy} + </if> + + <if test="params.pid != null and params.pid != ''"> + and pan.pid=#{params.pid} + </if> + <if test="params.link != null and params.link != ''"> and pan.link=#{params.link} </if> + + <if test="params.varType != null and params.varType != ''"> + and pan.var_type=#{params.varType} + </if> <if test="params.starred != null and params.starred != ''"> AND <if test=' params.starred eq 1 '> @@ -76,38 +93,46 @@ </if> </if> </where> - <!-- 按照 weight 排序 --> - ORDER BY pan.weight,pan.id + <if test="params.orderBy == null or params.orderBy == ''"> + <choose> + <when test="params.type == 'template'"> + ORDER BY pan.id + </when> + <otherwise> + ORDER BY pan.weight,pan.id + </otherwise> + </choose> + </if> </select> - <select id="queryListByType" resultMap="visualPanelResult"> + <select id="queryListByType" resultMap="dashboardResult"> SELECT pan.*, su.id AS su_userId, su.username AS su_username FROM - visual_panel pan + visual_dashboard pan LEFT JOIN sys_user su ON pan.create_by = su.id where pan.type = #{type} </select> <update id="updateWeightBatch"> - <foreach item="panel" collection="panels" separator=";"> - UPDATE visual_panel + <foreach item="dashboard" collection="dashboards" separator=";"> + UPDATE visual_dashboard <set> - weight = #{panel.weight}, - pid = #{panel.pid} + weight = #{dashboard.weight}, + pid = #{dashboard.pid} </set> WHERE - id = #{panel.id} + id = #{dashboard.id} </foreach> </update> <update id="delReceivers"> <foreach item="item" collection="list" separator=";"> UPDATE - visual_panel + visual_dashboard <set> param = JSON_REMOVE(param, JSON_UNQUOTE(JSON_SEARCH( param, 'one', #{item} ))) </set> @@ -116,15 +141,15 @@ </foreach> </update> - <select id="queryReportOfEmptyReceivers" resultMap="visualPanelResult"> + <select id="queryReportOfEmptyReceivers" resultMap="dashboardResult"> SELECT id, name, JSON_SET(param, '$.report.enable', false) param FROM - visual_panel + visual_dashboard WHERE JSON_EXTRACT(param, '$.report.receivers') = '[]' AND JSON_EXTRACT(param, '$.report.enable')= 'true' </select> -</mapper>
\ No newline at end of file +</mapper> diff --git a/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml index acc7bedc..64545fd3 100644 --- a/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml +++ b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointDao.xml @@ -490,29 +490,4 @@ AND ( mes.ver != #{version} || mes.state = 0 ) </select> - - <select id="endpointDetailList" resultMap="endpointDetail"> - SELECT - e.*, - - ass.id AS ass_id, - ass.sn AS ass_sn, - ass.NAME AS ass_name, - ass.manage_ip AS ass_manage_ip, - ass.dc_id AS ass_dc_id, - - state.id as ass_state_id, - state.name as ass_state_name, - state.monitor as ass_state_monitor, - - dc.id AS dc_id, - dc.NAME AS dc_name, - dc.state as dc_state - FROM - monitor_endpoint e - LEFT JOIN asset_asset ass ON e.asset_id = ass.id - LEFT JOIN asset_state_conf state ON ass.state_id = state.id - LEFT JOIN dc dc ON ass.dc_id = dc.id - </select> - </mapper> diff --git a/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointStateDao.xml b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointStateDao.xml index 925e6ea9..50f21e7a 100644 --- a/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointStateDao.xml +++ b/nz-admin/src/main/resources/mapper/endpoint/MonitorEndpointStateDao.xml @@ -3,10 +3,6 @@ <mapper namespace="com.nis.modules.endpoint.dao.MonitorEndpointStateDao"> - <delete id="deleteConfStateByType"> - DELETE FROM monitor_endpoint_state WHERE type = #{type}; - </delete> - <update id="updateBatchEndpointState"> <foreach collection="datas" separator=";" item="data"> update monitor_endpoint_state set state=#{data.state}, diff --git a/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml b/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml index eebb08ab..02cfb284 100644 --- a/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml +++ b/nz-admin/src/main/resources/mapper/module/MonitorModuleDao.xml @@ -14,6 +14,7 @@ <result property="assetNum" column="assetNum"/> <result property="alertNum" column="alertNum"/> <result property="chartIds" column="chart_ids"/> + <result property="dashboardId" column="dashboard_id"/> <result property="starred" column="starred"/> <association property="project" columnPrefix="p_" javaType="com.nis.modules.project.entity.MonitorProject"> @@ -21,6 +22,11 @@ <result column="name" property="name"/> <result column="remark" property="remark"/> </association> + + <association property="dashboard" columnPrefix="pan_" javaType="com.nis.modules.dashboard.entity.VisualDashboard"> + <id column="id" property="id"/> + <result column="name" property="name"/> + </association> </resultMap> <select id="queryPage" resultMap="module"> @@ -29,6 +35,8 @@ p.id AS p_id, p.NAME AS p_name, p.remark AS p_remark, + pan.id AS pan_id, + pan.NAME AS pan_name, IFNULL( me.endpointNum, 0 ) AS endpointNum, IFNULL( me.assetNum, 0 ) AS assetNum, IFNULL( msg.alertNum, 0 ) AS alertNum, @@ -36,6 +44,7 @@ FROM monitor_module m LEFT JOIN monitor_project p ON m.project_id = p.id + LEFT JOIN visual_dashboard pan ON m.dashboard_id = pan.id LEFT JOIN ( SELECT module_id, count( 1 ) AS endpointNum, count( DISTINCT asset_id ) AS assetNum FROM monitor_endpoint GROUP BY module_id ) me ON m.id = me.module_id LEFT JOIN ( SELECT module_id, count( 1 ) AS alertNum FROM alert_message_active WHERE module_id IS NOT NULL GROUP BY module_id ) msg ON m.id = msg.module_id LEFT JOIN ( SELECT IF(COUNT(1) > 0, 1, 0) AS starred,tid FROM sys_user_starred WHERE TYPE = "module" AND uid = #{params.uid} GROUP BY tid) sta ON m.id = sta.tid diff --git a/nz-admin/src/main/resources/mapper/panel/V3_0VisualChartDao.xml b/nz-admin/src/main/resources/mapper/panel/V3_0VisualChartDao.xml deleted file mode 100644 index 3edfc60e..00000000 --- a/nz-admin/src/main/resources/mapper/panel/V3_0VisualChartDao.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> -<mapper namespace="com.nis.common.update.v3_0_to_3_2.dao.V3_0VisualChartDao"> - - <resultMap id="chartResultMap" type="com.nis.modules.panel.entity.VisualChart"> - <result property="id" column="id"/> - <result property="name" column="name"/> - <result property="panelId" column="panel_id"/> - <result property="groupId" column="group_id"/> - <result property="span" column="span"/> - <result property="height" column="height"/> - <result property="updateAt" column="update_at"/> - <result property="updateBy" column="update_by"/> - <result property="type" column="type"/> - <result property="unit" column="unit"/> - <result property="weight" column="weight"/> - <result property="param" column="param"/> - <result property="pid" column="pid"/> - <result property="buildIn" column="build_in"/> - <result property="remark" column="remark"/> - <result property="seq" column="seq"/> - <result property="varType" column="var_type"/> - <result property="varId" column="var_id"/> - <result property="varName" column="var_name"/> - <!--<result property="datasource" column="datasource"/> - <result property="x" column="x"/> - <result property="y" column="y"/>--> - </resultMap> - - <select id="checkTableExists" resultType="java.util.Map"> - SHOW TABLES LIKE #{tableName}; - </select> - - <select id="queryList" resultMap="chartResultMap"> - SELECT - * - FROM - visual_chart_v3_2 - ORDER BY - panel_id, - group_id, - weight; - </select> - - <update id="dropTable"> - DROP TABLE ${tableName}; - </update> - -</mapper> diff --git a/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml b/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml index d0189383..b371151c 100644 --- a/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml +++ b/nz-admin/src/main/resources/mapper/terminal/TerminalSessionDao.xml @@ -6,11 +6,13 @@ SELECT ts.*, su.name as username, - cmd.cmdNum + cmd.cmdNum, + IFNULL(sftp.sftpNum, 0) sftpNum FROM terminal_session ts LEFT JOIN sys_user su ON ts.user_id = su.id LEFT JOIN ( SELECT uuid, ( count( 1 ) - 1 ) AS cmdNum FROM terminal_cmd GROUP BY uuid ) cmd ON cmd.uuid = ts.uuid + LEFT JOIN ( SELECT uuid, count( 1 ) AS sftpNum FROM terminal_sftp_log GROUP BY uuid ) sftp ON sftp.uuid = ts.uuid <where> <if test="params.protocol != null and params.protocol != ''"> ts.protocol = #{params.protocol} @@ -70,10 +72,11 @@ WHERE ts.start_time <= #{startCleanTerminalTime}; - DELETE tr.*,ts.* + DELETE tr.*,ts.*,tsl.* FROM terminal_session ts LEFT JOIN terminal_record tr ON ts.uuid = tr.uuid + LEFT JOIN terminal_sftp_log tsl on ts.uuid = tsl.uuid WHERE ts.start_time <= #{startCleanTerminalTime}; </delete> diff --git a/nz-admin/src/test/java/com/nis/modules/UTUtil.java b/nz-admin/src/test/java/com/nis/modules/UTUtil.java index fbcf13a0..7ad29937 100644 --- a/nz-admin/src/test/java/com/nis/modules/UTUtil.java +++ b/nz-admin/src/test/java/com/nis/modules/UTUtil.java @@ -6,7 +6,6 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.text.csv.CsvData; import cn.hutool.core.text.csv.CsvRow; import cn.hutool.core.util.CharsetUtil; -import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.nis.common.utils.Constant; diff --git a/nz-admin/src/test/java/com/nis/modules/dashboard/VisualDashboardTest.java b/nz-admin/src/test/java/com/nis/modules/dashboard/VisualDashboardTest.java new file mode 100644 index 00000000..a5ae3c9f --- /dev/null +++ b/nz-admin/src/test/java/com/nis/modules/dashboard/VisualDashboardTest.java @@ -0,0 +1,370 @@ +package com.nis.modules.dashboard; + +import com.alibaba.fastjson.JSONObject; +import com.nis.common.utils.RCode; +import com.nis.modules.BaseTest; +import com.nis.modules.UTUtil; +import com.nis.modules.dashboard.entity.VisualDashboard; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.Map; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class VisualDashboardTest extends BaseTest<VisualDashboard> { + + @Override + protected String jsonIndex() { + return "dashboard/VisualDashboardTestParameter.json"; + } + + /** + * GET /visual/dashboard/{id} SUCCESS + */ + @Test + public void queryVisualDashboard_id() throws Exception { + MvcResult result = UTUtil.performGet("/visual/dashboard/1", null); + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + + Map<String, Object> actualResult = JSONObject.parseObject(result.getResponse().getContentAsString(), Map.class); + Object projectInfo = actualResult.get("data"); + Assert.assertNotNull(projectInfo); + } + + /** + * GET /visual/dashboard SUCCESS + */ + @Test + public void queryVisualDashboard_success() throws Exception { + Map map = jsonToInParameter(testName.getMethodName(), Map.class); + MvcResult result = UTUtil.performGet("/visual/dashboard", map); + + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + + Map<String, Object> actualResult = JSONObject.parseObject(result.getResponse().getContentAsString(), Map.class); + Object listInfo = actualResult.get("data"); + Assert.assertNotNull(listInfo); + } + + /** + * POST /visual/dashboard SUCCESS + */ + @Test + public void addVisualDashboard_success(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + } + + /** + * POST /visual/dashboard DASHBOARD_NAME_ISNULL + */ + @Test + public void addVisualDashboard_nameIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NAME_ISNULL); + } + + /** + * POST /visual/dashboard DASHBOARD_NAME_FORMAT_ERROR + */ + @Test + public void addVisualDashboard_nameFormatError(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NAME_FORMAT_ERROR); + } + + /** + * POST /visual/dashboard DASHBOARD_NAME_DUPLICATE + */ + @Test + public void addVisualDashboard_nameDuplicate(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NAME_DUPLICATE); + } + + /** + * POST /visual/dashboard DASHBOARD_TYPE_ISNULL + */ + @Test + public void addVisualDashboard_typeIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_TYPE_ISNULL); + } + + /** + * POST /visual/dashboard DASHBOARD_TYPE_INVALIDE + */ + @Test + public void addVisualDashboard_typeInvalide(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_TYPE_INVALIDE); + } + + /** + * POST /visual/dashboard DASHBOARD_NOT_EXIST + */ + @Test + public void addVisualDashboard_notExist(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NOT_EXIST); + } + + /** + * POST /visual/dashboard DASHBOARD_NAME_TOO_LONG + */ + @Test + public void addVisualDashboard_error(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.CONTENT_MORETHAN_MAXLENGTH); + } + + /** + * PUT /visual/dashboard SUCCESS + */ + @Test + public void updateVisualDashboard_success(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPut("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + } + + /** + * PUT /visual/dashboard DASHBOARD_ID_ISNULL + */ + @Test + public void updateVisualDashboard_idIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPut("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_ID_ISNULL); + } + + /** + * PUT /visual/dashboard DASHBOARD_NAME_TOO_LONG + */ + @Test + public void updateVisualDashboard_error(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPut("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.CONTENT_MORETHAN_MAXLENGTH); + } + + /** + * DELETE /visual/dashboard SUCCESS + */ + @Test + public void deleteVisualDashboard_success(){ + Map map = jsonToInParameter(testName.getMethodName(), Map.class); + MvcResult result = UTUtil.performDelete("/visual/dashboard", map); + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + } + + /** + * DELETE /visual/dashboard DASHBOARD_ID_ISNULL + */ + @Test + public void deleteVisualDashboard_idIsnull(){ + Map map = jsonToInParameter(testName.getMethodName(), Map.class); + MvcResult result = UTUtil.performDelete("/visual/dashboard", map); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_ID_ISNULL); + } + + /** + * POST /duplicate/{id} SUCCESS + */ + @Test + public void duplicate_success(){ + MvcResult result = UTUtil.performPost("/visual/dashboard/duplicate/4", null); + UTUtil.assertEqualsRCode(result,RCode.SUCCESS); + } + + /** + * POST /duplicate/{id} DASHBOARD_NOT_EXIST + */ + @Test + public void duplicate_chartDashboardIsnull(){ + MvcResult result = UTUtil.performPost("/visual/dashboard/duplicate/8", null); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NOT_EXIST); + } + + /** + * POST /duplicate/{id} DASHBOARD_NAME_TOO_LONG + */ + @Test + public void duplicate_dashboardNameTooLong(){ + MvcResult result = UTUtil.performPost("/visual/dashboard/duplicate/1", null); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_NAME_TOO_LONG); + } + /** ------------------- param 参数校验 ---------------------- */ + /** + * DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL + */ + @Test + public void addVisualDashboard_receiversIsNull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL); + } + + /** + * DASHBOARD_PARAM_REPORTRANGE_ISNULL + */ + @Test + public void addVisualDashboard_rangeIsNull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_REPORTRANGE_ISNULL); + } + + /** + * DASHBOARD_PARAM_RANGETYPE_ISNULL + */ + @Test + public void addVisualDashboard_rangeTypeIsNull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_RANGETYPE_ISNULL); + } + + /** + * DASHBOARD_PARAM_RANGEINTERVAL_ISNULL + */ + @Test + public void addVisualDashboard_rangeIntervalIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_RANGEINTERVAL_ISNULL); + } + + /** + * DASHBOARD_PARAM_RANGEUNIT_ISNULL + */ + @Test + public void addVisualDashboard_rangeUnitIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_RANGEUNIT_ISNULL); + } + + /** + * DASHBOARD_PARAM_RANGETYPE_INVALIDE + */ + @Test + public void addVisualDashboard_rangeTypeInvalide(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_RANGETYPE_INVALIDE); + } + + /** + * DASHBOARD_PARAM_RANGEUNIT_INVALIDE + */ + @Test + public void addVisualDashboard_rangeUnitInvalide(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_RANGEUNIT_INVALIDE); + } + + /** + * DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL + */ + @Test + public void addVisualDashboard_reportScheduleIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL); + } + + /** + * DASHBOARD_PARAM_SCHEDULETYPE_ISNULL + */ + @Test + public void addVisualDashboard_scheduleTypeIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULETYPE_ISNULL); + } + + /** + * DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL + */ + @Test + public void addVisualDashboard_scheduleRepeatIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL); + } + + /** + * DASHBOARD_PARAM_SCHEDULESTIME_ISNULL + */ + @Test + public void addVisualDashboard_scheduleStimeIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULESTIME_ISNULL); + } + + /** + * DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE + */ + @Test + public void addVisualDashboard_scheduleTypeInvalide(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE); + } + + /** + * DASHBOARD_PARAM_SCHEDULENUMS_ISNULL + */ + @Test + public void addVisualDashboard_scheduleNumsIsnull(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULENUMS_ISNULL); + } + + /** + * DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE + */ + @Test + public void addVisualDashboard_scheduleNumsInvalide3(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE); + } + + /** + * DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE + */ + @Test + public void addVisualDashboard_scheduleNumsInvalide4(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE); + } + + /** + * DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE + */ + @Test + public void addVisualDashboard_reportChartShareInvalide(){ + VisualDashboard visualDashboard = jsonToInParameter(testName.getMethodName(), VisualDashboard.class); + MvcResult result = UTUtil.performPost("/visual/dashboard", visualDashboard); + UTUtil.assertEqualsRCode(result,RCode.DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE); + } +} diff --git a/nz-admin/src/test/java/com/nis/modules/ipam/IpamIpTest.java b/nz-admin/src/test/java/com/nis/modules/ipam/IpamIpTest.java index 7594af29..2c4968b2 100644 --- a/nz-admin/src/test/java/com/nis/modules/ipam/IpamIpTest.java +++ b/nz-admin/src/test/java/com/nis/modules/ipam/IpamIpTest.java @@ -190,7 +190,7 @@ public class IpamIpTest extends BaseTest<IpamIp> { IpamIp ipamIp = jsonToInParameter(testName.getMethodName(), IpamIp.class); MvcResult result = UTUtil.performPost("/ipam/ip", ipamIp); - UTUtil.assertEqualsRCode(result, RCode.IPAM_IP_SUBNET_ISNULL); + UTUtil.assertEqualsRCode(result, RCode.IPAM_IP_SUBNET_NOT_EXISTS); } diff --git a/nz-admin/src/test/java/com/nis/modules/panel/VisualPanelTest.java b/nz-admin/src/test/java/com/nis/modules/panel/VisualPanelTest.java deleted file mode 100644 index a823b5e6..00000000 --- a/nz-admin/src/test/java/com/nis/modules/panel/VisualPanelTest.java +++ /dev/null @@ -1,370 +0,0 @@ -package com.nis.modules.panel; - -import com.alibaba.fastjson.JSONObject; -import com.nis.common.utils.RCode; -import com.nis.modules.BaseTest; -import com.nis.modules.UTUtil; -import com.nis.modules.panel.entity.VisualPanel; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MvcResult; - -import java.util.Map; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class VisualPanelTest extends BaseTest<VisualPanel> { - - @Override - protected String jsonIndex() { - return "panel/VisualPanelTestParameter.json"; - } - - /** - * GET /visual/panel/{id} SUCCESS - */ - @Test - public void queryVisualPanel_id() throws Exception { - MvcResult result = UTUtil.performGet("/visual/panel/1", null); - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - - Map<String, Object> actualResult = JSONObject.parseObject(result.getResponse().getContentAsString(), Map.class); - Object projectInfo = actualResult.get("data"); - Assert.assertNotNull(projectInfo); - } - - /** - * GET /visual/panel SUCCESS - */ - @Test - public void queryVisualPanel_success() throws Exception { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performGet("/visual/panel", map); - - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - - Map<String, Object> actualResult = JSONObject.parseObject(result.getResponse().getContentAsString(), Map.class); - Object listInfo = actualResult.get("data"); - Assert.assertNotNull(listInfo); - } - - /** - * POST /visual/panel SUCCESS - */ - @Test - public void addVisualPanel_success(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - } - - /** - * POST /visual/panel PANEL_NAME_ISNULL - */ - @Test - public void addVisualPanel_nameIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_NAME_ISNULL); - } - - /** - * POST /visual/panel PANEL_NAME_FORMAT_ERROR - */ - @Test - public void addVisualPanel_nameFormatError(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_NAME_FORMAT_ERROR); - } - - /** - * POST /visual/panel PANEL_NAME_DUPLICATE - */ - @Test - public void addVisualPanel_nameDuplicate(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_NAME_DUPLICATE); - } - - /** - * POST /visual/panel PANEL_TYPE_ISNULL - */ - @Test - public void addVisualPanel_typeIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_TYPE_ISNULL); - } - - /** - * POST /visual/panel PANEL_TYPE_INVALIDE - */ - @Test - public void addVisualPanel_typeInvalide(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_TYPE_INVALIDE); - } - - /** - * POST /visual/panel PANEL_NOT_EXIST - */ - @Test - public void addVisualPanel_notExist(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_NOT_EXIST); - } - - /** - * POST /visual/panel PANEL_NAME_TOO_LONG - */ - @Test - public void addVisualPanel_error(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.ERROR); - } - - /** - * PUT /visual/panel SUCCESS - */ - @Test - public void updateVisualPanel_success(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPut("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - } - - /** - * PUT /visual/panel PANEL_ID_ISNULL - */ - @Test - public void updateVisualPanel_idIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPut("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_ID_ISNULL); - } - - /** - * PUT /visual/panel PANEL_NAME_TOO_LONG - */ - @Test - public void updateVisualPanel_error(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPut("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.ERROR); - } - - /** - * DELETE /visual/panel SUCCESS - */ - @Test - public void deleteVisualPanel_success(){ - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performDelete("/visual/panel", map); - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - } - - /** - * DELETE /visual/panel PANEL_ID_ISNULL - */ - @Test - public void deleteVisualPanel_idIsnull(){ - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performDelete("/visual/panel", map); - UTUtil.assertEqualsRCode(result,RCode.PANEL_ID_ISNULL); - } - - /** - * POST /duplicate/{id} SUCCESS - */ - @Test - public void duplicate_success(){ - MvcResult result = UTUtil.performPost("/visual/panel/duplicate/4", null); - UTUtil.assertEqualsRCode(result,RCode.SUCCESS); - } - - /** - * POST /duplicate/{id} CHART_PANEL_ISNULL - */ - @Test - public void duplicate_chartPanelIsnull(){ - MvcResult result = UTUtil.performPost("/visual/panel/duplicate/8", null); - UTUtil.assertEqualsRCode(result,RCode.CHART_PANEL_ISNULL); - } - - /** - * POST /duplicate/{id} PANEL_NAME_TOO_LONG - */ - @Test - public void duplicate_panelNameTooLong(){ - MvcResult result = UTUtil.performPost("/visual/panel/duplicate/1", null); - UTUtil.assertEqualsRCode(result,RCode.PANEL_NAME_TOO_LONG); - } - /** ------------------- param 参数校验 ---------------------- */ - /** - * PANEL_PARAM_REPORTRECEIVERS_ISNULL - */ - @Test - public void addVisualPanel_receiversIsNull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_REPORTRECEIVERS_ISNULL); - } - - /** - * PANEL_PARAM_REPORTRANGE_ISNULL - */ - @Test - public void addVisualPanel_rangeIsNull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_REPORTRANGE_ISNULL); - } - - /** - * PANEL_PARAM_RANGETYPE_ISNULL - */ - @Test - public void addVisualPanel_rangeTypeIsNull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_RANGETYPE_ISNULL); - } - - /** - * PANEL_PARAM_RANGEINTERVAL_ISNULL - */ - @Test - public void addVisualPanel_rangeIntervalIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_RANGEINTERVAL_ISNULL); - } - - /** - * PANEL_PARAM_RANGEUNIT_ISNULL - */ - @Test - public void addVisualPanel_rangeUnitIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_RANGEUNIT_ISNULL); - } - - /** - * PANEL_PARAM_RANGETYPE_INVALIDE - */ - @Test - public void addVisualPanel_rangeTypeInvalide(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_RANGETYPE_INVALIDE); - } - - /** - * PANEL_PARAM_RANGEUNIT_INVALIDE - */ - @Test - public void addVisualPanel_rangeUnitInvalide(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_RANGEUNIT_INVALIDE); - } - - /** - * PANEL_PARAM_REPORTSCHEDULE_ISNULL - */ - @Test - public void addVisualPanel_reportScheduleIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_REPORTSCHEDULE_ISNULL); - } - - /** - * PANEL_PARAM_SCHEDULETYPE_ISNULL - */ - @Test - public void addVisualPanel_scheduleTypeIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULETYPE_ISNULL); - } - - /** - * PANEL_PARAM_SCHEDULEREPEAT_ISNULL - */ - @Test - public void addVisualPanel_scheduleRepeatIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULEREPEAT_ISNULL); - } - - /** - * PANEL_PARAM_SCHEDULESTIME_ISNULL - */ - @Test - public void addVisualPanel_scheduleStimeIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULESTIME_ISNULL); - } - - /** - * PANEL_PARAM_SCHEDULETYPE_INVALIDE - */ - @Test - public void addVisualPanel_scheduleTypeInvalide(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULETYPE_INVALIDE); - } - - /** - * PANEL_PARAM_SCHEDULENUMS_ISNULL - */ - @Test - public void addVisualPanel_scheduleNumsIsnull(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULENUMS_ISNULL); - } - - /** - * PANEL_PARAM_SCHEDULENUMS_INVALIDE - */ - @Test - public void addVisualPanel_scheduleNumsInvalide3(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULENUMS_INVALIDE); - } - - /** - * PANEL_PARAM_SCHEDULENUMS_INVALIDE - */ - @Test - public void addVisualPanel_scheduleNumsInvalide4(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_SCHEDULENUMS_INVALIDE); - } - - /** - * PANEL_PARAM_REPORTCHARTSHARE_INVALIDE - */ - @Test - public void addVisualPanel_reportChartShareInvalide(){ - VisualPanel visualPanel = jsonToInParameter(testName.getMethodName(), VisualPanel.class); - MvcResult result = UTUtil.performPost("/visual/panel", visualPanel); - UTUtil.assertEqualsRCode(result,RCode.PANEL_PARAM_REPORTCHARTSHARE_INVALIDE); - } -} diff --git a/nz-admin/src/test/java/com/nis/modules/sys/SysRoleTest.java b/nz-admin/src/test/java/com/nis/modules/sys/SysRoleTest.java index e1e75fd7..c9ea0f21 100644 --- a/nz-admin/src/test/java/com/nis/modules/sys/SysRoleTest.java +++ b/nz-admin/src/test/java/com/nis/modules/sys/SysRoleTest.java @@ -182,7 +182,7 @@ public class SysRoleTest extends BaseTest<SysRoleEntity> { SysRoleEntity role = jsonToInParameter(testName.getMethodName(), SysRoleEntity.class); MvcResult result = UTUtil.performPut("/sys/role", role); - UTUtil.assertEqualsRCode(result, RCode.SYS_ROLE_NAME_CANNOT_MODIFY); + UTUtil.assertEqualsRCode(result, RCode.SYS_ROLE_NOT_SUPPORT_MODIFY); } /** diff --git a/nz-admin/src/test/java/com/nis/modules/terminal/TerminalHandlerTest.java b/nz-admin/src/test/java/com/nis/modules/terminal/TerminalHandlerTest.java index 7ab3abc6..6408a0f3 100644 --- a/nz-admin/src/test/java/com/nis/modules/terminal/TerminalHandlerTest.java +++ b/nz-admin/src/test/java/com/nis/modules/terminal/TerminalHandlerTest.java @@ -45,56 +45,6 @@ public class TerminalHandlerTest extends BaseTest<AssetTypeConf> { } /** - * POST /terminal/upload TERMINAL_UUID_ISNULL - */ - @Test() - public void upload_terminalUuidIsnull() { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performMultipart("/terminal/upload","/file/CESHI-MIB.txt","file",map,null); - UTUtil.assertEqualsRCode(result, RCode.TERMINAL_UUID_ISNULL); - } - - /** - * POST /terminal/upload TERMINAL_PATH_ISNULL - */ - @Test() - public void upload_terminalPathIsnull() { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performMultipart("/terminal/upload","/file/CESHI-MIB.txt","file",map,null); - UTUtil.assertEqualsRCode(result, RCode.TERMINAL_PATH_ISNULL); - } - - /** - * POST /terminal/upload TERMINAL_ISNULL - */ - @Test() - public void upload_terminalIsnull() { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performMultipart("/terminal/upload","/file/CESHI-MIB.txt","file",map,null); - UTUtil.assertEqualsRCode(result, RCode.TERMINAL_ISNULL); - } - - /** - * POST /terminal/download TERMINAL_UUID_ISNULL - */ - @Test() - public void download_terminalUuidIsnull() { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performPost("/terminal/download",map); - UTUtil.assertEqualsRCode(result, RCode.TERMINAL_UUID_ISNULL); - } - - /** - * POST /terminal/download TERMINAL_PATH_ISNULL - */ - @Test() - public void download_terminalPathIsnull() { - Map map = jsonToInParameter(testName.getMethodName(), Map.class); - MvcResult result = UTUtil.performPost("/terminal/download",map); - UTUtil.assertEqualsRCode(result, RCode.TERMINAL_PATH_ISNULL); - } - - /** * Get /terminal/session success */ @Test() diff --git a/nz-admin/src/test/resources/parameters/alert/AlertSilenceTestParameter.json b/nz-admin/src/test/resources/parameters/alert/AlertSilenceTestParameter.json index 9491efaa..79beb318 100644 --- a/nz-admin/src/test/resources/parameters/alert/AlertSilenceTestParameter.json +++ b/nz-admin/src/test/resources/parameters/alert/AlertSilenceTestParameter.json @@ -25,7 +25,7 @@ "name": "silence name", "matchers": "[{\"name\":\"asset\",\"value\":\"192\",\"regex\":1}]", "startAt": "2021-01-11 11:11:11", - "endAt": "2022-10-31 11:11:11", + "endAt": "2025-10-31 11:11:11", "remark": "机房维护" }, "updateAlertSilence_nameisnull": { @@ -41,7 +41,7 @@ "name": "silence name", "matchers": null, "startAt": "2021-01-11 11:11:11", - "endAt": "2022-10-31 11:11:11", + "endAt": "2025-10-31 11:11:11", "remark": "机房维护" }, "updateAlertSilence_startAtisnull": { diff --git a/nz-admin/src/test/resources/parameters/asset/AssetAssetTestParameter.json b/nz-admin/src/test/resources/parameters/asset/AssetAssetTestParameter.json index 9c93a85b..cf840b57 100644 --- a/nz-admin/src/test/resources/parameters/asset/AssetAssetTestParameter.json +++ b/nz-admin/src/test/resources/parameters/asset/AssetAssetTestParameter.json @@ -17,7 +17,8 @@ "------------------ POST /asset/comment data---------------------": "note", "addAssetComment_success": { "assetId": 2, - "content": "Add comment" + "content": "Add comment", + "html": "<div class=\"editor-core ql-container ql-snow\"><div class=\"ql-editor\"><p>1</p></div></div>" }, "addAssetComment_assetIdIsnull": { "content": "Add comment error" @@ -29,7 +30,8 @@ "editAssetComment_success": { "id": 1, "assetId": 2, - "content": "Edit comment" + "content": "Edit comment", + "html": "<div class=\"editor-core ql-container ql-snow\"><div class=\"ql-editor\"><p>1</p></div></div>" }, "editAssetComment_commentIdIsnull": { "assetId": 1, diff --git a/nz-admin/src/test/resources/parameters/panel/VisualPanelTestParameter.json b/nz-admin/src/test/resources/parameters/dashboard/VisualDashboardTestParameter.json index 6b00d46a..538c24b9 100644 --- a/nz-admin/src/test/resources/parameters/panel/VisualPanelTestParameter.json +++ b/nz-admin/src/test/resources/parameters/dashboard/VisualDashboardTestParameter.json @@ -1,13 +1,13 @@ { - "------------------ get /visual/panel---------------------": "note", - "queryVisualPanel_success": { + "------------------ get /visual/dashboard---------------------": "note", + "queryVisualDashboard_success": { "pageNo": 1, "pageSize": 20, "ids": "1,2" }, - "------------------ post /visual/panel---------------------": "note", - "addVisualPanel_success": { - "name": "panel_6", + "------------------ post /visual/dashboard---------------------": "note", + "addVisualDashboard_success": { + "name": "dashboard_6", "remark": "测试新增", "param": { "report": { @@ -27,44 +27,45 @@ } } }, - "addVisualPanel_nameIsnull": { + "addVisualDashboard_nameIsnull": { "name": "", "remark": "测试新增" }, - "addVisualPanel_nameFormatError": { - "name": "panel/7", + "addVisualDashboard_nameFormatError": { + "name": "dashboard/7", "remark": "测试新增" }, - "addVisualPanel_nameDuplicate": { - "name": "panel_4", + "addVisualDashboard_nameDuplicate": { + "name": "dashboard_4", "remark": "测试新增", + "type": "dashboard", "pid": 10 }, - "addVisualPanel_typeIsnull": { - "name": "panel_7", + "addVisualDashboard_typeIsnull": { + "name": "dashboard_7", "remark": "测试新增", "link": 1 }, - "addVisualPanel_typeInvalide": { - "name": "panel_7", + "addVisualDashboard_typeInvalide": { + "name": "dashboard_7", "remark": "测试新增", "link": 1, "type": "abcd" }, - "addVisualPanel_notExist": { - "name": "panel_7", + "addVisualDashboard_notExist": { + "name": "dashboard_7", "remark": "测试新增", "pid": 19 }, - "addVisualPanel_error": { - "name": "panel_7_add_________________________________this_name_length_is_66", + "addVisualDashboard_error": { + "name": "dashboard_7_add_________________________________this_name_length_is_66", "remark": "测试新增" }, - "------------------ put /visual/panel---------------------": "note", - "updateVisualPanel_success": { + "------------------ put /visual/dashboard---------------------": "note", + "updateVisualDashboard_success": { "id": 3, - "name": "panel_3_update", - "type": "overview", + "name": "dashboard_3_update", + "type": "dashboard", "link": 1, "pid": 1, "remark": "测试修改", @@ -86,9 +87,9 @@ } } }, - "updateVisualPanel_idIsnull": { + "updateVisualDashboard_idIsnull": { "id": null, - "name": "panel_3_update", + "name": "dashboard_3_update", "type": "overview", "link": 1, "pid": 1, @@ -100,9 +101,9 @@ } } }, - "updateVisualPanel_error": { + "updateVisualDashboard_error": { "id": 3, - "name": "panel_3_update______________________________this_name_length_is_66", + "name": "dashboard_3_update______________________________this_name_length_is_66", "type": "overview", "link": 1, "pid": 1, @@ -114,16 +115,16 @@ } } }, - "------------------ delete /visual/panel---------------------": "note", - "deleteVisualPanel_success": { + "------------------ delete /visual/dashboard---------------------": "note", + "deleteVisualDashboard_success": { "ids": "2, 5" }, - "deleteVisualPanel_idIsnull": { + "deleteVisualDashboard_idIsnull": { "ids": "" }, - "------------------ post /visual/panel param---------------------": "note", - "addVisualPanel_receiversIsNull": { - "name": "panel_param_test", + "------------------ post /visual/dashboard param---------------------": "note", + "addVisualDashboard_receiversIsNull": { + "name": "dashboard_param_test", "remark": "测试param receivers校验", "param": { "report": { @@ -138,8 +139,8 @@ } } }, - "addVisualPanel_rangeIsNull": { - "name": "panel_param_test", + "addVisualDashboard_rangeIsNull": { + "name": "dashboard_param_test", "remark": "测试report range校验", "param": { "report": { @@ -147,8 +148,8 @@ } } }, - "addVisualPanel_rangeTypeIsNull": { - "name": "panel_param_test", + "addVisualDashboard_rangeTypeIsNull": { + "name": "dashboard_param_test", "remark": "测试range type校验", "param": { "report": { @@ -163,8 +164,8 @@ } } }, - "addVisualPanel_rangeIntervalIsnull": { - "name": "panel_param_test", + "addVisualDashboard_rangeIntervalIsnull": { + "name": "dashboard_param_test", "remark": "测试range interval校验", "param": { "report": { @@ -179,8 +180,8 @@ } } }, - "addVisualPanel_rangeUnitIsnull": { - "name": "panel_param_test", + "addVisualDashboard_rangeUnitIsnull": { + "name": "dashboard_param_test", "remark": "测试range unit校验", "param": { "report": { @@ -196,8 +197,8 @@ } } }, - "addVisualPanel_rangeTypeInvalide": { - "name": "panel_param_test", + "addVisualDashboard_rangeTypeInvalide": { + "name": "dashboard_param_test", "remark": "测试range type校验", "param": { "report": { @@ -214,8 +215,8 @@ } } }, - "addVisualPanel_rangeUnitInvalide": { - "name": "panel_param_test", + "addVisualDashboard_rangeUnitInvalide": { + "name": "dashboard_param_test", "remark": "测试range unit校验", "param": { "report": { @@ -232,8 +233,8 @@ } } }, - "addVisualPanel_reportScheduleIsnull": { - "name": "panel_param_test", + "addVisualDashboard_reportScheduleIsnull": { + "name": "dashboard_param_test", "remark": "测试report schedule校验", "param": { "report": { @@ -244,8 +245,8 @@ } } }, - "addVisualPanel_scheduleTypeIsnull": { - "name": "panel_param_test", + "addVisualDashboard_scheduleTypeIsnull": { + "name": "dashboard_param_test", "remark": "测试schedule type校验", "param": { "report": { @@ -262,8 +263,8 @@ } } }, - "addVisualPanel_scheduleRepeatIsnull": { - "name": "panel_param_test", + "addVisualDashboard_scheduleRepeatIsnull": { + "name": "dashboard_param_test", "remark": "测试schedule repeat校验", "param": { "report": { @@ -281,8 +282,8 @@ } } }, - "addVisualPanel_scheduleStimeIsnull": { - "name": "panel_param_test", + "addVisualDashboard_scheduleStimeIsnull": { + "name": "dashboard_param_test", "remark": "测试schedule stime校验", "param": { "report": { @@ -299,8 +300,8 @@ } } }, - "addVisualPanel_scheduleTypeInvalide": { - "name": "panel_param_test", + "addVisualDashboard_scheduleTypeInvalide": { + "name": "dashboard_param_test", "remark": "测试schedule type校验", "param": { "report": { @@ -318,8 +319,8 @@ } } }, - "addVisualPanel_scheduleNumsIsnull": { - "name": "panel_param_test", + "addVisualDashboard_scheduleNumsIsnull": { + "name": "dashboard_param_test", "remark": "测试schedule nums校验", "param": { "report": { @@ -338,8 +339,8 @@ } } }, - "addVisualPanel_scheduleNumsInvalide3": { - "name": "panel_param_test", + "addVisualDashboard_scheduleNumsInvalide3": { + "name": "dashboard_param_test", "remark": "测试schedule type=3, nums校验", "param": { "report": { @@ -359,8 +360,8 @@ } } }, - "addVisualPanel_scheduleNumsInvalide4": { - "name": "panel_param_test", + "addVisualDashboard_scheduleNumsInvalide4": { + "name": "dashboard_param_test", "remark": "测试schedule type=4, nums校验", "param": { "report": { @@ -380,8 +381,8 @@ } } }, - "addVisualPanel_reportChartShareInvalide": { - "name": "panel_param_test", + "addVisualDashboard_reportChartShareInvalide": { + "name": "dashboard_param_test", "remark": "测试report chartShare校验", "param": { "report": { diff --git a/nz-admin/src/test/resources/parameters/sys/SnmpMibTestParameter.json b/nz-admin/src/test/resources/parameters/sys/SnmpMibTestParameter.json index 29ea230a..9d3ba64e 100644 --- a/nz-admin/src/test/resources/parameters/sys/SnmpMibTestParameter.json +++ b/nz-admin/src/test/resources/parameters/sys/SnmpMibTestParameter.json @@ -57,7 +57,7 @@ "------------------ POST /mibl/browser data---------------------": "note", "getSnmpMiblBrowser_success": { "community": "public", - "host": "192.168.40.41", + "host": "192.168.40.165", "oid": "1.3.6.1.2.1.74.1.1.1", "operation": "get", "port": 161, diff --git a/nz-admin/src/test/resources/parameters/terminal/TerminalHandlerTestParameter.json b/nz-admin/src/test/resources/parameters/terminal/TerminalHandlerTestParameter.json index 3f44a4bd..ee1ed55c 100644 --- a/nz-admin/src/test/resources/parameters/terminal/TerminalHandlerTestParameter.json +++ b/nz-admin/src/test/resources/parameters/terminal/TerminalHandlerTestParameter.json @@ -81,7 +81,7 @@ }, "------------------ PUT /terminal/kill data---------------------": "note", "kill_success": { - "uuid": "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" + "uuid": "8b883310-589f-4407-9c71-a7b171e83657" }, "kill_terminalUuidIsnull": { "uuid": "" diff --git a/nz-admin/src/test/resources/testdb/AssetComment.sql b/nz-admin/src/test/resources/testdb/AssetComment.sql index 3169df0c..c0acc529 100644 --- a/nz-admin/src/test/resources/testdb/AssetComment.sql +++ b/nz-admin/src/test/resources/testdb/AssetComment.sql @@ -1,5 +1,5 @@ truncate asset_comment; -INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`) VALUES (1, 1, -1, 'Comment 1', 1662448164526, 1662448164763, 1, 1); -INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`) VALUES (2, 1, 1, 'Comment 2', 1662448164526, 1662448164763, 1, 1); -INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`) VALUES (3, 1, -1, 'Comment 3', 1662448164526, 1662448164763, 1, 1);
\ No newline at end of file +INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`, `html`) VALUES (1, 1, -1, 'Comment 1', 1662448164526, 1662448164763, 1, 1,'<div class="editor-core ql-container ql-snow"><div class="ql-editor"><p>1</p></div></div>'); +INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`, `html`) VALUES (2, 1, 1, 'Comment 2', 1662448164526, 1662448164763, 1, 1,'<div class="editor-core ql-container ql-snow"><div class="ql-editor"><p>2</p></div></div>'); +INSERT INTO `asset_comment`(`id`, `asset_id`, `reply_id`, `content`, `cts`, `uts`, `cid`, `uid`, `html`) VALUES (3, 1, -1, 'Comment 3', 1662448164526, 1662448164763, 1, 1,'<div class="editor-core ql-container ql-snow"><div class="ql-editor"><p>3</p></div></div>');
\ No newline at end of file diff --git a/nz-admin/src/test/resources/testdb/Dashboard.sql b/nz-admin/src/test/resources/testdb/Dashboard.sql new file mode 100644 index 00000000..32371041 --- /dev/null +++ b/nz-admin/src/test/resources/testdb/Dashboard.sql @@ -0,0 +1,8 @@ +truncate `visual_dashboard`; + +INSERT INTO `visual_dashboard`(`id`, `name`, `create_by`, `type`, `link`, `pid`, `weight`, `build_in`, `seq`, `param`, `remark`, `uts`, `var_type`, `tmpl_id`) VALUES +(1, 'dashboard_1___________________________this_name_length_is_60', 1, 'dashboard', NULL, 0, 0, '0', '', '{}', '', 0, 0, -1), +(2, 'dashboard_2', 1, 'dashboard', NULL, 0, 0, '0', '', '{}', '', 0, 0, -1), +(3, 'dashboard_3', 1, 'dashboard', NULL, 0, 0, '0', '', '{}', '', 0, 0, -1), +(4, 'dashboard_4', 1, 'dashboard', 0, 10, 20, '1', 'seq', '{\"report\": {\"enable\": false,\"receivers\": [3]}}', '用于复制', 0, 0, -1), +(5, 'dashboard_5', 1, 'dashboard', NULL, 0, 0, '0', '', '{}', '', 0, 0, -1); diff --git a/nz-admin/src/test/resources/testdb/Panel.sql b/nz-admin/src/test/resources/testdb/Panel.sql deleted file mode 100644 index 32177ec0..00000000 --- a/nz-admin/src/test/resources/testdb/Panel.sql +++ /dev/null @@ -1,8 +0,0 @@ -truncate visual_panel; - -INSERT INTO `visual_panel`(`id`, `name`, `create_by`, `type`, `link`, `pid`, `weight`, `build_in`, `seq`, `param`, `remark`, `uts`) VALUES -(1, 'panel_1_______________________________this_name_length_is_60', 1, 'dashboard', null, 0, 0, '0', '', '{}', '', 0), -(2, 'panel_2', 1, 'dashboard', null, 0, 0, '0', '', '{}', '', 0), -(3, 'panel_3', 1, 'dashboard', null, 0, 0, '0', '', '{}', '', 0), -(4, 'panel_4', 1, 'dashboard', 0, 10, 20, '1', 'seq', '{"report": {enable: false}}', '用于复制', 0), -(5, 'panel_5', 1, 'dashboard', null, 0, 0, '0', '', '{}', '', 0);
\ No newline at end of file diff --git a/nz-admin/src/test/resources/testdb/TerminalSession.sql b/nz-admin/src/test/resources/testdb/TerminalSession.sql new file mode 100644 index 00000000..fe740df7 --- /dev/null +++ b/nz-admin/src/test/resources/testdb/TerminalSession.sql @@ -0,0 +1,3 @@ +truncate terminal_session; + +INSERT INTO `terminal_session`(`id`, `uuid`, `asset_id`, `host`, `port`, `protocol`, `auth_type`, `login_user`, `user_id`, `remote_addr`, `start_time`, `end_time`, `status`, `kill_user_id`) VALUES (null, '8b883310-589f-4407-9c71-a7b171e83657', 560, '192.168.44.69', 22, 'SSH', 1, 'root', 1, '192.168.32.45', '2023-02-28 06:27:57', '2023-02-28 06:30:47', 2, NULL); diff --git a/nz-common/src/main/java/com/nis/common/utils/RCode.java b/nz-common/src/main/java/com/nis/common/utils/RCode.java index 80c0b17f..5d882d4c 100644 --- a/nz-common/src/main/java/com/nis/common/utils/RCode.java +++ b/nz-common/src/main/java/com/nis/common/utils/RCode.java @@ -39,20 +39,19 @@ public enum RCode { /** * dashboard菜单项相关 */ - PANEL_WEIGHT_ISNULL(121001,"Panel weight not be empty"), - PANEL_TYPE_ISNULL(121002,"Panel type can not be empty when link is not empty"), - PANEL_TYPE_INVALIDE(124003,"Panel type must be dashboard, asset, project, module, endpoint or model"), - PANEL_PID_ISNULL(121004,"Panel pid can not be empty"), - PANEL_NOT_EXIST(126005,"Panel does not exist"), - PANEL_NAME_TOO_LONG(123006,"Panel name too long than 64"), - PANEL_NAME_ISNULL(121007,"Panel name can not be empty"), - PANEL_NAME_FORMAT_ERROR(123008,"Panel name format error, can not include /"), - PANEL_NAME_DUPLICATE(122009,"Panel name is duplicate"), - PANEL_ID_ISNULL(121010,"Panel id can not be empty"), - PANEL_CHART_TEMPLATE_TYPE_ISNULL(121011,"Panel charts template type is null"), - PANEL_CHART_TEMPLATE_TYPE_INCORRECT(123012,"Panel charts template type must be dashboard, asset, endpoint and template"), - PANEL_CHART_IMPORT_LINKID_ISNULL(121013,"When the type is model or asset, link Id cannot be empty"), - PANEL_BUILDIN_CAN_NOT_REMOVE(127014,"This panel is built-in and cannot be deleted"), + DASHBOARD_WEIGHT_ISNULL(121001,"Dashboard weight not be empty"), + DASHBOARD_TYPE_ISNULL(121002,"Dashboard type can not be empty when link is not empty"), + DASHBOARD_TYPE_INVALIDE(124003,"The type must be dashboard, asset, project, module, endpoint or template"), + DASHBOARD_PID_ISNULL(121004,"Dashboard pid can not be empty"), + DASHBOARD_NOT_EXIST(126005,"Dashboard does not exist"), + DASHBOARD_NAME_TOO_LONG(123006,"Dashboard name too long than 64"), + DASHBOARD_NAME_ISNULL(121007,"Dashboard name can not be empty"), + DASHBOARD_NAME_FORMAT_ERROR(123008,"Dashboard name format error, can not include /"), + DASHBOARD_NAME_DUPLICATE(122009,"Dashboard name is duplicate"), + DASHBOARD_ID_ISNULL(121010,"Dashboard id can not be empty"), + DASHBOARD_CHART_TEMPLATE_TYPE_ISNULL(121011,"Dashboard import type is null"), + DASHBOARD_CHART_TEMPLATE_TYPE_INCORRECT(123012,"The charts template type must be dashboard, asset, endpoint and template"), + DASHBOARD_BUILDIN_CAN_NOT_REMOVE(127014,"This dashboard is built-in and cannot be deleted"), CHART_Y_ISNULL(121015,"Chart y can not be empty"), CHART_Y_FORMAT(123016,"Chart y format should be a integer"), CHART_X_WIDTH_INVALIDE(123017,"Chart x and width sum cannot be greater than 12 "), @@ -79,8 +78,7 @@ public enum RCode { CHART_PARAM_FORMAT(123038,"Chart param must be JSON format"), CHART_PARAMURL_FORMAT(123039,"Chart param url value must be URL format"), CHART_PARAMSINGLESTAT_ISNULL(121040,"Chart param statistics not found when type is singleStat"), - CHART_PARAMSINGLESTAT_INVALIDE(124041,"Chart param statistics must be min, max, average, total, first, last, range or different"), - CHART_PANEL_ISNULL(126042,"Panel is not exsits"), + CHART_PARAMSINGLESTAT_INVALIDE(124041,"Chart param statistics must be min, max, average, total, first, first*, last, last*, range or different"), CHART_NOTEXSITS(126043,"Chart is not exsits"), CHART_NAME_TOO_LONG(121044,"Chart name too long than 64"), CHART_NAME_DUPLICATE_NOTLINK(122045,"Chart name is duplicated and cannot be linked"), @@ -99,21 +97,28 @@ public enum RCode { CHARTELEMENT_TYPE_INVALIDE(123058,"Chart element type is invalide"), CHARTELEMENT_NAME_ISNULL(121059,"Chart element name can not be empty"), CHARTELEMENT_EXPRESSION_ISNULL(121060,"Chart element expression can not be empty"), - PANEL_PARAM_REPORTRANGE_ISNULL(121082,"Panel param report range can not be empty"), - PANEL_PARAM_RANGETYPE_ISNULL(121083,"Panel param range type can not be empty"), - PANEL_PARAM_RANGETYPE_INVALIDE(123084,"Panel param range type must be previous or last"), - PANEL_PARAM_RANGEINTERVAL_ISNULL(121085,"Panel param range interval can not be empty"), - PANEL_PARAM_RANGEUNIT_ISNULL(121086,"Panel param range unit can not be empty"), - PANEL_PARAM_RANGEUNIT_INVALIDE(123087,"Panel param range unit must be hour, day, week or month"), - PANEL_PARAM_REPORTSCHEDULE_ISNULL(121088,"Panel param report schedule can not be empty"), - PANEL_PARAM_SCHEDULETYPE_ISNULL(121089,"Panel param schedule type can not be empty"), - PANEL_PARAM_SCHEDULETYPE_INVALIDE(123090,"Panel param schedule type must be 1, 2, 3 or 4"), - PANEL_PARAM_SCHEDULEREPEAT_ISNULL(121091,"Panel param schedule repeat can not be empty"), - PANEL_PARAM_SCHEDULESTIME_ISNULL(121092,"Panel param schedule stime can not be empty"), - PANEL_PARAM_SCHEDULENUMS_ISNULL(121093,"Panel param schedule nums can not be empty"), - PANEL_PARAM_SCHEDULENUMS_INVALIDE(123094,"Panel param schedule nums is invalide"), - PANEL_PARAM_REPORTRECEIVERS_ISNULL(121095,"Panel param report receivers can not be empty"), - PANEL_PARAM_REPORTCHARTSHARE_INVALIDE(123096,"Panel param report tooltip must be none, crosshair or tooltip"), + DASHBOARD_PARAM_REPORTRANGE_ISNULL(121082,"Dashboard param report range can not be empty"), + DASHBOARD_PARAM_RANGETYPE_ISNULL(121083,"Dashboard param range type can not be empty"), + DASHBOARD_PARAM_RANGETYPE_INVALIDE(123084,"Dashboard param range type must be previous or last"), + DASHBOARD_PARAM_RANGEINTERVAL_ISNULL(121085,"Dashboard param range interval can not be empty"), + DASHBOARD_PARAM_RANGEUNIT_ISNULL(121086,"Dashboard param range unit can not be empty"), + DASHBOARD_PARAM_RANGEUNIT_INVALIDE(123087,"Dashboard param range unit must be hour, day, week or month"), + DASHBOARD_PARAM_REPORTSCHEDULE_ISNULL(121088,"Dashboard param report schedule can not be empty"), + DASHBOARD_PARAM_SCHEDULETYPE_ISNULL(121089,"Dashboard param schedule type can not be empty"), + DASHBOARD_PARAM_SCHEDULETYPE_INVALIDE(123090,"Dashboard param schedule type must be 1, 2, 3 or 4"), + DASHBOARD_PARAM_SCHEDULEREPEAT_ISNULL(121091,"Dashboard param schedule repeat can not be empty"), + DASHBOARD_PARAM_SCHEDULESTIME_ISNULL(121092,"Dashboard param schedule stime can not be empty"), + DASHBOARD_PARAM_SCHEDULENUMS_ISNULL(121093,"Dashboard param schedule nums can not be empty"), + DASHBOARD_PARAM_SCHEDULENUMS_INVALIDE(123094,"Dashboard param schedule nums is invalide"), + DASHBOARD_PARAM_REPORTRECEIVERS_ISNULL(121095,"Dashboard param report receivers can not be empty"), + DASHBOARD_PARAM_REPORTCHARTSHARE_INVALIDE(123096,"Dashboard param report tooltip must be none, crosshair or tooltip"), + DASHBOARD_SNAPSHOT_TASK_NOT_EXIST(126097,"Dashboard snapshot task cancel error, the task does not exist or has expired."), + DASHBOARD_VARTYPE_ISNULL(121098,"Dashboard varType can not be empty when link is not empty"), + DASHBOARD_VARTYPE_INVALIDE(124099,"Dashboard varType must be 0, 1 or 2"), + DASHBOARD_LINK_ISNULL(121100,"Dashboard link can not be empty"), + DASHBOARD_IMPORT_TYPE_INCORRECT(123101,"The type must be dashboard or template"), + DASHBOARD_TEMPLATE_SYNC_PARAM_ISNULL(121102, "Dashboard template synchronization parameter is null"), + DASHBOARD_TEMPLATE_SYNC_FAILED_GET_LOCK(127103,"Dashboard template synchronization is in progress please try again later"), /** * EXPRETMPL @@ -266,6 +271,7 @@ public enum RCode { ASSET_TYPE_ID_ISNULL(311036,"Asset type id can not be empty"), ASSET_RELOBJ_CAN_NOT_REMOVE(317037, "Asset have associated data and cannot be deleted"), ASSET_FORCE_INVALIDE(314038,"Force param must be 0 or 1"), + ASSET_TERMINAL_ACCOUNT_INFO_NOTFOUND(316039, "Account information for asset terminal login is not configured"), /** * ASSET_MODEL @@ -526,8 +532,8 @@ public enum RCode { SYS_USER_PIN_NOT_CONTAIN_LOWERCASE_LETTERS(513026,"System user pin must contain lowercase letters"), SYS_USER_PIN_NOT_CONTAIN_UPPERCASE_LETTERS(513027,"System user pin must contain uppercase letters"), SYS_USER_PIN_NOT_CONTAIN_SPECIAL_LETTERS(513028,"System user pin must contain special letters"), - SYS_USER_PIN_LONGTIME_NO_MODIFY(513029,"System user pin has not been modified for a long time more than {0}"), - SYS_USER_PIN_RETRY_ERROR(513030,"System user pin too many errors more than {0} , please try again after {1} minutes"), + SYS_USER_PIN_LONGTIME_NO_MODIFY(513029,"System user pin has not been modified for a long time more than {0} days"), + SYS_USER_PIN_RETRY_ERROR(513030,"System user pin too many errors more than {0} times, please try again after {1} minutes"), SYS_MENU_ISNULL(516023, "Menu is not exsits"), SYS_MENU_ID_ISNULL(511024, "Menu id is required"), SYS_MENU_NAME_ISNULL(511025, "Menu name is required"), @@ -569,7 +575,7 @@ public enum RCode { AGENT_PORT_ERROR(523012, "Agent port is incorrect"), AGENT_HOST_ERROR(523013, "Agent host is incorrect"), AGENT_NOTEXSITS(526014, "Agent is not exsits"), // Agent 不存在 - AGENT_EXIST_ERROR(526015, "Agent is exists : host,type,port repeat"), + AGENT_EXIST_ERROR(526015, "Agent is exists : host,port repeat"), AGENT_TYPE_INVALIDE(523016,"Agent type is incorrect"), AGENT_UNAVAILABLE(526017,"No agent available"), AGENT_TOKEN_ISNULL(521018, "Agent token info can not be empty"), @@ -768,6 +774,7 @@ public enum RCode { SYS_ROLE_CANNOT_DELETE(587007, "Built-in roles cannot be deleted"), SYS_ROLE_REMOVE_ERROR(587008,"These roles contains user can't remove roles"), SYS_ROLE_RELOBJ_CAN_NOT_REMOVE(587009, "Role have associated data and cannot be deleted"), + SYS_ROLE_NOT_SUPPORT_MODIFY(587010, "The built-in role does not support modification"), /** @@ -790,6 +797,7 @@ public enum RCode { SYS_BACKUP_FILENAME_ISNULL(601000, "System backup file name cannot be empty"), SYS_BACKUP_FILENAME_NOTEXIST(601001, "System backup file does not exist"), SYS_BACKUP_ERROR(609002, "System data backup is abnormal"), + SYS_BACKUP_IN_PROGRESS(607003, "System data backup is in progress please try again later"), /** @@ -802,6 +810,25 @@ public enum RCode { TERMINAL_ISNULL(611004, "Error,Terminal is null"), TERMINAL_TELNET_TRANSFER(610005,"Telnet does not allow upload and download"), TERMINAL_QUERYSIZE_INVALIDED(613006, "Terminal query size cannot be less than 1"), + TERMINAL_CONNECTION_HOST_ISNULL(611007, "Terminal connection host can not be null"), + TERMINAL_CONNECTION_PORT_ISNULL(611008, "Terminal connection port can not be null"), + TERMINAL_CONNECTION_AUTHPROTOCOL_INVALIDED(614009, "Terminal connection authProtocol is not in the range of enumeration"), + TERMINAL_CONNECTION_AUTHTYPE_INVALIDED(614010, "Terminal connection authType is not in the range of enumeration"), + TERMINAL_CONNECTION_AUTHUSERNAME_ISNULL(611011, "Terminal connection authUsername can not be null"), + TERMINAL_CONNECTION_AUTHPIN_ISNULL(611012, "Terminal connection authPin can not be null"), + TERMINAL_CONNECTION_AUTHPRIKEY_ISNULL(611013, "Terminal connection authPriKey can not be null"), + TERMINAL_ASSET_NOT_SUPPORT(618014, "The asset does not support remote terminal"), + TERMINAL_SESSION_NOT_FOUND(616015, "Terminal session not found, expired or does not exist, please login again."), + TERMINAL_CANNOT_DELETE_DIR(617016, "Do not delete directories"), + TERMINAL_UPLOAD_DIRECTORY_ERROR(617017, "The upload path can only be a directory"), + TERMINAL_DOWNLOAD_NO_SUCH_FILE(616018, "No such file"), + TERMINAL_DOWNLOAD_NOT_SUPPORTED_DIRECTORY(617019, "Not supported to get directory"), + TERMINAL_UPLOAD_PROGRESS_NOT_FOUND(616020, "Terminal upload progress information not found, expired or does not exist."), + TERMINAL_NEW_PATH_ISNULL(611021, "File new path cannot be empty"), + TERMINAL_MKDIR_DIR_ALREADY_EXISTS(612022, "The specified file name already exists, please enter another name."), + TERMINAL_LS_FOLDER_ERROR(616023, "Cannot display remote folder"), + TERMINAL_DUPLICATE_SESSION_FAILED(618024, "Duplicate session failed."), + TERMINAL_STOP_SESSION_FAILED(618025, "Failed to stop session"), /** * LINK @@ -965,7 +992,7 @@ public enum RCode { IPAM_IP_ADDR_ERROR(731005,"Ipamip addr format error,please check ip format for ipv4/6"), IPAM_IP_INTERVAL_ERROR(731006,"Ipamip interval already exists"), IPAM_IP_ASSET_ISNULL(731007,"Ipamip asset can not be null"), - IPAM_IP_SUBNET_ISNULL(731008,"Ipamip subnet can not be null"), + IPAM_IP_SUBNET_NOT_EXISTS(731008,"Ipamip subnet not exists"), IPAM_IP_MAC_ERROR(731009,"Ipamip mac error, mac repeat"), IPAM_IP_SUBNET_ADDR_ERROR(731010,"Ipamip addr error, ip addr different subnet addr "), IPAM_IP_MAC_ADDR_ERROR(731011,"Ipamip mac and addr exist"), diff --git a/nz-common/src/main/java/com/nis/common/utils/TypeEnum.java b/nz-common/src/main/java/com/nis/common/utils/TypeEnum.java index eb62108f..6193156d 100644 --- a/nz-common/src/main/java/com/nis/common/utils/TypeEnum.java +++ b/nz-common/src/main/java/com/nis/common/utils/TypeEnum.java @@ -7,15 +7,15 @@ public enum TypeEnum { // 类型type ASSET("asset"), ASSETACCOUNT("asset account"), ASSETACCOUNTREL("asset account rel"), ASSETFIELDGROUP("asset field group"), ASSETFIELDMETA("asset field meta"), ENDPOINT("endpoint"), PROJECT("project"), - TOPO("project topo"), MODULE("module"), ALERTRULE("alert rule"), ALERTMESSAGE("alert message"), PANEL("panel"), - CHART("chart"), VISUALPANEL("visual panel"), VISUALCHART("visual chart"), DATACENTER("datacenter"), + TOPO("project topo"), MODULE("module"), ALERTRULE("alert rule"), ALERTMESSAGE("alert message"), + CHART("chart"), DASHBOARD("dashboard"), VISUALCHART("visual chart"), DATACENTER("datacenter"), CABINET("cabinet"), UNKNOWN("unknown"), MODEL("model"), PROMSERVER("promServer"), ACCOUNT("account"), MIB("mib"), SYSTEM("system"), LINK("link"), SCRIPT("notification script"), ALERTSILENCE("alert silence"), ALERTSEVERITY("alert severity"), ALERTNOTIFYMETHOD("alert notify method"), ASSETSTATECONF("asset state conf"), ASSETTYPECONF("asset type conf"), EXPRESSIONTMPL("expression tmpl"), ASSETBRAND("asset brand"), SNMPCREDENTIAL("snmp credential"), LICENSE("license"), SYSTEMAPIKEY("sys api key"),I18N("i18n"),CTL("ctl"),IPAMSUBNET("ipam subnet"), IPAMIP("ipam ip"),RECORD_RULE("record rule"), ISSUERECORD("issue record"), ISSUEACTIVITY("issue activity"), SYSFILE("sys file"), ASSETCOMMENT("asset comment"), - VSYS("vsys"); + VSYS("vsys"), TERMINAL("terminal"); private String value; @@ -191,10 +191,11 @@ <artifactId>mibble</artifactId> <version>${mibble.version}</version> </dependency> + <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> - <version>5.5.2</version> + <version>5.8.15</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> |
