package com.taobao.tddl.monitor;
import com.taobao.tddl.common.utils.GoogleConcurrentLruCache;
import com.taobao.tddl.common.utils.TStringUtil;
import com.taobao.tddl.monitor.logger.LoggerInit;
import com.taobao.tddl.monitor.stat.AbstractStatLogWriter.LogCounter;
import com.taobao.tddl.monitor.utils.MD5Maker;
import com.taobao.tddl.monitor.utils.PositiveAtomicCounter;
public class Monitor extends MonitorConfig {
public static final String KEY1 = "TDDL";
public static final String KEY3_PARSE_SQL = "PARSE_SQL_SUCCESS";
// 会记录走则引擎用的时间和总耗时
public static final String KEY3_GET_DB_AND_TABLES = "GET_DB_ANDTABLES_SUCCESS";
/**
* 执行sql的总时间,包含真正数据库的执行时间和总时间
*/
public static final String KEY3_EXECUTE_A_SQL_SUCCESS = "EXECUTE_A_SQL_SUCCESS";
/**
* 总共执行了几个库,几个表
*/
public static final String KEY3_EXECUTE_A_SQL_SUCCESS_DBTAB = "EXECUTE_A_SQL_SUCCESS_DBTAB";
/**
* 执行sql的总时间,包含真正数据库的执行时间和总时间
*/
public static final String KEY3_EXECUTE_A_SQL_TIMEOUT = "EXECUTE_A_SQL_TIMEOUT";
public static final String KEY3_EXECUTE_A_SQL_TIMEOUT_DBTAB = "EXECUTE_A_SQL_TIMEOUT_DBTAB";
public static final String KEY3_EXECUTE_A_SQL_EXCEPTION = "EXECUTE_A_SQL_WITH_EXCEPTION";
public static final String KEY3_EXECUTE_A_SQL_EXCEPTION_DBTAB = "EXECUTE_A_SQL_WITH_EXCEPTION_DBTAB";
/**
* TDDL 数据库(分桶)连接数
*/
public static final String KEY3_CONN_NUMBER = "CONN_NUM";
/**
* TDDL 数据库(分桶)连接阻塞时间
*/
public static final String KEY3_CONN_BLOCKING = "CONN_BLOCKING";
public static String blockingExecution = "blockingExecution";
public static String RPCClientcloseResultSetHandler = "RPCClient_closeResultSetHandler";
public static String RPCClientcommit = "RPCClient_commit";
public static String RPCClientrollback = "RPCClient_rollback";
public static String RPCClientfetchNext = "RPCClient_fetchNext";
public static String RPCClientfirst = "RPCClient_first";
public static String RPCClientpingFuture = "RPCClient_pingFuture";
public static String RPCClientexecuteFuture = "RPCClient_executeFuture";
public static String RPCClientfetchNextFuture = "RPCClient_fetchNextFuture";
public static String RPCClientfirstFuture = "RPCClient_firstFuture";
public static String RPCClientcloseResultSetHandlerFuture = "RPCClient_closeResultSetHandlerFuture";
public static String RPCClientcommitFuture = "RPCClient_commitFuture";
public static String RPCClientrollbackFuture = "RPCClient_rollbackFuture";
public static String AndOrExecutorParse = "AndOrExecutor_Parse";
public static String AndOrExecutorOptimize = "AndOrExecutorOptimize";
public static String TDDL_EXECUTE = "AndOrExecutorExecute";
public static String AndOrExecutorExecuteFuture = "AndOrExecutorExecuteFuture";
public static String QueryTdhsHandlerUseTdhsApi = "QueryTdhsHandlerUseTdhsApi";
/**
* 异步发送请求后,到拿结果集的时间
*/
public static String AndOrExecutorExecuteFuture_getResult = "AndOrExecutorExecuteFuture";
public static String ServerExecuteOnOthers = "Server_ExecuteOnOthers";
public static String ServerPut = "Server_Put";
public static String ServerQuery = "Server_Query";
public static String Key3Success = "success";
public static String Key3Fail = "fail";
public static String Key3FutureDone = "futureDone";
public static String Key3FutureGet = "futureGet";
public static String Key3True = "Key3True";
public static String Key3False = "Key3False";
private static final GoogleConcurrentLruCache<String, String> sqlToMD5Map = new GoogleConcurrentLruCache<String, String>();
private static MD5Maker md5Maker = MD5Maker.getInstance();
private final static PositiveAtomicCounter pc = new PositiveAtomicCounter();
static {
LoggerInit.initTddlLog();
MonitorConfig.initConfig();
}
/**
* 返回构建的表名
*
* @param virtualTableName
* @return
*/
public static String buildTableKey1(String virtualTableName) {
return "" + virtualTableName; // 保证不返回null
}
/**
* <pre>
* 记录sql
* 不记录sql
* 记录前截取sql
* 记录后截取sql
* 记录md5
*
* 先左后右
* </pre>
*
* @param sql
* @return
*/
public static String buildExecuteSqlKey2(String sql) {
if (sql == null) {
return "null";
}
switch (recordType) {
case RECORD_SQL:
String s = TStringUtil.fillTabWithSpace(sql);
if (left > 0) {
s = TStringUtil.left(s, left);
}
if (right > 0) {
s = TStringUtil.right(s, right);
}
return s;
case MD5:
String s1 = TStringUtil.fillTabWithSpace(sql);
if (left > 0) {
s1 = TStringUtil.left(s1, left);
}
if (right > 0) {
s1 = TStringUtil.right(s1, right);
}
String md5 = sqlToMD5Map.get(s1);
if (md5 != null) {
return md5;
} else {
String sqlmd5 = md5Maker.getMD5(s1);
StringBuilder sb = new StringBuilder();
sb.append("[md5]").append(sqlmd5).append(" [sql]").append(s1);
LoggerInit.TDDL_MD5_TO_SQL_MAPPING.warn(sb.toString());
sqlToMD5Map.put(s1, sqlmd5);
return sqlmd5;
}
case NONE:
return "";
default:
throw new IllegalArgumentException("不符合要求的记录log类型! " + recordType);
}
}
/**
* 构建KEY1的完整表名
*
* @param realDSKey
* @param realTable
* @return
*/
public static String buildExecuteDBAndTableKey1(String realDSKey, String realTable) {
StringBuilder sb = new StringBuilder();
sb.append(KEY1).append("|").append(realDSKey).append("|").append(realTable);
return sb.toString();
}
/**
* @param key1 一般是逻辑表名,appname等
* @param key2 一般是SQL
* @param key3 一些成功、失败、超时、命中率等标志
* @param value1 执行时间
* @param value2 次数
*/
public static void add(String key1, String key2, String key3, long value1, long value2) {
if (isExclude(key1, key2, key3)) {
return;
}
if ((statChannelMask & 4) == 4) { // 100
// MonitorLog.addStat(key1, "", key3, value1, value2); // 哈勃日志暂时保留
}
if ((statChannelMask & 2) == 2) { // 010
bufferedStatLogWriter.stat(key2, key1, key3, value1, value2); //
}
if ((statChannelMask & 1) == 1) { // 001
addMonitor(key1, key2, key3, value1, value2); // 平均响应时间等动态监控Nagois
}
}
/**
* @param key1 数据库名字
* @param key2 一般是SQL
* @param key3 一些成功、失败、超时、命中率等标志,比如SQL_EXCEPTION,SQL_TIMEOUT,SQL_SUCCESS
* @param key4 数据库ip
* @param key5 数据库ort
* @param key6 真实库名
* @param value1 执行时间
* @param value2 次数
*/
public static void atomSqlAdd(String key1, String key2, String key3, String key4, String key5, String key6,
long value1, long value2) {
// changyuan.lh : 输出顺序是 key1(sql), key2(group), attach1, attach2,
// attach3, key3(flag)
atomBufferedStatLogWriter.write(new Object[] { key2, key1, key3 }, new Object[] { key2, key1, key4, key5, key6,
key3 }, new long[] { value2, value1 });
}
/**
* @param key1 一般是逻辑表名,appname等
* @param key2 一般是SQL
* @param key3 一些成功、失败、超时、命中率等标志
* @param value1 执行时间
* @param value2 次数
*/
public static void matrixSqlAdd(String key1, String key2, String key3, long value1, long value2) {
matrixBufferedStatLogWriter.stat(key2, key1, key3, value2, value1);
}
/**
* 获得一个统计对象, 不用可以直接抛弃 <br/>
* 举个例子:datasourceKey, "-", Monitor.KEY3_CONN_NUMBER
*
* @param obj1
* @param obj2
* @param obj3
* @return
*/
public static LogCounter connStat(String obj1, String obj2, String obj3) {
Object[] objs = new Object[] { obj1, obj2, obj3 };
return connRefStatLogWriter.getCounter(objs, objs);
}
/**
* 根据rate率判断是否针对atom进行采样
*
* @return
*/
public static boolean isSamplingRecord() {
int ra = pc.incrementAndGet() % 100;
if (ra < Monitor.atomSamplingRate) {
return true;
} else {
return false;
}
}
// ====================== helper method ==============================
private static void addMonitor(String key1, String key2, String key3, long value1, long value2) {
// 一段时间内插日志库的失败率和平均响应时间
}
private static boolean isExclude(String key1, String key2, String key3) {
if (excludsKeys == null || excludsKeys.length == 0) {
return false;
}
for (String exclude : excludsKeys) {
if (key1.indexOf(exclude) != -1 || key2.indexOf(exclude) != -1 || key3.indexOf(exclude) != -1) {
return true;
}
}
return false;
}
public static boolean isInclude(String sql) {
if (includeKeys != null && includeKeys.length != 0) { // 存在白名单
boolean discard = true;
for (String whiteItem : includeKeys) {
if (sql.indexOf(whiteItem) != -1) {
discard = false;
break;
}
}
if (discard) {
return false; // 不在白名单中,不输出日志,以减少日志量
}
}
return true;
}
public static synchronized void addSnapshotValuesCallbask(SnapshotValuesOutputCallBack callbackList) {
statMonitor.addSnapshotValuesCallbask(callbackList);
}
public static synchronized void removeSnapshotValuesCallback(SnapshotValuesOutputCallBack callbackList) {
statMonitor.removeSnapshotValuesCallback(callbackList);
}
public static long monitorAndRenewTime(String key1, String key2, String key3, long count, long time) {
bufferedStatLogWriter.stat(key1, key2, key3, count, System.currentTimeMillis() - time);
time = System.currentTimeMillis();
return time;
}
public static long monitorAndRenewTime(String key1, String key2, String key3, long time) {
bufferedStatLogWriter.stat(key1, key2, key3, System.currentTimeMillis() - time);
time = System.currentTimeMillis();
return time;
}
}