邮件可读性;添加告警类型;邮件模板配置

This commit is contained in:
lizl9 2016-04-20 22:33:23 +08:00
parent 2f3917d7d4
commit 30bbf284c6
10 changed files with 360 additions and 78 deletions

View File

@ -84,11 +84,7 @@ public class Config {
public static boolean ALARM_OFF_FLAG = false;
public static class Checker {
public static boolean TURN_ON_EXCEPTION_CHECKER = true;
public static boolean TURN_ON_EXECUTE_TIME_CHECKER = true;
}
public static String ALARM_TYPE_CONFIG_ID = "1004";
}
public static class MailSenderInfo {
@ -97,5 +93,5 @@ public class Config {
public static class TemplateInfo {
public static String CONFIG_ID = "1001";
}
}
}

View File

@ -4,6 +4,7 @@ import com.ai.cloud.skywalking.alarm.util.DBConnectUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -12,15 +13,29 @@ public class SystemConfigDao {
private static Logger logger = LogManager.getLogger(AlarmMessageDao.class);
public static String getSystemConfig(String configId) throws SQLException {
PreparedStatement ps = DBConnectUtil.getConnection().prepareStatement(
"SELECT system_config.conf_value FROM system_config WHERE system_config.sts = " +
"? AND system_config.config_id = ?");
ps.setString(1, "A");
ps.setString(2, configId);
String result = "";
Connection connection = DBConnectUtil.getConnection();
try {
PreparedStatement ps = connection.prepareStatement(
"SELECT system_config.conf_value FROM system_config WHERE system_config.sts = " +
"? AND system_config.config_id = ?");
ps.setString(1, "A");
ps.setString(2, configId);
ResultSet resultSet = ps.executeQuery();
resultSet.next();
return resultSet.getString("conf_value");
ResultSet resultSet = ps.executeQuery();
resultSet.next();
result = resultSet.getString("conf_value");
} catch (Exception e) {
logger.error("Failed to find systemConfig.");
throw e;
} finally {
if(connection != null) {
connection.close();
}
}
return result;
}
}

View File

