optimize email and add charset for html

This commit is contained in:
huoyo 2023-04-07 14:51:20 +08:00
parent 2f16ef5c90
commit 3abd1b6436
8 changed files with 177 additions and 56 deletions

View File

@ -6,7 +6,7 @@
<groupId>cn.langpy</groupId> <groupId>cn.langpy</groupId>
<artifactId>ko-time</artifactId> <artifactId>ko-time</artifactId>
<version>2.3.9</version> <version>2.4.0</version>
<name>KoTime</name> <name>KoTime</name>
<description>A springboot tool for tracking the paths of the methods,which can help you find method's performances easily.</description> <description>A springboot tool for tracking the paths of the methods,which can help you find method's performances easily.</description>
<licenses> <licenses>

View File

@ -35,6 +35,97 @@ public class DefaultConfig {
private Long authExpire; private Long authExpire;
private Boolean mailEnable;
private String mailHost;
private Integer mailPort;
private String mailProtocol;
private String mailEncoding;
private String mailUser;
private String mailCode;
private String mailReceivers;
private Integer mailThreshold;
private String mailScope;
public Boolean getMailEnable() {
return mailEnable;
}
public void setMailEnable(Boolean mailEnable) {
this.mailEnable = mailEnable;
}
public String getMailHost() {
return mailHost;
}
public void setMailHost(String mailHost) {
this.mailHost = mailHost;
}
public Integer getMailPort() {
return mailPort;
}
public void setMailPort(Integer mailPort) {
this.mailPort = mailPort;
}
public String getMailProtocol() {
return mailProtocol;
}
public void setMailProtocol(String mailProtocol) {
this.mailProtocol = mailProtocol;
}
public String getMailEncoding() {
return mailEncoding;
}
public void setMailEncoding(String mailEncoding) {
this.mailEncoding = mailEncoding;
}
public String getMailUser() {
return mailUser;
}
public void setMailUser(String mailUser) {
this.mailUser = mailUser;
}
public String getMailCode() {
return mailCode;
}
public void setMailCode(String mailCode) {
this.mailCode = mailCode;
}
public String getMailReceivers() {
return mailReceivers;
}
public void setMailReceivers(String mailReceivers) {
this.mailReceivers = mailReceivers;
}
public Integer getMailThreshold() {
return mailThreshold;
}
public void setMailThreshold(Integer mailThreshold) {
this.mailThreshold = mailThreshold;
}
public String getMailScope() {
return mailScope;
}
public void setMailScope(String mailScope) {
this.mailScope = mailScope;
}
public String getStaticToken() { public String getStaticToken() {
return staticToken; return staticToken;
} }

View File

@ -56,18 +56,7 @@ public class LoadConfig {
@Value("${server.servlet.context-path:}") @Value("${server.servlet.context-path:}")
private String serverContext; private String serverContext;
@Value("${ko-time.mail-host:smtp.qq.com}")
private String host;
@Value("${ko-time.mail-port:587}")
private Integer port;
@Value("${ko-time.mail-protocol:smtp}")
private String protocol;
@Value("${ko-time.mail-encoding:UTF-8}")
private String encoding;
@Value("${ko-time.mail-user:}")
private String user;
@Value("${ko-time.mail-code:}")
private String mailCode;
@Value("${ko-time.mail-enable:false}") @Value("${ko-time.mail-enable:false}")
private Boolean mailEnable; private Boolean mailEnable;
@ -97,6 +86,18 @@ public class LoadConfig {
config.setDataReset(defaultConfig.getDataReset() == null ? false : defaultConfig.getDataReset()); config.setDataReset(defaultConfig.getDataReset() == null ? false : defaultConfig.getDataReset());
config.setVersionNotice(defaultConfig.getVersionNotice() == null ? true : defaultConfig.getVersionNotice()); config.setVersionNotice(defaultConfig.getVersionNotice() == null ? true : defaultConfig.getVersionNotice());
config.setStaticToken(defaultConfig.getStaticToken()); 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());
configDataSource(config); configDataSource(config);
configRedisTemplate(config); configRedisTemplate(config);
Context.setConfig(config); Context.setConfig(config);
@ -124,18 +125,7 @@ public class LoadConfig {
initMethodHandlers(); initMethodHandlers();
} }
@Bean
@Lazy
public EmailSendService emailSendService() {
EmailSendService sender = new EmailSendService();
sender.setHost(host);
sender.setPort(port);
sender.setUsername(user);
sender.setPassword(mailCode);
sender.setProtocol(protocol);
sender.setDefaultEncoding(encoding);
return sender;
}
public void configDataSource(DefaultConfig config) { public void configDataSource(DefaultConfig config) {
if (!"database".equals(config.getSaver())) { if (!"database".equals(config.getSaver())) {

View File

@ -79,7 +79,7 @@ public class KoTimeController {
@GetMapping @GetMapping
public void index(String kotoken, String test, HttpServletResponse response, HttpServletRequest request) { public void index(String kotoken, String test,String charset, HttpServletResponse response, HttpServletRequest request) {
if (!Context.getConfig().getEnable()) { if (!Context.getConfig().getEnable()) {
return; return;
} }
@ -90,7 +90,10 @@ public class KoTimeController {
if (StringUtils.hasText(kotoken)) { if (StringUtils.hasText(kotoken)) {
staticTokenVisit = true; staticTokenVisit = true;
} }
response.setContentType("text/html;charset=utf-8"); if (!StringUtils.hasText(charset)) {
charset = "utf-8";
}
response.setContentType("text/html;charset="+charset);
ClassPathResource classPathResource = new ClassPathResource(KoConstant.getViewName()); ClassPathResource classPathResource = new ClassPathResource(KoConstant.getViewName());
try ( try (
InputStream inputStream = classPathResource.getInputStream(); InputStream inputStream = classPathResource.getInputStream();
@ -248,6 +251,9 @@ public class KoTimeController {
if (config.getLogEnable() != null) { if (config.getLogEnable() != null) {
koTimeConfig.setLogEnable(config.getLogEnable()); koTimeConfig.setLogEnable(config.getLogEnable());
} }
if (config.getMailEnable() != null) {
koTimeConfig.setMailEnable(config.getMailEnable());
}
if (config.getThreshold() != null) { if (config.getThreshold() != null) {
koTimeConfig.setThreshold(config.getThreshold()); koTimeConfig.setThreshold(config.getThreshold());
} }

View File

@ -17,16 +17,17 @@ public class EmailHandler implements InvokedHandler {
private static Logger log = Logger.getLogger(EmailHandler.class.toString()); private static Logger log = Logger.getLogger(EmailHandler.class.toString());
@Value("${ko-time.mail-scope:Controller}") @Value("${ko-time.mail-scope:Controller}")
private String mailScope; private String mailScope;
@Autowired
private EmailSendService emailSendService;
@Override @Override
public void onInvoked(MethodNode current, MethodNode parent, Parameter[] names, Object[] values) { public void onInvoked(MethodNode current, MethodNode parent, Parameter[] names, Object[] values) {
if (!Context.getConfig().getMailEnable()) {
return;
}
if (current == null || current.getValue() < Context.getConfig().getThreshold()) { if (current == null || current.getValue() < Context.getConfig().getThreshold()) {
return; return;
} }
if (mailScope.equals("All") || current.getMethodType().name().equals(mailScope)) { if (mailScope.equals("All") || current.getMethodType().name().equals(mailScope)) {
emailSendService.sendNoticeAsync(current); EmailSendService.sendNoticeAsync(current);
} }
} }
} }

View File

@ -2,7 +2,7 @@ package cn.langpy.kotime.service;
import cn.langpy.kotime.model.MethodNode; import cn.langpy.kotime.model.MethodNode;
import cn.langpy.kotime.util.Context; import cn.langpy.kotime.util.Context;
import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -18,50 +18,61 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.logging.Logger; import java.util.logging.Logger;
public class EmailSendService extends JavaMailSenderImpl { public class EmailSendService{
private static Logger log = Logger.getLogger(EmailSendService.class.toString()); private static Logger log = Logger.getLogger(EmailSendService.class.toString());
private volatile static JavaMailSenderImpl javaMailSender;
private static ConcurrentMap<String, Integer> redMethods = new ConcurrentHashMap<>(); private static ConcurrentMap<String, Integer> redMethods = new ConcurrentHashMap<>();
private final static ExecutorService emailExecutors = Executors.newFixedThreadPool(5); private final static ExecutorService emailExecutors = Executors.newFixedThreadPool(5);
@Value("${ko-time.mail-receivers:}") public static JavaMailSender getMailSender() {
private String receivers; if (javaMailSender == null) {
@Value("${ko-time.mail-threshold:4}") synchronized (EmailSendService.class) {
private Integer threshold; if (javaMailSender == null) {
@Value("${ko-time.data-prefix:}") javaMailSender = new JavaMailSenderImpl();
private String dataPrefix; javaMailSender.setHost(Context.getConfig().getMailHost());
@Value("${ko-time.mail-user:}") javaMailSender.setPort(Context.getConfig().getMailPort());
private String user; javaMailSender.setUsername(Context.getConfig().getMailUser());
javaMailSender.setPassword(Context.getConfig().getMailCode());
javaMailSender.setProtocol(Context.getConfig().getMailProtocol());
javaMailSender.setDefaultEncoding(Context.getConfig().getMailEncoding());
}
}
}
return javaMailSender;
}
public void sendNoticeAsync(MethodNode current) { public static void sendNoticeAsync(MethodNode current) {
emailExecutors.submit(() -> sendNotice(current)); emailExecutors.submit(() -> sendNotice(current));
} }
public void sendNotice(MethodNode current) {
if (!StringUtils.hasText(receivers)) { public static void sendNotice(MethodNode current) {
if (!StringUtils.hasText(Context.getConfig().getMailReceivers())) {
return; return;
} }
JavaMailSender mailSender = getMailSender();
if (redMethods.containsKey(current.getId())) { if (redMethods.containsKey(current.getId())) {
int n = redMethods.get(current.getId()); int n = redMethods.get(current.getId());
n += 1; n += 1;
if (n >= threshold) { if (n >= Context.getConfig().getMailThreshold()) {
this.send(createMessage(current)); mailSender.send(createMessage(mailSender,current));
redMethods.put(current.getId(), -2000); redMethods.put(current.getId(), -2000);
} else { } else {
redMethods.put(current.getId(), n); redMethods.put(current.getId(), n);
} }
} else { } else {
redMethods.put(current.getId(), 1); redMethods.put(current.getId(), 1);
if (threshold == 1) { if (Context.getConfig().getMailThreshold() == 1) {
this.send(createMessage(current)); mailSender.send(createMessage(mailSender,current));
} }
} }
} }
private MimeMessage createMessage(MethodNode current) { private static MimeMessage createMessage(JavaMailSender mailSender, MethodNode current) {
MimeMessage mimeMessage = null; MimeMessage mimeMessage = null;
try { try {
mimeMessage = this.createMimeMessage(); mimeMessage = mailSender.createMimeMessage();
configMessage(current, mimeMessage); configMessage(current, mimeMessage);
} catch (MessagingException e) { } catch (MessagingException e) {
log.severe("Error email message!"); log.severe("Error email message!");
@ -69,20 +80,20 @@ public class EmailSendService extends JavaMailSenderImpl {
return mimeMessage; return mimeMessage;
} }
private void configMessage(MethodNode current, MimeMessage mimeMessage) throws MessagingException { private static void configMessage(MethodNode current, MimeMessage mimeMessage) throws MessagingException {
String[] receiversArray = receivers.split(","); String[] receiversArray = Context.getConfig().getMailReceivers().split(",");
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true); MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setSubject("KoTime耗时预警-" + dataPrefix + "-" + current.getName()); messageHelper.setSubject("KoTime耗时预警-" + Context.getConfig().getDataPrefix() + "-" + current.getName());
messageHelper.setFrom(user); messageHelper.setFrom(Context.getConfig().getMailUser());
messageHelper.setTo(receiversArray); messageHelper.setTo(receiversArray);
messageHelper.setSentDate(new Date()); messageHelper.setSentDate(new Date());
messageHelper.setText(createNoticeTemplate(current), true); messageHelper.setText(createNoticeTemplate(current), true);
} }
private String createNoticeTemplate(MethodNode current) { private static String createNoticeTemplate(MethodNode current) {
return "<h4>您有一个方法耗时有" + threshold + "次超过了阈值(" + Context.getConfig().getThreshold() + "),详情如下:</h4>\n" + return "<h4>您有一个方法耗时有" + Context.getConfig().getMailThreshold() + "次超过了阈值(" + Context.getConfig().getThreshold() + "ms),详情如下:</h4>\n" +
"<div style=\"background-color: #fafdfd;border-radius: 5px;width: 600px;padding: 10px;box-shadow: #75f1bf 2px 2px 2px 2px\">\n" + "<div style=\"background-color: #fafdfd;border-radius: 5px;width: 600px;padding: 10px;box-shadow: #75f1bf 2px 2px 2px 2px\">\n" +
" <div>项目:" + dataPrefix + "</div>\n" + " <div>项目:" + Context.getConfig().getDataPrefix() + "</div>\n" +
" <div>类名:" + current.getClassName() + "</div>\n" + " <div>类名:" + current.getClassName() + "</div>\n" +
" <div>方法:" + current.getMethodName() + "</div>\n" + " <div>方法:" + current.getMethodName() + "</div>\n" +
" <div>最近耗时:" + current.getValue() + " ms</div>\n" + " <div>最近耗时:" + current.getValue() + " ms</div>\n" +

View File

@ -366,6 +366,10 @@
let logEnableDom = document.getElementById('logEnable'); let logEnableDom = document.getElementById('logEnable');
logEnableDom.checked = logEnable; logEnableDom.checked = logEnable;
let mailEnable = data['mailEnable'];
let mailEnableDom = document.getElementById('mailEnable');
mailEnableDom.checked = mailEnable;
let language = data['language']; let language = data['language'];
$("#languageSwitch").val(language) $("#languageSwitch").val(language)
}); });
@ -388,6 +392,11 @@
UIkit.notification("<font color='green'>OK</font>",{}); UIkit.notification("<font color='green'>OK</font>",{});
}; };
document.getElementById('mailEnable').onclick = function(){
$.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({mailEnable:document.getElementById('mailEnable').checked}),dataType:'json', headers: {'Content-Type': 'application/json' }});
UIkit.notification("<font color='green'>OK</font>",{});
};
document.getElementById('languageSwitch').onchange = function(){ document.getElementById('languageSwitch').onchange = function(){
let selectedObj = document.getElementById('languageSwitch'); let selectedObj = document.getElementById('languageSwitch');
$.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({language:selectedObj.options[selectedObj.selectedIndex].value}),dataType:'json', headers: {'Content-Type': 'application/json' }}); $.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({language:selectedObj.options[selectedObj.selectedIndex].value}),dataType:'json', headers: {'Content-Type': 'application/json' }});
@ -776,6 +785,8 @@
<br> <br>
<label >console log switch</label> <input id='logEnable' type="checkbox"> <label >console log switch</label> <input id='logEnable' type="checkbox">
<br> <br>
<label >email switch</label> <input id='mailEnable' type="checkbox">
<br>
<label>language switch</label> <label>language switch</label>
<select id="languageSwitch" > <select id="languageSwitch" >
<option value="chinese">Chinese</option> <option value="chinese">Chinese</option>

View File

@ -154,6 +154,11 @@
UIkit.notification("<font color='green'>设置成功</font>",{}); UIkit.notification("<font color='green'>设置成功</font>",{});
}; };
document.getElementById('mailEnable').onclick = function(){
$.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({mailEnable:document.getElementById('mailEnable').checked}),dataType:'json', headers: {'Content-Type': 'application/json' }});
UIkit.notification("<font color='green'>设置成功</font>",{});
};
document.getElementById('languageSwitch').onchange = function(){ document.getElementById('languageSwitch').onchange = function(){
let selectedObj = document.getElementById('languageSwitch'); let selectedObj = document.getElementById('languageSwitch');
$.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({language:selectedObj.options[selectedObj.selectedIndex].value}),dataType:'json', headers: {'Content-Type': 'application/json' }}); $.ajax({type:'POST',url:concatToken('contextPath/koTime/updateConfig'),data:JSON.stringify({language:selectedObj.options[selectedObj.selectedIndex].value}),dataType:'json', headers: {'Content-Type': 'application/json' }});
@ -198,6 +203,10 @@
let logEnableDom = document.getElementById('logEnable'); let logEnableDom = document.getElementById('logEnable');
logEnableDom.checked = logEnable; logEnableDom.checked = logEnable;
let mailEnable = data['mailEnable'];
let mailEnableDom = document.getElementById('mailEnable');
mailEnableDom.checked = mailEnable;
let language = data['language']; let language = data['language'];
$("#languageSwitch").val(language) $("#languageSwitch").val(language)
}); });
@ -769,6 +778,8 @@
<br> <br>
<label >开启控制台日志:</label> <input id='logEnable' type="checkbox"> <label >开启控制台日志:</label> <input id='logEnable' type="checkbox">
<br> <br>
<label >开启邮件通知:</label> <input id='mailEnable' type="checkbox">
<br>
<label>语言选择:</label> <label>语言选择:</label>
<select id="languageSwitch" > <select id="languageSwitch" >
<option value="chinese">中文</option> <option value="chinese">中文</option>