Skip to content

Commit 5bc8dc2

Browse files
committed
agent asm buf fix & end user script error gathering
1 parent b7385ae commit 5bc8dc2

File tree

7 files changed

+280
-197
lines changed

7 files changed

+280
-197
lines changed

scouter.agent.java/src/scouter/agent/AgentTransformer.java

+157-120
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
*/
1717
package scouter.agent;
1818

19-
import scouter.agent.asm.IASM;
20-
import scouter.agent.asm.ScouterClassWriter;
19+
import scouter.agent.asm.*;
2120
import scouter.agent.asm.util.AsmUtil;
2221
import scouter.agent.util.AsyncRunner;
2322
import scouter.lang.conf.ConfObserver;
@@ -30,123 +29,161 @@
3029
import java.security.ProtectionDomain;
3130
import java.util.ArrayList;
3231
import java.util.List;
32+
3333
public class AgentTransformer implements ClassFileTransformer {
34-
public static ThreadLocal<ClassLoader> hookingCtx = new ThreadLocal<ClassLoader>();
35-
private static List<IASM> asms = new ArrayList<IASM>();
36-
// hook 관련 설정이 변경되면 자동으로 변경된다.
37-
private static int hook_signature;
38-
static {
39-
final Configure conf = Configure.getInstance();
40-
reload();
41-
hook_signature = conf.getHookSignature();
42-
ConfObserver.add("AgentTransformer", new Runnable() {
43-
public void run() {
44-
if (conf.getHookSignature() != hook_signature) {
45-
reload();
46-
}
47-
hook_signature = conf.getHookSignature();
48-
}
49-
});
50-
}
51-
public static void reload() {
52-
Configure conf = Configure.getInstance();
53-
List<IASM> temp = new ArrayList<IASM>();
54-
asms = temp;
55-
}
56-
// //////////////////////////////////////////////////////////////
57-
// boot class이지만 Hooking되어야하는 클래스를 등록한다.
58-
private static IntSet asynchook = new IntSet();
59-
static {
60-
asynchook.add("sun/net/www/protocol/http/HttpURLConnection".hashCode());
61-
asynchook.add("sun/net/www/http/HttpClient".hashCode());
62-
asynchook.add("java/net/Socket".hashCode());
63-
asynchook.add("javax/naming/InitialContext".hashCode());
64-
}
65-
private Configure conf = Configure.getInstance();
66-
private Logger.FileLog bciOut;
67-
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
68-
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
69-
try {
70-
hookingCtx.set(loader);
71-
if (className == null)
72-
return null;
73-
if (classBeingRedefined == null) {
74-
if (asynchook.contains(className.hashCode())) {
75-
AsyncRunner.getInstance().add(loader, className, classfileBuffer);
76-
return null;
77-
}
78-
if (loader == null) {
79-
return null;
80-
}
81-
}
82-
if (className.startsWith("scouter/")) {
83-
return null;
84-
}
85-
//
86-
classfileBuffer = DirectPatch.patch(className, classfileBuffer);
87-
ObjTypeDetector.check(className);
88-
final ClassDesc classDesc = new ClassDesc();
89-
ClassReader cr = new ClassReader(classfileBuffer);
90-
cr.accept(new ClassVisitor(Opcodes.ASM4) {
91-
public void visit(int version, int access, String name, String signature, String superName,
92-
String[] interfaces) {
93-
classDesc.set(version, access, name, signature, superName, interfaces);
94-
}
95-
@Override
96-
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
97-
classDesc.anotation += desc;
98-
return super.visitAnnotation(desc, visible);
99-
}
100-
}, 0);
101-
if (AsmUtil.isInterface(classDesc.access)) {
102-
return null;
103-
}
104-
classDesc.classBeingRedefined = classBeingRedefined;
105-
ClassWriter cw = getClassWriter(classDesc);
106-
ClassVisitor cv = cw;
107-
List<IASM> workAsms = asms;
108-
for (int i = 0, max = workAsms.size(); i < max; i++) {
109-
cv = workAsms.get(i).transform(cv, className, classDesc);
110-
if (cv != cw) {
111-
cr = new ClassReader(classfileBuffer);
112-
cr.accept(cv, ClassReader.EXPAND_FRAMES);
113-
classfileBuffer = cw.toByteArray();
114-
cv = cw = getClassWriter(classDesc);
115-
if (conf.log_asm_enabled) {
116-
if (this.bciOut == null) {
117-
this.bciOut = new Logger.FileLog("./scouter.bci");
118-
}
119-
this.bciOut.println(className + "\t\t[" + loader + "]");
120-
}
121-
}
122-
}
123-
return classfileBuffer;
124-
} catch (Throwable t) {
125-
Logger.println("A101", "Transformer Error", t);
126-
t.printStackTrace();
127-
} finally {
128-
hookingCtx.set(null);
129-
}
130-
return null;
131-
}
132-
private ClassWriter getClassWriter(final ClassDesc classDesc) {
133-
ClassWriter cw;
134-
switch (classDesc.version) {
135-
case Opcodes.V1_1:
136-
case Opcodes.V1_2:
137-
case Opcodes.V1_3:
138-
case Opcodes.V1_4:
139-
case Opcodes.V1_5:
140-
case Opcodes.V1_6:
141-
cw = new ScouterClassWriter(ClassWriter.COMPUTE_MAXS);
142-
break;
143-
default:
144-
cw = new ScouterClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
145-
}
146-
return cw;
147-
}
148-
private void dump(String className, byte[] bytes) {
149-
String fname = "/tmp/" + className.replace('/', '_');
150-
FileUtil.save(fname, bytes);
151-
}
34+
public static ThreadLocal<ClassLoader> hookingCtx = new ThreadLocal<ClassLoader>();
35+
private static List<IASM> asms = new ArrayList<IASM>();
36+
// hook 관련 설정이 변경되면 자동으로 변경된다.
37+
private static int hook_signature;
38+
39+
static {
40+
final Configure conf = Configure.getInstance();
41+
reload();
42+
hook_signature = conf.getHookSignature();
43+
ConfObserver.add("AgentTransformer", new Runnable() {
44+
public void run() {
45+
if (conf.getHookSignature() != hook_signature) {
46+
reload();
47+
}
48+
hook_signature = conf.getHookSignature();
49+
}
50+
});
51+
}
52+
53+
public static void reload() {
54+
Configure conf = Configure.getInstance();
55+
List<IASM> temp = new ArrayList<IASM>();
56+
temp.add(new HttpServiceASM());
57+
temp.add(new ServiceASM());
58+
59+
temp.add(new JDBCPreparedStatementASM());
60+
temp.add(new JDBCResultSetASM());
61+
temp.add(new JDBCStatementASM());
62+
temp.add(new SqlMapASM());
63+
temp.add(new UserTxASM());
64+
65+
temp.add(new JDBCConnectionOpenASM());
66+
temp.add(new JDBCDriverASM());
67+
temp.add(new InitialContextASM());
68+
69+
temp.add(new CapArgsASM());
70+
temp.add(new CapReturnASM());
71+
temp.add(new CapThisASM());
72+
73+
temp.add(new MethodASM());
74+
temp.add(new ApicallASM());
75+
temp.add(new ApicallInfoASM());
76+
temp.add(new SpringReqMapASM());
77+
78+
temp.add(new SocketASM());
79+
80+
temp.add(new JspServletASM());
81+
82+
temp.add(new AddFieldASM());
83+
84+
asms = temp;
85+
}
86+
87+
// //////////////////////////////////////////////////////////////
88+
// boot class이지만 Hooking되어야하는 클래스를 등록한다.
89+
private static IntSet asynchook = new IntSet();
90+
91+
static {
92+
asynchook.add("sun/net/www/protocol/http/HttpURLConnection".hashCode());
93+
asynchook.add("sun/net/www/http/HttpClient".hashCode());
94+
asynchook.add("java/net/Socket".hashCode());
95+
asynchook.add("javax/naming/InitialContext".hashCode());
96+
}
97+
98+
private Configure conf = Configure.getInstance();
99+
private Logger.FileLog bciOut;
100+
101+
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
102+
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
103+
try {
104+
hookingCtx.set(loader);
105+
if (className == null)
106+
return null;
107+
if (classBeingRedefined == null) {
108+
if (asynchook.contains(className.hashCode())) {
109+
AsyncRunner.getInstance().add(loader, className, classfileBuffer);
110+
return null;
111+
}
112+
if (loader == null) {
113+
return null;
114+
}
115+
}
116+
if (className.startsWith("scouter/")) {
117+
return null;
118+
}
119+
//
120+
classfileBuffer = DirectPatch.patch(className, classfileBuffer);
121+
ObjTypeDetector.check(className);
122+
final ClassDesc classDesc = new ClassDesc();
123+
ClassReader cr = new ClassReader(classfileBuffer);
124+
cr.accept(new ClassVisitor(Opcodes.ASM4) {
125+
public void visit(int version, int access, String name, String signature, String superName,
126+
String[] interfaces) {
127+
classDesc.set(version, access, name, signature, superName, interfaces);
128+
}
129+
130+
@Override
131+
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
132+
classDesc.anotation += desc;
133+
return super.visitAnnotation(desc, visible);
134+
}
135+
}, 0);
136+
if (AsmUtil.isInterface(classDesc.access)) {
137+
return null;
138+
}
139+
classDesc.classBeingRedefined = classBeingRedefined;
140+
ClassWriter cw = getClassWriter(classDesc);
141+
ClassVisitor cv = cw;
142+
List<IASM> workAsms = asms;
143+
for (int i = 0, max = workAsms.size(); i < max; i++) {
144+
cv = workAsms.get(i).transform(cv, className, classDesc);
145+
if (cv != cw) {
146+
cr = new ClassReader(classfileBuffer);
147+
cr.accept(cv, ClassReader.EXPAND_FRAMES);
148+
classfileBuffer = cw.toByteArray();
149+
cv = cw = getClassWriter(classDesc);
150+
if (conf.log_asm_enabled) {
151+
if (this.bciOut == null) {
152+
this.bciOut = new Logger.FileLog("./scouter.bci");
153+
}
154+
this.bciOut.println(className + "\t\t[" + loader + "]");
155+
}
156+
}
157+
}
158+
return classfileBuffer;
159+
} catch (Throwable t) {
160+
Logger.println("A101", "Transformer Error", t);
161+
t.printStackTrace();
162+
} finally {
163+
hookingCtx.set(null);
164+
}
165+
return null;
166+
}
167+
168+
private ClassWriter getClassWriter(final ClassDesc classDesc) {
169+
ClassWriter cw;
170+
switch (classDesc.version) {
171+
case Opcodes.V1_1:
172+
case Opcodes.V1_2:
173+
case Opcodes.V1_3:
174+
case Opcodes.V1_4:
175+
case Opcodes.V1_5:
176+
case Opcodes.V1_6:
177+
cw = new ScouterClassWriter(ClassWriter.COMPUTE_MAXS);
178+
break;
179+
default:
180+
cw = new ScouterClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
181+
}
182+
return cw;
183+
}
184+
185+
private void dump(String className, byte[] bytes) {
186+
String fname = "/tmp/" + className.replace('/', '_');
187+
FileUtil.save(fname, bytes);
188+
}
152189
}

