Skip to content

Commit

Permalink
Merge pull request #314 from scouter-project/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
bill23-kim authored Apr 13, 2017
2 parents c1b4d13 + 8b45344 commit 7e241ba
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,11 @@ public void disk(CounterBasket pw) {
if (conf.disk_ignore_names.hasKey(dir))
continue;

usage = sigar.getFileSystemUsage(dir);
try {
usage = sigar.getFileSystemUsage(dir);
} catch (SigarException e) {
continue;
}

float pct = (float) (usage.getUsePercent() * 100);
if (pct >= conf.disk_fatal_pct && fatal.length() < 32756) {
Expand Down
7 changes: 3 additions & 4 deletions scouter.agent.java/src/scouter/agent/AgentTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,14 @@ public static void reload() {
temp.add(new CallRunnableASM());

temp.add(new SpringReqMapASM());

temp.add(new SocketASM());

temp.add(new JspServletASM());
temp.add(new MapImplASM());
temp.add(new UserExceptionASM());
temp.add(new UserExceptionHandlerASM());

temp.add(new AddFieldASM());

temp.add(new MapImplASM());

asms = temp;
}

Expand Down
17 changes: 17 additions & 0 deletions scouter.agent.java/src/scouter/agent/Configure.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public final static synchronized Configure getInstance() {
public boolean profile_http_parameter_enabled;
@ConfigDesc("Service URL prefix for Http parameter profile")
public String profile_http_parameter_url_prefix = "/";
@ConfigDesc("spring controller method parameter profile")
public boolean profile_spring_controller_method_parameter_enabled = false;
@ConfigDesc("Activating profile summary function")
public boolean profile_summary_mode_enabled = false;
@ConfigDesc("Calculating CPU time by profile")
Expand Down Expand Up @@ -137,6 +139,8 @@ public final static synchronized Configure getInstance() {
public boolean profile_fullstack_sql_error_enabled = false;
@ConfigDesc("Stack profile in occurrence of commit error")
public boolean profile_fullstack_sql_commit_enabled = false;
@ConfigDesc("Stack profile in occurrence of sql error")
public boolean profile_fullstack_hooked_exception_enabled = false;
@ConfigDesc("Number of stack profile lines in occurrence of error")
public int profile_fullstack_max_lines = 0;
@ConfigDesc("Activating SQL literal task")
Expand Down Expand Up @@ -352,6 +356,12 @@ public final static synchronized Configure getInstance() {
public String hook_jdbc_rs_classes = "";
@ConfigDesc("Method set for dbconnection wrapping")
public String hook_jdbc_wrapping_driver_patterns = "";
@ConfigDesc("Exception class patterns - These will seem as error on xlog view. (ex) my.app.BizException,my.app.exception.*Exception")
public String hook_exception_class_patterns = "";
@ConfigDesc("Exception class exlude patterns")
public String hook_exception_exlude_class_patterns = "";
@ConfigDesc("Exception handler patterns - exceptions passed to these methods are treated as error on xlog view. (ex) my.app.myHandler.handleException")
public String hook_exception_handler_method_patterns = "";

@ConfigDesc("Hook for supporting async servlet")
public boolean hook_async_servlet_enabled = true;
Expand Down Expand Up @@ -556,6 +566,7 @@ private void apply() {
this.profile_http_querystring_enabled = getBoolean("profile_http_querystring_enabled", false);
this.profile_http_header_enabled = getBoolean("profile_http_header_enabled", false);
this.profile_http_parameter_enabled = getBoolean("profile_http_parameter_enabled", false);
this.profile_spring_controller_method_parameter_enabled = getBoolean("profile_spring_controller_method_parameter_enabled", false);
this.profile_summary_mode_enabled = getBoolean("profile_summary_mode_enabled", false);
this.xlog_lower_bound_time_ms = getInt("xlog_lower_bound_time_ms", 0);
this.trace_service_name_header_key = getValue("trace_service_name_header_key", null);
Expand Down Expand Up @@ -651,6 +662,10 @@ private void apply() {
this.hook_jdbc_stmt_classes = getValue("hook_jdbc_stmt_classes", "");
this.hook_jdbc_rs_classes = getValue("hook_jdbc_rs_classes", "");
this.hook_jdbc_wrapping_driver_patterns = getValue("hook_jdbc_wrapping_driver_patterns", "");
this.hook_exception_class_patterns = getValue("hook_exception_class_patterns", "");
this.hook_exception_exlude_class_patterns = getValue("hook_exception_exlude_class_patterns", "");
this.hook_exception_handler_method_patterns = getValue("hook_exception_handler_method_patterns", "");

this.hook_async_servlet_enabled = getBoolean("_hook_async_servlet_enabled", true);

this.hook_async_context_dispatch_patterns = getValue("hook_async_context_dispatch_patterns", "");
Expand Down Expand Up @@ -691,6 +706,8 @@ private void apply() {
this.profile_fullstack_apicall_error_enabled = getBoolean("profile_fullstack_apicall_error_enabled", false);
this.profile_fullstack_sql_error_enabled = getBoolean("profile_fullstack_sql_error_enabled", false);
this.profile_fullstack_sql_commit_enabled = getBoolean("profile_fullstack_sql_commit_enabled", false);
this.profile_fullstack_hooked_exception_enabled = getBoolean("profile_fullstack_hooked_exception_enabled", false);

this.profile_fullstack_max_lines = getInt("profile_fullstack_max_lines", 0);
this.profile_fullstack_rs_leak_enabled = getBoolean("profile_fullstack_rs_leak_enabled", false);
this.profile_fullstack_stmt_leak_enabled = getBoolean("profile_fullstack_stmt_leak_enabled", false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class JDBCPreparedStatementASM implements IASM, Opcodes {
public final HashSet<String> noField = new HashSet<String>();

public JDBCPreparedStatementASM() {
//mariadb 1.5.9
target.add("org/mariadb/jdbc/AbstractPrepareStatement");

target.add("org/mariadb/jdbc/AbstractMariaDbPrepareStatement");
target.add("org/mariadb/jdbc/MariaDbClientPreparedStatement");
target.add("org/mariadb/jdbc/MariaDbServerPreparedStatement");
Expand Down
85 changes: 85 additions & 0 deletions scouter.agent.java/src/scouter/agent/asm/SpringReqMapASM.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import scouter.org.objectweb.asm.ClassVisitor;
import scouter.org.objectweb.asm.MethodVisitor;
import scouter.org.objectweb.asm.Opcodes;
import scouter.org.objectweb.asm.Type;
import scouter.org.objectweb.asm.commons.LocalVariablesSorter;
import scouter.util.StringUtil;

Expand Down Expand Up @@ -132,12 +133,25 @@ class SpringReqMapMV extends LocalVariablesSorter implements Opcodes {
private static final String TRACEMAIN = "scouter/agent/trace/TraceMain";
private final static String SET_METHOD = "setServiceName";
private static final String SET_METHOD_SIGNATURE = "(Ljava/lang/String;)V";

private final static String CONTROLLER_START_METHOD = "startSpringControllerMethod";
private static final String CONTROLLER_START_METHOD_SIGNATURE = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V";

private String methodRequestMappingUrl;
private String methodType;
private boolean isRequestHandler = false;

private String className;
private int access;
private String methodName;
private String desc;

public SpringReqMapMV(String className, int access, String methodName, String desc, MethodVisitor mv) {
super(ASM4, access, desc, mv);
this.className = className;
this.access = access;
this.methodName = methodName;
this.desc = desc;
}

@Override
Expand Down Expand Up @@ -166,6 +180,77 @@ public void visitCode() {
Logger.println("[Apply Spring F/W REST URL] " + serviceUrl);
AsmUtil.PUSH(mv, serviceUrl);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, TRACEMAIN, SET_METHOD, SET_METHOD_SIGNATURE, false);

//=========== call for spring request mapping method capture plugin ============
Type[] types = Type.getArgumentTypes(desc);
boolean isStatic = (access & ACC_STATIC) != 0;

int sidx = isStatic ? 0 : 1;

int arrVarIdx = newLocal(Type.getType("[Ljava/lang/Object;"));
AsmUtil.PUSH(mv, types.length);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
mv.visitVarInsn(Opcodes.ASTORE, arrVarIdx);

for (int i = 0; i < types.length; i++) {
Type type = types[i];
mv.visitVarInsn(Opcodes.ALOAD, arrVarIdx);
AsmUtil.PUSH(mv, i);

switch (type.getSort()) {
case Type.BOOLEAN:
mv.visitVarInsn(Opcodes.ILOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;",
false);
break;
case Type.BYTE:
mv.visitVarInsn(Opcodes.ILOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
break;
case Type.CHAR:
mv.visitVarInsn(Opcodes.ILOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;",
false);
break;
case Type.SHORT:
mv.visitVarInsn(Opcodes.ILOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
break;
case Type.INT:
mv.visitVarInsn(Opcodes.ILOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;",
false);
break;
case Type.LONG:
mv.visitVarInsn(Opcodes.LLOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
break;
case Type.FLOAT:
mv.visitVarInsn(Opcodes.FLOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
break;
case Type.DOUBLE:
mv.visitVarInsn(Opcodes.DLOAD, sidx);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
break;
default:
mv.visitVarInsn(Opcodes.ALOAD, sidx);
}
mv.visitInsn(Opcodes.AASTORE);
sidx += type.getSize();
}
AsmUtil.PUSH(mv, className);
AsmUtil.PUSH(mv, methodName);
AsmUtil.PUSH(mv, desc);
if (isStatic) {
AsmUtil.PUSHNULL(mv);
} else {
mv.visitVarInsn(Opcodes.ALOAD, 0);
}
mv.visitVarInsn(Opcodes.ALOAD, arrVarIdx);

mv.visitMethodInsn(Opcodes.INVOKESTATIC, TRACEMAIN, CONTROLLER_START_METHOD, CONTROLLER_START_METHOD_SIGNATURE, false);

}
mv.visitCode();
}
Expand Down
102 changes: 102 additions & 0 deletions scouter.agent.java/src/scouter/agent/asm/UserExceptionASM.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* 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 scouter.agent.asm;

import scouter.agent.ClassDesc;
import scouter.agent.Configure;
import scouter.agent.asm.util.AsmUtil;
import scouter.agent.asm.util.HookingSet;
import scouter.agent.trace.TraceMain;
import scouter.org.objectweb.asm.ClassVisitor;
import scouter.org.objectweb.asm.MethodVisitor;
import scouter.org.objectweb.asm.Opcodes;

import java.util.List;

public class UserExceptionASM implements IASM, Opcodes {
String exceptionPatterns = HookingSet.classPattrensToMethodPatterns(Configure.getInstance().hook_exception_class_patterns, "<init>");
String exceptionExcludePatterns = HookingSet.classPattrensToMethodPatterns(Configure.getInstance().hook_exception_exlude_class_patterns, "<init>");

private List<HookingSet> target = HookingSet.getHookingMethodSet(exceptionPatterns);
private List<HookingSet> excludeTarget = HookingSet.getHookingMethodSet(exceptionExcludePatterns);

public ClassVisitor transform(ClassVisitor cv, String className, ClassDesc classDesc) {
for (int i = 0; i < target.size(); i++) {
HookingSet mset = target.get(i);
if (mset.classMatch.include(className)) {
for (int j = 0; j < excludeTarget.size(); j++) {
HookingSet excludeHookinSet = excludeTarget.get(j);
if (excludeHookinSet.classMatch.include(className)) {
return cv;
}
}
return new UserExceptionCV(cv, mset, className);
}
}
return cv;
}
}

class UserExceptionCV extends ClassVisitor implements Opcodes {

private HookingSet mset;
private String className;

public UserExceptionCV(ClassVisitor cv, HookingSet mset, String className) {
super(ASM4, cv);
this.mset = mset;
this.className = className;
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (mv == null || mset.isA(name, desc) == false) {
return mv;
}
return new UserExceptionConsturtorMV(className, desc, mv);
}
}

// ///////////////////////////////////////////////////////////////////////////
class UserExceptionConsturtorMV extends MethodVisitor implements Opcodes {
private static final String CLASS = TraceMain.class.getName().replace('.', '/');
private static final String METHOD = "endExceptionConstructor";
private static final String SIGNATURE = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V";

private String className;
private String methodDesc;

public UserExceptionConsturtorMV(String classname, String methoddesc, MethodVisitor mv) {
super(ASM4, mv);
this.className = classname;
this.methodDesc = methoddesc;
}

@Override
public void visitInsn(int opcode) {
if ((opcode >= IRETURN && opcode <= RETURN) || opcode == ATHROW) {
AsmUtil.PUSH(mv, className);
AsmUtil.PUSH(mv, methodDesc);
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, CLASS, METHOD, SIGNATURE,false);
}
mv.visitInsn(opcode);
}
}

Loading

0 comments on commit 7e241ba

Please sign in to comment.