/*
* Copyright 2014 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.profiler.logging;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.common.util.ArrayUtils;
import org.slf4j.Marker;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.*;
/**
* @author emeroad
*/
public class Slf4jPLoggerAdapter implements PLogger {
public static final int BUFFER_SIZE = 512;
private static final Map<Class<?>, Class<?>> SIMPLE_TYPE = new IdentityHashMap<Class<?>, Class<?>>();
static {
SIMPLE_TYPE.put(String.class, String.class);
SIMPLE_TYPE.put(Boolean.class, Boolean.class);
SIMPLE_TYPE.put(boolean.class, boolean.class);
SIMPLE_TYPE.put(Byte.class, Byte.class);
SIMPLE_TYPE.put(byte.class, byte.class);
SIMPLE_TYPE.put(Short.class, Short.class);
SIMPLE_TYPE.put(short.class, short.class);
SIMPLE_TYPE.put(Integer.class, Integer.class);
SIMPLE_TYPE.put(int.class, int.class);
SIMPLE_TYPE.put(Long.class, Long.class);
SIMPLE_TYPE.put(long.class, long.class);
SIMPLE_TYPE.put(Float.class, Float.class);
SIMPLE_TYPE.put(float.class, float.class);
SIMPLE_TYPE.put(Double.class, Double.class);
SIMPLE_TYPE.put(double.class, double.class);
SIMPLE_TYPE.put(Character.class, Character.class);
SIMPLE_TYPE.put(char.class, char.class);
SIMPLE_TYPE.put(BigDecimal.class, BigDecimal.class);
SIMPLE_TYPE.put(StringBuffer.class, StringBuffer.class);
SIMPLE_TYPE.put(BigInteger.class, BigInteger.class);
SIMPLE_TYPE.put(Class.class, Class.class);
SIMPLE_TYPE.put(java.sql.Date.class, java.sql.Date.class);
SIMPLE_TYPE.put(java.util.Date.class, java.util.Date.class);
SIMPLE_TYPE.put(Time.class, Time.class);
SIMPLE_TYPE.put(Timestamp.class, Timestamp.class);
SIMPLE_TYPE.put(Calendar.class, Calendar.class);
SIMPLE_TYPE.put(GregorianCalendar.class, GregorianCalendar.class);
SIMPLE_TYPE.put(URL.class, URL.class);
SIMPLE_TYPE.put(Object.class, Object.class);
}
private final org.slf4j.Logger logger;
public Slf4jPLoggerAdapter(org.slf4j.Logger logger) {
if (logger == null) {
throw new NullPointerException("logger must not be null");
}
this.logger = logger;
}
public String getName() {
return logger.getName();
}
@Override
public void beforeInterceptor(Object target, String className, String methodName, String parameterDescription, Object[] args) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("BEFORE ");
logMethod(sb, target, className, methodName, parameterDescription, args);
logger.debug(sb.toString());
}
@Override
public void beforeInterceptor(Object target, Object[] args) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("BEFORE ");
logMethod(sb, target, args);
logger.debug(sb.toString());
}
@Override
public void afterInterceptor(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result, Throwable throwable) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("AFTER ");
logMethod(sb, target, className, methodName, parameterDescription, args);
logResult(sb, result, throwable);
if (throwable == null) {
logger.debug(sb.toString());
} else {
logger.debug(sb.toString(), throwable);
}
}
@Override
public void afterInterceptor(Object target, Object[] args, Object result, Throwable throwable) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("AFTER ");
logMethod(sb, target, args);
logResult(sb, result, throwable);
if (throwable == null) {
logger.debug(sb.toString());
} else {
logger.debug(sb.toString(), throwable);
}
}
private static void logResult(StringBuilder sb, Object result, Throwable throwable) {
if (throwable == null) {
sb.append(" result:");
sb.append(normalizedParameter(result));
} else {
sb.append(" Caused:");
sb.append(throwable.getMessage());
}
}
@Override
public void afterInterceptor(Object target, String className, String methodName, String parameterDescription, Object[] args) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("AFTER ");
logMethod(sb, target, className, methodName, parameterDescription, args);
logger.debug(sb.toString());
}
@Override
public void afterInterceptor(Object target, Object[] args) {
StringBuilder sb = new StringBuilder(BUFFER_SIZE);
sb.append("AFTER ");
logMethod(sb, target, args);
logger.debug(sb.toString());
}
private static void logMethod(StringBuilder sb, Object target, String className, String methodName, String parameterDescription, Object[] args) {
sb.append(getTarget(target));
sb.append(' ');
sb.append(className);
sb.append(' ');
sb.append(methodName);
sb.append(parameterDescription);
sb.append(" args:");
appendParameterList(sb, args);
}
private static void logMethod(StringBuilder sb, Object target, Object[] args) {
sb.append(getTarget(target));
sb.append(' ');
sb.append(" args:");
appendParameterList(sb, args);
}
private static String getTarget(Object target) {
// Use class name instead of target.toString() because latter could cause side effects.
if (target == null) {
return "target=null";
} else {
return target.getClass().getName();
}
}
private static void appendParameterList(StringBuilder sb, Object[] args) {
if (ArrayUtils.isEmpty(args)) {
sb.append("()");
return;
}
if (args.length > 0) {
sb.append('(');
sb.append(normalizedParameter(args[0]));
for (int i = 1; i < args.length; i++) {
sb.append(", ");
sb.append(normalizedParameter(args[i]));
}
sb.append(')');
}
}
private static String normalizedParameter(Object arg) {
// Do not call toString() because it could cause some side effects.
if (arg == null) {
return "null";
} else {
// Check if arg is simple type which is safe to invoke toString()
if (isSimpleType(arg)) {
return arg.toString();
} else {
return arg.getClass().getSimpleName();
}
}
}
private static boolean isSimpleType(Object arg) {
Class<?> find = SIMPLE_TYPE.get(arg.getClass());
if (find == null) {
return false;
}
return true;
}
@Override
public boolean isTraceEnabled() {
return logger.isTraceEnabled();
}
@Override
public void trace(String msg) {
logger.trace(msg);
}
@Override
public void trace(String format, Object arg) {
logger.trace(format, arg);
}
@Override
public void trace(String format, Object arg1, Object arg2) {
logger.trace(format, arg1, arg2);
}
@Override
public void trace(String format, Object[] argArray) {
logger.trace(format, argArray);
}
@Override
public void trace(String msg, Throwable t) {
logger.trace(msg, t);
}
public boolean isTraceEnabled(Marker marker) {
return logger.isTraceEnabled(marker);
}
public void trace(Marker marker, String msg) {
logger.trace(marker, msg);
}
public void trace(Marker marker, String format, Object arg) {
logger.trace(marker, format, arg);
}
public void trace(Marker marker, String format, Object arg1, Object arg2) {
logger.trace(marker, format, arg1, arg2);
}
public void trace(Marker marker, String format, Object[] argArray) {
logger.trace(marker, format, argArray);
}
public void trace(Marker marker, String msg, Throwable t) {
logger.trace(marker, msg, t);
}
@Override
public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}
@Override
public void debug(String msg) {
logger.debug(msg);
}
@Override
public void debug(String format, Object arg) {
logger.debug(format, arg);
}
@Override
public void debug(String format, Object arg1, Object arg2) {
logger.debug(format, arg1, arg2);
}
@Override
public void debug(String format, Object[] argArray) {
logger.debug(format, argArray);
}
@Override
public void debug(String msg, Throwable t) {
logger.debug(msg, t);
}
public boolean isDebugEnabled(Marker marker) {
return logger.isDebugEnabled(marker);
}
public void debug(Marker marker, String msg) {
logger.debug(marker, msg);
}
public void debug(Marker marker, String format, Object arg) {
logger.debug(marker, format, arg);
}
public void debug(Marker marker, String format, Object arg1, Object arg2) {
logger.debug(marker, format, arg1, arg2);
}
public void debug(Marker marker, String format, Object[] argArray) {
logger.debug(marker, format, argArray);
}
public void debug(Marker marker, String msg, Throwable t) {
logger.debug(marker, msg, t);
}
@Override
public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}
@Override
public void info(String msg) {
logger.info(msg);
}
@Override
public void info(String format, Object arg) {
logger.info(format, arg);
}
@Override
public void info(String format, Object arg1, Object arg2) {
logger.info(format, arg1, arg2);
}
@Override
public void info(String format, Object[] argArray) {
logger.info(format, argArray);
}
@Override
public void info(String msg, Throwable t) {
logger.info(msg, t);
}
public boolean isInfoEnabled(Marker marker) {
return logger.isInfoEnabled(marker);
}
public void info(Marker marker, String msg) {
logger.info(marker, msg);
}
public void info(Marker marker, String format, Object arg) {
logger.info(marker, format, arg);
}
public void info(Marker marker, String format, Object arg1, Object arg2) {
logger.info(marker, format, arg1, arg2);
}
public void info(Marker marker, String format, Object[] argArray) {
logger.info(marker, format, argArray);
}
public void info(Marker marker, String msg, Throwable t) {
logger.info(marker, msg, t);
}
@Override
public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}
@Override
public void warn(String msg) {
logger.warn(msg);
}
@Override
public void warn(String format, Object arg) {
logger.warn(format, arg);
}
@Override
public void warn(String format, Object[] argArray) {
logger.warn(format, argArray);
}
@Override
public void warn(String format, Object arg1, Object arg2) {
logger.warn(format, arg1, arg2);
}
@Override
public void warn(String msg, Throwable t) {
logger.warn(msg, t);
}
public boolean isWarnEnabled(Marker marker) {
return logger.isWarnEnabled(marker);
}
public void warn(Marker marker, String msg) {
logger.warn(marker, msg);
}
public void warn(Marker marker, String format, Object arg) {
logger.warn(marker, format, arg);
}
public void warn(Marker marker, String format, Object arg1, Object arg2) {
logger.warn(marker, format, arg1, arg2);
}
public void warn(Marker marker, String format, Object[] argArray) {
logger.warn(marker, format, argArray);
}
public void warn(Marker marker, String msg, Throwable t) {
logger.warn(marker, msg, t);
}
@Override
public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}
@Override
public void error(String msg) {
logger.error(msg);
}
@Override
public void error(String format, Object arg) {
logger.error(format, arg);
}
@Override
public void error(String format, Object arg1, Object arg2) {
logger.error(format, arg1, arg2);
}
@Override
public void error(String format, Object[] argArray) {
logger.error(format, argArray);
}
@Override
public void error(String msg, Throwable t) {
logger.error(msg, t);
}
public boolean isErrorEnabled(Marker marker) {
return logger.isErrorEnabled(marker);
}
public void error(Marker marker, String msg) {
logger.error(marker, msg);
}
public void error(Marker marker, String format, Object arg) {
logger.error(marker, format, arg);
}
public void error(Marker marker, String format, Object arg1, Object arg2) {
logger.error(marker, format, arg1, arg2);
}
public void error(Marker marker, String format, Object[] argArray) {
logger.error(marker, format, argArray);
}
public void error(Marker marker, String msg, Throwable t) {
logger.error(marker, msg, t);
}
}