package scouter.agent.counter.task;
import scouter.agent.Configure;
import scouter.agent.Logger;
import scouter.agent.counter.CounterBasket;
import scouter.agent.counter.anotation.Counter;
import scouter.agent.netio.data.DataProxy;
import scouter.agent.proxy.ToolsMainFactory;
import scouter.agent.trace.TraceContext;
import scouter.agent.trace.TraceContextManager;
import scouter.lang.pack.StackPack;
import scouter.lang.step.DumpStep;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.Enumeration;
public class MakeStack {
static Configure conf = Configure.getInstance();
public long lastStackTime;
@Counter
public void make(CounterBasket pw) {
if (isPStackEnabled()== false){
ToolsMainFactory.activeStack=false;
return;
}
long now = System.currentTimeMillis();
if (now < lastStackTime + getSFAInterval())
return;
lastStackTime = now;
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter(sw);
try {
ToolsMainFactory.threadDump(out);
} catch (Throwable e) {
} finally {
out.close();
}
String stack = sw.getBuffer().toString();
StackPack p = new StackPack();
p.time = System.currentTimeMillis();
p.objHash = conf.getObjHash();
p.setStack(stack);
DataProxy.sendDirect(p);
long elapsed = (System.currentTimeMillis() - now);
Logger.trace("[SFA Counter Elasped]" + elapsed);
}
public static long pstack_requested;
private boolean isPStackEnabled() {
return conf.sfa_dump_enabled || System.currentTimeMillis() < pstack_requested;
}
private long getSFAInterval() {
return conf.sfa_dump_interval_ms;
}
long lastStackTraceGenTime = 0;
@Counter
public void stackTraceStepGenerator(CounterBasket pw) {
if (!conf._psts_enabled){
return;
}
long now = System.currentTimeMillis();
if (now < lastStackTraceGenTime + conf._psts_dump_interval_ms) {
return;
}
lastStackTraceGenTime = now;
ThreadMXBean tmxBean = ManagementFactory.getThreadMXBean();
Enumeration<TraceContext> en = TraceContextManager.getContextEnumeration();
while (en.hasMoreElements()) {
TraceContext ctx = en.nextElement();
if(ctx == null || ctx.threadId <= 0) {
continue;
}
ThreadInfo tInfo = tmxBean.getThreadInfo(ctx.threadId, 50);
if (tInfo == null) continue;
StackTraceElement[] elements = tInfo.getStackTrace();
int length = elements.length;
int[] stacks = new int[length];
for(int i=0; i<length; i++) {
stacks[i] = DataProxy.sendStackElement(elements[i]);
}
DumpStep dumpStep = new DumpStep();
dumpStep.start_time = (int) (System.currentTimeMillis() - ctx.startTime);
dumpStep.stacks = stacks;
dumpStep.threadId = ctx.threadId;
dumpStep.threadName = tInfo.getThreadName();
dumpStep.threadState = tInfo.getThreadState().toString();
dumpStep.lockOwnerId = tInfo.getLockOwnerId();
dumpStep.lockName = tInfo.getLockName();
dumpStep.lockOwnerName = tInfo.getLockOwnerName();
ctx.temporaryDumpSteps.offer(dumpStep);
ctx.hasDumpStack = true;
}
long elapsed = (System.currentTimeMillis() - now);
Logger.trace("[ASTS Elasped]" + elapsed);
}
}