邮件可读性;添加告警类型;邮件模板配置
This commit is contained in:
parent
2f3917d7d4
commit
30bbf284c6
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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">    Our 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>    <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>
|
||||
Loading…
Reference in New Issue