package com.taobao.tddl.monitor.stat; import java.util.Date; import org.apache.commons.lang.time.FastDateFormat; import com.taobao.tddl.common.utils.logger.Logger; /** * 基于 Tddl Logger 的统计日志输出类。 保证向下兼容, 日志刷出的结构为: * * <pre> * key1(sql) key2(dbname) key3(flag) val1(count) val2(sum) val3(min) val4(max) time * sql logicDbName 执行成功 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql realDbName1 执行成功 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql realDbName2 执行成功 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql realDbName2 执行失败 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql realDbName2 执行超时 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql null 解析成功 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql null 解析失败 执行次数 响应时间 最小响应时间 最大响应时间 日志时间 * sql null 解析命中 执行次数 命中次数 NA NA 日志时间 * </pre> * * @author changyuan.lh */ public class LoggerLogWriter extends StatLogWriter { /** XXX: 改成 commons-lang 自带的 {@link FastDateFormat}, 这个才是线程安全的 */ public static final FastDateFormat df = FastDateFormat.getInstance("yyy-MM-dd HH:mm:ss:SSS"); protected String fieldSeperator = "#@#"; // SQL中出现概率小, // 和正则式不冲突 protected String lineSeperator = System.getProperty("line.separator"); protected final Logger statLogger; public LoggerLogWriter(Logger statLogger){ this.statLogger = statLogger; } public LoggerLogWriter(String fieldSeperator, Logger statLogger){ this.fieldSeperator = fieldSeperator; this.statLogger = statLogger; } public LoggerLogWriter(String fieldSeperator, String lineSeperator, Logger statLogger){ this.fieldSeperator = fieldSeperator; this.lineSeperator = lineSeperator; this.statLogger = statLogger; } // XXX: 输出中首先写信息, 然后写数据, 最后写时间, 保持向后兼容 protected StringBuffer format(StringBuffer buf, Object[] fields, Date time, long... values) { for (Object field : fields) { buf.append(field).append(fieldSeperator); } for (long value : values) { buf.append(value).append(fieldSeperator); } return buf.append(df.format(time)).append(lineSeperator); } public void write(Object[] keys, Object[] fields, long... values) { StringBuffer buf = new StringBuffer(); format(buf, (fields == null) ? keys : fields, new Date(), values); statLogger.warn(buf.toString()); } }