1 package org.mortbay.jetty.servlet;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import java.io.IOException;
18 import java.io.PrintWriter;
19 import java.lang.management.ManagementFactory;
20 import java.lang.management.MemoryMXBean;
21
22 import javax.servlet.ServletContext;
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServlet;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import org.mortbay.jetty.Connector;
29 import org.mortbay.jetty.Handler;
30 import org.mortbay.jetty.Server;
31 import org.mortbay.jetty.handler.ContextHandler;
32 import org.mortbay.jetty.handler.StatisticsHandler;
33 import org.mortbay.log.Log;
34
35 public class StatisticsServlet extends HttpServlet
36 {
37 boolean _restrictToLocalhost = true;
38 private Server _server = null;
39 private StatisticsHandler _statsHandler;
40 private MemoryMXBean _memoryBean;
41 private Connector[] _connectors;
42
43 public void init() throws ServletException
44 {
45 _memoryBean = ManagementFactory.getMemoryMXBean();
46
47 ServletContext context = getServletContext();
48 ContextHandler.SContext scontext = (ContextHandler.SContext) context;
49 _server = scontext.getContextHandler().getServer();
50
51 Handler handler = _server.getChildHandlerByClass(StatisticsHandler.class);
52
53 if (handler != null)
54 {
55 _statsHandler = (StatisticsHandler) handler;
56 }
57 else
58 {
59 Log.info("Installing Statistics Handler");
60 _statsHandler = new StatisticsHandler();
61 _server.addHandler(_statsHandler);
62 }
63
64
65 _connectors = _server.getConnectors();
66
67 if (getInitParameter("restrictToLocalhost") != null)
68 {
69 _restrictToLocalhost = "true".equals(getInitParameter("restrictToLocalhost"));
70 }
71
72 }
73
74 public void doPost(HttpServletRequest sreq, HttpServletResponse sres) throws ServletException, IOException
75 {
76 doGet(sreq, sres);
77 }
78
79 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
80 {
81
82 if (_restrictToLocalhost)
83 {
84 if (!"127.0.0.1".equals(req.getRemoteAddr()))
85 {
86 resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
87 return;
88 }
89 }
90
91 if (req.getParameter("xml") != null && "true".equals(req.getParameter("xml")))
92 {
93 sendXmlResponse(resp);
94 } else
95 {
96 sendTextResponse(resp);
97 }
98
99 }
100
101 private void sendXmlResponse(HttpServletResponse response) throws IOException
102 {
103 StringBuilder sb = new StringBuilder();
104
105 sb.append("<statistics>\n");
106
107 sb.append(" <requests>\n");
108 sb.append(" <statsOnMs>").append(_statsHandler.getStatsOnMs()).append("</statsOnMs>\n");
109 sb.append(" <requests>").append(_statsHandler.getRequests()).append("</requests>\n");
110 sb.append(" <requestsTimedout>").append(_statsHandler.getRequestsTimedout()).append("</requestsTimedout>\n");
111 sb.append(" <requestsResumed>").append(_statsHandler.getRequestsResumed()).append("</requestsResumed>\n");
112 sb.append(" <requestsActive>").append(_statsHandler.getRequestsActive()).append("</requestsActive>\n");
113 sb.append(" <requestsActiveMin>").append(_statsHandler.getRequestsActiveMin()).append("</requestsActiveMin>\n");
114 sb.append(" <requestsActiveMax>").append(_statsHandler.getRequestsActiveMax()).append("</requestsActiveMax>\n");
115 sb.append(" <requestsDurationTotal>").append(_statsHandler.getRequestsDurationTotal()).append("</requestsDurationTotal>\n");
116 sb.append(" <requestsDurationAve>").append(_statsHandler.getRequestsDurationAve()).append("</requestsDurationAve>\n");
117 sb.append(" <requestsDurationMin>").append(_statsHandler.getRequestsDurationMin()).append("</requestsDurationMin>\n");
118 sb.append(" <requestsDurationMax>").append(_statsHandler.getRequestsDurationMax()).append("</requestsDurationMax>\n");
119 sb.append(" <requestsActiveDurationAve>").append(_statsHandler.getRequestsActiveDurationAve()).append("</requestsActiveDurationAve>\n");
120 sb.append(" <requestsActiveDurationMin>").append(_statsHandler.getRequestsActiveDurationMin()).append("</requestsActiveDurationMin>\n");
121 sb.append(" <requestsActiveDurationMax>").append(_statsHandler.getRequestsActiveDurationMax()).append("</requestsActiveDurationMax>\n");
122 sb.append(" </requests>\n");
123
124 sb.append(" <responses>\n");
125 sb.append(" <responses1xx>").append(_statsHandler.getResponses1xx()).append("</responses1xx>\n");
126 sb.append(" <responses2xx>").append(_statsHandler.getResponses2xx()).append("</responses2xx>\n");
127 sb.append(" <responses3xx>").append(_statsHandler.getResponses3xx()).append("</responses3xx>\n");
128 sb.append(" <responses4xx>").append(_statsHandler.getResponses4xx()).append("</responses4xx>\n");
129 sb.append(" <responses5xx>").append(_statsHandler.getResponses5xx()).append("</responses5xx>\n");
130 sb.append(" <responsesBytesTotal>").append(_statsHandler.getResponsesBytesTotal()).append("</responsesBytesTotal>\n");
131 sb.append(" </responses>\n");
132
133 sb.append(" <connections>\n");
134 for (Connector connector : _connectors)
135 {
136 sb.append(" <connector>\n");
137 sb.append(" <name>").append(connector.getName()).append("</name>\n");
138 sb.append(" <statsOn>").append(connector.getStatsOn()).append("</statsOn>\n");
139 if (connector.getStatsOn())
140 {
141 sb.append(" <statsOnMs>").append(connector.getStatsOnMs()).append("</statsOnMs>\n");
142 sb.append(" <connections>").append(connector.getConnections()).append("</connections>\n");
143 sb.append(" <connectionsOpen>").append(connector.getConnectionsOpen()).append("</connectionsOpen>\n");
144 sb.append(" <connectionsOpenMin>").append(connector.getConnectionsOpenMin()).append("</connectionsOpenMin>\n");
145 sb.append(" <connectionsOpenMax>").append(connector.getConnectionsOpenMax()).append("</connectionsOpenMax>\n");
146 sb.append(" <connectionsDurationTotal>").append(connector.getConnectionsDurationTotal()).append("</connectionsDurationTotal>\n");
147 sb.append(" <connectionsDurationAve>").append(connector.getConnectionsDurationAve()).append("</connectionsDurationAve>\n");
148 sb.append(" <connectionsDurationMin>").append(connector.getConnectionsDurationMin()).append("</connectionsDurationMin>\n");
149 sb.append(" <connectionsDurationMax>").append(connector.getConnectionsDurationMax()).append("</connectionsDurationMax>\n");
150 sb.append(" <requests>").append(connector.getRequests()).append("</requests>\n");
151 sb.append(" <connectionsRequestsAve>").append(connector.getConnectionsRequestsAve()).append("</connectionsRequestsAve>\n");
152 sb.append(" <connectionsRequestsMin>").append(connector.getConnectionsRequestsMin()).append("</connectionsRequestsMin>\n");
153 sb.append(" <connectionsRequestsMax>").append(connector.getConnectionsRequestsMax()).append("</connectionsRequestsMax>\n");
154 }
155 sb.append(" </connector>\n");
156 }
157 sb.append(" </connections>\n");
158
159 sb.append(" <memory>\n");
160 sb.append(" <heapMemoryUsage>").append(_memoryBean.getHeapMemoryUsage().getUsed()).append("</heapMemoryUsage>\n");
161 sb.append(" <nonHeapMemoryUsage>").append(_memoryBean.getNonHeapMemoryUsage().getUsed()).append("</nonHeapMemoryUsage>\n");
162 sb.append(" </memory>\n");
163
164 sb.append("</statistics>\n");
165
166 response.setContentType("text/xml");
167 PrintWriter pout = null;
168 pout = response.getWriter();
169 pout.write(sb.toString());
170 }
171
172 private void sendTextResponse(HttpServletResponse response) throws IOException
173 {
174
175 StringBuilder sb = new StringBuilder();
176
177 sb.append("<h1>Statistics:</h1>\n");
178
179 sb.append("<h2>Requests:</h2>\n");
180 sb.append("Statistics gathering started " + _statsHandler.getStatsOnMs() + "ms ago").append("<br />\n");
181 sb.append("Total requests: " + _statsHandler.getRequests()).append("<br />\n");
182 sb.append("Total requests timed out: " + _statsHandler.getRequestsTimedout()).append("<br />\n");
183 sb.append("Total requests resumed: " + _statsHandler.getRequestsResumed()).append("<br />\n");
184 sb.append("Current requests active: " + _statsHandler.getRequestsActive()).append("<br />\n");
185 sb.append("Min concurrent requests active: " + _statsHandler.getRequestsActiveMin()).append("<br />\n");
186 sb.append("Max concurrent requests active: " + _statsHandler.getRequestsActiveMax()).append("<br />\n");
187 sb.append("Total requests duration: " + _statsHandler.getRequestsDurationTotal()).append("<br />\n");
188 sb.append("Average request duration: " + _statsHandler.getRequestsDurationAve()).append("<br />\n");
189 sb.append("Min request duration: " + _statsHandler.getRequestsDurationMin()).append("<br />\n");
190 sb.append("Max request duration: " + _statsHandler.getRequestsDurationMax()).append("<br />\n");
191 sb.append("Average request active duration: " + _statsHandler.getRequestsActiveDurationAve()).append("<br />\n");
192 sb.append("Min request active duration: " + _statsHandler.getRequestsActiveDurationMin()).append("<br />\n");
193 sb.append("Max request active duration: " + _statsHandler.getRequestsActiveDurationMax()).append("<br />\n");
194
195 sb.append("<h2>Responses:</h2>\n");
196 sb.append("1xx responses: " + _statsHandler.getResponses1xx()).append("<br />\n");
197 sb.append("2xx responses: " + _statsHandler.getResponses2xx()).append("<br />\n");
198 sb.append("3xx responses: " + _statsHandler.getResponses3xx()).append("<br />\n");
199 sb.append("4xx responses: " + _statsHandler.getResponses4xx()).append("<br />\n");
200 sb.append("5xx responses: " + _statsHandler.getResponses5xx()).append("<br />\n");
201 sb.append("Bytes sent total: " + _statsHandler.getResponsesBytesTotal()).append("<br />\n");
202
203 sb.append("<h2>Connections:</h2>\n");
204 for (Connector connector : _connectors)
205 {
206 sb.append("<h3>" + connector.getName() + "</h3>");
207
208 if (connector.getStatsOn())
209 {
210 sb.append("Statistics gathering started " + connector.getStatsOnMs() + "ms ago").append("<br />\n");
211 sb.append("Total connections: " + connector.getConnections()).append("<br />\n");
212 sb.append("Current connections open: " + connector.getConnectionsOpen());
213 sb.append("Min concurrent connections open: " + connector.getConnectionsOpenMin()).append("<br />\n");
214 sb.append("Max concurrent connections open: " + connector.getConnectionsOpenMax()).append("<br />\n");
215 sb.append("Total connections duration: " + connector.getConnectionsDurationTotal()).append("<br />\n");
216 sb.append("Average connection duration: " + connector.getConnectionsDurationAve()).append("<br />\n");
217 sb.append("Min connection duration: " + connector.getConnectionsDurationMin()).append("<br />\n");
218 sb.append("Max connection duration: " + connector.getConnectionsDurationMax()).append("<br />\n");
219 sb.append("Total requests: " + connector.getRequests()).append("<br />\n");
220 sb.append("Average requests per connection: " + connector.getConnectionsRequestsAve()).append("<br />\n");
221 sb.append("Min requests per connection: " + connector.getConnectionsRequestsMin()).append("<br />\n");
222 sb.append("Max requests per connection: " + connector.getConnectionsRequestsMax()).append("<br />\n");
223 }
224 else
225 {
226 sb.append("Statistics gathering off.\n");
227 }
228
229 }
230
231 sb.append("<h2>Memory:</h2>\n");
232 sb.append("Heap memory usage: " + _memoryBean.getHeapMemoryUsage().getUsed() + " bytes").append("<br />\n");
233 sb.append("Non-heap memory usage: " + _memoryBean.getNonHeapMemoryUsage().getUsed() + " bytes").append("<br />\n");
234
235 response.setContentType("text/html");
236 PrintWriter pout = null;
237 pout = response.getWriter();
238 pout.write(sb.toString());
239
240 }
241 }