package com.cloudhopper.mq.broker.server;
/*
* #%L
* ch-mq
* %%
* Copyright (C) 2012 Cloudhopper by Twitter
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import com.cloudhopper.commons.util.LoadBalancedList;
import com.cloudhopper.commons.util.PeriodFormatterUtil;
import com.cloudhopper.mq.broker.DistributedQueueManager;
import com.cloudhopper.mq.broker.DistributedQueueState;
import com.cloudhopper.mq.broker.RemoteBrokerInfo;
import com.cloudhopper.mq.broker.RemoteQueueInfo;
import com.cloudhopper.mq.queue.Queue;
import com.cloudhopper.mq.queue.QueueManager;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.joda.time.DateTime;
/**
* Simple servlet providing an interface to a QueueManager.
*/
public class StatusServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(StatusServlet.class);
// reference to queue manager
private final QueueManager queueManager;
// reference to distributed queue configuration
private final DistributedQueueManager dqm;
public StatusServlet(QueueManager queueManager, DistributedQueueManager dqm) {
this.queueManager = queueManager;
this.dqm = dqm;
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter ps = response.getWriter();
ps.println("<html>");
ps.println(" <head>");
ps.println(" <title>Queue Status</title>");
ps.println(" <style type=\"text/css\">");
ps.println(" h1, p, table, a, body { font-family: Helvetica,Verdana,Arial; font-size: 11px; }");
ps.println(" h1 { font-size: 13px; font-weight: bold; }");
ps.println(" table { border: solid 1px #999999; border-collapse:collapse; empty-cells: show; padding:2px; }");
ps.println(" th { font-weight: bold; background-color:#666666; color:#FFFFFF; text-align: left; }");
ps.println(" th, td { border-collapse:collapse; border: solid 1px #999999; }");
ps.println(" tr.queue { background-color:#F5F5F5; }");
ps.println(" </style>");
ps.println(" </head>");
ps.println(" <body>");
ps.println("<h1>Services</h1>");
ps.println("<table>");
ps.println("<tr><th>Service</th><th>Status</th></tr>");
ps.println("<tr><td>QueueManager</td><td>" + (queueManager.isStarted() ? "Started" : "Stopped") + "</td></tr>");
ps.println("<tr><td>DistributedQueueManager</td><td>" + (dqm.isStarted() ? "Started" : "Stopped") + "</td></tr>");
ps.println("</table>");
ps.println("<h1>Queues</h1>");
ps.println("<table>");
ps.println("<tr><th>Queue Name</th><th>Size</th><th>Puts</th><th>Takes</th><th>Errors</th><th>Sessions</th><th>Consumers</th><th>Producers</th><th>Remote Processor?</th><th>Item Type</th></tr>");
if (queueManager.getQueueCount() <= 0) {
ps.println("<tr><td colspan=9>None</td></tr>");
} else {
// create TreeMap of queues so that queue names are sorted alphabetically
TreeMap<String,Queue> sortedQueues = new TreeMap<String,Queue>();
Enumeration<Queue> queues = queueManager.getQueues();
while (queues.hasMoreElements()) {
Queue queue = queues.nextElement();
sortedQueues.put(queue.getName(), queue);
}
for (Queue queue : sortedQueues.values()) {
ps.print("<tr><td>");
ps.print(queue.getName());
ps.print("</td><td align=right>");
ps.print(queue.getSize());
ps.print("</td><td align=right>");
ps.print(queue.getPutCount());
ps.print("</td><td align=right>");
ps.print(queue.getTakeCount());
ps.print("</td><td align=right>");
ps.print(queue.getErrorCount());
ps.print("</td><td align=right>");
ps.print(queue.getSessionCount());
ps.print("</td><td align=right>");
ps.print(queue.getConsumerCount());
ps.print("</td><td align=right>");
ps.print(queue.getProducerCount());
ps.print("</td><td align=center>");
ps.print(dqm.getQueueProcessors().containsKey(queue.getName()));
ps.print("</td><td>");
ps.print(queue.getElementType().getCanonicalName());
ps.print("</td></tr>");
}
}
ps.println("</table>");
DistributedQueueState dqs = dqm.getDistributedQueueState();
ps.println("<h1>Distributed Queue State - Viewed By Remote Broker</h1>");
ps.println("<table>");
ps.println("<tr><th>Remote Broker</th><th>Area</th><th>State</th><th>State Time</th><th>Last Available Date</th><th>Last Error Message</th></tr>");
// sort brokers by name (url)
TreeMap<String,RemoteBrokerInfo> sortedRemoteBrokers = new TreeMap<String,RemoteBrokerInfo>();
for (RemoteBrokerInfo bi : dqs.getRemoteBrokers().values()) {
sortedRemoteBrokers.put(bi.getUrl(), bi);
}
for (RemoteBrokerInfo bi : sortedRemoteBrokers.values()) {
ps.print("<tr><td>");
ps.print(bi.getUrl());
ps.print("</td><td>");
ps.print(bi.getAreaId());
ps.print("</td><td>");
ps.print(RemoteBrokerInfo.STATES[bi.getState()]);
ps.print("</td><td>");
long stateDuration = System.currentTimeMillis() - bi.getLastStateChangedTime();
//ps.print(formatter.print(new Period(stateDuration)));
ps.print(PeriodFormatterUtil.toLinuxUptimeStyleString(stateDuration));
ps.print("</td><td>");
ps.print((bi.getLastAvailableTime() <= 0 ? "Never" : new DateTime(bi.getLastAvailableTime())));
ps.print("</td><td>");
ps.print((bi.getLastErrorMessage() == null ? "" : bi.getLastErrorMessage()));
ps.print("</td></tr>");
// print out queues if they exist
if (bi.getRemoteQueues().size() > 0) {
ps.print("<tr class=\"queue\"><td colspan=6>");
ps.print(" > Remote Queues: ");
// sort by name
TreeSet<String> sortedRemoteQueues = new TreeSet<String>();
for (String q : bi.getRemoteQueues()) {
sortedRemoteQueues.add(q);
}
// print them out
int i = 0;
for (String q : sortedRemoteQueues) {
if (i != 0) ps.print(", ");
ps.print(q);
i++;
}
ps.print("</td></tr>");
}
}
ps.println("</table>");
ps.println("<h1>Distributed Queue State - Viewed By Remote Queue</h1>");
ps.println("<table>");
ps.println("<tr><th>Queue Name</th><th>State</th><th>State Time</th><th>Remote Brokers</th></tr>");
if (dqs.getRemoteQueues().size() <= 0) {
ps.println("<tr><td colspan=3>None</td></tr>");
} else {
// sort queues by name (url)
TreeMap<String,RemoteQueueInfo> sortedRemoteQueues = new TreeMap<String,RemoteQueueInfo>();
for (RemoteQueueInfo qi : dqs.getRemoteQueues().values()) {
sortedRemoteQueues.put(qi.getName(), qi);
}
for (RemoteQueueInfo qi : sortedRemoteQueues.values()) {
ps.print("<tr><td>");
ps.print(qi.getName());
ps.print("</td><td>");
ps.print(RemoteQueueInfo.STATES[qi.getState()]);
ps.print("</td><td>");
long stateDuration = System.currentTimeMillis() - qi.getLastStateChangedTime();
ps.print(PeriodFormatterUtil.toLinuxUptimeStyleString(stateDuration));
ps.print("</td><td>");
ps.print("all: ");
ps.print(qi.getSize());
ps.print(" [primary: ");
ps.print(qi.getPrimarySize());
ps.print(", failover: ");
ps.print(qi.getFailoverSize());
ps.print("]");
ps.print("</td></tr>");
for (LoadBalancedList.Node<String> entry : qi.getPrimaryList()) {
ps.print("<tr class=\"queue\"><td colspan=4>");
ps.print(" > Primary Broker: " + entry.getValue() + " [weight: " + entry.getWeight() + "]");
ps.print("</td></tr>");
}
for (LoadBalancedList.Node<String> entry : qi.getFailoverList()) {
ps.print("<tr class=\"queue\"><td colspan=4>");
ps.print(" > Failover Broker: " + entry.getValue() + " [weight: " + entry.getWeight() + "]");
ps.print("</td></tr>");
}
}
}
ps.println("</table>");
ps.println(" </body>");
ps.println("</html>");
response.setStatus(HttpServletResponse.SC_OK);
}
}