scouter.agent.java/src/scouter/agent/Configure.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ public final static synchronized Configure getInstance() {
209209
public int summary_enduser_error_max_count = 5000;
210210

211211
//EndUser
212-
public String enduser_trace_endpoint_url = "_scouter_browser.jsp";
212+
public String enduser_trace_endpoint_url = "/_scouter_browser.jsp";
213213

214214
//internal variables
215215
private int objHash;

scouter.agent.java/src/scouter/agent/summary/EndUserErrorData.java

+24-7
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,31 @@
1717
package scouter.agent.summary;
1818

1919
public class EndUserErrorData {
20-
public int stacktrace;
20+
public int count;
21+
22+
public int host;
23+
public int uri;
24+
public int stacktrace;
2125
public int userAgent;
22-
public int count;
23-
//
24-
public int uri;
26+
public int name;
2527
public int message;
2628
public int file;
27-
public int lineNumber;// :1
28-
public int columnNumber;// :26
29-
public int payloadVersion;// :2
29+
public int lineNumber;
30+
public int columnNumber;
31+
32+
@Override
33+
public String toString() {
34+
return "EndUserErrorData{" +
35+
"count=" + count +
36+
", host=" + host +
37+
", uri=" + uri +
38+
", stacktrace=" + stacktrace +
39+
", userAgent=" + userAgent +
40+
", name=" + name +
41+
", message=" + message +
42+
", file=" + file +
43+
", lineNumber=" + lineNumber +
44+
", columnNumber=" + columnNumber +
45+
'}';
46+
}
3047
}

0 commit comments

Comments
 (0)