1 29 30 package com.caucho.servlets; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.jmx.Jmx; 34 import com.caucho.log.Log; 35 import com.caucho.management.server.*; 36 import com.caucho.util.L10N; 37 import com.caucho.util.QDate; 38 39 import javax.management.MBeanServer ; 40 import javax.management.ObjectName ; 41 import javax.servlet.GenericServlet ; 42 import javax.servlet.ServletException ; 43 import javax.servlet.ServletRequest ; 44 import javax.servlet.ServletResponse ; 45 import javax.servlet.http.HttpServletRequest ; 46 import javax.servlet.http.HttpServletResponse ; 47 import java.io.IOException ; 48 import java.io.PrintWriter ; 49 import java.util.ArrayList ; 50 import java.util.Collections ; 51 import java.util.Comparator ; 52 import java.util.Iterator ; 53 import java.util.Set ; 54 import java.util.logging.Level ; 55 import java.util.logging.Logger ; 56 57 64 public class ResinStatusServlet extends GenericServlet { 65 static final protected Logger log = Log.open(ResinStatusServlet.class); 66 static final L10N L = new L10N(ResinStatusServlet.class); 67 68 private static final long SECOND = 1000L; 69 private static final long MINUTE = 60 * SECOND; 70 private static final long HOUR = 60 * MINUTE; 71 private static final long DAY = 24 * HOUR; 72 73 private String _enable; 74 75 private MBeanServer _mbeanServer; 76 private ResinMXBean _resin; 77 private ServerMXBean _server; 78 private ClusterMXBean _cluster; 79 private ProxyCacheMXBean _proxyCache; 80 81 84 public void setEnable(String enable) 85 throws ConfigException 86 { 87 if ("read".equals(enable) || "write".equals(enable)) 88 _enable = enable; 89 else 90 throw new ConfigException(L.l("enable value '{0}' must either be read or write.", 91 enable)); 92 } 93 94 97 public void init() 98 throws ServletException 99 { 100 if (_enable == null) 101 throw new ServletException (L.l("ResinStatusServlet requires an explicit enable attribute.")); 102 103 try { 104 106 108 _mbeanServer = 110 Jmx.getGlobalMBeanServer(); 111 112 115 _resin = (ResinMXBean) Jmx.findGlobal("resin:type=Resin"); 116 _server = (ServerMXBean) Jmx.findGlobal("resin:type=Server"); 117 _cluster = (ClusterMXBean) Jmx.findGlobal("resin:type=Cluster"); 118 _proxyCache = (ProxyCacheMXBean) Jmx.findGlobal("resin:type=ProxyCache"); 119 } catch (Exception e) { 120 throw new ServletException (e); 121 } 122 } 123 124 127 public void service(ServletRequest request, ServletResponse response) 128 throws IOException , ServletException 129 { 130 try { 131 HttpServletRequest req = (HttpServletRequest ) request; 132 HttpServletResponse res = (HttpServletResponse ) response; 133 134 res.setContentType("text/html"); 135 136 Thread thread = Thread.currentThread(); 137 thread.setContextClassLoader(ClassLoader.getSystemClassLoader()); 138 139 PrintWriter out = res.getWriter(); 140 141 printHeader(out); 142 143 String hostName = req.getParameter("host"); 144 String appName = req.getParameter("app"); 145 146 printServerHeader(out); 147 printPorts(out); 148 printSrun(out); 149 152 printApplicationSummary(out, req.getRequestURI()); 153 printFooter(out); 154 } catch (IOException e) { 155 throw e; 156 } catch (ServletException e) { 157 throw e; 158 } catch (Exception e) { 159 throw new ServletException (e); 160 } 161 } 162 163 187 188 191 public void printHeader(PrintWriter out) 192 throws IOException , ServletException 193 { 194 } 195 196 199 public void printServerHeader(PrintWriter out) 200 throws Exception 201 { 202 out.println("<b>resin-status</b><br><br>"); 203 204 String id = _server.getId(); 205 206 out.println("<table border=\"0\">"); 207 if (id != null) 208 out.println("<tr><td><b>Server:</b><td>" + id); 209 210 String configFile = _resin.getConfigFile(); 211 if (configFile != null) 212 out.println("<tr><td><b>Config:</b><td>" + configFile); 213 214 long startTime = _server.getStartTime().getTime(); 215 216 out.println("<tr><td><b>Server Start:</b><td> " + 217 QDate.formatLocal(startTime)); 218 219 long totalMemory = _server.getRuntimeMemory(); 220 out.println("<tr><td><b>Total Memory:</b><td> " + 221 (totalMemory / 1000000) + "." + 222 (totalMemory / 100000) % 10 + 223 (totalMemory / 10000) % 10 + 224 "Meg"); 225 long freeMemory = _server.getRuntimeMemoryFree(); 226 out.println("<tr><td><b>Free Memory:</b><td> " + 227 (freeMemory / 1000000) + "." + 228 (freeMemory / 100000) % 10 + 229 (freeMemory / 10000) % 10 + 230 "Meg"); 231 232 long invocationHitCount = _server.getInvocationCacheHitCountTotal(); 233 long invocationMissCount = _server.getInvocationCacheMissCountTotal(); 234 235 long totalCount = invocationHitCount + invocationMissCount; 236 if (totalCount == 0) 237 totalCount = 1; 238 239 long hitRatio = (10000 * invocationHitCount) / totalCount; 240 241 out.print("<tr><td><b>Invocation Hit Ratio:</b><td> " + 242 (hitRatio / 100) + "." + 243 (hitRatio / 10) % 10 + 244 (hitRatio) % 10 + "%"); 245 out.println(" (" + invocationHitCount + "/" + totalCount + ")"); 246 247 if (_proxyCache != null) { 248 long proxyHitCount = _proxyCache.getHitCountTotal(); 249 long proxyMissCount = _proxyCache.getMissCountTotal(); 250 251 totalCount = proxyHitCount + proxyMissCount; 252 if (totalCount == 0) 253 totalCount = 1; 254 255 hitRatio = (10000 * proxyHitCount) / totalCount; 256 257 out.print("<tr><td><b>Proxy Cache Hit Ratio:</b><td> " + 258 (hitRatio / 100) + "." + 259 (hitRatio / 10) % 10 + 260 (hitRatio) % 10 + "%"); 261 out.println(" (" + proxyHitCount + "/" + totalCount + ")"); 262 } 263 264 out.println("</table>"); 265 266 printThreadHeader(out); 267 printConnectionPools(out, ""); 268 } 269 270 273 public void printThreadHeader(PrintWriter out) 274 throws Exception 275 { 276 out.println("<table border='3'>"); 277 278 ThreadPoolMXBean threadPool = (ThreadPoolMXBean) Jmx.findGlobal("resin:type=ThreadPool"); 279 out.println("<tr><th colspan='3'>Threads"); 280 out.println(" <th colspan='3'>Config"); 281 out.println("<tr><th>Active<th>Idle<th>Total"); 282 out.println(" <th>thread-max<th>thread-idle-min"); 283 out.println("<tr align='right'>"); 284 out.println(" <td>" + threadPool.getThreadActiveCount()); 285 out.println(" <td>" + threadPool.getThreadIdleCount()); 286 out.println(" <td>" + threadPool.getThreadCount()); 287 288 out.println(" <td>" + threadPool.getThreadMax()); 289 out.println(" <td>" + threadPool.getThreadIdleMin()); 290 291 out.println("</table>"); 292 } 293 294 297 347 348 public void printPorts(PrintWriter out) 349 throws IOException , ServletException 350 { 351 try { 352 PortMXBean []portList = _server.getPorts(); 353 354 if (portList.length > 0) { 355 out.println("<h3>TCP ports</h3>"); 356 out.println("<table border='2'>"); 357 out.println("<tr><th><th colspan='3'>Threads<th> "); 358 out.println("<tr><th>Protocol:Port"); 359 out.println(" <th>Active<th>Idle<th>Total"); 360 out.println(" <th>Keepalive<th>Select"); 361 362 for (int i = 0; i < portList.length; i++) { 363 PortMXBean port = portList[i]; 364 365 if (port == null || ! "active".equals(port.getState())) 366 continue; 367 368 String host = port.getAddress(); 369 if (host == null) 370 host = "*"; 371 372 out.print("<tr><td>"); 373 out.print(port.getProtocolName() + "://" + host + ":" + port.getPort()); 374 out.println(); 375 376 out.print(" <td>" + port.getThreadActiveCount()); 377 out.print("<td>" + port.getThreadIdleCount()); 378 out.print("<td>" + port.getThreadActiveCount()); 379 out.print("<td>" + port.getThreadKeepaliveCount()); 380 out.print("<td>" + port.getSelectKeepaliveCount()); 381 out.println(); 382 383 out.println(); 384 } 385 out.println("</table>"); 386 } 387 } catch (Exception e) { 388 throw new ServletException (e); 389 } 390 } 391 392 public void printSrun(PrintWriter out) 393 throws IOException , ServletException 394 { 395 try { 396 String []clusterList = new String [0]; 398 for (int i = 0; i < clusterList.length; i++) { 399 ClusterMXBean cluster = (ClusterMXBean) Jmx.findGlobal(clusterList[i]); 400 401 if (cluster == null) { 402 out.println("<h3>Cluster " + clusterList[i] + " null</h3>"); 403 continue; 404 } 405 406 ObjectName objectName = cluster.getObjectName(); 407 408 String clusterName = objectName.getKeyProperty("name"); 409 410 out.println("<h3>Cluster " + clusterName + "</h3>"); 411 out.println("<table border='2'>"); 412 out.println("<tr><th>Host"); 413 out.println(" <th>Active"); 414 415 ServerConnectorMXBean []servers = cluster.getServers(); 416 417 for (int j = 0; j < servers.length; j++) { 418 ServerConnectorMXBean client = servers[j]; 419 420 String host = client.getAddress(); 421 String port = String.valueOf(client.getPort()); 422 423 out.println("<tr>"); 424 425 boolean canConnect = client.ping(); 426 427 if (canConnect) 428 out.print("<td bgcolor='#80ff80'>"); 429 else 430 out.print("<td>"); 431 432 out.print(host + ":" + port); 433 434 if (canConnect) 435 out.println(" (up)"); 436 else 437 out.println(" (down)"); 438 439 out.println("<td>" + client.getConnectionActiveCount()); 440 } 441 442 out.println("</table>"); 443 } 444 } catch (Exception e) { 445 throw new ServletException (e); 446 } 447 } 448 449 public void printConnectionPools(PrintWriter out, String context) 450 throws Exception 451 { 452 ObjectName pattern = new ObjectName ("resin:*,type=ConnectionPool" + context); 453 454 Set <ObjectName > poolNames; 455 poolNames = _mbeanServer.queryNames(pattern, null); 456 457 if (poolNames.size() == 0) 458 return; 459 460 out.println("<h3>Connection Pools</h3>"); 461 462 out.println("<table border='2'>"); 463 out.println("<tr><th> <th colspan='3'>Connections<th colspan='2'>Config"); 464 out.println("<tr><th>Name<th>Active<th>Idle<th>Total"); 465 out.println(" <th>max-connections<th>idle-time"); 466 467 Iterator <ObjectName > iter = poolNames.iterator(); 468 while (iter.hasNext()) { 469 ObjectName name = iter.next(); 470 471 ConnectionPoolMXBean pool = (ConnectionPoolMXBean) Jmx.findGlobal(name); 472 473 if (pool != null) { 474 out.println("<tr><td>" + pool.getName()); 475 out.println(" <td>" + pool.getConnectionActiveCount()); 476 out.println(" <td>" + pool.getConnectionIdleCount()); 477 out.println(" <td>" + pool.getConnectionCount()); 478 479 out.println(" <td>" + pool.getMaxConnections()); 480 out.println(" <td>" + periodToString(pool.getMaxIdleTime())); 481 } 482 } 483 484 out.println("</table>"); 485 } 486 487 private String periodToString(long time) 488 { 489 if (time == 0) 490 return "0s"; 491 else if (time % DAY == 0) 492 return (time / DAY) + "d"; 493 else if (time % HOUR == 0) 494 return (time / HOUR) + "h"; 495 else if (time % MINUTE == 0) 496 return (time / MINUTE) + "min"; 497 else if (time % SECOND == 0) 498 return (time / SECOND) + "s"; 499 else 500 return time + "ms"; 501 } 502 503 709 710 public void printApplicationSummary(PrintWriter out, String pwd) 711 throws Exception 712 { 713 out.println("<h3>Hosts and Applications</h3>"); 714 715 out.println("<table border=\"2\">"); 716 out.println("<tr><th>Host<th>Web-App<th>State<th>Sessions"); 717 718 ObjectName hostPattern = new ObjectName ("resin:*,type=Host"); 719 720 Set <ObjectName > names = _mbeanServer.queryNames(hostPattern, null); 721 Iterator <ObjectName > iter = names.iterator(); 722 723 ArrayList <HostMXBean> hosts = new ArrayList <HostMXBean>(); 724 725 while (iter.hasNext()) { 726 ObjectName name = iter.next(); 727 728 if ("current".equals(name.getKeyProperty("name"))) 730 continue; 731 732 HostMXBean host = (HostMXBean) Jmx.findGlobal(name); 733 734 if (host != null) { 735 hosts.add(host); 736 } 737 } 738 739 Collections.sort(hosts, new HostCompare()); 740 741 for (int i = 0; i < hosts.size(); i++) { 742 HostMXBean host = hosts.get(i); 743 744 out.println("<tr><td><b>" + host.getURL() + "</b>"); 745 746 748 String hostName = host.getHostName(); 749 if (hostName.equals("")) 750 hostName = "default"; 751 752 ObjectName appPattern = new ObjectName ("resin:*,Host=" + hostName + ",type=WebApp"); 753 754 names = _mbeanServer.queryNames(appPattern, null); 755 iter = names.iterator(); 756 757 ArrayList <WebAppMXBean> apps = new ArrayList <WebAppMXBean>(); 758 759 while (iter.hasNext()) { 760 ObjectName name = iter.next(); 761 762 try { 763 WebAppMXBean app = (WebAppMXBean) Jmx.findGlobal(name); 764 765 if (app != null) 766 apps.add(app); 767 } catch (Exception e) { 768 log.log(Level.WARNING, e.toString()); 769 out.println("<tr><td>" + name + "<td>" + e.toString()); 770 } 771 } 772 773 Collections.sort(apps, new AppCompare()); 774 775 for (int j = 0; j < apps.size(); j++) { 776 WebAppMXBean app = apps.get(j); 777 SessionManagerMXBean session = app.getSessionManager(); 778 779 String contextPath = app.getContextPath(); 780 781 if (contextPath.equals("")) 782 contextPath = "/"; 783 784 out.print("<tr><td><td>"); 785 out.print("<a HREF=\"" + pwd + "?host=" + host.getHostName() + 786 "&app=" + app.getContextPath() + "\">"); 787 out.print(contextPath); 788 out.print("</a>"); 789 790 String state = app.getState(); 791 if (state.equals("active")) 792 out.print("<td bgcolor='#80ff80'>" + app.getState()); 793 else 794 out.print("<td>" + app.getState()); 795 out.print("<td>" + session.getSessionActiveCount()); 796 } 797 } 798 799 out.println("</table>"); 800 } 801 802 public void printVirtualHosts(PrintWriter out) 803 throws IOException , ServletException 804 { 805 } 806 807 810 public void printFooter(PrintWriter out) 811 throws IOException , ServletException 812 { 813 818 out.println("<br><em>" + com.caucho.Version.FULL_VERSION + "</em>"); 819 } 820 821 static class HostCompare implements Comparator <HostMXBean> { 822 public int compare(HostMXBean a, HostMXBean b) 823 { 824 String urlA = a.getURL(); 825 String urlB = b.getURL(); 826 827 if (urlA == urlB) 828 return 0; 829 else if (urlA == null) 830 return -1; 831 else if (urlB == null) 832 return 1; 833 else 834 return urlA.compareTo(urlB); 835 } 836 } 837 838 static class AppCompare implements Comparator <WebAppMXBean> { 839 public int compare(WebAppMXBean a, WebAppMXBean b) 840 { 841 String cpA = a.getContextPath(); 842 String cpB = b.getContextPath(); 843 844 return cpA.compareTo(cpB); 845 } 846 } 847 } 848 | Popular Tags |