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