You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

411 lines
13 KiB

using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Aliyun.Acs.Dysmsapi.Model.V20170525;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Sms.V20190711;
using TencentCloud.Sms.V20190711.Models;
using AliSendSmsRequest = Aliyun.Acs.Dysmsapi.Model.V20170525.SendSmsRequest;
using AliSendSmsResponse = Aliyun.Acs.Dysmsapi.Model.V20170525.SendSmsResponse;
using TxSendSmsRequest = TencentCloud.Sms.V20190711.Models.SendSmsRequest;
using TxSendSmsResponse = TencentCloud.Sms.V20190711.Models.SendSmsResponse;
using System.Net.Http;
using LitJson;
using System.Text;
using System.Net.Http.Headers;
namespace Sog
{
public class AppAlerter
{
private bool USE_TENCENT_CLOUD_SMS = true;
private const int DEFAULT_ALERT_INTERVAL = 120;
ServerApp m_app;
string m_serverId;
string m_smsMsg;
string m_robotMsg;
long m_crushUid;
object m_locker = new object();
Dictionary<string, long> m_lastSendSmsTimeDict = new Dictionary<string, long>();
Dictionary<string, long> m_lastSendRobotTimeDict = new Dictionary<string, long>();
private long m_lastSendRobotTime;
private int m_sendRobotCount;
public AppAlerter(ServerApp app)
{
m_app = app;
m_serverId = ServerIDUtils.IDToString(m_app.ServerID);
}
public void AlertException(Exception ex, long uid = 0)
{
lock (m_locker)
{
m_crushUid = uid;
m_smsMsg = "exception: " + ex.Message;
m_robotMsg = ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace;
TrySendSms(DEFAULT_ALERT_INTERVAL);
TrySendRobot(DEFAULT_ALERT_INTERVAL);
}
}
public void AlertMsg(string msg, int interval = DEFAULT_ALERT_INTERVAL, bool bOnlyRobot = false)
{
if(msg == null)
{
return;
}
lock (m_locker)
{
m_smsMsg = msg;
m_robotMsg = msg;
if (!bOnlyRobot)
{
TrySendSms(interval);
}
TrySendRobot(interval);
}
}
private long GetLastSendSmsTime(string msg)
{
if(m_lastSendSmsTimeDict.ContainsKey(msg))
{
return m_lastSendSmsTimeDict[msg];
}
return 0;
}
private void SetLastSendSmsTime(string msg, long lastTime)
{
if (m_lastSendSmsTimeDict.ContainsKey(msg))
{
m_lastSendSmsTimeDict[msg] = lastTime;
}
else
{
m_lastSendSmsTimeDict.Add(msg, lastTime);
}
}
private long GetLastSendRobotTime(string msg)
{
if (m_lastSendRobotTimeDict.ContainsKey(msg))
{
return m_lastSendRobotTimeDict[msg];
}
return 0;
}
private void SetLastSendRobotTime(string msg, long lastTime)
{
if (m_lastSendRobotTimeDict.ContainsKey(msg))
{
m_lastSendRobotTimeDict[msg] = lastTime;
}
else
{
m_lastSendRobotTimeDict.Add(msg, lastTime);
}
}
private void TrySendSms(int interval)
{
if(m_app.AppParam.ServerConfig.alertPhoneNumber == null)
{
//TraceLog.Error("AppAlerter.TrySendSms alertPhoneNumber is null");
return;
}
if (m_app.AppParam.ServerConfig.alertPhoneNumber.Length == 0)
{
//TraceLog.Error("AppAlerter.TrySendSms alertPhoneNumber is 0");
return;
}
long now = m_app.Time.GetTimeSecond();
long lastTime = GetLastSendSmsTime(m_smsMsg);
//每种类型的告警1分钟最多发一条短信
if (now - lastTime < interval)
{
return;
}
SetLastSendSmsTime(m_smsMsg, now);
TraceLog.Error("AppAlerter.TrySendSms new task to send sms msg:{0}", m_smsMsg);
Task sendTask = new Task(SendSmsTask);
sendTask.Start();
}
private void TrySendRobot(int interval)
{
if (!m_app.AppParam.ServerConfig.bWechatRobot)
{
//TraceLog.Error("AppAlerter.TrySendRobot bWechatRobot is false");
return;
}
if (String.IsNullOrEmpty(m_app.AppParam.ServerConfig.wechatRobotKey))
{
//TraceLog.Error("AppAlerter.TrySendRobot wechatRobotKey is null");
return;
}
long now = m_app.Time.GetTimeSecond();
long lastTime = GetLastSendRobotTime(m_robotMsg);
//每种类型的告警1分钟最多发一条短信
if (now - lastTime < interval)
{
return;
}
SetLastSendRobotTime(m_robotMsg, now);
if (now - m_lastSendRobotTime > DEFAULT_ALERT_INTERVAL)
{
m_lastSendRobotTime = now;
m_sendRobotCount = 0;
}
if (m_sendRobotCount >= 1) //限制发送次数
{
//TraceLog.Error("AppAlerter.TrySendRobot m_sendWechatRobotCount is {0}", m_sendRobotCount);
return;
}
m_sendRobotCount++;
TraceLog.Trace("AppAlerter.TrySendRobot new task to send WechatRobot msg:{0}", m_robotMsg);
Task sendTask = new Task(SendWechatRobotTask);
sendTask.Start();
}
private void SendSmsTask()
{
if (USE_TENCENT_CLOUD_SMS)
{
SendSmsTaskTencent();
}
else
{
SendSmsTaskAli();
}
}
private void SendSmsTaskAli()
{
try
{
string product = "Dysmsapi";//短信API产品名称
string domain = "dysmsapi.aliyuncs.com";//短信API产品域名
string accessId = "LTAIwbt8GxIlFWa0";
string accessSecret = "qvGEdOJZB60Toq1YMgo5R4QuYTYmQZ";
string regionIdForPop = "cn-hangzhou";
IClientProfile profile = DefaultProfile.GetProfile(regionIdForPop, accessId, accessSecret);
DefaultProfile.AddEndpoint(regionIdForPop, regionIdForPop, product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
AliSendSmsRequest request = new AliSendSmsRequest();
request.PhoneNumbers = m_app.AppParam.ServerConfig.alertPhoneNumber[0];
request.SignName = "服务器告警";
request.TemplateCode = "SMS_25220245";
string preStr = m_app.AppParam.ServerConfig.alertMsgPre;
if (preStr == null)
{
preStr = "";
}
string json = "{\"serverid\":\"" + preStr + m_serverId + m_smsMsg + "\"}";//用于替换短信模板中的变量
request.TemplateParam = json;
request.OutId = "xxxxxxxx";
//请求失败这里会抛ClientException异常
AliSendSmsResponse sendSmsResponse = acsClient.GetAcsResponse(request);
if (sendSmsResponse == null)
{
TraceLog.Error("AppAlerter.SendSmsTaskAli SendSmsResponse null");
}
else
{
TraceLog.Error("AppAlerter.SendSmsTaskAli SendSmsResponse code {0}", sendSmsResponse.Code);
}
}
catch (Exception)
{
}
}
private void SendSmsTaskTencent()
{
try
{
Credential cred = new Credential
{
SecretId = "AKIDjdGdx1MK7vSjkWwmV7oGQJwKTLwioNpo",
SecretKey = "wc9U0IcgvtazA6nEOfhV3PYPzJH1Yqqb"
};
HttpProfile httpProfile = new HttpProfile();
httpProfile.Endpoint = ("sms.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.HttpProfile = httpProfile;
TxSendSmsRequest req = new TxSendSmsRequest();
req.SmsSdkAppid = "1400194039";
req.Sign = "紫晓互动";
req.PhoneNumberSet = m_app.AppParam.ServerConfig.alertPhoneNumber;
// 模板618826, 参数: 机器{1} 进程{2} 发生错误{3}
req.TemplateID = "618826";
req.TemplateParamSet = new string[] { GetAlertHostName(), m_serverId, m_smsMsg };
TraceLog.Trace("AppAlerter.SendSmsTaskTencent app {0} msg {1}", m_serverId, m_smsMsg);
SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
TxSendSmsResponse res = client.SendSmsSync(req);
TraceLog.Trace("AppAlerter.SendSmsTaskTencent res {0}", AbstractModel.ToJsonString(res));
}
catch (Exception e)
{
TraceLog.Error(e.ToString());
TraceLog.Exception(e);
}
}
private string GetAlertHostName()
{
string hostname = Dns.GetHostName();
//// 后续把hostname修改的直观一些, 就不用这么山寨了
//if (hostname == "VM-0-10-ubuntu")
//{
// return "xjp";
// //return "119.28.105.46 xjp";
//}
//if (hostname == "VM-0-11-ubuntu")
//{
// return "US";
// //return "150.109.151.80 hk";
//}
//if (hostname == "VM-34-242-ubuntu")
//{
// return "guanzhou";
// //return "111.231.250.180 guanzhou";
//}
////短信有长度限制
//if (hostname != null && hostname.Length > 11)
//{
// hostname = hostname.Substring(0, 11);
//}
return hostname;
}
private void SendWechatRobotTask()
{
HttpClient httpClient = null;
try
{
string key = m_app.AppParam.ServerConfig.wechatRobotKey;
if(key == null)
{
key = "";
return;
}
JsonData jbuilder = new JsonData();
//@人员
// JsonData mentioned_list = new JsonData();
// mentioned_list.Add("@all");
// jtext["mentioned_list"] = mentioned_list;
//内容
string szcontent = $"hostname:{GetAlertHostName()}\nserverid:{m_serverId}msg:{m_robotMsg}";
if (m_crushUid != 0)
{
szcontent = $"hostname:{GetAlertHostName()}\nserverid:{m_serverId}\ncrushuid:{m_crushUid}\nmsg:{m_robotMsg}";
}
string urlHead = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key="; //企业微信
if (m_app.AppParam.ServerConfig.robotMode == 1) //飞书
{
urlHead = "https://open.feishu.cn/open-apis/bot/v2/hook/";
jbuilder["msg_type"] = "text";
JsonData jtext = new JsonData();
jtext["text"] = szcontent;
jbuilder["content"] = jtext;
}
else
{
jbuilder["msgtype"] = "text";
JsonData jtext = new JsonData();
jtext["content"] = szcontent;
jbuilder["text"] = jtext;
}
string szContent = jbuilder.ToJson();
string szurl = $"{urlHead}{key}";
TraceLog.Debug("http req {0}", szcontent);
HttpContent content = null;
string strutf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(szContent));
content = new StringContent(strutf8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient = new HttpClient();
httpClient.MaxResponseContentBufferSize = 256000;
httpClient.Timeout = TimeSpan.FromSeconds(10);
HttpResponseMessage response = httpClient.PostAsync(new Uri(szurl), content).Result;
if (response != null)
{
var result = response.Content.ReadAsStringAsync().Result;
TraceLog.Trace("AppAlerter.SendWechatRobotTask result {0}", result.ToString());
}
else
{
TraceLog.Error("AppAlerter.SendWechatRobotTask response is null");
}
}
catch (Exception ex)
{
TraceLog.Error("AppAlerter.SendWechatRobotTask ex {0}", ex.ToString());
}
finally
{
if (httpClient != null)
{
httpClient.Dispose();
}
}
}
}
}