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&nbsp;Used", diskUsed);
 +        if (fs.getUsed() != 0)
 +          tableRow(sb, (highlight = !highlight), "%&nbsp;of&nbsp;Used&nbsp;DFS", consumed);
 +        tableRow(sb, (highlight = !highlight), "<a href='/tables'>Tables</a>", NumberType.commas(Monitor.getTotalTables()));
 +        tableRow(sb, (highlight = !highlight), "<a href='/tservers'>Tablet&nbsp;Servers</a>", NumberType.commas(info.tServerInfo.size(), 1, Long.MAX_VALUE));
 +        tableRow(sb, (highlight = !highlight), "<a href='/tservers'>Dead&nbsp;Tablet&nbsp;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");
 +  }
 +}