You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by el...@apache.org on 2014/01/13 18:58:33 UTC
[08/11] git commit: Merge branch '1.4.5-SNAPSHOT' into 1.5.1-SNAPSHOT
Merge branch '1.4.5-SNAPSHOT' into 1.5.1-SNAPSHOT
Conflicts:
server/src/main/java/org/apache/accumulo/server/monitor/servlets/DefaultServlet.java
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/0603edbb
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/0603edbb
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/0603edbb
Branch: refs/heads/master
Commit: 0603edbbe3dc7b4bfae379111dda60d4ea0d9266
Parents: aa5c921 8e0e0e1
Author: Josh Elser <el...@apache.org>
Authored: Mon Jan 13 12:46:24 2014 -0500
Committer: Josh Elser <el...@apache.org>
Committed: Mon Jan 13 12:46:24 2014 -0500
----------------------------------------------------------------------
.../apache/accumulo/server/monitor/servlets/DefaultServlet.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/0603edbb/server/src/main/java/org/apache/accumulo/server/monitor/servlets/DefaultServlet.java
----------------------------------------------------------------------
diff --cc server/src/main/java/org/apache/accumulo/server/monitor/servlets/DefaultServlet.java
index b12dda5,0000000..0bdd34d
mode 100644,000000..100644
--- a/server/src/main/java/org/apache/accumulo/server/monitor/servlets/DefaultServlet.java
+++ b/server/src/main/java/org/apache/accumulo/server/monitor/servlets/DefaultServlet.java
@@@ -1,375 -1,0 +1,375 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.accumulo.server.monitor.servlets;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.file.FileUtil;
+import org.apache.accumulo.core.master.thrift.MasterMonitorInfo;
+import org.apache.accumulo.core.util.CachedConfiguration;
+import org.apache.accumulo.core.util.Duration;
+import org.apache.accumulo.core.util.Pair;
+import org.apache.accumulo.server.conf.ServerConfiguration;
+import org.apache.accumulo.server.monitor.Monitor;
+import org.apache.accumulo.server.monitor.ZooKeeperStatus;
+import org.apache.accumulo.server.monitor.ZooKeeperStatus.ZooKeeperState;
+import org.apache.accumulo.server.monitor.util.celltypes.NumberType;
+import org.apache.accumulo.server.trace.TraceFileSystem;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.ContentSummary;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+
+public class DefaultServlet extends BasicServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected String getTitle(HttpServletRequest req) {
+ return req.getRequestURI().startsWith("/docs") ? "Documentation" : "Accumulo Overview";
+ }
+
+ private void getResource(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ try {
+ String path = req.getRequestURI();
+
+ if (path.endsWith(".jpg"))
+ resp.setContentType("image/jpeg");
+
+ if (path.endsWith(".html"))
+ resp.setContentType("text/html");
+
+ path = path.substring(1);
+ InputStream data = BasicServlet.class.getClassLoader().getResourceAsStream(path);
+ ServletOutputStream out = resp.getOutputStream();
+ try {
+ if (data != null) {
+ byte[] buffer = new byte[1024];
+ int n;
+ while ((n = data.read(buffer)) > 0)
+ out.write(buffer, 0, n);
+ } else {
+ out.write(("could not get resource " + path + "").getBytes());
+ }
+ } finally {
+ if (data != null)
+ data.close();
+ }
+ } catch (Throwable t) {
+ log.error(t, t);
+ throw new IOException(t);
+ }
+ }
+
+ private void getDocResource(HttpServletRequest req, final HttpServletResponse resp) throws IOException {
+ final String path = req.getRequestURI();
+ if (path.endsWith(".html"))
+ resp.setContentType("text/html");
+
+ // Allow user to only read any file in docs directory
+ final String aHome = System.getenv("ACCUMULO_HOME");
+ PermissionCollection pc = new Permissions();
+ pc.add(new FilePermission(aHome + "/docs/-", "read"));
+
+ AccessControlContext acc = new AccessControlContext(new ProtectionDomain[] {new ProtectionDomain(null, pc)});
+
+ IOException e = AccessController.doPrivileged(new PrivilegedAction<IOException>() {
+
+ @Override
+ public IOException run() {
+ InputStream data = null;
+ try {
+ File file = new File(aHome + path);
+ data = new FileInputStream(file.getAbsolutePath());
+ byte[] buffer = new byte[1024];
+ int n;
+ ServletOutputStream out = resp.getOutputStream();
+ while ((n = data.read(buffer)) > 0)
+ out.write(buffer, 0, n);
+ return null;
+ } catch (IOException e) {
+ return e;
+ } finally {
+ if (data != null) {
+ try {
+ data.close();
+ } catch (IOException ex) {
+ log.error(ex, ex);
+ }
+ }
+ }
+ }
+ }, acc);
+
+ if (e != null)
+ throw e;
+ }
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ if (req.getRequestURI().startsWith("/web"))
+ getResource(req, resp);
+ else if (req.getRequestURI().equals("/docs") || req.getRequestURI().equals("/docs/apidocs"))
+ super.doGet(req, resp);
+ else if (req.getRequestURI().startsWith("/docs"))
+ getDocResource(req, resp);
+ else if (req.getRequestURI().startsWith("/monitor"))
+ resp.sendRedirect("/master");
+ else if (req.getRequestURI().startsWith("/errors"))
+ resp.sendRedirect("/problems");
+ else
+ super.doGet(req, resp);
+ }
+
+ public static final int GRAPH_WIDTH = 450;
+ public static final int GRAPH_HEIGHT = 150;
+
+ private static void plotData(StringBuilder sb, String title, @SuppressWarnings("rawtypes") List data, boolean points) {
+ plotData(sb, title, points, new ArrayList<String>(), data);
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static void plotData(StringBuilder sb, String title, boolean points, List<String> labels, List... series) {
+ sb.append("<div class=\"plotHeading\">");
+ sb.append(title);
+ sb.append("</div>");
+ sb.append("</br>");
+ String id = "c" + title.hashCode();
+ sb.append("<div id=\"" + id + "\" style=\"width:" + GRAPH_WIDTH + "px;height:" + GRAPH_HEIGHT + "px;\"></div>\n");
+
+ sb.append("<script type=\"text/javascript\">\n");
+ sb.append("$(function () {\n");
+
+ for (int i = 0; i < series.length; i++) {
+
+ @SuppressWarnings("unchecked")
+ List<Pair<Long,? extends Number>> data = series[i];
+ sb.append(" var d" + i + " = [");
+
+ String sep = "";
+ for (Pair<Long,? extends Number> point : data) {
+ if (point.getSecond() == null)
+ continue;
+
+ String y;
+ if (point.getSecond() instanceof Double)
+ y = String.format("%1.2f", point.getSecond());
+ else
+ y = point.getSecond().toString();
+
+ sb.append(sep);
+ sep = ",";
+ sb.append("[" + utc2local(point.getFirst()) + "," + y + "]");
+ }
+ sb.append(" ];\n");
+ }
+
+ String opts = "lines: { show: true }";
+ if (points)
+ opts = "points: { show: true, radius: 1 }";
+
+ sb.append(" $.plot($(\"#" + id + "\"),");
+ String sep = "";
+
+ String colors[] = new String[] {"red", "blue", "green", "black"};
+
+ sb.append("[");
+ for (int i = 0; i < series.length; i++) {
+ sb.append(sep);
+ sep = ",";
+ sb.append("{ ");
+ if (labels.size() > 0) {
+ sb.append("label: \"" + labels.get(i) + "\", ");
+ }
+ sb.append("data: d" + i + ", " + opts + ", color:\"" + colors[i] + "\" }");
+ }
+ sb.append("], ");
+ sb.append("{yaxis:{}, xaxis:{mode:\"time\",minTickSize: [1, \"minute\"],timeformat: \"%H:%M<br />" + getShortTZName() + "\", ticks:3}});");
+ sb.append(" });\n");
+ sb.append("</script>\n");
+ }
+
+ /**
+ * Shows the current time zone (based on the current time) short name
+ */
+ private static String getShortTZName() {
+ TimeZone tz = TimeZone.getDefault();
+ return tz.getDisplayName(tz.inDaylightTime(new Date()), TimeZone.SHORT);
+ }
+
+ /**
+ * Converts a unix timestamp in UTC to one that is relative to the local timezone
+ */
+ private static Long utc2local(Long utcMillis) {
+ Calendar currentCalendar = Calendar.getInstance(); // default timezone
+ currentCalendar.setTimeInMillis(utcMillis + currentCalendar.getTimeZone().getOffset(utcMillis));
+ return currentCalendar.getTime().getTime();
+ }
+
+ @Override
+ protected void pageBody(HttpServletRequest req, HttpServletResponse resp, StringBuilder sb) throws IOException {
+ if (req.getRequestURI().equals("/docs") || req.getRequestURI().equals("/docs/apidocs")) {
+ sb.append("<object data='").append(req.getRequestURI()).append("/index.html' type='text/html' width='100%' height='100%'></object>");
+ return;
+ }
+
+ sb.append("<table class='noborder'>\n");
+ sb.append("<tr>\n");
+
+ sb.append("<td class='noborder'>\n");
+ doAccumuloTable(sb);
+ sb.append("</td>\n");
+
+ sb.append("<td class='noborder'>\n");
+ doZooKeeperTable(sb);
+ sb.append("</td>\n");
+
+ sb.append("</tr></table>\n");
+ sb.append("<br/>\n");
+
+ sb.append("<p/><table class=\"noborder\">\n");
+
+ sb.append("<tr><td>\n");
+ plotData(sb, "Ingest (Entries/s)", Monitor.getIngestRateOverTime(), false);
+ sb.append("</td><td>\n");
+ plotData(sb, "Scan (Entries/s)", false, Arrays.asList("Read", "Returned"), Monitor.getScanRateOverTime(), Monitor.getQueryRateOverTime());
+ sb.append("</td></tr>\n");
+
+ sb.append("<tr><td>\n");
+ plotData(sb, "Ingest (MB/s)", Monitor.getIngestByteRateOverTime(), false);
+ sb.append("</td><td>\n");
+ plotData(sb, "Scan (MB/s)", Monitor.getQueryByteRateOverTime(), false);
+ sb.append("</td></tr>\n");
+
+ sb.append("<tr><td>\n");
+ plotData(sb, "Load Average", Monitor.getLoadOverTime(), false);
+ sb.append("</td><td>\n");
+ plotData(sb, "Seeks", Monitor.getLookupsOverTime(), false);
+ sb.append("</td></tr>\n");
+
+ sb.append("<tr><td>\n");
+ plotData(sb, "Minor Compactions", Monitor.getMinorCompactionsOverTime(), false);
+ sb.append("</td><td>\n");
+ plotData(sb, "Major Compactions", Monitor.getMajorCompactionsOverTime(), false);
+ sb.append("</td></tr>\n");
+
+ sb.append("<tr><td>\n");
+ plotData(sb, "Index Cache Hit Rate", Monitor.getIndexCacheHitRateOverTime(), true);
+ sb.append("</td><td>\n");
+ plotData(sb, "Data Cache Hit Rate", Monitor.getDataCacheHitRateOverTime(), true);
+ sb.append("</td></tr>\n");
+
+ sb.append("</table>\n");
+ }
+
+ private void doAccumuloTable(StringBuilder sb) throws IOException {
+ // Accumulo
+ Configuration conf = CachedConfiguration.getInstance();
+ FileSystem fs = TraceFileSystem.wrap(FileUtil.getFileSystem(conf, ServerConfiguration.getSiteConfiguration()));
+ MasterMonitorInfo info = Monitor.getMmi();
+ sb.append("<table>\n");
+ sb.append("<tr><th colspan='2'><a href='/master'>Accumulo Master</a></th></tr>\n");
+ if (info == null) {
+ sb.append("<tr><td colspan='2'><span class='error'>Master is Down</span></td></tr>\n");
+ } else {
+ String consumed = "Unknown";
+ String diskUsed = "Unknown";
+ try {
+ Path path = new Path(Monitor.getSystemConfiguration().get(Property.INSTANCE_DFS_DIR));
+ log.debug("Reading the content summary for " + path);
+ try {
+ ContentSummary acu = fs.getContentSummary(path);
++ diskUsed = bytes(acu.getSpaceConsumed());
+ ContentSummary rootSummary = fs.getContentSummary(new Path("/"));
+ consumed = String.format("%.2f%%", acu.getSpaceConsumed() * 100. / rootSummary.getSpaceConsumed());
- diskUsed = bytes(acu.getSpaceConsumed());
+ } catch (Exception ex) {
+ log.trace("Unable to get disk usage information from hdfs", ex);
+ }
+
+ boolean highlight = false;
+ tableRow(sb, (highlight = !highlight), "Disk Used", diskUsed);
+ if (fs.getUsed() != 0)
+ tableRow(sb, (highlight = !highlight), "% of Used DFS", consumed);
+ tableRow(sb, (highlight = !highlight), "<a href='/tables'>Tables</a>", NumberType.commas(Monitor.getTotalTables()));
+ tableRow(sb, (highlight = !highlight), "<a href='/tservers'>Tablet Servers</a>", NumberType.commas(info.tServerInfo.size(), 1, Long.MAX_VALUE));
+ tableRow(sb, (highlight = !highlight), "<a href='/tservers'>Dead Tablet Servers</a>", NumberType.commas(info.deadTabletServers.size(), 0, 0));
+ tableRow(sb, (highlight = !highlight), "Tablets", NumberType.commas(Monitor.getTotalTabletCount(), 1, Long.MAX_VALUE));
+ tableRow(sb, (highlight = !highlight), "Entries", NumberType.commas(Monitor.getTotalEntries()));
+ tableRow(sb, (highlight = !highlight), "Lookups", NumberType.commas(Monitor.getTotalLookups()));
+ tableRow(sb, (highlight = !highlight), "Uptime", Duration.format(System.currentTimeMillis() - Monitor.getStartTime()));
+ } catch (Exception e) {
+ log.debug(e, e);
+ }
+ }
+ sb.append("</table>\n");
+ }
+
+ private void doZooKeeperTable(StringBuilder sb) throws IOException {
+ // Zookeepers
+ sb.append("<table>\n");
+ sb.append("<tr><th colspan='3'>Zookeeper</th></tr>\n");
+ sb.append("<tr><th>Server</th><th>Mode</th><th>Clients</th></tr>\n");
+
+ boolean highlight = false;
+ for (ZooKeeperState k : ZooKeeperStatus.getZooKeeperStatus()) {
+ if (k.clients >= 0) {
+ tableRow(sb, (highlight = !highlight), k.keeper, k.mode, k.clients);
+ } else {
+ tableRow(sb, false, k.keeper, "<span class='error'>Down</span>", "");
+ }
+ }
+ sb.append("</table>\n");
+ }
+
+ private static final String BYTES[] = {"", "K", "M", "G", "T", "P", "E", "Z"};
+
+ private static String bytes(long big) {
+ return NumberType.bigNumber(big, BYTES, 1024);
+ }
+
+ public static void tableRow(StringBuilder sb, boolean highlight, Object... cells) {
+ sb.append(highlight ? "<tr class='highlight'>" : "<tr>");
+ for (int i = 0; i < cells.length; ++i) {
+ Object cell = cells[i];
+ String cellValue = cell == null ? "" : String.valueOf(cell).trim();
+ sb.append("<td class='").append(i < cells.length - 1 ? "left" : "right").append("'>").append(cellValue.isEmpty() ? "-" : cellValue).append("</td>");
+ }
+ sb.append("</tr>\n");
+ }
+}