mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-20 18:25:55 +10:00
[강운덕] [LUCYSUS-1744] 바인딩 변수 api 할당 api의 아규먼트를 문자열로 치환하는 로직 부분 개발.
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@626 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
@@ -4,10 +4,7 @@ import java.lang.reflect.Method;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.logging.Level;
|
||||
@@ -57,7 +54,7 @@ public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
preparedStatement.addTraceVariable("__url", "__setUrl", "__getUrl", "java.lang.String");
|
||||
preparedStatement.addTraceVariable("__sql", "__setSql", "__getSql", "java.lang.String");
|
||||
|
||||
preparedStatement.addTraceVariable("__bindValue", "__setBindValue", "__getBindValue", "java.util.List", "java.util.Collections.synchronizedList(new java.util.LinkedList());");
|
||||
preparedStatement.addTraceVariable("__bindValue", "__setBindValue", "__getBindValue", "java.util.Map", "java.util.Collections.synchronizedMap(new java.util.HashMap());");
|
||||
bindVariableIntercept(preparedStatement, classLoader, protectedDomain);
|
||||
|
||||
return preparedStatement.toBytecode();
|
||||
@@ -90,14 +87,15 @@ public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
String methodName = method.getName();
|
||||
String[] parameterType = JavaAssistUtils.getParameterType(method.getParameterTypes());
|
||||
try {
|
||||
preparedStatement.addInterceptor(methodName, parameterType , interceptor);
|
||||
preparedStatement.addInterceptor(methodName, parameterType, interceptor);
|
||||
} catch (NotFoundInstrumentException e) {
|
||||
// bind variable setter메소드를 못찾을 경우는 그냥 경고만 표시
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, "bindVariable api modify fail. Cause:" + e.getMessage(), e);
|
||||
// bind variable setter메소드를 못찾을 경우는 그냥 경고만 표시, 에러 아님.
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.log(Level.INFO, "bindVariable api not found. Cause:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-4
@@ -3,17 +3,19 @@ package com.profiler.modifier.db.mysql.interceptors;
|
||||
import com.profiler.context.Trace;
|
||||
import com.profiler.interceptor.StaticAfterInterceptor;
|
||||
import com.profiler.util.MetaObject;
|
||||
import com.profiler.util.NumberUtils;
|
||||
import com.profiler.util.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PreparedStatementBindVariableInterceptor implements StaticAfterInterceptor {
|
||||
private final Logger logger = Logger.getLogger(PreparedStatementBindVariableInterceptor.class.getName());
|
||||
|
||||
private final MetaObject<List> getBindValue = new MetaObject<List>("__getBindValue");
|
||||
private final MetaObject<Map> getBindValue = new MetaObject<Map>("__getBindValue");
|
||||
|
||||
@Override
|
||||
public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) {
|
||||
@@ -23,9 +25,13 @@ public class PreparedStatementBindVariableInterceptor implements StaticAfterInte
|
||||
if (Trace.getCurrentTraceId() == null) {
|
||||
return;
|
||||
}
|
||||
List bindList = getBindValue.invoke(target);
|
||||
String index = StringUtils.toString(args[0]);
|
||||
Map bindList = getBindValue.invoke(target);
|
||||
Integer index = NumberUtils.toInteger(args[0]);
|
||||
if(index == null) {
|
||||
// 어딘가 잘못됨.
|
||||
return;
|
||||
}
|
||||
String value = StringUtils.toString(args[1]);
|
||||
bindList.add(index + ":" + value);
|
||||
bindList.put(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-5
@@ -1,9 +1,7 @@
|
||||
package com.profiler.modifier.db.mysql.interceptors;
|
||||
|
||||
import com.mysql.jdbc.PreparedStatement;
|
||||
import com.profiler.context.Annotation;
|
||||
import com.profiler.context.Trace;
|
||||
import com.profiler.interceptor.StaticAfterInterceptor;
|
||||
import com.profiler.interceptor.StaticAroundInterceptor;
|
||||
import com.profiler.util.InterceptorUtils;
|
||||
import com.profiler.util.MetaObject;
|
||||
@@ -19,8 +17,8 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept
|
||||
|
||||
private final MetaObject<String> getSql = new MetaObject("__getSql");
|
||||
private final MetaObject<String> getUrl = new MetaObject("__getUrl");
|
||||
private final MetaObject<List<String>> getBindValue = new MetaObject("__getBindValue");
|
||||
private final MetaObject<List<String>> setBindValue = new MetaObject("__setBindValue");
|
||||
private final MetaObject<Map> getBindValue = new MetaObject("__getBindValue");
|
||||
private final MetaObject<Map> setBindValue = new MetaObject("__setBindValue");
|
||||
|
||||
|
||||
@Override
|
||||
@@ -39,7 +37,8 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept
|
||||
String sql = getSql.invoke(target);
|
||||
Trace.recordAttibute("PreparedStatement", sql);
|
||||
|
||||
List<String> bindValue = getBindValue.invoke(target);
|
||||
Map bindValue = getBindValue.invoke(target);
|
||||
String bindString = toBindVariable(bindValue);
|
||||
Trace.recordAttibute("BindValue", bindValue.toString());
|
||||
setBindValue.invoke(target, Collections.synchronizedList(new LinkedList<String>()));
|
||||
|
||||
@@ -52,6 +51,14 @@ public class PreparedStatementMethodInterceptor implements StaticAroundIntercept
|
||||
|
||||
}
|
||||
|
||||
private String toBindVariable(Map bindValue) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i =0; i<bindValue.size(); i++) {
|
||||
Object o = bindValue.get(i);
|
||||
}
|
||||
return null; //To change body of created methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) {
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.profiler.util;
|
||||
|
||||
|
||||
public class ArrayUtils {
|
||||
|
||||
public static String dropToString(byte[] bytes) {
|
||||
return dropToString(bytes, 10);
|
||||
}
|
||||
|
||||
public static String dropToString(byte[] bytes, int limit) {
|
||||
if (bytes == null) {
|
||||
return "null";
|
||||
}
|
||||
// TODO limit음수일 경우 예외처리 필요.
|
||||
// size 4인 배열의 경 3에서 멈춰야 하므로 -1
|
||||
int iMax = bytes.length - 1;
|
||||
int iLimit = limit - 1;
|
||||
if (iMax > iLimit) {
|
||||
iMax = iLimit;
|
||||
}
|
||||
if (iMax == -1) {
|
||||
if (bytes.length == 0) {
|
||||
return "[]";
|
||||
} else {
|
||||
return "[...(" + bytes.length + ")]";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
for (int i = 0; ; i++) {
|
||||
sb.append(bytes[i]);
|
||||
if (i == iMax) {
|
||||
if (iMax < iLimit) {
|
||||
return sb.append(']').toString();
|
||||
} else {
|
||||
if (i > 0) {
|
||||
|
||||
}
|
||||
sb.append(", ");
|
||||
sb.append("...(");
|
||||
sb.append(bytes.length);
|
||||
sb.append(")]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -23,4 +23,15 @@ public class NumberUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Integer toInteger(Object integer) {
|
||||
if(integer == null) {
|
||||
return null;
|
||||
}
|
||||
if (integer instanceof Integer) {
|
||||
return (Integer)integer;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,4 +12,24 @@ public class StringUtils {
|
||||
}
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
public static String drop(String str) {
|
||||
return drop(str, 20, getDropString(str));
|
||||
}
|
||||
|
||||
public static String getDropString(String str) {
|
||||
return "...(" + str.length() + ")";
|
||||
}
|
||||
|
||||
public static String drop(String str, int length, String padding) {
|
||||
if (str == null) {
|
||||
return "null";
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder(length + 10);
|
||||
if(str.length() > length) {
|
||||
buffer.append(str.substring(0, length));
|
||||
buffer.append(padding);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.profiler.util.bindvalue;
|
||||
|
||||
import com.profiler.util.StringUtils;
|
||||
import com.profiler.util.bindvalue.converter.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -8,6 +8,81 @@ import java.util.Map;
|
||||
public class BindValueConverter {
|
||||
public static final Map<String, Converter> convertermap = new HashMap<String, Converter>() ;
|
||||
|
||||
private void register() {
|
||||
simpleType();
|
||||
classNameType();
|
||||
|
||||
// null argument 가 3개인것도 있음.
|
||||
convertermap.put("setNull", new NullTypeConterver());
|
||||
|
||||
BytesConverter bytesConverter = new BytesConverter();
|
||||
convertermap.put("setBytes", bytesConverter);
|
||||
|
||||
|
||||
// setObject
|
||||
convertermap.put("setObject", null);
|
||||
}
|
||||
|
||||
private void classNameType() {
|
||||
// className 데이터를 까볼수 없는 객체의 경우 class명으로 치환
|
||||
ClassNameConverter classNameConverter = new ClassNameConverter();
|
||||
// 3개짜리 존재
|
||||
convertermap.put("setAsciiStream", classNameConverter);
|
||||
convertermap.put("setUnicodeStream", classNameConverter);
|
||||
convertermap.put("setBinaryStream", classNameConverter);
|
||||
|
||||
//3개 짜리 존재
|
||||
convertermap.put("setBlob", classNameConverter);
|
||||
//3개 짜리 존재
|
||||
convertermap.put("setClob", classNameConverter);
|
||||
convertermap.put("setArray", classNameConverter);
|
||||
convertermap.put("setNCharacterStream", classNameConverter);
|
||||
|
||||
// 3개 짜리 존재
|
||||
convertermap.put("setNClob", classNameConverter);
|
||||
|
||||
|
||||
convertermap.put("setCharacterStream", classNameConverter);
|
||||
convertermap.put("setSQLXML", classNameConverter);
|
||||
convertermap.put("setSQLXML", classNameConverter);
|
||||
convertermap.put("setSQLXML", classNameConverter);
|
||||
convertermap.put("setSQLXML", classNameConverter);
|
||||
|
||||
}
|
||||
|
||||
private void simpleType() {
|
||||
|
||||
SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter();
|
||||
convertermap.put("setByte", simpleTypeConverter);
|
||||
convertermap.put("setShort", simpleTypeConverter);
|
||||
convertermap.put("setInt", simpleTypeConverter);
|
||||
convertermap.put("setLong", simpleTypeConverter);
|
||||
convertermap.put("setFloat", simpleTypeConverter);
|
||||
convertermap.put("setDouble", simpleTypeConverter);
|
||||
convertermap.put("setBigDecimal", simpleTypeConverter);
|
||||
convertermap.put("setString", simpleTypeConverter);
|
||||
convertermap.put("setDate", simpleTypeConverter);
|
||||
|
||||
// argument 가 3개 가능.
|
||||
convertermap.put("setTime", simpleTypeConverter);
|
||||
//convertermap.put("setTime", simpleTypeConverter);
|
||||
|
||||
// argument 가 3개 가능
|
||||
convertermap.put("setTimestamp", simpleTypeConverter);
|
||||
//convertermap.put("setTimestamp", simpleTypeConverter);
|
||||
|
||||
|
||||
// 문자열로 치환 가능할것으로 보임.
|
||||
convertermap.put("setURL", simpleTypeConverter);
|
||||
// ref도 문자열로 치환 가능할것으로 보임
|
||||
convertermap.put("setRef", simpleTypeConverter);
|
||||
convertermap.put("setNString", simpleTypeConverter);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String bindValueToString(String methodName, Object[] args) {
|
||||
Converter converter = convertermap.get(methodName);
|
||||
if (converter == null) {
|
||||
@@ -16,26 +91,6 @@ public class BindValueConverter {
|
||||
return converter.convert(args);
|
||||
}
|
||||
|
||||
interface Converter {
|
||||
String convert(Object[] args);
|
||||
}
|
||||
|
||||
class CommonConverter implements Converter {
|
||||
@Override
|
||||
public String convert(Object[] args) {
|
||||
if(args == null) {
|
||||
return "null";
|
||||
}
|
||||
if (args.length == 1) {
|
||||
return StringUtils.toString(args[1]);
|
||||
}
|
||||
else if(args.length == 2) {
|
||||
return StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]);
|
||||
}
|
||||
else if(args.length == 3) {
|
||||
return StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]);
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.profiler.util.bindvalue.converter;
|
||||
|
||||
import com.profiler.util.ArrayUtils;
|
||||
import com.profiler.util.StringUtils;
|
||||
|
||||
|
||||
public class BytesConverter implements Converter {
|
||||
@Override
|
||||
public String convert(Object[] args) {
|
||||
if (args == null) {
|
||||
return "null";
|
||||
}
|
||||
if (args.length == 2) {
|
||||
byte[] bytes = (byte[]) args[1];
|
||||
if (bytes == null) {
|
||||
return "null";
|
||||
} else {
|
||||
return StringUtils.drop(ArrayUtils.dropToString(bytes));
|
||||
}
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.profiler.util.bindvalue.converter;
|
||||
|
||||
import com.profiler.util.StringUtils;
|
||||
|
||||
public class ClassNameConverter implements Converter {
|
||||
@Override
|
||||
public String convert(Object[] args) {
|
||||
if (args == null) {
|
||||
return "null";
|
||||
}
|
||||
if (args.length == 2) {
|
||||
String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(getClassName(args[1]));
|
||||
return StringUtils.drop(str);
|
||||
} else if (args.length == 3) {
|
||||
// TODO 3일때 추가 처리?
|
||||
String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(getClassName(args[1]));
|
||||
return StringUtils.drop(str);
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
private Object getClassName(Object args) {
|
||||
if (args == null) {
|
||||
return "null";
|
||||
}
|
||||
return args.getClass().getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.profiler.util.bindvalue.converter;
|
||||
|
||||
public interface Converter {
|
||||
String convert(Object[] args);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.profiler.util.bindvalue.converter;
|
||||
|
||||
public class NullTypeConterver implements Converter {
|
||||
|
||||
@Override
|
||||
public String convert(Object[] args) {
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.profiler.util.bindvalue.converter;
|
||||
|
||||
import com.profiler.util.StringUtils;
|
||||
|
||||
public class SimpleTypeConverter implements Converter {
|
||||
@Override
|
||||
public String convert(Object[] args) {
|
||||
if (args == null) {
|
||||
return "null";
|
||||
}
|
||||
if (args.length == 2) {
|
||||
String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]);
|
||||
return StringUtils.drop(str);
|
||||
} else if (args.length == 3) {
|
||||
// TODO 3일때 추가 처리?
|
||||
String str = StringUtils.toString(args[0]) + ":" + StringUtils.toString(args[1]);
|
||||
return StringUtils.drop(str);
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user