Home | History | Annotate | Download | only in servlet
      1 //
      2 //  ========================================================================
      3 //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
      4 //  ------------------------------------------------------------------------
      5 //  All rights reserved. This program and the accompanying materials
      6 //  are made available under the terms of the Eclipse Public License v1.0
      7 //  and Apache License v2.0 which accompanies this distribution.
      8 //
      9 //      The Eclipse Public License is available at
     10 //      http://www.eclipse.org/legal/epl-v10.html
     11 //
     12 //      The Apache License v2.0 is available at
     13 //      http://www.opensource.org/licenses/apache2.0.php
     14 //
     15 //  You may elect to redistribute this code under either of these licenses.
     16 //  ========================================================================
     17 //
     18 
     19 package org.eclipse.jetty.servlet;
     20 
     21 import java.io.IOException;
     22 import java.io.PrintWriter;
     23 import java.lang.management.ManagementFactory;
     24 import java.lang.management.MemoryMXBean;
     25 import java.net.InetAddress;
     26 import java.net.UnknownHostException;
     27 
     28 import javax.servlet.ServletContext;
     29 import javax.servlet.ServletException;
     30 import javax.servlet.http.HttpServlet;
     31 import javax.servlet.http.HttpServletRequest;
     32 import javax.servlet.http.HttpServletResponse;
     33 
     34 import org.eclipse.jetty.server.Connector;
     35 import org.eclipse.jetty.server.Handler;
     36 import org.eclipse.jetty.server.Server;
     37 import org.eclipse.jetty.server.handler.ContextHandler;
     38 import org.eclipse.jetty.server.handler.StatisticsHandler;
     39 import org.eclipse.jetty.util.log.Log;
     40 import org.eclipse.jetty.util.log.Logger;
     41 
     42 public class StatisticsServlet extends HttpServlet
     43 {
     44     private static final Logger LOG = Log.getLogger(StatisticsServlet.class);
     45 
     46     boolean _restrictToLocalhost = true; // defaults to true
     47     private StatisticsHandler _statsHandler;
     48     private MemoryMXBean _memoryBean;
     49     private Connector[] _connectors;
     50 
     51     public void init() throws ServletException
     52     {
     53         ServletContext context = getServletContext();
     54         ContextHandler.Context scontext = (ContextHandler.Context) context;
     55         Server _server = scontext.getContextHandler().getServer();
     56 
     57         Handler handler = _server.getChildHandlerByClass(StatisticsHandler.class);
     58 
     59         if (handler != null)
     60         {
     61             _statsHandler = (StatisticsHandler) handler;
     62         }
     63         else
     64         {
     65             LOG.warn("Statistics Handler not installed!");
     66             return;
     67         }
     68 
     69         _memoryBean = ManagementFactory.getMemoryMXBean();
     70         _connectors = _server.getConnectors();
     71 
     72         if (getInitParameter("restrictToLocalhost") != null)
     73         {
     74             _restrictToLocalhost = "true".equals(getInitParameter("restrictToLocalhost"));
     75         }
     76 
     77     }
     78 
     79     public void doPost(HttpServletRequest sreq, HttpServletResponse sres) throws ServletException, IOException
     80     {
     81         doGet(sreq, sres);
     82     }
     83 
     84     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
     85     {
     86         if (_statsHandler == null)
     87         {
     88             LOG.warn("Statistics Handler not installed!");
     89             resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
     90             return;
     91         }
     92         if (_restrictToLocalhost)
     93         {
     94             if (!isLoopbackAddress(req.getRemoteAddr()))
     95             {
     96                 resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
     97                 return;
     98             }
     99         }
    100 
    101         String wantXml = req.getParameter("xml");
    102         if (wantXml == null)
    103           wantXml = req.getParameter("XML");
    104 
    105         if (wantXml != null && "true".equalsIgnoreCase(wantXml))
    106         {
    107             sendXmlResponse(resp);
    108         }
    109         else
    110         {
    111             sendTextResponse(resp);
    112         }
    113 
    114     }
    115 
    116     private boolean isLoopbackAddress(String address)
    117     {
    118         try
    119         {
    120             InetAddress addr = InetAddress.getByName(address);
    121             return addr.isLoopbackAddress();
    122         }
    123         catch (UnknownHostException e )
    124         {
    125             LOG.warn("Warning: attempt to access statistics servlet from " + address, e);
    126             return false;
    127         }
    128     }
    129 
    130     private void sendXmlResponse(HttpServletResponse response) throws IOException
    131     {
    132         StringBuilder sb = new StringBuilder();
    133 
    134         sb.append("<statistics>\n");
    135 
    136         sb.append("  <requests>\n");
    137         sb.append("    <statsOnMs>").append(_statsHandler.getStatsOnMs()).append("</statsOnMs>\n");
    138 
    139         sb.append("    <requests>").append(_statsHandler.getRequests()).append("</requests>\n");
    140         sb.append("    <requestsActive>").append(_statsHandler.getRequestsActive()).append("</requestsActive>\n");
    141         sb.append("    <requestsActiveMax>").append(_statsHandler.getRequestsActiveMax()).append("</requestsActiveMax>\n");
    142         sb.append("    <requestsTimeTotal>").append(_statsHandler.getRequestTimeTotal()).append("</requestsTimeTotal>\n");
    143         sb.append("    <requestsTimeMean>").append(_statsHandler.getRequestTimeMean()).append("</requestsTimeMean>\n");
    144         sb.append("    <requestsTimeMax>").append(_statsHandler.getRequestTimeMax()).append("</requestsTimeMax>\n");
    145         sb.append("    <requestsTimeStdDev>").append(_statsHandler.getRequestTimeStdDev()).append("</requestsTimeStdDev>\n");
    146 
    147         sb.append("    <dispatched>").append(_statsHandler.getDispatched()).append("</dispatched>\n");
    148         sb.append("    <dispatchedActive>").append(_statsHandler.getDispatchedActive()).append("</dispatchedActive>\n");
    149         sb.append("    <dispatchedActiveMax>").append(_statsHandler.getDispatchedActiveMax()).append("</dispatchedActiveMax>\n");
    150         sb.append("    <dispatchedTimeTotal>").append(_statsHandler.getDispatchedTimeTotal()).append("</dispatchedTimeTotal>\n");
    151         sb.append("    <dispatchedTimeMean>").append(_statsHandler.getDispatchedTimeMean()).append("</dispatchedTimeMean>\n");
    152         sb.append("    <dispatchedTimeMax>").append(_statsHandler.getDispatchedTimeMax()).append("</dispatchedTimeMax>\n");
    153         sb.append("    <dispatchedTimeStdDev").append(_statsHandler.getDispatchedTimeStdDev()).append("</dispatchedTimeStdDev>\n");
    154 
    155         sb.append("    <requestsSuspended>").append(_statsHandler.getSuspends()).append("</requestsSuspended>\n");
    156         sb.append("    <requestsExpired>").append(_statsHandler.getExpires()).append("</requestsExpired>\n");
    157         sb.append("    <requestsResumed>").append(_statsHandler.getResumes()).append("</requestsResumed>\n");
    158         sb.append("  </requests>\n");
    159 
    160         sb.append("  <responses>\n");
    161         sb.append("    <responses1xx>").append(_statsHandler.getResponses1xx()).append("</responses1xx>\n");
    162         sb.append("    <responses2xx>").append(_statsHandler.getResponses2xx()).append("</responses2xx>\n");
    163         sb.append("    <responses3xx>").append(_statsHandler.getResponses3xx()).append("</responses3xx>\n");
    164         sb.append("    <responses4xx>").append(_statsHandler.getResponses4xx()).append("</responses4xx>\n");
    165         sb.append("    <responses5xx>").append(_statsHandler.getResponses5xx()).append("</responses5xx>\n");
    166         sb.append("    <responsesBytesTotal>").append(_statsHandler.getResponsesBytesTotal()).append("</responsesBytesTotal>\n");
    167         sb.append("  </responses>\n");
    168 
    169         sb.append("  <connections>\n");
    170         for (Connector connector : _connectors)
    171         {
    172         	sb.append("    <connector>\n");
    173         	sb.append("      <name>").append(connector.getName()).append("</name>\n");
    174         	sb.append("      <statsOn>").append(connector.getStatsOn()).append("</statsOn>\n");
    175             if (connector.getStatsOn())
    176             {
    177             	sb.append("    <statsOnMs>").append(connector.getStatsOnMs()).append("</statsOnMs>\n");
    178             	sb.append("    <connections>").append(connector.getConnections()).append("</connections>\n");
    179             	sb.append("    <connectionsOpen>").append(connector.getConnectionsOpen()).append("</connectionsOpen>\n");
    180             	sb.append("    <connectionsOpenMax>").append(connector.getConnectionsOpenMax()).append("</connectionsOpenMax>\n");
    181             	sb.append("    <connectionsDurationTotal>").append(connector.getConnectionsDurationTotal()).append("</connectionsDurationTotal>\n");
    182             	sb.append("    <connectionsDurationMean>").append(connector.getConnectionsDurationMean()).append("</connectionsDurationMean>\n");
    183             	sb.append("    <connectionsDurationMax>").append(connector.getConnectionsDurationMax()).append("</connectionsDurationMax>\n");
    184                 sb.append("    <connectionsDurationStdDev>").append(connector.getConnectionsDurationStdDev()).append("</connectionsDurationStdDev>\n");
    185                 sb.append("    <requests>").append(connector.getRequests()).append("</requests>\n");
    186                 sb.append("    <connectionsRequestsMean>").append(connector.getConnectionsRequestsMean()).append("</connectionsRequestsMean>\n");
    187                 sb.append("    <connectionsRequestsMax>").append(connector.getConnectionsRequestsMax()).append("</connectionsRequestsMax>\n");
    188                 sb.append("    <connectionsRequestsStdDev>").append(connector.getConnectionsRequestsStdDev()).append("</connectionsRequestsStdDev>\n");
    189             }
    190             sb.append("    </connector>\n");
    191         }
    192         sb.append("  </connections>\n");
    193 
    194         sb.append("  <memory>\n");
    195         sb.append("    <heapMemoryUsage>").append(_memoryBean.getHeapMemoryUsage().getUsed()).append("</heapMemoryUsage>\n");
    196         sb.append("    <nonHeapMemoryUsage>").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append("</nonHeapMemoryUsage>\n");
    197         sb.append("  </memory>\n");
    198 
    199         sb.append("</statistics>\n");
    200 
    201         response.setContentType("text/xml");
    202         PrintWriter pout = response.getWriter();
    203         pout.write(sb.toString());
    204     }
    205 
    206     private void sendTextResponse(HttpServletResponse response) throws IOException
    207     {
    208         StringBuilder sb = new StringBuilder();
    209         sb.append(_statsHandler.toStatsHTML());
    210 
    211         sb.append("<h2>Connections:</h2>\n");
    212         for (Connector connector : _connectors)
    213         {
    214             sb.append("<h3>").append(connector.getName()).append("</h3>");
    215 
    216             if (connector.getStatsOn())
    217             {
    218                 sb.append("Statistics gathering started ").append(connector.getStatsOnMs()).append("ms ago").append("<br />\n");
    219                 sb.append("Total connections: ").append(connector.getConnections()).append("<br />\n");
    220                 sb.append("Current connections open: ").append(connector.getConnectionsOpen()).append("<br />\n");
    221                 sb.append("Max concurrent connections open: ").append(connector.getConnectionsOpenMax()).append("<br />\n");
    222                 sb.append("Total connections duration: ").append(connector.getConnectionsDurationTotal()).append("<br />\n");
    223                 sb.append("Mean connection duration: ").append(connector.getConnectionsDurationMean()).append("<br />\n");
    224                 sb.append("Max connection duration: ").append(connector.getConnectionsDurationMax()).append("<br />\n");
    225                 sb.append("Connection duration standard deviation: ").append(connector.getConnectionsDurationStdDev()).append("<br />\n");
    226                 sb.append("Total requests: ").append(connector.getRequests()).append("<br />\n");
    227                 sb.append("Mean requests per connection: ").append(connector.getConnectionsRequestsMean()).append("<br />\n");
    228                 sb.append("Max requests per connection: ").append(connector.getConnectionsRequestsMax()).append("<br />\n");
    229                 sb.append("Requests per connection standard deviation: ").append(connector.getConnectionsRequestsStdDev()).append("<br />\n");
    230             }
    231             else
    232             {
    233                 sb.append("Statistics gathering off.\n");
    234             }
    235 
    236         }
    237 
    238         sb.append("<h2>Memory:</h2>\n");
    239         sb.append("Heap memory usage: ").append(_memoryBean.getHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
    240         sb.append("Non-heap memory usage: ").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
    241 
    242         response.setContentType("text/html");
    243         PrintWriter pout = response.getWriter();
    244         pout.write(sb.toString());
    245 
    246     }
    247 }
    248