package com.sohu.cache.inspect.impl;
import com.sohu.cache.alert.impl.BaseAlertService;
import com.sohu.cache.constant.InstanceStatusEnum;
import com.sohu.cache.dao.AppDao;
import com.sohu.cache.dao.InstanceDao;
import com.sohu.cache.dao.InstanceFaultDao;
import com.sohu.cache.entity.AppDesc;
import com.sohu.cache.entity.InstanceFault;
import com.sohu.cache.entity.InstanceInfo;
import com.sohu.cache.inspect.InspectParamEnum;
import com.sohu.cache.inspect.Inspector;
import com.sohu.cache.redis.RedisCenter;
import com.sohu.cache.util.TypeUtil;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Created by yijunzhang on 15-1-20.
*/
public class InstanceRunInspector extends BaseAlertService implements Inspector {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 实例相关
*/
private InstanceDao instanceDao;
/**
* redis相关
*/
private RedisCenter redisCenter;
/**
* 应用相关dao
*/
private AppDao appDao;
private InstanceFaultDao instanceFaultDao;
@Override
public boolean inspect(Map<InspectParamEnum, Object> paramMap) {
String host = MapUtils.getString(paramMap, InspectParamEnum.SPLIT_KEY);
List<InstanceInfo> list = (List<InstanceInfo>) paramMap.get(InspectParamEnum.INSTANCE_LIST);
for (InstanceInfo info : list) {
final int port = info.getPort();
final int type = info.getType();
long appId = info.getAppId();
if (TypeUtil.isRedisType(type)) {
boolean isRun;
if (TypeUtil.isRedisSentinel(type)) {
isRun = redisCenter.isRun(host, port);
} else {
isRun = redisCenter.isRun(appId, host, port);
}
Boolean isUpdate = updateInstanceByRun(isRun, info);
if (isUpdate == null) {
continue;
} else if (isUpdate) {
redisCenter.deployRedisCollection(appId, host, port);
redisCenter.deployRedisSlowLogCollection(appId, host, port);
} else {
redisCenter.unDeployRedisCollection(appId, host, port);
redisCenter.unDeployRedisSlowLogCollection(appId, host, port);
}
// 错误
if (isUpdate != null) {
alertInstanceInfo(info);
}
}
}
return true;
}
/**
* 邮箱+短信
* @param info
*/
private void alertInstanceInfo(InstanceInfo info){
sendEmailAlert(info);
sendPhoneAlert(info);
}
/**
* 发送短信报警
*
* @param info
*/
private void sendPhoneAlert(InstanceInfo info) {
if (info == null) {
return;
}
String message = generateMessage(info, false);
mobileAlertComponent.sendPhoneToAdmin(message);
}
/**
* 发送邮箱报警
*
* @param info
*/
private void sendEmailAlert(InstanceInfo info) {
if (info == null) {
return;
}
String title = "实例(" + info.getIp() + ":" + info.getPort() + ")状态发生变化";
String message = generateMessage(info, true);
emailComponent.sendMailToAdmin(title, message);
}
/**
* 返回示例消息
*
* @param info
* @return
*/
private String generateMessage(InstanceInfo info, boolean isEmail) {
StringBuffer message = new StringBuffer();
long appId = info.getAppId();
AppDesc appDesc = appDao.getAppDescById(appId);
message.append("CacheCloud系统-实例(" + info.getIp() + ":" + info.getPort() + ")-");
if (info.getStatus() == InstanceStatusEnum.ERROR_STATUS.getStatus()) {
message.append("由运行中变为心跳停止");
} else if (info.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) {
message.append("由心跳停止变为运行中");
}
if(isEmail){
message.append(", appId:");
message.append(appId + "-" + appDesc.getName());
}else{
message.append("-appId(" + appId +"-" + appDesc.getName() +")");
}
return message.toString();
}
private void saveFault(InstanceInfo info, boolean isRun) {
InstanceFault instanceFault = new InstanceFault();
instanceFault.setAppId((int) info.getAppId());
instanceFault.setInstId(info.getId());
instanceFault.setIp(info.getIp());
instanceFault.setPort(info.getPort());
instanceFault.setType(info.getType());
instanceFault.setCreateTime(new Date());
if (isRun) {
instanceFault.setReason("恢复运行");
} else {
instanceFault.setReason("心跳停止");
}
instanceFaultDao.insert(instanceFault);
}
private Boolean updateInstanceByRun(boolean isRun, InstanceInfo info) {
if (isRun) {
if (info.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) {
info.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus());
instanceDao.update(info);
logger.warn("instance:{} instance is run", info);
saveFault(info, isRun);
return true;
}
} else {
if (info.getStatus() != InstanceStatusEnum.ERROR_STATUS.getStatus()) {
info.setStatus(InstanceStatusEnum.ERROR_STATUS.getStatus());
instanceDao.update(info);
logger.error("instance:{} instance failed", info);
saveFault(info, isRun);
return false;
}
}
return null;
}
public void setInstanceDao(InstanceDao instanceDao) {
this.instanceDao = instanceDao;
}
public void setRedisCenter(RedisCenter redisCenter) {
this.redisCenter = redisCenter;
}
public void setAppDao(AppDao appDao) {
this.appDao = appDao;
}
public void setInstanceFaultDao(InstanceFaultDao instanceFaultDao) {
this.instanceFaultDao = instanceFaultDao;
}
}