public class LoggingInterceptor {
private final static Logger log = LoggerFactory.getLogger("MethodLogging");
public final static String IO_LOGGER_KEY = "method";
public Object doAround(ProceedingJoinPoint point) throws Throwable {
Method method = getMethod(point);
LogIgnore ignore = method.getAnnotation(LogIgnore.class);
if (ignore == null && method != null) {
logInputMessage(point, method);
}
Object output = point.proceed();
if (ignore == null && method != null) {
logOutputMessage(point, method, output);
}
return output;
}
protected void logInputMessage(JoinPoint jp, Method method) {
boolean mdc = false;
try {
InputLog ann = method.getAnnotation(InputLog.class);
// check whether need to log input arguments
if (ann != null && !ArrayUtils.isEmpty(jp.getArgs())) {
// if LogIgnore applied on method, will ignored whole method
// log
Object[] args = jp.getArgs();
Annotation[][] anns = method.getParameterAnnotations();
for (int i = 0; i < args.length; i++) {
LogMask mask = null;
if (anns != null) {
LogIgnore ignore = getParameterAnnotation(anns[i], LogIgnore.class);
if (ignore != null) {
continue; // ignore output the parameter log
}
mask = getParameterAnnotation(anns[i], LogMask.class);
}
StringBuilder text = new StringBuilder();
String prefix = ann.prefix();
// build object log
Object body = buildLogMessageBody(args[i], mask, text);
String logPrefix = getInputPrefix(jp, method, prefix, i);
String loggerText = getLoggerText(jp, method);
putLoggerText(loggerText);
mdc = true;
outputMessage(logPrefix, body, ann.value());
}
}
} catch (Throwable t) {
log.warn("exception occured when logging input {}", t.toString());
}finally{
if(mdc){
removeLoggerText();
}
}
}
protected void logOutputMessage(JoinPoint jp, Method method, Object output) {
boolean mdc = false;
try {
OutputLog ann = method.getAnnotation(OutputLog.class);
if (ann != null) {
StringBuilder text = new StringBuilder();
String prefix = ann.prefix();
// build object log
LogMask mask = method.getAnnotation(LogMask.class);
Object body = buildLogMessageBody(output, mask, text);
String logPrefix = getOutputPrefix(jp, method, prefix);
String loggerText = getLoggerText(jp, method);
putLoggerText(loggerText);
mdc = true;
outputMessage(logPrefix, body, ann.value());
}
} catch (Throwable t) {
log.warn("exception occured when logging output {}", t.toString());
}finally{
if(mdc){
removeLoggerText();
}
}
}
protected Object buildLogMessageBody(Object arg, LogMask mask, StringBuilder text) {
Object body = null;
if (arg != null && LogUtils.isSimpleType(arg.getClass())) {
// for simple types, log as string way
if (mask != null) {
if (mask.value() == LogMaskType.SimpleMask) {
// for simple mask, mark some chars
text = text.append(LogUtils.markString(String.valueOf(arg), LogMaskType.SimpleMask.getMask()));
} else {
// for full mask, mask all chars with mask chars
text = text.append(LogUtils.markFullString(String.valueOf(arg), LogMaskType.FullMask.getMask()));
}
} else {
// no mask, output object directly
text = text.append(String.valueOf(arg));
}
body = text;
} else {
// output object
body = arg;
}
return body;
}
protected String getLoggerText(JoinPoint jp, Method method){
return StringUtils.join(new Object[] {jp.getTarget().getClass().getCanonicalName(), ".", method.getName()});
}
protected String getInputPrefix(JoinPoint jp, Method method, String prefix, int index) {
String text = prefix;
if (StringUtils.isBlank(prefix)) {
// text = StringUtils.join(new Object[] { jp.getTarget().getClass().getCanonicalName(), ".", method.getName(),
// " args[", index, "]->" });
text = StringUtils.join(new Object[] { "input args[", index, "]->" });
}
return text;
}
protected String getOutputPrefix(JoinPoint jp, Method method, String prefix) {
String text = prefix;
if (StringUtils.isBlank(prefix)) {
// text = StringUtils.join(new Object[] { "==>", jp.getTarget().getClass().getCanonicalName(), ".", method.getName(),
// " output->" });
text = StringUtils.join(new Object[] { "output==>"}); }
return text;
}
protected void outputMessage(String prefix, Object text, LogLevel level) {
if (level == LogLevel.INFO) {
log.info("{}[{}]", prefix, text);
} else if (level == LogLevel.DEBUG) {
log.debug("{}[{}]", prefix, text);
} else if (level == LogLevel.WARN) {
log.warn("{}[{}]", prefix, text);
} else if (level == LogLevel.ERROR) {
log.error("{}[{}]", prefix, text);
} else if (level == LogLevel.TRACE) {
log.trace("{}[{}]", prefix, text);
}
}
protected void putLoggerText(String loggerText){
MDC.put(IO_LOGGER_KEY, loggerText);
}
protected void removeLoggerText(){
MDC.remove(IO_LOGGER_KEY);
}
@SuppressWarnings("unchecked")
private <T extends Annotation> T getParameterAnnotation(Annotation[] anns, Class<T> c) {
T t = null;
if (!ArrayUtils.isEmpty(anns)) {
for (Annotation ann : anns) {
if (ann.annotationType() == c) {
t = (T) ann;
break;
}
}
}
return t;
}
private Method getMethod(JoinPoint jp) {
Method method = null;
Signature signature = jp.getSignature();
if (signature instanceof MethodSignature) {
MethodSignature ms = (MethodSignature) jp.getSignature();
method = AopUtils.getMostSpecificMethod(ms.getMethod(), jp.getTarget().getClass());
}
return method;
}
}