Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f3d744c

Browse files
proto of tracing method call stack
1 parent 1c736ee commit f3d744c

File tree

5 files changed

+361
-0
lines changed

5 files changed

+361
-0
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package trace.method;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
*
8+
* @GitHub : https://github.com/zacscoding
9+
*/
10+
public class MethodContext {
11+
12+
// classname::methodname
13+
private String id;
14+
// start time
15+
private long startTime;
16+
// end time
17+
private long endTime;
18+
// parameters
19+
private List<String> params = new ArrayList<>();
20+
// return value
21+
private String returnValue;
22+
// exception
23+
private Exception exception;
24+
// depth in call stack
25+
private int depth;
26+
27+
public MethodContext(String id, long startTime) {
28+
this.id = id;
29+
this.startTime = startTime;
30+
}
31+
32+
public void appendParam(Object obj) {
33+
params.add(obj == null ? "null" : obj.toString());
34+
}
35+
36+
public void appendReturnValue(Object obj, long endTime) {
37+
this.returnValue = obj == null ? "null" : obj.toString();
38+
this.endTime = endTime;
39+
}
40+
41+
// getters, setters
42+
public String getId() {
43+
return id;
44+
}
45+
46+
public void setId(String id) {
47+
this.id = id;
48+
}
49+
50+
public List<String> getParams() {
51+
return params;
52+
}
53+
54+
public void setParams(List<String> params) {
55+
this.params = params;
56+
}
57+
58+
public String getReturnValue() {
59+
return returnValue;
60+
}
61+
62+
public void setReturnValue(String returnValue) {
63+
this.returnValue = returnValue;
64+
}
65+
66+
public Exception getException() {
67+
return exception;
68+
}
69+
70+
public void setException(Exception exception) {
71+
this.exception = exception;
72+
}
73+
74+
public int getDepth() {
75+
return depth;
76+
}
77+
78+
public void setDepth(int depth) {
79+
this.depth = depth;
80+
}
81+
82+
public long getStartTime() {
83+
return startTime;
84+
}
85+
86+
public void setStartTime(long startTime) {
87+
this.startTime = startTime;
88+
}
89+
90+
public long getEndTime() {
91+
return endTime;
92+
}
93+
94+
public void setEndTime(long endTime) {
95+
this.endTime = endTime;
96+
}
97+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package trace.method;
2+
3+
import java.util.ArrayList;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.Stack;
7+
8+
/**
9+
*
10+
* @GitHub : https://github.com/zacscoding
11+
*/
12+
public class TransactionContext {
13+
14+
private List<MethodContext> methods = new LinkedList<>();
15+
public Stack<MethodContext> callStack = new Stack<>();
16+
17+
/**
18+
* Return traced method contexts
19+
*/
20+
public List<MethodContext> getMethods() {
21+
return new ArrayList<>(methods);
22+
}
23+
24+
public void appendParam(Object value) {
25+
if (callStack.isEmpty()) {
26+
System.err.println("appendParam(Object) called although has no trace method call");
27+
return;
28+
}
29+
30+
callStack.peek().appendParam(value);
31+
}
32+
33+
public void appendReturnValue(Object value, long endTime) {
34+
if (callStack.isEmpty()) {
35+
System.err.println("appendReturnValue(Object,long) called although has no trace method call");
36+
return;
37+
}
38+
39+
callStack.peek().appendReturnValue(value, endTime);
40+
}
41+
42+
/**
43+
* Start trace method call
44+
*/
45+
public void startMethod(MethodContext methodContext) {
46+
if (methodContext == null) {
47+
System.err.println("received null method context");
48+
return;
49+
}
50+
51+
methodContext.setDepth(callStack.size());
52+
callStack.push(methodContext);
53+
methods.add(methodContext);
54+
}
55+
56+
/**
57+
* End trace method call
58+
*/
59+
public void endMethod() {
60+
if (callStack.isEmpty()) {
61+
System.err.println("endMethod called with empty stack.");
62+
return;
63+
}
64+
65+
callStack.pop();
66+
}
67+
68+
public boolean hasTrace() {
69+
return !callStack.isEmpty();
70+
}
71+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package trace.method;
2+
3+
/**
4+
*
5+
* @GitHub : https://github.com/zacscoding
6+
*/
7+
public class TransactionContextManager {
8+
9+
// trace context
10+
private static ThreadLocal<TransactionContext> contexts = new ThreadLocal<TransactionContext>();
11+
12+
/**
13+
* Return a transaction context.
14+
*
15+
* If not exist, then create a new TransactionContext instance.
16+
*/
17+
public static TransactionContext getOrCreateContext() {
18+
TransactionContext ctx = contexts.get();
19+
20+
if (ctx == null) {
21+
ctx = new TransactionContext();
22+
contexts.set(ctx);
23+
}
24+
25+
return contexts.get();
26+
}
27+
28+
/**
29+
* Return a transaction context in current thread
30+
*
31+
* @return ctx or null if not exist
32+
*/
33+
public static TransactionContext getContext() {
34+
return contexts.get();
35+
}
36+
37+
/**
38+
* Remove transaction context in current thread.
39+
*
40+
* @return prev context or null
41+
*/
42+
public static TransactionContext dispose() {
43+
TransactionContext ctx = contexts.get();
44+
45+
if (ctx != null) {
46+
contexts.set(null);
47+
}
48+
49+
return ctx;
50+
}
51+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package trace.method;
2+
3+
import java.util.List;
4+
5+
/**
6+
*
7+
* @GitHub : https://github.com/zacscoding
8+
*/
9+
public class TransactionTrace {
10+
11+
public static void startTransaction(String id) {
12+
TransactionContext ctx = TransactionContextManager.getOrCreateContext();
13+
14+
if (ctx == null) {
15+
System.err.println("Cannot create a TransactionContext");
16+
return;
17+
}
18+
19+
MethodContext methodCtx = new MethodContext(id, System.currentTimeMillis());
20+
ctx.startMethod(methodCtx);
21+
}
22+
23+
public static void appendParam(Object value) {
24+
TransactionContext ctx = TransactionContextManager.getOrCreateContext();
25+
26+
if (ctx == null) {
27+
System.err.println("appendParam(Object) is called although not exit tx ctx");
28+
return;
29+
}
30+
31+
ctx.appendParam(value);
32+
}
33+
34+
public static void appendReturnValue(Object value) {
35+
TransactionContext ctx = TransactionContextManager.getOrCreateContext();
36+
37+
if (ctx == null) {
38+
System.err.println("appendReturnValue(Object) is called although not exit tx ctx");
39+
return;
40+
}
41+
42+
ctx.appendReturnValue(value, System.currentTimeMillis());
43+
}
44+
45+
public static void endTransaction() {
46+
TransactionContext ctx = TransactionContextManager.getOrCreateContext();
47+
48+
if (ctx == null) {
49+
System.err.println("endTransaction() is called although not exist TransactionContext");
50+
return;
51+
}
52+
53+
ctx.endMethod();
54+
55+
if (ctx.hasTrace()) {
56+
return;
57+
}
58+
59+
displayTracedCallStack(ctx);
60+
}
61+
62+
private static void displayTracedCallStack(TransactionContext ctx) {
63+
synchronized (System.out) {
64+
List<MethodContext> methods = ctx.getMethods();
65+
StringBuilder sb = new StringBuilder();
66+
67+
for (int i = 0; i < methods.size(); i++) {
68+
MethodContext methodCtx = methods.get(i);
69+
70+
// append depth
71+
int depth = methodCtx.getDepth();
72+
String depthPrefix = "";
73+
74+
while (depth-- > 0) {
75+
depthPrefix += "| ";
76+
}
77+
78+
sb.append(depthPrefix)
79+
.append("+--")
80+
.append(methodCtx.getId())
81+
.append('[')
82+
.append(methodCtx.getEndTime() - methodCtx.getStartTime())
83+
.append("ms] : ")
84+
.append(methodCtx.getReturnValue())
85+
.append('\n');
86+
87+
List<String> params = methodCtx.getParams();
88+
89+
/*if (i == 0 && !params.isEmpty()) {
90+
depthPrefix += "| ";
91+
}*/
92+
93+
for (int j = 0; j < params.size(); j++) {
94+
sb.append(depthPrefix)
95+
.append(" -- ")
96+
.append(j + 1)
97+
.append(" : ")
98+
.append(params.get(j))
99+
.append('\n');
100+
}
101+
}
102+
103+
System.out.println(sb);
104+
}
105+
}
106+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package trace.method;
2+
3+
import org.junit.Test;
4+
5+
/**
6+
*
7+
* @GitHub : https://github.com/zacscoding
8+
*/
9+
public class TransactionTraceTest {
10+
11+
@Test
12+
public void traceCallStackSample() {
13+
14+
TransactionTrace.startTransaction("ClassA::method1(String,int)");
15+
TransactionTrace.appendParam("param1");
16+
TransactionTrace.appendParam(Integer.valueOf(1));
17+
18+
TransactionTrace.startTransaction("ClassB::method11(int)");
19+
TransactionTrace.appendParam(Integer.valueOf(2));
20+
TransactionTrace.appendReturnValue("returnValue~");
21+
22+
TransactionTrace.startTransaction("ClassC::method112(double)");
23+
TransactionTrace.appendParam(Double.valueOf(2.2D));
24+
TransactionTrace.appendReturnValue("void");
25+
TransactionTrace.endTransaction();
26+
27+
TransactionTrace.endTransaction();
28+
29+
TransactionTrace.startTransaction("ClassD::method12()");
30+
TransactionTrace.appendReturnValue("void");
31+
TransactionTrace.endTransaction();
32+
33+
TransactionTrace.appendReturnValue("return value~!");
34+
TransactionTrace.endTransaction();
35+
}
36+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /