001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.monitors;
028
029
030
031 import java.util.ArrayList;
032 import java.util.LinkedHashSet;
033 import java.util.Map;
034 import java.util.Map.Entry;
035 import java.util.TreeMap;
036
037 import org.opends.server.admin.std.server.StackTraceMonitorProviderCfg;
038 import org.opends.server.api.MonitorProvider;
039 import org.opends.server.config.ConfigException;
040 import org.opends.server.core.DirectoryServer;
041 import org.opends.server.types.Attribute;
042 import org.opends.server.types.AttributeType;
043 import org.opends.server.types.AttributeValue;
044 import org.opends.server.types.InitializationException;
045
046
047
048 /**
049 * This class defines a Directory Server monitor provider that can be used to
050 * obtain a stack trace from all server threads that are currently defined in
051 * the JVM.
052 */
053 public class StackTraceMonitorProvider
054 extends MonitorProvider<StackTraceMonitorProviderCfg>
055 {
056 /**
057 * Initializes this monitor provider.
058 */
059 public StackTraceMonitorProvider()
060 {
061 super("Stack Trace Monitor Provider");
062
063 // No initialization should be performed here.
064 }
065
066
067
068 /**
069 * {@inheritDoc}
070 */
071 public void initializeMonitorProvider(
072 StackTraceMonitorProviderCfg configuration)
073 throws ConfigException, InitializationException
074 {
075 // No initialization is required.
076 }
077
078
079
080 /**
081 * Retrieves the name of this monitor provider. It should be unique among all
082 * monitor providers, including all instances of the same monitor provider.
083 *
084 * @return The name of this monitor provider.
085 */
086 public String getMonitorInstanceName()
087 {
088 return "JVM Stack Trace";
089 }
090
091
092
093 /**
094 * Retrieves the length of time in milliseconds that should elapse between
095 * calls to the <CODE>updateMonitorData()</CODE> method. A negative or zero
096 * return value indicates that the <CODE>updateMonitorData()</CODE> method
097 * should not be periodically invoked.
098 *
099 * @return The length of time in milliseconds that should elapse between
100 * calls to the <CODE>updateMonitorData()</CODE> method.
101 */
102 public long getUpdateInterval()
103 {
104 // This monitor does not need to run periodically.
105 return 0;
106 }
107
108
109
110 /**
111 * Performs any processing periodic processing that may be desired to update
112 * the information associated with this monitor. Note that best-effort
113 * attempts will be made to ensure that calls to this method come
114 * <CODE>getUpdateInterval()</CODE> milliseconds apart, but no guarantees will
115 * be made.
116 */
117 public void updateMonitorData()
118 {
119 // This monitor does not need to run periodically.
120 return;
121 }
122
123
124
125 /**
126 * Retrieves a set of attributes containing monitor data that should be
127 * returned to the client if the corresponding monitor entry is requested.
128 *
129 * @return A set of attributes containing monitor data that should be
130 * returned to the client if the corresponding monitor entry is
131 * requested.
132 */
133 public ArrayList<Attribute> getMonitorData()
134 {
135 Map<Thread,StackTraceElement[]> threadStacks = Thread.getAllStackTraces();
136
137
138 // Re-arrange all of the elements by thread ID so that there is some logical
139 // order.
140 TreeMap<Long,Map.Entry<Thread,StackTraceElement[]>> orderedStacks =
141 new TreeMap<Long,Map.Entry<Thread,StackTraceElement[]>>();
142 for (Map.Entry<Thread,StackTraceElement[]> e : threadStacks.entrySet())
143 {
144 orderedStacks.put(e.getKey().getId(), e);
145 }
146
147
148 AttributeType attrType =
149 DirectoryServer.getDefaultAttributeType("jvmThread");
150 LinkedHashSet<AttributeValue> values = new LinkedHashSet<AttributeValue>();
151
152 for (Map.Entry<Thread,StackTraceElement[]> e : orderedStacks.values())
153 {
154 Thread t = e.getKey();
155 StackTraceElement[] stackElements = e.getValue();
156
157 long id = t.getId();
158
159 StringBuilder buffer = new StringBuilder();
160 buffer.append("id=");
161 buffer.append(id);
162 buffer.append(" ---------- ");
163 buffer.append(t.getName());
164 buffer.append(" ----------");
165 values.add(new AttributeValue(attrType, buffer.toString()));
166
167 // Create an attribute for the stack trace.
168 if (stackElements != null)
169 {
170 for (int j=0; j < stackElements.length; j++)
171 {
172 buffer = new StringBuilder();
173 buffer.append("id=");
174 buffer.append(id);
175 buffer.append(" frame[");
176 buffer.append(j);
177 buffer.append("]=");
178
179 buffer.append(stackElements[j].getClassName());
180 buffer.append(".");
181 buffer.append(stackElements[j].getMethodName());
182 buffer.append("(");
183 buffer.append(stackElements[j].getFileName());
184 buffer.append(":");
185 if (stackElements[j].isNativeMethod())
186 {
187 buffer.append("native");
188 }
189 else
190 {
191 buffer.append(stackElements[j].getLineNumber());
192 }
193 buffer.append(")");
194
195 values.add(new AttributeValue(attrType, buffer.toString()));
196 }
197 }
198 }
199
200 ArrayList<Attribute> attrs = new ArrayList<Attribute>();
201 attrs.add(new Attribute(attrType, "jvmThread", values));
202
203 return attrs;
204 }
205 }
206