View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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  
26  import javax.servlet.ServletContext;
27  import javax.servlet.ServletException;
28  import javax.servlet.http.HttpServlet;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.eclipse.jetty.server.AbstractConnector;
33  import org.eclipse.jetty.server.Connector;
34  import org.eclipse.jetty.server.ConnectorStatistics;
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  /**
43   * StatisticsServlet
44   *
45   *
46   */
47  public class StatisticsServlet extends HttpServlet
48  {
49      private static final Logger LOG = Log.getLogger(StatisticsServlet.class);
50  
51      boolean _restrictToLocalhost = true; // defaults to true
52      private StatisticsHandler _statsHandler;
53      private MemoryMXBean _memoryBean;
54      private Connector[] _connectors;
55  
56      
57      
58      /** 
59       * @see javax.servlet.GenericServlet#init()
60       */
61      public void init() throws ServletException
62      {
63          ServletContext context = getServletContext();
64          ContextHandler.Context scontext = (ContextHandler.Context) context;
65          Server _server = scontext.getContextHandler().getServer();
66  
67          Handler handler = _server.getChildHandlerByClass(StatisticsHandler.class);
68  
69          if (handler != null)
70          {
71              _statsHandler = (StatisticsHandler) handler;
72          }
73          else
74          {
75              LOG.warn("Statistics Handler not installed!");
76              return;
77          }
78          
79          _memoryBean = ManagementFactory.getMemoryMXBean();
80          _connectors = _server.getConnectors();
81  
82          if (getInitParameter("restrictToLocalhost") != null)
83          {
84              _restrictToLocalhost = "true".equals(getInitParameter("restrictToLocalhost"));
85          }
86      }
87  
88      
89      
90      /** 
91       * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
92       */
93      public void doPost(HttpServletRequest sreq, HttpServletResponse sres) throws ServletException, IOException
94      {
95          doGet(sreq, sres);
96      }
97  
98      
99      
100     /** 
101      * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
102      */
103     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
104     {
105         if (_statsHandler == null)
106         {
107             LOG.warn("Statistics Handler not installed!");
108             resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
109             return;
110         }
111         if (_restrictToLocalhost)
112         {
113             if (!"127.0.0.1".equals(req.getRemoteAddr()))
114             {
115                 resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
116                 return;
117             }
118         }
119 
120         String wantXml = req.getParameter("xml");
121         if (wantXml == null)
122           wantXml = req.getParameter("XML");
123 
124         if (wantXml != null && "true".equalsIgnoreCase(wantXml))
125         {
126             sendXmlResponse(resp);
127         }
128         else
129         {
130             sendTextResponse(resp);
131         }
132 
133     }
134 
135     
136     
137     /**
138      * @param response
139      * @throws IOException
140      */
141     private void sendXmlResponse(HttpServletResponse response) throws IOException
142     {
143         StringBuilder sb = new StringBuilder();
144 
145         sb.append("<statistics>\n");
146 
147         sb.append("  <requests>\n");
148         sb.append("    <statsOnMs>").append(_statsHandler.getStatsOnMs()).append("</statsOnMs>\n");
149         
150         sb.append("    <requests>").append(_statsHandler.getRequests()).append("</requests>\n");
151         sb.append("    <requestsActive>").append(_statsHandler.getRequestsActive()).append("</requestsActive>\n");
152         sb.append("    <requestsActiveMax>").append(_statsHandler.getRequestsActiveMax()).append("</requestsActiveMax>\n");
153         sb.append("    <requestsTimeTotal>").append(_statsHandler.getRequestTimeTotal()).append("</requestsTimeTotal>\n");
154         sb.append("    <requestsTimeMean>").append(_statsHandler.getRequestTimeMean()).append("</requestsTimeMean>\n");
155         sb.append("    <requestsTimeMax>").append(_statsHandler.getRequestTimeMax()).append("</requestsTimeMax>\n");
156         sb.append("    <requestsTimeStdDev>").append(_statsHandler.getRequestTimeStdDev()).append("</requestsTimeStdDev>\n");
157 
158         sb.append("    <dispatched>").append(_statsHandler.getDispatched()).append("</dispatched>\n");
159         sb.append("    <dispatchedActive>").append(_statsHandler.getDispatchedActive()).append("</dispatchedActive>\n");
160         sb.append("    <dispatchedActiveMax>").append(_statsHandler.getDispatchedActiveMax()).append("</dispatchedActiveMax>\n");
161         sb.append("    <dispatchedTimeTotalMs>").append(_statsHandler.getDispatchedTimeTotal()).append("</dispatchedTimeTotalMs>\n");
162         sb.append("    <dispatchedTimeMeanMs>").append(_statsHandler.getDispatchedTimeMean()).append("</dispatchedTimeMeanMs>\n");
163         sb.append("    <dispatchedTimeMaxMs>").append(_statsHandler.getDispatchedTimeMax()).append("</dispatchedTimeMaxMs>\n");
164         sb.append("    <dispatchedTimeStdDevMs>").append(_statsHandler.getDispatchedTimeStdDev()).append("</dispatchedTimeStdDevMs>\n");
165  
166         sb.append("    <asyncRequests>").append(_statsHandler.getAsyncRequests()).append("</asyncRequests>\n");
167         sb.append("    <requestsSuspended>").append(_statsHandler.getAsyncRequestsWaiting()).append("</requestsSuspended>\n");
168         sb.append("    <requestsSuspendedMax>").append(_statsHandler.getAsyncRequestsWaitingMax()).append("</requestsSuspendedMax>\n");
169         sb.append("    <requestsResumed>").append(_statsHandler.getAsyncDispatches()).append("</requestsResumed>\n");
170         sb.append("    <requestsExpired>").append(_statsHandler.getExpires()).append("</requestsExpired>\n");
171         sb.append("  </requests>\n");
172 
173         sb.append("  <responses>\n");
174         sb.append("    <responses1xx>").append(_statsHandler.getResponses1xx()).append("</responses1xx>\n");
175         sb.append("    <responses2xx>").append(_statsHandler.getResponses2xx()).append("</responses2xx>\n");
176         sb.append("    <responses3xx>").append(_statsHandler.getResponses3xx()).append("</responses3xx>\n");
177         sb.append("    <responses4xx>").append(_statsHandler.getResponses4xx()).append("</responses4xx>\n");
178         sb.append("    <responses5xx>").append(_statsHandler.getResponses5xx()).append("</responses5xx>\n");
179         sb.append("    <responsesBytesTotal>").append(_statsHandler.getResponsesBytesTotal()).append("</responsesBytesTotal>\n");
180         sb.append("  </responses>\n");
181 
182         sb.append("  <connections>\n");
183         for (Connector connector : _connectors)
184         {
185             sb.append("    <connector>\n");
186             sb.append("      <name>").append(connector.getClass().getName()).append("@").append(connector.hashCode()).append("</name>\n");
187             sb.append("      <protocols>\n");
188             for (String protocol:connector.getProtocols())
189                 sb.append("      <protocol>").append(protocol).append("</protocol>\n");
190             sb.append("      </protocols>\n");
191 
192             ConnectorStatistics connectorStats = null;
193 
194             if (connector instanceof AbstractConnector)
195                 connectorStats = ((AbstractConnector)connector).getBean(ConnectorStatistics.class);
196             if (connectorStats == null)
197                 sb.append("      <statsOn>false</statsOn>\n");
198             else
199             {
200                 sb.append("      <statsOn>true</statsOn>\n");
201                 sb.append("      <connections>").append(connectorStats.getConnections()).append("</connections>\n");
202                 sb.append("      <connectionsOpen>").append(connectorStats.getConnectionsOpen()).append("</connectionsOpen>\n");
203                 sb.append("      <connectionsOpenMax>").append(connectorStats.getConnectionsOpenMax()).append("</connectionsOpenMax>\n");
204                 sb.append("      <connectionsDurationTotal>").append(connectorStats.getConnectionsDurationTotal()).append("</connectionsDurationTotal>\n");
205                 sb.append("      <connectionsDurationMean>").append(connectorStats.getConnectionsDurationMean()).append("</connectionsDurationMean>\n");
206                 sb.append("      <connectionsDurationMax>").append(connectorStats.getConnectionsDurationMax()).append("</connectionsDurationMax>\n");
207                 sb.append("      <connectionsDurationStdDev>").append(connectorStats.getConnectionsDurationStdDev()).append("</connectionsDurationStdDev>\n");
208                 sb.append("      <messagesIn>").append(connectorStats.getMessagesIn()).append("</messagesIn>\n");
209                 sb.append("      <messagesOut>").append(connectorStats.getMessagesIn()).append("</messagesOut>\n");
210                 sb.append("      <elapsedMs>").append(connectorStats.getStartedMillis()).append("</elapsedMs>\n");
211             }
212             sb.append("    </connector>\n");
213         }
214         sb.append("  </connections>\n");
215 
216         sb.append("  <memory>\n");
217         sb.append("    <heapMemoryUsage>").append(_memoryBean.getHeapMemoryUsage().getUsed()).append("</heapMemoryUsage>\n");
218         sb.append("    <nonHeapMemoryUsage>").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append("</nonHeapMemoryUsage>\n");
219         sb.append("  </memory>\n");
220         
221         sb.append("</statistics>\n");
222 
223         response.setContentType("text/xml");
224         PrintWriter pout = response.getWriter();
225         pout.write(sb.toString());
226     }
227 
228     
229     
230     /**
231      * @param response
232      * @throws IOException
233      */
234     private void sendTextResponse(HttpServletResponse response) throws IOException
235     {
236         StringBuilder sb = new StringBuilder();
237         sb.append(_statsHandler.toStatsHTML());
238 
239         sb.append("<h2>Connections:</h2>\n");
240         for (Connector connector : _connectors)
241         {
242             sb.append("<h3>").append(connector.getClass().getName()).append("@").append(connector.hashCode()).append("</h3>");
243             sb.append("Protocols:");
244             for (String protocol:connector.getProtocols())
245                 sb.append(protocol).append("&nbsp;");
246             sb.append("    <br />\n");
247 
248             ConnectorStatistics connectorStats = null;
249 
250             if (connector instanceof AbstractConnector)
251                 connectorStats = ((AbstractConnector)connector).getBean(ConnectorStatistics.class);
252 
253             if (connectorStats != null)
254             {
255                 sb.append("Statistics gathering started ").append(connectorStats.getStartedMillis()).append("ms ago").append("<br />\n");
256                 sb.append("Total connections: ").append(connectorStats.getConnections()).append("<br />\n");
257                 sb.append("Current connections open: ").append(connectorStats.getConnectionsOpen()).append("<br />\n");;
258                 sb.append("Max concurrent connections open: ").append(connectorStats.getConnectionsOpenMax()).append("<br />\n");
259                 sb.append("Total connections duration: ").append(connectorStats.getConnectionsDurationTotal()).append("<br />\n");
260                 sb.append("Mean connection duration: ").append(connectorStats.getConnectionsDurationMean()).append("<br />\n");
261                 sb.append("Max connection duration: ").append(connectorStats.getConnectionsDurationMax()).append("<br />\n");
262                 sb.append("Connection duration standard deviation: ").append(connectorStats.getConnectionsDurationStdDev()).append("<br />\n");
263                 sb.append("Total messages in: ").append(connectorStats.getMessagesIn()).append("<br />\n");                
264                 sb.append("Total messages out: ").append(connectorStats.getMessagesOut()).append("<br />\n");
265             }
266             else
267             {
268                 sb.append("Statistics gathering off.\n");
269             }
270 
271         }
272 
273         sb.append("<h2>Memory:</h2>\n");
274         sb.append("Heap memory usage: ").append(_memoryBean.getHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
275         sb.append("Non-heap memory usage: ").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append(" bytes").append("<br />\n");
276 
277         response.setContentType("text/html");
278         PrintWriter pout = response.getWriter();
279         pout.write(sb.toString());
280 
281     }
282 }