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