From ed2c9977b48e200893793378a16c70471daa1827 Mon Sep 17 00:00:00 2001 From: huoyo <1729913829@qq.com> Date: Sat, 6 May 2023 18:28:14 +0800 Subject: [PATCH] add dynamic properties --- pom.xml | 2 +- .../langpy/kotime/config/DefaultConfig.java | 9 ++ .../cn/langpy/kotime/config/LoadConfig.java | 97 +++++++++++----- .../kotime/controller/KoTimeController.java | 43 +++++++ .../cn/langpy/kotime/model/TextParam.java | 13 +++ .../java/cn/langpy/kotime/util/Context.java | 12 ++ .../java/cn/langpy/kotime/util/KoUtil.java | 60 ++++++++-- src/main/resources/kotime-en.html | 106 +++++++++++++----- src/main/resources/kotime.html | 103 ++++++++++++----- 9 files changed, 354 insertions(+), 91 deletions(-) create mode 100644 src/main/java/cn/langpy/kotime/model/TextParam.java diff --git a/pom.xml b/pom.xml index 172132a..774fb49 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.langpy ko-time - 2.4.0 + 2.4.1 KoTime A springboot tool for tracking the paths of the methods,which can help you find method's performances easily. diff --git a/src/main/java/cn/langpy/kotime/config/DefaultConfig.java b/src/main/java/cn/langpy/kotime/config/DefaultConfig.java index 2d5c541..631dad7 100644 --- a/src/main/java/cn/langpy/kotime/config/DefaultConfig.java +++ b/src/main/java/cn/langpy/kotime/config/DefaultConfig.java @@ -45,6 +45,15 @@ public class DefaultConfig { private String mailReceivers; private Integer mailThreshold; private String mailScope; + private String propertyFile; + + public String getPropertyFile() { + return propertyFile; + } + + public void setPropertyFile(String propertyFile) { + this.propertyFile = propertyFile; + } public Boolean getMailEnable() { return mailEnable; diff --git a/src/main/java/cn/langpy/kotime/config/LoadConfig.java b/src/main/java/cn/langpy/kotime/config/LoadConfig.java index a625cb8..318ef14 100644 --- a/src/main/java/cn/langpy/kotime/config/LoadConfig.java +++ b/src/main/java/cn/langpy/kotime/config/LoadConfig.java @@ -3,7 +3,6 @@ package cn.langpy.kotime.config; import cn.langpy.kotime.annotation.KoListener; import cn.langpy.kotime.handler.RunTimeHandler; import cn.langpy.kotime.handler.InvokedHandler; -import cn.langpy.kotime.service.EmailSendService; import cn.langpy.kotime.service.GraphService; import cn.langpy.kotime.service.InvokedQueue; import cn.langpy.kotime.util.Common; @@ -17,7 +16,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Lazy; +import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @@ -25,6 +24,7 @@ import org.springframework.util.StringUtils; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.sql.DataSource; +import java.io.*; import java.util.Map; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -68,35 +68,7 @@ public class LoadConfig { @PostConstruct public void initConfig() { - DefaultConfig config = new DefaultConfig(); - config.setLogEnable(defaultConfig.getLogEnable() == null ? logEnable : defaultConfig.getLogEnable()); - config.setLogLanguage(defaultConfig.getLogLanguage() == null ? logLanguage : defaultConfig.getLogLanguage()); - config.setThreshold(defaultConfig.getThreshold() == null ? timeThreshold : defaultConfig.getThreshold()); - config.setExceptionEnable(defaultConfig.getExceptionEnable() == null ? exceptionEnable : defaultConfig.getExceptionEnable()); - config.setSaver(defaultConfig.getSaver() == null ? saveSaver : defaultConfig.getSaver()); - config.setEnable(defaultConfig.getEnable() == null ? kotimeEnable : defaultConfig.getEnable()); - config.setDataPrefix(defaultConfig.getDataPrefix() == null ? (StringUtils.hasText(serverContext)?serverContext.substring(1):"KOTIME") : defaultConfig.getDataPrefix()); - config.setContextPath(defaultConfig.getContextPath()); - config.setLanguage(defaultConfig.getLanguage() == null ? "chinese" : defaultConfig.getLanguage()); - config.setThreadNum(defaultConfig.getThreadNum() == null ? 2 : defaultConfig.getThreadNum()); - config.setDiscardRate(defaultConfig.getDiscardRate() == null ? 0.3 : defaultConfig.getDiscardRate()); - config.setAuthExpire(defaultConfig.getAuthExpire() == null ? (12*60*60l) : defaultConfig.getAuthExpire()); - config.setAuthEnable(defaultConfig.getAuthEnable() == null ? false : defaultConfig.getAuthEnable()); - config.setParamAnalyse(defaultConfig.getParamAnalyse() == null ? true : defaultConfig.getParamAnalyse()); - config.setDataReset(defaultConfig.getDataReset() == null ? false : defaultConfig.getDataReset()); - config.setVersionNotice(defaultConfig.getVersionNotice() == null ? true : defaultConfig.getVersionNotice()); - config.setStaticToken(defaultConfig.getStaticToken()); - - config.setMailEnable(defaultConfig.getMailEnable()); - config.setMailProtocol(defaultConfig.getMailProtocol() == null ? "smtp" : defaultConfig.getMailProtocol()); - config.setMailHost(defaultConfig.getMailHost() == null ? "smtp.qq.com" : defaultConfig.getMailHost()); - config.setMailPort(defaultConfig.getMailPort() == null ? 587 : defaultConfig.getMailPort()); - config.setMailEncoding(defaultConfig.getMailEncoding() == null ? "UTF-8" : defaultConfig.getMailEncoding()); - config.setMailThreshold(defaultConfig.getMailThreshold() == null ? 4: defaultConfig.getMailThreshold()); - config.setMailScope(defaultConfig.getMailScope() == null ? "Controller": defaultConfig.getMailScope()); - config.setMailUser(defaultConfig.getMailUser()); - config.setMailCode(defaultConfig.getMailCode()); - config.setMailReceivers(defaultConfig.getMailReceivers()); + DefaultConfig config = improveConfig(); configDataSource(config); configRedisTemplate(config); @@ -123,8 +95,71 @@ public class LoadConfig { log.info("kotime=>view:http://localhost:" + serverPort + serverContext + "/koTime"); } initMethodHandlers(); + + loadPropertyFile(); } + public DefaultConfig improveConfig() { + DefaultConfig config = new DefaultConfig(); + config.setLogEnable(defaultConfig.getLogEnable() == null ? logEnable : defaultConfig.getLogEnable()); + config.setLogLanguage(defaultConfig.getLogLanguage() == null ? logLanguage : defaultConfig.getLogLanguage()); + config.setThreshold(defaultConfig.getThreshold() == null ? timeThreshold : defaultConfig.getThreshold()); + config.setExceptionEnable(defaultConfig.getExceptionEnable() == null ? exceptionEnable : defaultConfig.getExceptionEnable()); + config.setSaver(defaultConfig.getSaver() == null ? saveSaver : defaultConfig.getSaver()); + config.setEnable(defaultConfig.getEnable() == null ? kotimeEnable : defaultConfig.getEnable()); + config.setDataPrefix(defaultConfig.getDataPrefix() == null ? (StringUtils.hasText(serverContext) ? serverContext.substring(1) : "KOTIME") : defaultConfig.getDataPrefix()); + config.setContextPath(defaultConfig.getContextPath()); + config.setLanguage(defaultConfig.getLanguage() == null ? "chinese" : defaultConfig.getLanguage()); + config.setThreadNum(defaultConfig.getThreadNum() == null ? 2 : defaultConfig.getThreadNum()); + config.setDiscardRate(defaultConfig.getDiscardRate() == null ? 0.3 : defaultConfig.getDiscardRate()); + config.setAuthExpire(defaultConfig.getAuthExpire() == null ? (12 * 60 * 60l) : defaultConfig.getAuthExpire()); + config.setAuthEnable(defaultConfig.getAuthEnable() == null ? false : defaultConfig.getAuthEnable()); + config.setParamAnalyse(defaultConfig.getParamAnalyse() == null ? true : defaultConfig.getParamAnalyse()); + config.setDataReset(defaultConfig.getDataReset() == null ? false : defaultConfig.getDataReset()); + config.setVersionNotice(defaultConfig.getVersionNotice() == null ? true : defaultConfig.getVersionNotice()); + config.setStaticToken(defaultConfig.getStaticToken()); + + config.setMailEnable(defaultConfig.getMailEnable()); + config.setMailProtocol(defaultConfig.getMailProtocol() == null ? "smtp" : defaultConfig.getMailProtocol()); + config.setMailHost(defaultConfig.getMailHost() == null ? "smtp.qq.com" : defaultConfig.getMailHost()); + config.setMailPort(defaultConfig.getMailPort() == null ? 587 : defaultConfig.getMailPort()); + config.setMailEncoding(defaultConfig.getMailEncoding() == null ? "UTF-8" : defaultConfig.getMailEncoding()); + config.setMailThreshold(defaultConfig.getMailThreshold() == null ? 4 : defaultConfig.getMailThreshold()); + config.setMailScope(defaultConfig.getMailScope() == null ? "Controller" : defaultConfig.getMailScope()); + config.setMailUser(defaultConfig.getMailUser()); + config.setMailCode(defaultConfig.getMailCode()); + config.setMailReceivers(defaultConfig.getMailReceivers()); + config.setPropertyFile(defaultConfig.getPropertyFile() == null ? "dynamic.properties" : defaultConfig.getPropertyFile()); + return config; + } + + public void loadPropertyFile() { + ClassPathResource classPathResource = new ClassPathResource(Context.getConfig().getPropertyFile()); + try ( + InputStream inputStream = classPathResource.getInputStream(); + InputStreamReader streamReader = new InputStreamReader(inputStream, "utf-8"); + BufferedReader reader = new BufferedReader(streamReader)) { + String line = ""; + Map dynamicProperties = Context.getDynamicProperties(); + while ((line = reader.readLine()) != null) { + line = line.trim(); + int i = line.indexOf("="); + if (i<1) { + continue; + } + String propertyStr = line.substring(0, i).trim(); + String valueStr = line.substring(i+1).trim(); + dynamicProperties.put(propertyStr,valueStr); + } + } catch (UnsupportedEncodingException e) { + log.severe("kotime=>dynamic.properties requires utf-8"); + e.printStackTrace(); + } catch (FileNotFoundException e){ + log.warning("kotime=>No dynamic.properties found so that you can not use dynamic properties to set."); + }catch (IOException e) { + e.printStackTrace(); + } + } public void configDataSource(DefaultConfig config) { diff --git a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java index 7086ea1..655b3cd 100644 --- a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java +++ b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java @@ -385,4 +385,47 @@ public class KoTimeController { map.put("threads", threads); return map; } + + @PostMapping("/updateDynamicProperties") + @ResponseBody + @Auth + public boolean updateDynamicProperties(@RequestBody TextParam textParam) { + if (!StringUtils.hasText(textParam.getText())) { + return false; + } + String[] textSplit = textParam.getText().trim().split("\n"); + Map dynamicProperties = Context.getDynamicProperties(); + for (String line : textSplit) { + line = line.trim(); + int i = line.indexOf("="); + if (i<1) { + continue; + } + String propertyStr = line.substring(0, i).trim(); + String valueStr = line.substring(i+1).trim(); + log.info("updated property: "+propertyStr+"=("+dynamicProperties.get(propertyStr)+"->"+valueStr+")"); + dynamicProperties.put(propertyStr,valueStr); + } + + return true; + } + + @GetMapping("/getDynamicProperties") + @ResponseBody + @Auth + public Map getDynamicProperties() { + Map map = new HashMap(); + map.put("state", 0); + map.put("message", "文件不能为空"); + Map dynamicProperties = Context.getDynamicProperties(); + StringBuilder stringBuilder = new StringBuilder(); + for (String key : dynamicProperties.keySet()) { + String value = dynamicProperties.get(key); + if (value!=null) { + stringBuilder.append(key+"="+value+"\n"); + } + } + map.put("data", stringBuilder.toString()); + return map; + } } diff --git a/src/main/java/cn/langpy/kotime/model/TextParam.java b/src/main/java/cn/langpy/kotime/model/TextParam.java new file mode 100644 index 0000000..97ce02c --- /dev/null +++ b/src/main/java/cn/langpy/kotime/model/TextParam.java @@ -0,0 +1,13 @@ +package cn.langpy.kotime.model; + +public class TextParam { + private String text; + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } +} diff --git a/src/main/java/cn/langpy/kotime/util/Context.java b/src/main/java/cn/langpy/kotime/util/Context.java index 09f1b0a..ac0119c 100644 --- a/src/main/java/cn/langpy/kotime/util/Context.java +++ b/src/main/java/cn/langpy/kotime/util/Context.java @@ -9,6 +9,8 @@ import javax.sql.DataSource; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * zhangchang @@ -20,6 +22,7 @@ public class Context { private static DataSource dataSource; private static StringRedisTemplate stringRedisTemplate; private static GraphService saver; + private static Map dynamicProperties; static { config = new DefaultConfig(); @@ -27,6 +30,7 @@ public class Context { config.setEnable(true); config.setLogLanguage("chinese"); invokedHandlers = new ArrayList<>(); + dynamicProperties = new ConcurrentHashMap<>(); } @@ -77,4 +81,12 @@ public class Context { public static void setSaver(GraphService saver) { Context.saver = saver; } + + public static Map getDynamicProperties() { + return dynamicProperties; + } + + public static void setDynamicProperties(Map dynamicProperties) { + Context.dynamicProperties = dynamicProperties; + } } diff --git a/src/main/java/cn/langpy/kotime/util/KoUtil.java b/src/main/java/cn/langpy/kotime/util/KoUtil.java index af39d74..7ccfa0e 100644 --- a/src/main/java/cn/langpy/kotime/util/KoUtil.java +++ b/src/main/java/cn/langpy/kotime/util/KoUtil.java @@ -10,13 +10,14 @@ import org.springframework.data.redis.core.StringRedisTemplate; import javax.sql.DataSource; import java.util.*; +import java.util.stream.Collectors; public class KoUtil { private final static String koTimeSecret = UUID.randomUUID().toString().replace("-", ""); private final static List choices = randomSecretIndexs(); - private static Map caches = new HashMap<>(); + private static Map caches = new HashMap<>(); /** * nothing to introduce for this, that everyone knows! @@ -50,11 +51,11 @@ public class KoUtil { * note: this Datasource will not affect project's datasource */ public static void setDataSource(DataSource dataSource) { - caches.put("dataSource",dataSource); + caches.put("dataSource", dataSource); } public static DataSource getDataSource() { - return (DataSource)caches.get("dataSource"); + return (DataSource) caches.get("dataSource"); } /** @@ -62,11 +63,11 @@ public class KoUtil { * note: you can choose one between setRedisTemplate and setJedisPool to save data */ public static void setStringRedisTemplate(RedisTemplate redisTemplate) { - caches.put("redisTemplate",redisTemplate); + caches.put("redisTemplate", redisTemplate); } public static StringRedisTemplate getStringRedisTemplate() { - return (StringRedisTemplate)caches.get("redisTemplate"); + return (StringRedisTemplate) caches.get("redisTemplate"); } @@ -86,9 +87,9 @@ public class KoUtil { ExceptionNode exception = new ExceptionNode(); exception.setName(e.getClass().getSimpleName()); exception.setClassName(e.getClass().getName()); - exception.setMessage(e.getMessage()+""); - exception.setId(exception.getClassName() +"."+ exception.getName()); - MethodNode current = getCurrentMethodInfo(); + exception.setMessage(e.getMessage() + ""); + exception.setId(exception.getClassName() + "." + exception.getName()); + MethodNode current = getCurrentMethodInfo(); for (StackTraceElement stackTraceElement : e.getStackTrace()) { if (stackTraceElement.getClassName().equals(current.getClassName())) { exception.setValue(stackTraceElement.getLineNumber()); @@ -104,6 +105,7 @@ public class KoUtil { /** * get the current method + * * @return */ public static MethodNode getCurrentMethodInfo() { @@ -172,4 +174,46 @@ public class KoUtil { return decodeStr; } + public static void setProperty(String propertyName, String propertyValue) { + Context.getDynamicProperties().put(propertyName, propertyValue); + } + + public static String getProperty(String propertyName) { + String value = Context.getDynamicProperties().get(propertyName); + return value; + } + + public static int getPropertyAsInteger(String propertyName) { + String value = getProperty(propertyName); + return Integer.valueOf(value); + } + + public static double getPropertyAsDouble(String propertyName) { + String value = getProperty(propertyName); + return Double.valueOf(value); + } + + public static double getPropertyAsFloat(String propertyName) { + String value = getProperty(propertyName); + return Float.valueOf(value); + } + + public static boolean getPropertyAsBoolean(String propertyName) { + String value = getProperty(propertyName); + if ("true".equals(value) || "false".equals(value)) { + return Boolean.valueOf(value); + } + throw new RuntimeException("can not convert null value to boolean value."); + } + + public static List getPropertyAsList(String propertyName, String split) { + String value = getProperty(propertyName); + if (value == null) { + throw new RuntimeException("can not convert null value to list values."); + } + String[] split1 = value.split(split); + return Arrays.stream(split1).collect(Collectors.toList()); + } + + } diff --git a/src/main/resources/kotime-en.html b/src/main/resources/kotime-en.html index e1a68a5..eaba05d 100644 --- a/src/main/resources/kotime-en.html +++ b/src/main/resources/kotime-en.html @@ -260,6 +260,40 @@ complete: function () {} }) } + + function updateDynamicProperties(){ + let propertiesDom = document.querySelector("#dynamicText"); + let propertiesText = propertiesDom.value; + if (propertiesText && propertiesText.indexOf("=")>0) { + $.ajax({ + type:'POST', + url:concatToken('contextPath/koTime/updateDynamicProperties'), + data:JSON.stringify({ + text:propertiesText + }), + dataType:'json', + headers: { + 'Content-Type': 'application/json' + }, + success:function (re) { + UIkit.notification.closeAll(); + UIkit.notification("更新成功",{}); + } + }); + }else { + UIkit.notification.closeAll(); + UIkit.notification("更新失败,请正确编写配置!",{}); + } + + } + + function loadDynamicProperties() { + $.get(concatToken('contextPath/koTime/getDynamicProperties'), function (data) { + let text = data['data']; + document.querySelector("#dynamicText").value = text; + }); + } + function loadLatestVersion(){ /*get the latest version so that you can update kotime immediately*/ $.ajax({ @@ -515,6 +549,7 @@ loadHeapMemoryInfo(); loadPhysicalMemoryInfo(); loadThreadsInfo(); + loadDynamicProperties(); } }); } @@ -778,32 +813,51 @@ - - KoTime switch: - - exception switch: - - console log switch: - - email switch: - - language switch: - - Chinese - English - - - time threshold: OK - - clear data:OK - - - - - - Please refresh this page after updating configurations - - + + KoTime Configuration + dynamic.properties Configuration + + + + + + KoTime switch: + + exception switch: + + console log switch: + + email switch: + + language switch: + + Chinese + English + + + time threshold: OK + + clear data:OK + + + + + + Please refresh this page after updating configurations + + + + + + + + + + OK + + + + diff --git a/src/main/resources/kotime.html b/src/main/resources/kotime.html index 830407e..9f34fef 100644 --- a/src/main/resources/kotime.html +++ b/src/main/resources/kotime.html @@ -50,6 +50,7 @@ loadHeapMemoryInfo(); loadPhysicalMemoryInfo(); loadThreadsInfo(); + loadDynamicProperties(); } }); @@ -438,6 +439,39 @@ }) } + function updateDynamicProperties(){ + let propertiesDom = document.querySelector("#dynamicText"); + let propertiesText = propertiesDom.value; + if (propertiesText && propertiesText.indexOf("=")>0) { + $.ajax({ + type:'POST', + url:concatToken('contextPath/koTime/updateDynamicProperties'), + data:JSON.stringify({ + text:propertiesText + }), + dataType:'json', + headers: { + 'Content-Type': 'application/json' + }, + success:function (re) { + UIkit.notification.closeAll(); + UIkit.notification("更新成功",{}); + } + }); + }else { + UIkit.notification.closeAll(); + UIkit.notification("更新失败,请正确编写配置!",{}); + } + + } + + function loadDynamicProperties() { + $.get(concatToken('contextPath/koTime/getDynamicProperties'), function (data) { + let text = data['data']; + document.querySelector("#dynamicText").value = text; + }); + } + function loadLatestVersion(){ $.ajax({ url: 'http://www.kotime.cn/common/latestVersion?version=2.3.8', @@ -771,31 +805,50 @@ - - 开启koTime: - - 开启异常监测: - - 开启控制台日志: - - 开启邮件通知: - - 语言选择: - - 中文 - 英文 - - - 方法运行时间阈值: 确认 - - 清空链路数据:确认 - - - - - 变更配置以后请重新刷新页面 - - + + KoTime配置 + dynamic.properties配置 + + + + + + 开启koTime: + + 开启异常监测: + + 开启控制台日志: + + 开启邮件通知: + + 语言选择: + + 中文 + 英文 + + + 方法运行时间阈值: 确认 + + 清空链路数据:确认 + + + + + 变更配置以后请重新刷新页面 + + + + + + + + + + 更新 + + + +
Please refresh this page after updating configurations
变更配置以后请重新刷新页面