1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.esigate.server;
17
18 import java.io.IOException;
19 import java.io.Writer;
20 import java.lang.management.ManagementFactory;
21 import java.util.Map;
22 import java.util.Map.Entry;
23 import java.util.TreeMap;
24
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.eclipse.jetty.server.Request;
30 import org.eclipse.jetty.server.Server;
31 import org.eclipse.jetty.server.handler.AbstractHandler;
32
33 import com.codahale.metrics.Counter;
34 import com.codahale.metrics.Gauge;
35 import com.codahale.metrics.Meter;
36 import com.codahale.metrics.MetricRegistry;
37 import com.codahale.metrics.Timer;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class ControlHandler extends AbstractHandler {
53 private static final String PREFIX_CONTEXT = "org.eclipse.jetty.webapp.WebAppContext.main.";
54 private static final String PREFIX_THREAD_POOL = "org.eclipse.jetty.util.thread.QueuedThreadPool.esigate.";
55
56
57
58 private static final String URL_STATUS = "/server-status";
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 private final MetricRegistry registry;
78
79
80
81
82
83
84
85 public ControlHandler(MetricRegistry registry) {
86 this.registry = registry;
87 }
88
89 private static boolean fromControlConnection(Request serverRequest) {
90 return EsigateServer.getControlPort() == serverRequest.getLocalPort();
91 }
92
93
94
95
96
97
98
99 public static void shutdown(int port) {
100 Http.doPOST("http://127.0.0.1:" + port + "/shutdown");
101 }
102
103
104
105
106
107
108
109 public static void status(int port) {
110 Http.doGET("http://127.0.0.1:" + port + URL_STATUS);
111 }
112
113 @Override
114 public void handle(String target, Request serverRequest, HttpServletRequest request, HttpServletResponse response)
115 throws IOException, ServletException {
116
117 if (fromControlConnection(serverRequest)) {
118 serverRequest.setHandled(true);
119
120 switch (target) {
121
122 case "/shutdown":
123 if ("POST".equals(serverRequest.getMethod())) {
124 response.setStatus(HttpServletResponse.SC_OK);
125 stopServer();
126 }
127 break;
128
129 case URL_STATUS:
130 if ("GET".equals(serverRequest.getMethod())) {
131
132 if (request.getParameter("auto") != null) {
133 response.setStatus(HttpServletResponse.SC_OK);
134 try (Writer sos = response.getWriter()) {
135 Map<String, Object> status = getServerStatus();
136 for (String key : status.keySet()) {
137 sos.append(key).append(": ").append(String.valueOf(status.get(key))).append("\n");
138 }
139 }
140
141 } else {
142 response.setStatus(HttpServletResponse.SC_OK);
143 try (Writer sos = response.getWriter()) {
144 sos.append("Esigate Server Status\n");
145 Map<String, Object> status = getServerStatus();
146 for (String key : status.keySet()) {
147 sos.append(key).append(": ").append(String.valueOf(status.get(key))).append("\n");
148 }
149 }
150 }
151
152 }
153 break;
154
155 default:
156 response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
157 break;
158 }
159
160 }
161
162 }
163
164 private Map<String, Object> getServerStatus() {
165 Map<String, Object> result = new TreeMap<>();
166
167 Map<String, Counter> counters = this.registry.getCounters();
168 for (Entry<String, Counter> c : counters.entrySet()) {
169 result.put(cleanupStatusKey(c.getKey()), String.valueOf(c.getValue().getCount()));
170 }
171
172 Map<String, Meter> meters = this.registry.getMeters();
173 for (Entry<String, Meter> c : meters.entrySet()) {
174 result.put(cleanupStatusKey(c.getKey()), String.valueOf(c.getValue().getCount()));
175 result.put(cleanupStatusKey(c.getKey()) + "PerSec", String.valueOf(c.getValue().getOneMinuteRate()));
176 }
177
178 Map<String, Gauge> gauges = this.registry.getGauges();
179 for (Entry<String, Gauge> c : gauges.entrySet()) {
180 result.put(cleanupStatusKey(c.getKey()), String.valueOf(c.getValue().getValue()));
181 }
182
183 Map<String, Timer> timers = this.registry.getTimers();
184 for (Entry<String, Timer> c : timers.entrySet()) {
185 result.put(cleanupStatusKey(c.getKey()), String.valueOf(c.getValue().getOneMinuteRate()));
186 }
187
188
189 Long accesses =
190 meters.get(PREFIX_CONTEXT + "1xx-responses").getCount()
191 + meters.get(PREFIX_CONTEXT + "2xx-responses").getCount()
192 + meters.get(PREFIX_CONTEXT + "3xx-responses").getCount()
193 + meters.get(PREFIX_CONTEXT + "4xx-responses").getCount()
194 + meters.get(PREFIX_CONTEXT + "5xx-responses").getCount();
195 result.put("Total Accesses", accesses);
196
197
198 Double reqPerSec =
199 meters.get(PREFIX_CONTEXT + "1xx-responses").getOneMinuteRate()
200 + meters.get(PREFIX_CONTEXT + "2xx-responses").getOneMinuteRate()
201 + meters.get(PREFIX_CONTEXT + "3xx-responses").getOneMinuteRate()
202 + meters.get(PREFIX_CONTEXT + "4xx-responses").getOneMinuteRate()
203 + meters.get(PREFIX_CONTEXT + "5xx-responses").getOneMinuteRate();
204 result.put("ReqPerSec", reqPerSec);
205
206
207 result.put("Uptime", ManagementFactory.getRuntimeMXBean().getUptime());
208
209
210 Double cpuLoad = ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
211 if (cpuLoad >= 0d) {
212 result.put("CPULoad", cpuLoad);
213 }
214
215 return result;
216
217 }
218
219
220
221
222
223
224
225 private static String cleanupStatusKey(String s) {
226 String result = s;
227 if (s.startsWith(PREFIX_CONTEXT)) {
228 result = s.substring(PREFIX_CONTEXT.length());
229
230 }
231
232 if (s.startsWith(PREFIX_THREAD_POOL)) {
233 result = s.substring(PREFIX_THREAD_POOL.length());
234 }
235
236 return result;
237 }
238
239
240
241
242 private void stopServer() {
243
244 final Server targetServer = this.getServer();
245
246
247
248 new Thread() {
249 @Override
250 public void run() {
251 try {
252 targetServer.stop();
253 } catch (Exception e) {
254
255 }
256 }
257 }.start();
258
259 }
260 }