@ -1,14 +1,18 @@
package com.ai.cloud.skywalking.alarm.model;
import java.util.Date;
public class AlarmMessage {
private String traceid;
private String traceid;
private String exceptionMsg;
private Date date;
public AlarmMessage(String traceid, String exceptionMsg) {
super();
this.traceid = traceid;
this.exceptionMsg = exceptionMsg;
this.date = this.getDate(traceid);
}
public String getTraceid() {
@ -17,5 +21,28 @@ public class AlarmMessage {
public String getExceptionMsg() {
return exceptionMsg;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
private Date getDate(String traceid) {
Date date;
String[] traceidPartitions = traceid.split("\\.");
try {
String timeStr = traceidPartitions[2];
Long timeStamp = Long.parseLong(timeStr);
date = new Date(timeStamp);
} catch (Exception e) {
return null;
}
return date;
}
}

View File

@ -0,0 +1,36 @@
package com.ai.cloud.skywalking.alarm.model;
public class AlarmType {
//告警类型名称
private String type;
//告警标签
private String label;
//告警描述
private String desc;
@Override
public String toString() {
return "AlarmType [type=" + type + ", label=" + label + ", desc=" + desc + "]";
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@ -1,28 +1,30 @@
package com.ai.cloud.skywalking.alarm.procesor;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import redis.clients.jedis.Jedis;
import com.ai.cloud.skywalking.alarm.model.AlarmMessage;
import com.ai.cloud.skywalking.alarm.model.AlarmRule;
import com.ai.cloud.skywalking.alarm.model.AlarmType;
import com.ai.cloud.skywalking.alarm.model.ApplicationInfo;
import com.ai.cloud.skywalking.alarm.model.MailInfo;
import com.ai.cloud.skywalking.alarm.model.UserInfo;
import com.ai.cloud.skywalking.alarm.util.AlarmTypeUtil;
import com.ai.cloud.skywalking.alarm.util.MailUtil;
import com.ai.cloud.skywalking.alarm.util.RedisUtil;
import com.ai.cloud.skywalking.alarm.util.RedisUtil.Executable;
@ -30,62 +32,74 @@ import com.ai.cloud.skywalking.alarm.util.TemplateConfigurationUtil;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import redis.clients.jedis.Jedis;
public class AlarmMessageProcessor {
private static Logger logger = LogManager
.getLogger(AlarmMessageProcessor.class);
static String mailTemplate = "";
private static Logger logger = LogManager .getLogger(AlarmMessageProcessor.class);
static List<AlarmType> alarmTypeList;
static Template t;
static {
Properties properties = new Properties();
try {
properties.load(AlarmMessageProcessor.class.getResourceAsStream("/mail-template_new.config"));
mailTemplate = properties.getProperty("template.default");
} catch (IOException e) {
e.printStackTrace();
}
alarmTypeList = AlarmTypeUtil.getAlarmTypeList();
}
public void process(UserInfo userInfo, AlarmRule rule) throws TemplateException, IOException, SQLException {
Set<AlarmMessage> warningObjects = new HashSet<AlarmMessage>();
public void process(UserInfo userInfo, AlarmRule rule) throws TemplateException, IOException, SQLException {
Map<String, List<AlarmMessage>> warningMap = new HashMap<String, List<AlarmMessage>>();
Set<String> warningMessageKeys = new HashSet<String>();
long currentFireMinuteTime = System.currentTimeMillis() / (10000 * 6);
long currentFireMinuteTime = System.currentTimeMillis() / (1000 * 60);
long warningTimeWindowSize = currentFireMinuteTime
- rule.getPreviousFireTimeM();
// 获取待发送数据
if (warningTimeWindowSize >= rule.getConfigArgsDescriber().getPeriod()) {
for (ApplicationInfo applicationInfo : rule.getApplicationInfos()) {
for (int period = 0; period < warningTimeWindowSize; period++) {
String alarmKey = userInfo.getUserId()
+ "-"
+ applicationInfo.getAppCode()
+ "-"
+ (currentFireMinuteTime - period - 1);
warningMessageKeys.add(alarmKey);
setAlarmMessages(alarmKey, warningObjects);
// 获取待发送数据
if (warningTimeWindowSize >= rule.getConfigArgsDescriber().getPeriod()) {
for(AlarmType alarmType : alarmTypeList) {
String type = alarmType.getType();
List<AlarmMessage> warningObjects = new ArrayList<AlarmMessage>();
for (ApplicationInfo applicationInfo : rule.getApplicationInfos()) {
for (int period = 0; period < warningTimeWindowSize; period++) {
Long currentMinuteTime = currentFireMinuteTime - period - 1;
String alarmKey = userInfo.getUserId()
+ "-"
+ applicationInfo.getAppCode()
+ "-"
+ currentMinuteTime;
if(!type.equals("default")) {
alarmKey += "-" + type;
}
warningMessageKeys.add(alarmKey);
setAlarmMessages(alarmKey, warningObjects);
}
}
if(warningObjects.size() > 0) {
warningMap.put(type, warningObjects);
}
}
}
// 发送告警数据
if (warningObjects.size() > 0) {
int warningSize = this.getWarningSize(warningMap);
if ( warningSize > 0) {
if ("0".equals(rule.getTodoType())) {
logger.info("A total of {} alarm information needs to be sent {}", warningObjects.size(),
logger.info("A total of {} alarm information needs to be sent {}", warningSize,
rule.getConfigArgsDescriber().getMailInfo().getMailTo());
// 发送邮件
String subjects = generateSubject(warningObjects.size(),
String subjects = generateSubject(userInfo.getUserName(), warningSize,
rule.getPreviousFireTimeM(), currentFireMinuteTime);
Map<String, Object> parameter = new HashMap<String, Object>();
parameter.put("warningObjects", warningObjects);
parameter.put("alarmTypeList", alarmTypeList);
parameter.put("warningMap", warningMap);
parameter.put("name", userInfo.getUserName());
parameter.put("startDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(
rule.getPreviousFireTimeM() * 10000 * 6)));
parameter.put("endDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(
currentFireMinuteTime * 10000 * 6)));
String mailContext = generateContent(mailTemplate, parameter);
String mailContext = generateContent(parameter);
if (mailContext.length() > 0) {
MailInfo mailInfo = rule.getConfigArgsDescriber()
.getMailInfo();
@ -113,8 +127,11 @@ public class AlarmMessageProcessor {
currentFireMinuteTime);
}
private String generateSubject(int count, long startTime, long endTime) {
String title = "[Warning] There were "
private String generateSubject(String userName, int count, long startTime, long endTime) {
//TODO:邮件标题修改添加了名称
String title = "[Warning] Dear "
+ userName
+ ", there were "
+ count
+ " alarm information between "
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(
@ -145,7 +162,7 @@ public class AlarmMessageProcessor {
});
}
private void setAlarmMessages(final String key, final Collection<AlarmMessage> warningTracingIds) {
private void setAlarmMessages(final String key, final Collection<AlarmMessage> warningTracingIds) {
RedisUtil.execute(new Executable<Object>() {
@Override
public Collection<String> exe(Jedis client) {
@ -160,11 +177,23 @@ public class AlarmMessageProcessor {
});
}
private String generateContent(String templateStr, Map parameter) throws IOException, TemplateException, SQLException {
Template t = null;
t = new Template(null, new StringReader(templateStr), TemplateConfigurationUtil.getConfiguration());
private String generateContent(Map parameter) throws IOException, TemplateException, SQLException {
if(t == null) {
t = TemplateConfigurationUtil.getConfiguration().getTemplate("mail-template.ftl");
}
StringWriter out = new StringWriter();
t.process(parameter, out);
return out.getBuffer().toString();
}
}
private int getWarningSize(Map<String, List<AlarmMessage>> warningMap) {
int result = 0;
for(Entry<String, List<AlarmMessage>> entry :warningMap.entrySet()) {
if(entry.getValue() != null) {
result += entry.getValue().size();
}
}
return result;
}
}

View File

@ -0,0 +1,45 @@
package com.ai.cloud.skywalking.alarm.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.ai.cloud.skywalking.alarm.conf.Config;
import com.ai.cloud.skywalking.alarm.dao.SystemConfigDao;
import com.ai.cloud.skywalking.alarm.model.AlarmType;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class AlarmTypeUtil {
private static Logger logger = LogManager.getLogger(AlarmTypeUtil.class);
private static List<AlarmType> alarmTypeList;
static {
try {
String typeInfo = SystemConfigDao.getSystemConfig(Config.Alarm.ALARM_TYPE_CONFIG_ID);
alarmTypeList = new Gson().fromJson(typeInfo, new TypeToken<ArrayList<AlarmType>>() {
}.getType());
} catch (Exception e) {
logger.error("Failed to load alarm type info.", e);
System.exit(-1);
}
}
public static List<AlarmType> getAlarmTypeList() {
if (alarmTypeList == null || alarmTypeList.isEmpty()) {
alarmTypeList = new ArrayList<AlarmType>();
}
AlarmType defaultType = new AlarmType();
defaultType.setType("default");
defaultType.setLabel("mark");
defaultType.setDesc("Others");
alarmTypeList.add(defaultType);
return alarmTypeList;
}
}

View File

@ -1,31 +1,37 @@
package com.ai.cloud.skywalking.alarm.util;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.ai.cloud.skywalking.alarm.conf.Config;
import com.ai.cloud.skywalking.alarm.dao.SystemConfigDao;
import com.google.gson.Gson;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public class MailUtil {
private static Logger logger = LogManager.getLogger(MailUtil.class);
private static String sendAccount;
private static String mailSender;
private static Properties config;
static {
try {
String senderInfo = SystemConfigDao.getSystemConfig(Config.MailSenderInfo.configId);
config = new Gson().fromJson(senderInfo, Properties.class);
sendAccount = config.getProperty("mail.username") + config.getProperty("mail.account.prefix");
mailSender = config.getProperty("mail.sender");
} catch (Exception e) {
logger.error("Failed to connect the mail System.", e);
logger.error("Failed to load mail sender info.", e);
System.exit(-1);
}
}
@ -38,7 +44,7 @@ public class MailUtil {
ts = session.getTransport();
ts.connect(config.getProperty("mail.host"), config.getProperty("mail.username"), config.getProperty("mail.password"));
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(sendAccount));
message.setFrom(new InternetAddress(mailSender));
InternetAddress[] recipientAccountArray = new InternetAddress[recipientAccounts.length];
for (int i = 0; i < recipientAccounts.length; i++) {
recipientAccountArray[i] = new InternetAddress(recipientAccounts[i]);

View File

@ -1,22 +1,29 @@
package com.ai.cloud.skywalking.alarm.util;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import com.ai.cloud.skywalking.alarm.conf.Config;
import com.ai.cloud.skywalking.alarm.dao.SystemConfigDao;
import freemarker.template.Configuration;
import freemarker.template.TemplateModelException;
import freemarker.template.Version;
import java.sql.SQLException;
public class TemplateConfigurationUtil {
private static Configuration cfg;
public static Configuration getConfiguration() throws SQLException, TemplateModelException {
public static Configuration getConfiguration() throws SQLException, TemplateModelException, IOException {
if (cfg == null) {
cfg = new Configuration(new Version("2.3.23"));
cfg.setDefaultEncoding("UTF-8");
cfg.setSharedVariable("portalAddr", SystemConfigDao.getSystemConfig(Config.TemplateInfo.CONFIG_ID));
//获取资源路径
String classPath = cfg.getClass().getResource("/").getFile().toString();
cfg.setDirectoryForTemplateLoading(new File(classPath));
}
return cfg;

View File

@ -59,11 +59,8 @@ alarm.redis_min_idle=1
alarm.redis_max_total=50
#是否关闭告警发送
alarm.alarm_off_flag=false
#告警检查器:异常告警检查
alarm.checker.turn_on_exception_checker=true
#告警检查器:执行时间超时告警检查
alarm.checker.turn_on_execute_time_checker=true
#告警类型配置id
alarm.alarm_type_config_id=1004
#邮件发送配置id
mailsenderinfo.configid=1000

View File

@ -0,0 +1,124 @@
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<meta http-equiv="Content-Type"content="text/html;charset=utf-8">
<style type="text/css">
li{text-indent:2em}
body {
color: #4f6b72;0
background: #E6EAE9;
}
#mainTable {
text-align:left;
font:12px/15px simsun;
line-height:20px;
color:#000;
background: #fff;
padding:30px 20px;
border:20px solid #fff;
margin:0 auto;
border-collapse:collapse;
border-spacing:0;
}
a {
color: #c75f3e;
}
.greetings {
background:#f9f9f9;
font-family:Microsoft YaHei,SimHei,Arial;
}
#mainTd {
margin:0;
padding:0;
}
#mainDiv {
background:#f9f9f9;
padding:25px;
font-size:14px;
line-height:25px;
margin:5px 0;
overflow:hidden;
}
#dataTable {
border-collapse:collapse;
border:none;
}
#dataTableHead {
display: none
}
#dataTable td {
border-bottom: 1px solid #C1DAD7;
background: #fff;
font-size:11px;
padding: 6px 6px 6px 12px;
color: #4f6b72;
}
#dataTable td.alt {
border-right: 1px solid #C1DAD7;
background: #F5FAFA;
color: #797268;
}
th.spec {
border: 1px solid #C1DAD7;
background: #CAE8EA ;
font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
padding: 6px 6px 6px 12px;
}
th.specalt {
border: 1px solid #C1DAD7;
background: #f5fafa;
font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
color: #797268;
padding: 6px 6px 6px 12px;
}
.type td p {
font: bold 14px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
}
</style>
<title>
templete1_welcome
</title>
</head>
<body>
<div id="mainDiv">
<p class="greetings">Dear ${name!}:</p>
<p class="greetings">&nbsp&nbsp&nbsp&nbspOur platform received alarm infomation between <b>${startDate!} </b>to<b> ${endDate!}</b> as follows:
</p>
<table id="dataTable" width="80%">
<tr id="dataTableHead">
<td width="15%"></td>
<td></td>
</tr>
<#list alarmTypeList as alarmType>
<#if warningMap?exists>
<#if warningMap[alarmType.type]?exists>
<tr class="type">
<td class="typeTd" colspan="2" style="padding: 6px 6px 6px 6px;"><p>${alarmType.desc}</p></td>
</tr>
<#list warningMap[alarmType.type] as element>
<tr>
<th class="spec"><p>traceid</p></th>
<td class="alt"><a href=\"${(portalAddr + warningObject.traceid)!}\">${element.traceid!}</a><#if element.date?exists>&nbsp&nbsp&nbsp&nbsp<span>${element.date?string("yyyy-MM-dd HH:mm:ss ")}</span></#if></td>
</tr>
<tr>
<th class="specalt"><p>${(alarmType.label)}</p></th>
<td class="alt"><p>${element.exceptionMsg}</p></td>
</tr>
</#list>
</#if>
</#if>
</#list>
</table>
</body>
</html>