001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.solr.handler.admin;
017:
018: import java.io.IOException;
019: import java.lang.management.ManagementFactory;
020: import java.lang.management.ThreadInfo;
021: import java.lang.management.ThreadMXBean;
022:
023: import org.apache.solr.handler.RequestHandlerBase;
024: import org.apache.solr.handler.RequestHandlerUtils;
025: import org.apache.solr.request.SolrQueryRequest;
026: import org.apache.solr.request.SolrQueryResponse;
027: import org.apache.solr.util.NamedList;
028: import org.apache.solr.util.SimpleOrderedMap;
029:
030: /**
031: * Copied from "admin/threaddump.jsp"
032: *
033: * NOTE: the response format is still likely to change. It should be designed so
034: * that it works nicely with an XSLT transformation. Until we have a nice
035: * XSLT front end for /admin, the format is still open to change.
036: *
037: * @author ryan
038: * @version $Id: ThreadDumpHandler.java 533815 2007-04-30 17:57:52Z ryan $
039: * @since solr 1.2
040: */
041: public class ThreadDumpHandler extends RequestHandlerBase {
042: @Override
043: public void handleRequestBody(SolrQueryRequest req,
044: SolrQueryResponse rsp) throws IOException {
045: RequestHandlerUtils.addExperimentalFormatWarning(rsp);
046:
047: SimpleOrderedMap<Object> system = new SimpleOrderedMap<Object>();
048: rsp.add("system", system);
049:
050: ThreadMXBean tmbean = ManagementFactory.getThreadMXBean();
051:
052: // Thread Count
053: SimpleOrderedMap<Object> nl = new SimpleOrderedMap<Object>();
054: nl.add("current", tmbean.getThreadCount());
055: nl.add("peak", tmbean.getPeakThreadCount());
056: nl.add("daemon", tmbean.getDaemonThreadCount());
057: system.add("threadCount", nl);
058:
059: // Deadlocks
060: ThreadInfo[] tinfos;
061: long[] tids = tmbean.findMonitorDeadlockedThreads();
062: if (tids != null) {
063: tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
064: NamedList<SimpleOrderedMap<Object>> lst = new NamedList<SimpleOrderedMap<Object>>();
065: for (ThreadInfo ti : tinfos) {
066: lst.add("thread", getThreadInfo(ti, tmbean));
067: }
068: system.add("deadlocks", lst);
069: }
070:
071: // Now show all the threads....
072: tids = tmbean.getAllThreadIds();
073: tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
074: NamedList<SimpleOrderedMap<Object>> lst = new NamedList<SimpleOrderedMap<Object>>();
075: for (ThreadInfo ti : tinfos) {
076: lst.add("thread", getThreadInfo(ti, tmbean));
077: }
078: system.add("threadDump", lst);
079: }
080:
081: //--------------------------------------------------------------------------------
082: //--------------------------------------------------------------------------------
083:
084: private static SimpleOrderedMap<Object> getThreadInfo(
085: ThreadInfo ti, ThreadMXBean tmbean) throws IOException {
086: SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
087: long tid = ti.getThreadId();
088:
089: info.add("id", tid);
090: info.add("name", ti.getThreadName());
091: info.add("state", ti.getThreadState().toString());
092:
093: if (ti.getLockName() != null) {
094: info.add("lock", ti.getLockName());
095: }
096: if (ti.isSuspended()) {
097: info.add("suspended", true);
098: }
099: if (ti.isInNative()) {
100: info.add("native", true);
101: }
102:
103: if (tmbean.isThreadCpuTimeSupported()) {
104: info.add("cpuTime", formatNanos(tmbean
105: .getThreadCpuTime(tid)));
106: info.add("userTime", formatNanos(tmbean
107: .getThreadUserTime(tid)));
108: }
109:
110: if (ti.getLockOwnerName() != null) {
111: SimpleOrderedMap<Object> owner = new SimpleOrderedMap<Object>();
112: owner.add("name", ti.getLockOwnerName());
113: owner.add("id", ti.getLockOwnerId());
114: }
115:
116: // Add the stack trace
117: int i = 0;
118: String[] trace = new String[ti.getStackTrace().length];
119: for (StackTraceElement ste : ti.getStackTrace()) {
120: trace[i++] = ste.toString();
121: }
122: info.add("stackTrace", trace);
123: return info;
124: }
125:
126: private static String formatNanos(long ns) {
127: return String.format("%.4fms", ns / (double) 1000000);
128: }
129:
130: //////////////////////// SolrInfoMBeans methods //////////////////////
131:
132: @Override
133: public String getDescription() {
134: return "Thread Dump";
135: }
136:
137: @Override
138: public String getVersion() {
139: return "$Revision: 533815 $";
140: }
141:
142: @Override
143: public String getSourceId() {
144: return "$Id: ThreadDumpHandler.java 533815 2007-04-30 17:57:52Z ryan $";
145: }
146:
147: @Override
148: public String getSource() {
149: return "$URL: https://svn.apache.org/repos/asf/lucene/solr/branches/branch-1.2/src/java/org/apache/solr/handler/admin/ThreadDumpHandler.java $";
150: }
151: }
|