class LoggerBase {
private static final String NA = "UnknowClass";
private static final org.slf4j.Logger ACCESS_LOGGER;
private static final org.slf4j.Logger PERF_LOGGER;
private static ThreadLocal<Long> tlAccessStart = new ThreadLocal<Long>();
private static final String NULL = "NULL";
public static final String LINE_SEP = System.getProperty("line.separator");
public static final int LINE_SEP_LEN = LINE_SEP.length();
public static final String FQCN = Logger.class.getName();
private final org.slf4j.Logger delegate;
static {
ACCESS_LOGGER = LoggerFactory.getLogger(System.getProperty("logger.access.name", "ACCESS"));
PERF_LOGGER = LoggerFactory.getLogger(System.getProperty("logger.performance.name", "PERFORMANCE"));
}
/**
* 构造函数
*
* @param cls
*/
public LoggerBase(String cls) {
delegate = LoggerFactory.getLogger(cls);
}
@SuppressWarnings("unchecked")
public LoggerBase(Class clazz) {
if (clazz == com.huawei.it.hwpay.common.log.LoggerFactory.class
|| clazz == com.huawei.it.hwpay.common.log.Logger.class) {
final String clazzName = clazz.getName() + ".";
String cls = getCallingClassName(clazzName);
delegate = LoggerFactory.getLogger(cls);
} else {
delegate = LoggerFactory.getLogger(clazz);
}
}
/**
* isTraceEnabled
*
* @return TraceEnabled
*/
public boolean isTraceEnabled() {
return delegate.isTraceEnabled();
}
/**
* isDebugEnabled
*
* @return isDebugEnabled
*/
public boolean isDebugEnabled() {
return delegate.isDebugEnabled();
}
/**
* isInfoEnabled
*
* @return isInfoEnabled
*/
public boolean isInfoEnabled() {
return delegate.isInfoEnabled();
}
/**
* isWarnEnabled
*
* @return isWarnEnabled
*/
public boolean isWarnEnabled() {
return delegate.isWarnEnabled();
}
/**
* isErrorEnabled
*
* @return isErrorEnabled
*/
public boolean isErrorEnabled() {
return delegate.isErrorEnabled();
}
/**
* 标记access的开始
*/
public static void accessStart() {
tlAccessStart.set(Long.valueOf(System.nanoTime()));
}
/**
* 记录access日志
*
* @param args
*/
public static void access(Object... args) {
if (args == null) {
args = new Object[] {NULL};
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < args.length; i++) {
if (i > 0) {
sb.append(',');
}
sb.append(unull(args[i]));
}
// 如果标记了开始时间,则在access最后追加耗时
Long startNS = tlAccessStart.get();
if (startNS != null) {
sb.append(',').append(Formatter.formatNS(System.nanoTime() - startNS.longValue())).append("ns");
tlAccessStart.remove();
}
((LocationAwareLogger) ACCESS_LOGGER).log(null, FQCN, LocationAwareLogger.TRACE_INT, null, null, null);
}
private static Object unull(Object obj) {
return obj == null ? NULL : JsonUtil.formatJson(obj);
}
private static String concat(Object... objects) {
StringBuilder sb = new StringBuilder();
concat(sb, objects);
return sb.toString();
}
private static void concat(StringBuilder sb, Object... objects) {
for (int i = 0; i < objects.length; i++) {
if ((i + 1) == objects.length && objects[i] instanceof Throwable) {
break;
}
if (objects[i] != null && objects[i].getClass().isArray()) {
concat(sb, (Object[]) objects[i]);
} else {
sb.append(unull(objects[i]));
}
}
}
private String logf(String format, Object... args) {
StringBuilder sb = new StringBuilder();
java.util.Formatter formatter = new java.util.Formatter(sb);
formatter.format(format, args);
return sb.toString();
}
/**
* allformat
*
* @param format format
* @param args args
*/
public void allf(String format, Object... args) {
if (delegate.isTraceEnabled()) {
all(logf(format, args));
}
}
/**
* all log format
*
* @param objects objects
*/
public void all(Object... objects) {
if (delegate.isTraceEnabled()) {
if (objects[objects.length - 1] instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.TRACE_INT, concat(objects), null,
(Throwable) objects[objects.length - 1]);
} else {
String obj = concat(objects);
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, obj, null, null);
}
}
}
/**
* all log format
*
* @param obj obj
*/
public void all(Object obj) {
if (!delegate.isTraceEnabled()) {
return;
}
if (obj instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.TRACE_INT, "StackTrace:", null,
(Throwable) obj);
} else {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.TRACE_INT,
obj == null ? NULL : obj.toString(), null, null);
}
}
/**
* debug format
*
* @param format format
* @param args args
*/
public void debugf(String format, Object... args) {
if (delegate.isDebugEnabled()) {
debug(logf(format, args));
}
}
/**
* debug
*
* @param objects
*/
public void debug(Object... objects) {
if (delegate.isDebugEnabled()) {
if (objects[objects.length - 1] instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.DEBUG_INT, concat(objects), null,
(Throwable) objects[objects.length - 1]);
} else {
String obj = concat(objects);
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, obj, null, null);
}
}
}
/**
* debug
*
* @param obj
*/
public void debug(Object obj) {
if (!delegate.isDebugEnabled()) {
return;
}
if (obj instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.DEBUG_INT, "StackTrace:", null,
(Throwable) obj);
} else {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.TRACE_INT,
obj == null ? NULL : obj.toString(), null, null);
}
}
/**
* info format
*
* @param format
* @param args
*/
public void infof(String format, Object... args) {
if (delegate.isInfoEnabled()) {
info(logf(format, args));
}
}
/**
* info
*
* @param objects
*/
public void info(Object... objects) {
if (delegate.isInfoEnabled()) {
if (objects[objects.length - 1] instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, concat(objects), null,
(Throwable) objects[objects.length - 1]);
} else {
String obj = concat(objects);
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, obj, null, null);
}
}
}
/**
* info
*
* @param obj
*/
public void info(Object obj) {
if (!delegate.isInfoEnabled()) {
return;
}
if (obj instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, "StackTrace:", null,
(Throwable) obj);
} else {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT,
obj == null ? NULL : obj.toString(), null, null);
}
}
/**
* warn format
*
* @param format
* @param args
*/
public void warnf(String format, Object... args) {
if (delegate.isWarnEnabled()) {
warn(logf(format, args));
}
}
/**
* warn
*
* @param objects
*/
public void warn(Object... objects) {
if (delegate.isWarnEnabled()) {
if (objects[objects.length - 1] instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.WARN_INT, concat(objects), null,
(Throwable) objects[objects.length - 1]);
} else {
String obj = concat(objects);
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, obj, null, null);
}
}
}
/**
* warn
*
* @param obj
*/
public void warn(Object obj) {
if (!delegate.isWarnEnabled()) {
return;
}
if (obj instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.WARN_INT, "StackTrace:", null,
(Throwable) obj);
} else {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.WARN_INT,
obj == null ? NULL : obj.toString(), null, null);
}
}
/**
* error format
*
* @param format
* @param args
*/
public void errorf(String format, Object... args) {
if (delegate.isErrorEnabled()) {
error(logf(format, args));
}
}
/**
* error
*
* @param objects
*/
public void error(Object... objects) {
if (delegate.isErrorEnabled()) {
if (objects[objects.length - 1] instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.ERROR_INT, concat(objects), null,
(Throwable) objects[objects.length - 1]);
} else {
String obj = concat(objects);
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.INFO_INT, obj, null, null);
}
}
}
/**
* error
*
* @param obj
*/
public void error(Object obj) {
if (!delegate.isErrorEnabled()) {
return;
}
if (obj instanceof Throwable) {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.ERROR_INT, "StackTrace:", null,
(Throwable) obj);
} else {
((LocationAwareLogger) delegate).log(null, FQCN, LocationAwareLogger.ERROR_INT,
obj == null ? NULL : obj.toString(), null, null);
}
}
private String getCallingClassName(String className) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
(new Throwable()).printStackTrace(pw);
String stack = sw.toString();
// Given the current structure of the package, the line
// containing "org.apache.log4j.Category." should be printed just
// before the caller.
// This method of searching may not be fastest but it's safer
// than counting the stack depth which is not guaranteed to be
// constant across JVM implementations.
int ibegin = stack.lastIndexOf(className);
if (ibegin == -1) {
return NA;
}
ibegin = stack.indexOf(LINE_SEP, ibegin);
if (ibegin == -1) {
return NA;
}
ibegin += LINE_SEP_LEN;
// determine end of line
int iend = stack.indexOf(LINE_SEP, ibegin);
if (iend == -1) {
return NA;
}
// VA has a different stack trace format which doesn't
// need to skip the inital 'at'
// back up to first blank character
ibegin = stack.lastIndexOf("at ", iend);
if (ibegin == -1) {
return NA;
}
// Add 3 to skip "at ";
ibegin += 3;
// everything between is the requested stack item
String fullInfo = stack.substring(ibegin, iend);
// Starting the search from '(' is safer because there is
// potentially a dot between the parentheses.
iend = fullInfo.lastIndexOf('(');
if (iend == -1) {
return NA;
}
iend = fullInfo.lastIndexOf('.', iend);
/*
* This is because a stack trace in VisualAge looks like:
* java.lang.RuntimeException
* java.lang.Throwable()
* java.lang.Exception()
* java.lang.RuntimeException()
* void test.test.B.print()
* void test.test.A.printIndirect()
* void test.test.Run.main(java.lang.String [])
*/
if (iend == -1) {
return NA;
} else {
return fullInfo.substring(0, iend);
}
}
private static String getShortName(TimeUnit unit) {
if (unit == TimeUnit.NANOSECONDS) {
return "ns";
} else if (unit == TimeUnit.MICROSECONDS) {
return "micro";
} else if (unit == TimeUnit.MILLISECONDS) {
return "ms";
} else if (unit == TimeUnit.SECONDS) {
return "sec";
} else if (unit == TimeUnit.MINUTES) {
return "min";
}
return "...";
}
/**
* 输出性能日志
*
* @param info 输出信息
* @param startTime 开始时间
* @param unit 时间单位
* @param threshold 阈值
* @param delta 增量,超过一倍增量输出info日志,超过2倍增量以上输出warn
*/
public static final void timeSpent(String info, long startTime, TimeUnit unit, long threshold, long delta) {
long now;
if (unit == TimeUnit.NANOSECONDS) { // 计算方法不一样
now = System.nanoTime();
} else {
now = unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
long spent = now - startTime;
if (spent >= threshold) {
if (delta > 0) { // 按级别输入日志
int multiple = (int) ((spent - threshold) / delta);
if (multiple == 0) {
((LocationAwareLogger) PERF_LOGGER).log(null, FQCN, LocationAwareLogger.DEBUG_INT, concat(info,
" spent ", spent, getShortName(unit), ", but expect in ", threshold, getShortName(unit)), null,
null);
} else if (multiple == 1) {
((LocationAwareLogger) PERF_LOGGER).log(null, FQCN, LocationAwareLogger.INFO_INT, concat(info,
" spent ", spent, getShortName(unit), ", but expect in ", threshold, getShortName(unit)), null,
null);
} else {
((LocationAwareLogger) PERF_LOGGER).log(null, FQCN, LocationAwareLogger.WARN_INT, concat(info,
" spent ", spent, getShortName(unit), ", but expect in ", threshold, getShortName(unit)), null,
null);
}
} else { // 统一debug
((LocationAwareLogger) PERF_LOGGER).log(null, FQCN, LocationAwareLogger.DEBUG_INT, concat(info,
" spent ", spent, getShortName(unit), ", but expect in ", threshold, getShortName(unit)), null,
null);
}
}
}
/**
* @see #timeSpent(String, long, TimeUnit, long, long)
*/
public static final void timeSpent(String info, long startTime, TimeUnit unit, long threshold) {
timeSpent(info, startTime, unit, threshold, threshold);
}
/**
* @see #timeSpent(String, long, TimeUnit, long, long)
*/
public static final void timeSpentNan(String info, long startTime, long threshold) {
timeSpent(info, startTime, TimeUnit.NANOSECONDS, threshold, threshold);
}
/**
* @see #timeSpent(String, long, TimeUnit, long, long)
*/
public static final void timeSpentNan(String info, long startTime, long threshold, long delta) {
timeSpent(info, startTime, TimeUnit.NANOSECONDS, threshold, delta);
}
/**
* @see #timeSpent(String, long, TimeUnit, long, long)
*/
public static final void timeSpentMillSec(String info, long startTime, long threshold) {
timeSpent(info, startTime, TimeUnit.MILLISECONDS, threshold, threshold);
}
/**
* @see #timeSpent(String, long, TimeUnit, long, long)
*/
public static final void timeSpentMillSec(String info, long startTime, long threshold, long delta) {
timeSpent(info, startTime, TimeUnit.MILLISECONDS, threshold, delta);
}
}