/* * 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.netio.request.handle; import scouter.agent.AgentCommonConstant; import scouter.agent.Configure; import scouter.agent.Logger; import scouter.agent.counter.task.MakeStack; import scouter.agent.netio.request.anotation.RequestHandler; import scouter.agent.netio.request.worker.DumpOnCpuExceedanceWorker; import scouter.agent.proxy.ToolsMainFactory; import scouter.agent.trace.TraceContext; import scouter.agent.trace.TraceContextManager; import scouter.agent.util.DumpUtil; import scouter.lang.pack.MapPack; import scouter.lang.pack.Pack; import scouter.lang.value.*; import scouter.util.CastUtil; import scouter.util.Hexa32; import scouter.util.SysJMX; import scouter.util.ThreadUtil; import java.io.IOException; import java.util.Enumeration; import static scouter.net.RequestCmd.*; public class AgentThread { @RequestHandler(OBJECT_THREAD_DETAIL) public Pack threadDetail(Pack param) { MapPack paramPack = (MapPack) param; long thread = paramPack.getLong("id"); long txid = paramPack.getLong("txid"); MapPack p; TraceContext ctx; if(thread != 0L) { p = ThreadUtil.getThreadDetail(thread); ctx = TraceContextManager.getContext(thread); } else { p = new MapPack(); ctx = TraceContextManager.getDeferredContext(txid); } if (ctx != null) { p.put("Thread Id", new DecimalValue(0L)); p.put("Thread Name", new TextValue("[No Thread] wait on deferred queue")); p.put("State", new TextValue("n/a")); p.put("Service Txid", new TextValue(Hexa32.toString32(ctx.txid))); p.put("Service Name", new TextValue(AgentCommonConstant.removeSpringRequestMappingPostfixFlag(ctx.serviceName))); long etime = System.currentTimeMillis() - ctx.startTime; p.put("Service Elapsed", new DecimalValue(etime)); } return p; } @RequestHandler(OBJECT_THREAD_CONTROL) public Pack threadKill(Pack param) { long thread = ((MapPack) param).getLong("id"); String action = ((MapPack) param).getText("action"); // 쓰레드 상세 화면에서 쓰레드를 제어한다. TraceContext ctx = TraceContextManager.getContext(thread); try { if (ctx != null) { if ("interrupt".equalsIgnoreCase(action)) { ctx.thread.interrupt(); } else if ("stop".equalsIgnoreCase(action)) { ctx.thread.stop(); } else if ("resume".equalsIgnoreCase(action)) { ctx.thread.resume(); } else if ("suspend".equalsIgnoreCase(action)) { ctx.thread.suspend(); } } } catch (Throwable t) { } MapPack p = ThreadUtil.getThreadDetail(thread); if (ctx != null) { p.put("Service Txid", new TextValue(Hexa32.toString32(ctx.txid))); p.put("Service Name", new TextValue(AgentCommonConstant.removeSpringRequestMappingPostfixFlag(ctx.serviceName))); long etime = System.currentTimeMillis() - ctx.startTime; p.put("Service Elapsed", new DecimalValue(etime)); String sql = ctx.sqltext; if (sql != null) { p.put("SQL", sql); } String subcall = ctx.apicall_name; if (subcall != null) { p.put("Subcall", subcall); } } return p; } @RequestHandler(OBJECT_THREAD_LIST) public Pack threadList(Pack param) { MapPack mpack = ThreadUtil.getThreadList(); ListValue ids = mpack.getList("id"); ListValue txid = mpack.newList("txid"); ListValue elapsed = mpack.newList("elapsed"); ListValue service = mpack.newList("service"); for (int i = 0; i < ids.size(); i++) { long tid = CastUtil.clong(ids.get(i)); TraceContext ctx = TraceContextManager.getContext(tid); if (ctx != null) { txid.add(new TextValue(Hexa32.toString32(ctx.txid))); service.add(new TextValue(AgentCommonConstant.removeSpringRequestMappingPostfixFlag(ctx.serviceName))); long etime = System.currentTimeMillis() - ctx.startTime; elapsed.add(new DecimalValue(etime)); } else { txid.add(new NullValue()); elapsed.add(new NullValue()); service.add(new NullValue()); } } return mpack; } Configure conf = Configure.getInstance(); @RequestHandler(OBJECT_ACTIVE_SERVICE_LIST) public Pack activeThreadList(Pack param) { MapPack rPack = new MapPack(); ListValue id = rPack.newList("id"); ListValue elapsed = rPack.newList("elapsed"); ListValue service = rPack.newList("service"); ListValue stat = rPack.newList("stat"); ListValue name = rPack.newList("name"); ListValue cpu = rPack.newList("cpu"); ListValue txid = rPack.newList("txid"); ListValue ip = rPack.newList("ip"); ListValue sql = rPack.newList("sql"); ListValue subcall = rPack.newList("subcall"); ListValue login = rPack.newList("login"); ListValue desc = rPack.newList("desc"); Enumeration<TraceContext> en = TraceContextManager.getContextEnumeration(); while (en.hasMoreElements()) { TraceContext ctx = en.nextElement(); if (ctx == null) { continue; } id.add(ctx.thread.getId()); name.add(ctx.thread.getName()); stat.add(ctx.thread.getState().name()); txid.add(new TextValue(Hexa32.toString32(ctx.txid))); service.add(new TextValue(AgentCommonConstant.removeSpringRequestMappingPostfixFlag(ctx.serviceName))); ip.add(ctx.remoteIp); long etime = System.currentTimeMillis() - ctx.startTime; elapsed.add(new DecimalValue(etime)); sql.add(ctx.sqltext); subcall.add(ctx.apicall_name); try { cpu.add(SysJMX.getThreadCpuTime(ctx.thread)); } catch (Throwable th) { Logger.println("A128", th); cpu.add(0L); } login.add(ctx.login); desc.add(ctx.desc); } Enumeration<TraceContext> enDeferred = TraceContextManager.getDeferredContextEnumeration(); while (enDeferred.hasMoreElements()) { TraceContext ctx = enDeferred.nextElement(); if (ctx == null) { continue; } id.add(0L); name.add("[No Thread] wait on deferred queue"); stat.add("n/a"); txid.add(new TextValue(Hexa32.toString32(ctx.txid))); service.add(new TextValue(AgentCommonConstant.removeSpringRequestMappingPostfixFlag(ctx.serviceName))); ip.add(ctx.remoteIp); long etime = System.currentTimeMillis() - ctx.startTime; elapsed.add(new DecimalValue(etime)); sql.add(ctx.sqltext); subcall.add(""); cpu.add(0L); login.add(ctx.login); desc.add(ctx.desc); } rPack.put("complete", new BooleanValue(true)); return rPack; } @RequestHandler(OBJECT_THREAD_DUMP) public Pack threadDump(Pack param) { try { return ToolsMainFactory.threadDump(param); } catch (Throwable e) { e.printStackTrace(); } return null; } @RequestHandler(TRIGGER_ACTIVE_SERVICE_LIST) public Pack triggerActiveServiceList(Pack param) { return DumpUtil.triggerActiveService(); } @RequestHandler(TRIGGER_THREAD_LIST) public Pack triggerThreadList(Pack param) { return DumpUtil.triggerThreadList(); } @RequestHandler(TRIGGER_THREAD_DUMP) public Pack triggerThreadDump(Pack param) { return DumpUtil.triggerThreadDump(); } @RequestHandler(TRIGGER_THREAD_DUMPS_FROM_CONDITIONS) public Pack triggerThreadDumpsFromConditions(Pack param) { MapPack mpack = (MapPack) param; DumpOnCpuExceedanceWorker.getInstance().add(mpack.getText(TRIGGER_DUMP_REASON)); return null; } @RequestHandler(PSTACK_ON) public Pack turnOn(Pack param) { MapPack p = (MapPack) param; long time = p.getLong("time"); if (time <= 0) { MakeStack.pstack_requested = 0; } else { MakeStack.pstack_requested = System.currentTimeMillis() + time; } return param; } public static void main(String[] args) throws IOException { } }