package com.taobao.tddl.monitor;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import com.taobao.tddl.config.ConfigDataHandler;
import com.taobao.tddl.config.ConfigDataHandlerFactory;
import com.taobao.tddl.config.ConfigDataListener;
import com.taobao.tddl.config.ConfigServerHelper;
import com.taobao.tddl.config.ConfigServerHelper.TddlLConfigKey;
import com.taobao.tddl.config.impl.UnitConfigDataHandlerFactory;
import com.taobao.tddl.monitor.logger.LoggerInit;
import com.taobao.tddl.monitor.stat.BufferedLogWriter;
import com.taobao.tddl.monitor.stat.LoggerLogWriter;
import com.taobao.tddl.monitor.stat.MinMaxAvgLogWriter;
import com.taobao.tddl.monitor.stat.SoftRefLogWriter;
import com.taobao.tddl.common.utils.logger.Logger;
import com.taobao.tddl.common.utils.logger.LoggerFactory;
/**
* 维护Monitor需要的参数
*
* @author jianghang 2013-10-30 下午5:49:16
* @since 5.0.0
*/
public class MonitorConfig {
static final Logger logger = LoggerFactory.getLogger(Monitor.class); // 使用monitor.class,兼容
public static volatile String APPNAME = "TDDL";
public static volatile Boolean isStatRealDbInWrapperDs = null;
public static volatile RECORD_TYPE recordType = RECORD_TYPE.RECORD_SQL;
public static volatile int left = 0; // 从左起保留多少个字符
public static volatile int right = 0; // 从右起保留多少个字符
public static volatile String[] excludsKeys = null;
public static volatile String[] includeKeys = null; // 白名单
// modify by junyu,2012-3-28
public static volatile boolean isStatAtomSql = true; // 默认不打印sql日志
public static volatile int sqlTimeout = 500; // 默认超时500毫秒
public static volatile int atomSamplingRate = 100; // 值只能为0-100,日志的采样频率
public static volatile int statChannelMask = 7; // 按位:哈勃|BufferedStatLogWriter|StatMonitor
public static volatile int dumpInterval = -1;
public static volatile int cacheSize = -1;
public static final StatMonitor statMonitor = StatMonitor.getInstance();
/** changyuan.lh: TDDL 统计日志 */
/* 记录行复制日志与 SQL 解析日志, Key 的量与 SQL 数量相同 */
public static final BufferedLogWriter bufferedStatLogWriter = new BufferedLogWriter(1024,
4096,
new LoggerLogWriter(LoggerInit.TDDL_Statistic_LOG));
/* 记录单库的 SQL 执行记录, Key 的量是 SQL x 单库物理表 x 物理库数量 */
public static final BufferedLogWriter atomBufferedStatLogWriter = new BufferedLogWriter(2048,
131072,
new LoggerLogWriter(LoggerInit.TDDL_Atom_Statistic_LOG));
/* 记录逻辑表以及物理库/物理表 的 SQL 执行记录, Key 量最大是 SQL x 单库物理表 x 物理库数量 */
public static final BufferedLogWriter matrixBufferedStatLogWriter = new BufferedLogWriter(2048,
131072,
new LoggerLogWriter(LoggerInit.TDDL_Matrix_Statistic_LOG));
/* 记录 Atom 连接池以及业务分桶的连接申请记录, Key 量最大是物理库 x 业务分桶数量 */
public static final SoftRefLogWriter connRefStatLogWriter = new SoftRefLogWriter(false,
new MinMaxAvgLogWriter(", ",
LoggerInit.TDDL_Conn_Statistic_LOG));
public enum RECORD_TYPE {
RECORD_SQL, MD5, NONE
}
static void initConfig() {
if ("TDDL".equals(APPNAME)) {
logger.warn("不指定TDDL以外的appName则不订阅");
return;
}
String dataId = ConfigServerHelper.getTddlConfigDataId(APPNAME);
ConfigDataHandlerFactory cdhf = new UnitConfigDataHandlerFactory(UnitConfigDataHandlerFactory.DEFAULT_UNITNAME,
APPNAME);
ConfigDataListener tddlConfigListener = new ConfigDataListener() {
public void onDataRecieved(String dataId, String data) {
if (StringUtils.isEmpty(data)) {
return;
}
Properties p = new Properties();
try {
p.load(new ByteArrayInputStream(data.getBytes()));
} catch (Exception e) {
logger.error("[tddlConfigListener] 无法解析推送的配置,dataid:" + dataId + ", data:" + data, e);
return;
}
try {
for (Map.Entry<Object, Object> entry : p.entrySet()) {
String key = ((String) entry.getKey()).trim();
String value = ((String) entry.getValue()).trim();
switch (TddlLConfigKey.valueOf(key)) {
case statKeyRecordType: {
RECORD_TYPE old = recordType;
recordType = RECORD_TYPE.valueOf(value);
logger.warn("statKeyRecordType switch from [" + old + "] to [" + recordType + "]");
break;
}
case statKeyLeftCutLen: {
int old = left;
left = Integer.valueOf(value);
logger.warn("statKeyLeftCutLen switch from [" + old + "] to [" + left + "]");
break;
}
case statKeyRightCutLen: {
int old = right;
right = Integer.valueOf(value);
logger.warn("statKeyRightCutLen switch from [" + old + "] to [" + right + "]");
break;
}
case statKeyExcludes: {
String[] old = excludsKeys;
excludsKeys = value.split(",");
logger.warn("statKeyExcludes switch from " + Arrays.toString(old) + " to [" + value
+ "]");
break;
}
case statKeyIncludes: {
String[] old = includeKeys;
includeKeys = value.split(",");
logger.warn("statKeyIncludes switch from " + Arrays.toString(old) + " to [" + value
+ "]");
break;
}
case StatRealDbInWrapperDs: {
boolean old = isStatRealDbInWrapperDs;
isStatRealDbInWrapperDs = Boolean.valueOf(value);
logger.warn("StatRealDbInWrapperDs switch from [" + old + "] to [" + value + "]");
break;
}
case StatChannelMask: {
int old = statChannelMask;
statChannelMask = Integer.valueOf(value);
logger.warn("statChannelMask switch from [" + old + "] to [" + value + "]");
break;
}
case statDumpInterval: {
int old = dumpInterval;
dumpInterval = Integer.valueOf(value);
statMonitor.setFlushInterval(dumpInterval);
bufferedStatLogWriter.setFlushInterval(dumpInterval);
logger.warn("statDumpInterval switch from [" + old + "] to [" + value + "]");
break;
}
case statCacheSize: {
int old = cacheSize;
cacheSize = Integer.valueOf(value);
statMonitor.setMaxKeySize(cacheSize);
bufferedStatLogWriter.setMaxKeySize(cacheSize);
logger.warn("statCacheSize switch from [" + old + "] to [" + value + "]");
break;
}
case statAtomSql: {
boolean old = isStatAtomSql;
isStatAtomSql = Boolean.parseBoolean(value);
logger.warn("isStatAtomSql switch from [" + old + "] to [" + value + "]");
break;
}
case sqlExecTimeOutMilli: {
int old = sqlTimeout;
sqlTimeout = Integer.valueOf(value);
logger.warn("sqlTimeout switch from [" + old + "] to [" + value + "]");
break;
}
case atomSqlSamplingRate: {
int old = atomSamplingRate;
if (old > 0) {
int rate = 0;
if (Integer.valueOf(value) % 100 == 0) {
rate = 100;
} else {
rate = Integer.valueOf(value) % 100;// 如果超过100,取余量
}
atomSamplingRate = rate;
logger.warn("atomSqlSamplingRate switch from [" + old + "] to [" + atomSamplingRate
+ "]");
} else {
logger.warn("atomSqlSamplingRate will not change,because the value got is nagetive!old value is:"
+ old);
}
}
default:
logger.warn("Not cared TDDLConfigKey:" + key);
}
}
} catch (Exception e) {
logger.error("[tddlConfigListener.onDataReceive]", e);
}
}
};
ConfigDataHandler dataHandler = cdhf.getConfigDataHandler(dataId, tddlConfigListener);
String data = dataHandler.getNullableData(15 * 1000, ConfigDataHandler.FIRST_CACHE_THEN_SERVER_STRATEGY);
tddlConfigListener.onDataRecieved(dataId, data);
}
public static void setAppName(String appname) {
if (appname != null) {
APPNAME = appname;
initConfig();
}
}
}