线上日志线上流量回放-预发环境-接入报警篇
程序员文章站
2022-07-13 15:18:23
...
http接口解析见https://blog.csdn.net/weixin_42498050/article/details/105039318
本篇介绍接入报警能力
钉钉机器人报警钉钉开放平台
https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq
1. 群添加机器人-自定义机器人
2. webhook就是机器人接口,除了token还需要传
timestamp和sign
3. 报警消息发送到机器人
package com.alibaba.logPlayBack.sdksearch.utils;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.Header;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import java.net.URLEncoder;
/**
* 报警-钉钉消息-机器人
*/
public class DingTalkUtil {
public static int alert(String token, String text, List<String> mobiles, boolean isAtAll) throws IOException {
// 是否@所有人,true为会在报警信息后面@所有人,false不会在报警信息后面@所有人
isAtAll = false;
// 安全设置加签timestamp和sign(这个问题排查了半天,原来的机器人可以发报警,最新创建的不可以,原来钉钉增加了此选项,接口传参参数变了)
Long timestamp = System.currentTimeMillis();
String secret = "this is secret";
String stringToSign = timestamp + "\n" + secret;
Mac mac = null;
try {
mac = Mac.getInstance("HmacSHA256");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
System.out.println(sign);
// 以上代码是安全设置加签timestamp和sign参数传参,保持之前的token不变
if (null == token || token.isEmpty()) {
// 日志流量回放群钉钉机器人token
token = "xx";
}
String url = "https://oapi.dingtalk.com/robot/send?access_token=" + token + "×tamp=" + timestamp + "&sign=" + sign;
// 以下为改版之前老的机器人传参,不需要timestamp和sign
// String url = "https://oapi.dingtalk.com/robot/send?access_token=" + token;
//System.out.println(url);
Header header = new Header("Content-type", "application/json");
// 其他传参 msgtype content atMobiles isAtAll
JSONObject bodyJson = new JSONObject();
bodyJson.put("msgtype", "text");
JSONObject textJson = new JSONObject();
textJson.put("content", text);
bodyJson.put("text", textJson);
JSONObject at = new JSONObject();
if (null != mobiles && !mobiles.isEmpty()) {
at.put("atMobiles", mobiles.toArray());
}
at.put("isAtAll", isAtAll);
bodyJson.put("at", at);
//String info="";
String info = HttpUtilAdd.doPost(url, bodyJson.toJSONString(), header);
if (info != null && !info.isEmpty()) {
return 1;
} else {
return 0;
}
}
public static void main(String[] args) throws IOException {
String err = "钉钉发不出消息了吗?日志";
// 群钉钉机器人
alert("xx", err, null, false);
}
}
业务代码
package com.alibaba.logPlayBack.sdksearch.searchScene;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.logPlayBack.sdksearch.logDeal.logJoinPrint;
import com.alibaba.logPlayBack.FileOperate.FileWrite;
import com.alibaba.logPlayBack.sdksearch.utils.DingTalkUtil;
import com.alibaba.logPlayBack.sdksearch.utils.TimeTransfer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
public class mobile_multi {
private static Logger logger = LoggerFactory.getLogger(mobile_multi.class);
/**
* @param responseToJson
* @param count mobile_multi为搜索默认页场景
*/
public static void parse2JSON(JSONObject requestToJson, JSONObject responseToJson, int count, long currentTimeMillis) {
boolean mobile_multi = requestToJson.getString("appScene").equals("mobile_multi");
// 读取的日志里,记录用户行为的时间clientTimeStamp
String clientTimeStamp = TimeTransfer.clientTimeStamp(requestToJson);
StringBuilder sb = new StringBuilder();
HashMap<String, Integer> appScenes = new HashMap<>();
if (mobile_multi) {
Object ob = appScenes.get("mobile_multi");
if (ob != null) {
int value = Integer.parseInt(ob.toString());
appScenes.put("mobile_multi", value);
} else {
appScenes.put("mobile_multi", 1);
}
// 取[]是JSONArray,如nodes: [] ,取{}是JSONObject,如data:{},取int类型的返回值是getString,如status: 0
// 发现在浏览器里的返回key没有"",如level: 0, 在Charles里key有"",如"level": 0,
// 1. 返回类型为JSONObject,data: {}
System.out.println("responseToJson为" + responseToJson);
JSONObject data = responseToJson.getJSONObject("data");
Integer pz = responseToJson.getJSONObject("data").getInteger("pz");
Integer rstate = data.getInteger("rstate");
Integer isEnd = data.getInteger("isEnd");
String highlightWord = data.getString("highlightWord");
// JSONObject trackInfo = responseToJson.getJSONObject("data").getJSONObject("action").getJSONObject("report").getJSONObject("trackInfo");
if (!data.containsKey("1111")) {
System.err.println(logJoinPrint.bugDesc(requestToJson, count) + "data为空");
// 用于写入错误日志文件errorLog,再做字段拆分,从而写入数据库,记录读取的log日志
FileWrite.errorLog(logJoinPrint.errLogJoint(currentTimeMillis, count, requestToJson) +
"条日志,搜索场景为【搜索结果页】,接口返参data为空,BUG BUG BUG!!!" + FileWrite.rex + "1");
// 记录error级别的信息
logger.error(logJoinPrint.logBugDesc(requestToJson, count) + "data为空");
//2019-10-28新增钉钉机器人接入报警,打印出问题的参数以及在数据库查询出的原始日志,便于排查
sb.append("第" + count + "条日志,预发环境流量回放接口返回===搜索场景为【" + requestToJson.getString("appScene") +
"】,data为空。请求参数为==" + requestToJson);
// 搜索线上-日志监控机器人报警,此处填写自己创建机器人时的token
if (!sb.toString().isEmpty()) {
try {
// 机器人报警,此处填写自己创建机器人时的token
DingTalkUtil.alert(null, sb.toString(), null, false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (pz != 30) {
System.err.println(logJoinPrint.bugDesc(requestToJson, count) + "pz不为30");
// 用于写入错误日志文件errorLog,再做字段拆分,从而写入数据库,记录读取的log日志
FileWrite.errorLog(currentTimeMillis + FileWrite.rex + clientTimeStamp + FileWrite.rex + count + FileWrite.rex + "条日志,搜索场景为【搜索结果页】,接口返参" +
"data结果为空,BUG BUG BUG!!!" + FileWrite.rex + "1");
System.err.println("第" + count + "条日志,搜索场景为【搜索结果页】,接口返参data结果为空,BUG BUG BUG!!!");
// 记录error级别的信息
logger.error("第" + count + "条日志,搜索场景为【搜索结果页】,接口返参data结果为空,BUG BUG BUG!!!");
}
System.out.println("搜索场景【mobile_multi】日志回放结束,共" + count + "条日志");
System.err.println("mobile_multi的个数为:" + appScenes.size());
}
}
}
保存原始日志以及错误日志,以后开发接口写库用
待续。。
上一篇: 原始因子处理之手写标准化函数