accumulo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ctubb...@apache.org
Subject [23/54] [abbrv] accumulo git commit: ACCUMULO-2181/3005 Porting Monitor
Date Thu, 06 Jul 2017 20:43:17 GMT
http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/RecoveryStatusInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/RecoveryStatusInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/RecoveryStatusInformation.java
new file mode 100644
index 0000000..4eb6de6
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/RecoveryStatusInformation.java
@@ -0,0 +1,64 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+import org.apache.accumulo.core.master.thrift.RecoveryStatus;
+
+/**
+ *
+ * Generates a recovery status
+ *
+ * @since 2.0.0
+ *
+ */
+public class RecoveryStatusInformation {
+
+  // Variable names become JSON keys
+  public String name;
+  public Integer runtime;
+  public Double progress;
+
+  public RecoveryStatusInformation() {}
+
+  /**
+   * Stores recovery information
+   *
+   * @param name
+   *          Name of the table
+   * @param runtime
+   *          Runtime of the recovery
+   * @param progress
+   *          Progress of the recovery
+   */
+  public RecoveryStatusInformation(String name, Integer runtime, Double progress) {
+    this.name = name;
+    this.runtime = runtime;
+    this.progress = progress;
+  }
+
+  /**
+   * Stores recovery information
+   *
+   * @param recovery
+   *          Recovery status to obtain name, runtime, and progress
+   */
+  public RecoveryStatusInformation(RecoveryStatus recovery) {
+    this.name = recovery.name;
+    this.runtime = recovery.runtime;
+    this.progress = recovery.progress;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceInformation.java
new file mode 100644
index 0000000..a7a4ca7
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceInformation.java
@@ -0,0 +1,64 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+/**
+ *
+ * Generates a list of traces for an ID
+ *
+ * @since 2.0.0
+ *
+ */
+public class TraceInformation {
+
+  // Variable names become JSON keys
+  public int level;
+  public long time, start;
+  public long spanID;
+  public String location, name;
+  public AddlInformation addlData;
+
+  public TraceInformation() {}
+
+  /**
+   * Generates a trace
+   *
+   * @param level
+   *          Level of the trace
+   * @param time
+   *          Amount of time the trace ran
+   * @param start
+   *          Start time of the trace
+   * @param spanID
+   *          ID of the span
+   * @param location
+   *          Location of the trace
+   * @param name
+   *          Name of the trace
+   * @param addlData
+   *          Additional data for the trace
+   */
+  public TraceInformation(int level, long time, long start, long spanID, String location, String name, AddlInformation addlData) {
+    this.level = level;
+    this.time = time;
+    this.start = start;
+    this.spanID = spanID;
+    this.location = location;
+    this.name = name;
+    this.addlData = addlData;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceList.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceList.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceList.java
new file mode 100644
index 0000000..4d712fb
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceList.java
@@ -0,0 +1,70 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Generates a list of traces for an ID
+ *
+ * @since 2.0.0
+ *
+ */
+public class TraceList {
+
+  // Variable names become JSON keys
+  public String id;
+  public Long start;
+  public List<TraceInformation> traces;
+
+  public TraceList() {
+    traces = new ArrayList<>();
+  }
+
+  /**
+   * Creates a new trace list grouped by ID
+   *
+   * @param id
+   *          ID of the trace
+   */
+  public TraceList(String id) {
+    this.id = id;
+    this.traces = new ArrayList<>();
+  }
+
+  /**
+   * Adds a trace to the list
+   *
+   * @param traces
+   *          Trace to add
+   */
+  public void addTrace(TraceInformation traces) {
+    this.traces.add(traces);
+  }
+
+  /**
+   * Adds a start time to the trace
+   *
+   * @param start
+   *          Trace start time
+   */
+  public void addStartTime(Long start) {
+    this.start = start;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceType.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceType.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceType.java
new file mode 100644
index 0000000..b080c42
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TraceType.java
@@ -0,0 +1,59 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Generates a list of traces grouped by type
+ *
+ * @since 2.0.0
+ *
+ */
+public class TraceType {
+
+  // Variable names become JSON objects
+  public String traceType;
+  public List<TracesForTypeInformation> traces;
+
+  public TraceType() {
+    traces = new ArrayList<>();
+  }
+
+  /**
+   * Creates a new list grouped by type
+   *
+   * @param type
+   *          Type of the trace group
+   */
+  public TraceType(String type) {
+    this.traceType = type;
+    this.traces = new ArrayList<>();
+  }
+
+  /**
+   * Adds a new trace to the list
+   *
+   * @param traces
+   *          Trace to add
+   */
+  public void addTrace(TracesForTypeInformation traces) {
+    this.traces.add(traces);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesForTypeInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesForTypeInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesForTypeInformation.java
new file mode 100644
index 0000000..94a1e61
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesForTypeInformation.java
@@ -0,0 +1,77 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+import org.apache.accumulo.tracer.thrift.RemoteSpan;
+
+/**
+ *
+ * Generates a list of traces per type
+ *
+ * @since 2.0.0
+ *
+ */
+public class TracesForTypeInformation {
+
+  // Variable names become JSON keys
+  public String id, source;
+  public Long start, ms;
+
+  public TracesForTypeInformation() {}
+
+  /**
+   * Generates the trace information based on a span
+   *
+   * @param span
+   *          Remote span with trace information
+   */
+  public TracesForTypeInformation(RemoteSpan span) {
+    this.id = getIDFromSpan(span);
+    this.start = getDateFromSpan(span);
+    this.ms = getSpanTime(span);
+    this.source = getLocation(span);
+  }
+
+  protected String getIDFromSpan(RemoteSpan span) {
+    if (span == null)
+      return null;
+
+    return String.format("%s", Long.toHexString(span.traceId));
+  }
+
+  protected Long getDateFromSpan(RemoteSpan span) {
+    if (span == null)
+      return null;
+
+    return span.start;
+  }
+
+  protected Long getSpanTime(RemoteSpan span) {
+    if (span == null)
+      return null;
+
+    return span.stop - span.start;
+  }
+
+  protected String getLocation(RemoteSpan span) {
+    if (span == null)
+      return null;
+
+    return span.svc + ":" + span.sender;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesResource.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesResource.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesResource.java
new file mode 100644
index 0000000..bc77ece
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/trace/TracesResource.java
@@ -0,0 +1,372 @@
+/*
+ * 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.monitor.rest.api.trace;
+
+import static java.lang.Math.min;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.io.IOException;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
+import org.apache.accumulo.core.client.Connector;
+import org.apache.accumulo.core.client.Scanner;
+import org.apache.accumulo.core.client.TableNotFoundException;
+import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
+import org.apache.accumulo.core.client.security.tokens.AuthenticationToken.Properties;
+import org.apache.accumulo.core.client.security.tokens.KerberosToken;
+import org.apache.accumulo.core.client.security.tokens.PasswordToken;
+import org.apache.accumulo.core.conf.AccumuloConfiguration;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.data.Key;
+import org.apache.accumulo.core.data.Range;
+import org.apache.accumulo.core.data.Value;
+import org.apache.accumulo.monitor.Monitor;
+import org.apache.accumulo.monitor.rest.api.BasicResource;
+import org.apache.accumulo.monitor.servlets.trace.NullScanner;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.security.SecurityUtil;
+import org.apache.accumulo.tracer.SpanTree;
+import org.apache.accumulo.tracer.SpanTreeVisitor;
+import org.apache.accumulo.tracer.TraceDump;
+import org.apache.accumulo.tracer.TraceFormatter;
+import org.apache.accumulo.tracer.thrift.Annotation;
+import org.apache.accumulo.tracer.thrift.RemoteSpan;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.security.UserGroupInformation;
+
+/**
+ *
+ * Generates a list of traces with the summary, by type, and trace details
+ *
+ * @since 2.0.0
+ *
+ */
+public class TracesResource extends BasicResource {
+
+  /**
+   * Generates a trace summary
+   *
+   * @param minutes
+   *          Range of minutes to filter traces
+   * @return Trace summary in specified range
+   */
+  @Path("/summary/{minutes}")
+  @GET
+  public RecentTracesList getTraces(@PathParam("minutes") int minutes) throws Exception {
+
+    RecentTracesList recentTraces = new RecentTracesList();
+
+    Entry<Scanner,UserGroupInformation> pair = getScanner();
+    final Scanner scanner = pair.getKey();
+    if (scanner == null) {
+      return null;
+    }
+
+    Range range = getRangeForTrace(minutes);
+    scanner.setRange(range);
+
+    final Map<String,RecentTracesInformation> summary = new TreeMap<>();
+    if (null != pair.getValue()) {
+      pair.getValue().doAs(new PrivilegedAction<Void>() {
+        @Override
+        public Void run() {
+          parseSpans(scanner, summary);
+          return null;
+        }
+      });
+    } else {
+      parseSpans(scanner, summary);
+    }
+
+    // Adds the traces to the list
+    for (Entry<String,RecentTracesInformation> entry : summary.entrySet()) {
+      RecentTracesInformation stat = entry.getValue();
+      recentTraces.addTrace(stat);
+    }
+    return recentTraces;
+  }
+
+  /**
+   * Generates a list of traces filtered by type and range of minutes
+   *
+   * @param type
+   *          Type of the trace
+   * @param minutes
+   *          Range of minutes
+   * @return List of traces filtered by type and range
+   */
+  @Path("/listType/{type}/{minutes}")
+  @GET
+  public TraceType getTracesType(@PathParam("type") String type, @PathParam("minutes") int minutes) throws Exception {
+
+    TraceType typeTraces = new TraceType(type);
+
+    Entry<Scanner,UserGroupInformation> pair = getScanner();
+    final Scanner scanner = pair.getKey();
+    if (scanner == null) {
+      return null;
+    }
+
+    Range range = getRangeForTrace(minutes);
+
+    scanner.setRange(range);
+
+    if (null != pair.getValue()) {
+      pair.getValue().doAs(new PrivilegedAction<Void>() {
+        @Override
+        public Void run() {
+          for (Entry<Key,Value> entry : scanner) {
+            RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
+
+            if (span.description.equals(type)) {
+              typeTraces.addTrace(new TracesForTypeInformation(span));
+            }
+          }
+          return null;
+        }
+      });
+    } else {
+      for (Entry<Key,Value> entry : scanner) {
+        RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
+        if (span.description.equals(type)) {
+          typeTraces.addTrace(new TracesForTypeInformation(span));
+        }
+      }
+    }
+    return typeTraces;
+  }
+
+  /**
+   * Generates a list of traces filtered by ID
+   *
+   * @param id
+   *          ID of the trace to display
+   * @return traces by ID
+   */
+  @Path("/show/{id}")
+  @GET
+  public TraceList getTracesType(@PathParam("id") String id) throws Exception {
+    TraceList traces = new TraceList(id);
+
+    if (id == null) {
+      return null;
+    }
+
+    Entry<Scanner,UserGroupInformation> entry = getScanner();
+    final Scanner scanner = entry.getKey();
+    if (scanner == null) {
+      return null;
+    }
+
+    Range range = new Range(new Text(id));
+    scanner.setRange(range);
+    final SpanTree tree = new SpanTree();
+    long start;
+
+    if (null != entry.getValue()) {
+      start = entry.getValue().doAs(new PrivilegedAction<Long>() {
+        @Override
+        public Long run() {
+          return addSpans(scanner, tree, Long.MAX_VALUE);
+        }
+      });
+    } else {
+      start = addSpans(scanner, tree, Long.MAX_VALUE);
+    }
+
+    traces.addStartTime(start);
+
+    final long finalStart = start;
+    Set<Long> visited = tree.visit(new SpanTreeVisitor() {
+      @Override
+      public void visit(int level, RemoteSpan parent, RemoteSpan node, Collection<RemoteSpan> children) {
+        traces.addTrace(addTraceInformation(level, node, finalStart));
+      }
+    });
+    tree.nodes.keySet().removeAll(visited);
+    if (!tree.nodes.isEmpty()) {
+      for (RemoteSpan span : TraceDump.sortByStart(tree.nodes.values())) {
+        traces.addTrace(addTraceInformation(0, span, finalStart));
+      }
+    }
+    return traces;
+  }
+
+  private static TraceInformation addTraceInformation(int level, RemoteSpan node, long finalStart) {
+
+    boolean hasData = node.data != null && !node.data.isEmpty();
+    boolean hasAnnotations = node.annotations != null && !node.annotations.isEmpty();
+
+    AddlInformation addlData = new AddlInformation();
+
+    if (hasData || hasAnnotations) {
+
+      if (hasData) {
+        for (Entry<String,String> entry : node.data.entrySet()) {
+          DataInformation data = new DataInformation(entry.getKey(), entry.getValue());
+          addlData.addData(data);
+        }
+      }
+      if (hasAnnotations) {
+        for (Annotation entry : node.annotations) {
+          AnnotationInformation annotations = new AnnotationInformation(entry.getMsg(), entry.getTime() - finalStart);
+          addlData.addAnnotations(annotations);
+        }
+      }
+    }
+
+    return new TraceInformation(level, node.stop - node.start, node.start - finalStart, node.spanId, node.svc + "@" + node.sender, node.description, addlData);
+  }
+
+  protected Range getRangeForTrace(long minutesSince) {
+    long endTime = System.currentTimeMillis();
+    long millisSince = minutesSince * 60 * 1000;
+    // Catch the overflow
+    if (millisSince < minutesSince) {
+      millisSince = endTime;
+    }
+    long startTime = endTime - millisSince;
+
+    String startHexTime = Long.toHexString(startTime), endHexTime = Long.toHexString(endTime);
+    while (startHexTime.length() < endHexTime.length()) {
+      startHexTime = "0" + startHexTime;
+    }
+
+    return new Range(new Text("start:" + startHexTime), new Text("start:" + endHexTime));
+  }
+
+  private void parseSpans(Scanner scanner, Map<String,RecentTracesInformation> summary) {
+    for (Entry<Key,Value> entry : scanner) {
+      RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
+      RecentTracesInformation stats = summary.get(span.description);
+      if (stats == null) {
+        summary.put(span.description, stats = new RecentTracesInformation(span.description));
+      }
+      stats.addSpan(span);
+    }
+  }
+
+  protected Entry<Scanner,UserGroupInformation> getScanner() throws AccumuloException, AccumuloSecurityException {
+    AccumuloConfiguration conf = Monitor.getContext().getConfiguration();
+    final boolean saslEnabled = conf.getBoolean(Property.INSTANCE_RPC_SASL_ENABLED);
+    UserGroupInformation traceUgi = null;
+    final String principal;
+    final AuthenticationToken at;
+    Map<String,String> loginMap = conf.getAllPropertiesWithPrefix(Property.TRACE_TOKEN_PROPERTY_PREFIX);
+    // May be null
+    String keytab = loginMap.get(Property.TRACE_TOKEN_PROPERTY_PREFIX.getKey() + "keytab");
+    if (keytab == null || keytab.length() == 0) {
+      keytab = conf.getPath(Property.GENERAL_KERBEROS_KEYTAB);
+    }
+
+    if (saslEnabled && null != keytab) {
+      principal = SecurityUtil.getServerPrincipal(conf.get(Property.TRACE_USER));
+      try {
+        traceUgi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytab);
+      } catch (IOException e) {
+        throw new RuntimeException("Failed to login as trace user", e);
+      }
+    } else {
+      principal = conf.get(Property.TRACE_USER);
+    }
+
+    if (!saslEnabled) {
+      if (loginMap.isEmpty()) {
+        Property p = Property.TRACE_PASSWORD;
+        at = new PasswordToken(conf.get(p).getBytes(UTF_8));
+      } else {
+        Properties props = new Properties();
+        int prefixLength = Property.TRACE_TOKEN_PROPERTY_PREFIX.getKey().length();
+        for (Entry<String,String> entry : loginMap.entrySet()) {
+          props.put(entry.getKey().substring(prefixLength), entry.getValue());
+        }
+
+        AuthenticationToken token = Property.createInstanceFromPropertyName(conf, Property.TRACE_TOKEN_TYPE, AuthenticationToken.class, new PasswordToken());
+        token.init(props);
+        at = token;
+      }
+    } else {
+      at = null;
+    }
+
+    final String table = conf.get(Property.TRACE_TABLE);
+    Scanner scanner;
+    if (null != traceUgi) {
+      try {
+        scanner = traceUgi.doAs(new PrivilegedExceptionAction<Scanner>() {
+
+          @Override
+          public Scanner run() throws Exception {
+            // Make the KerberosToken inside the doAs
+            AuthenticationToken token = at;
+            if (null == token) {
+              token = new KerberosToken();
+            }
+            return getScanner(table, principal, token);
+          }
+
+        });
+      } catch (IOException | InterruptedException e) {
+        throw new RuntimeException("Failed to obtain scanner", e);
+      }
+    } else {
+      if (null == at) {
+        throw new AssertionError("AuthenticationToken should not be null");
+      }
+      scanner = getScanner(table, principal, at);
+    }
+
+    return new AbstractMap.SimpleEntry<>(scanner, traceUgi);
+  }
+
+  private Scanner getScanner(String table, String principal, AuthenticationToken at) throws AccumuloException, AccumuloSecurityException {
+    try {
+      Connector conn = HdfsZooInstance.getInstance().getConnector(principal, at);
+      if (!conn.tableOperations().exists(table)) {
+        return new NullScanner();
+      }
+      Scanner scanner = conn.createScanner(table, conn.securityOperations().getUserAuthorizations(principal));
+      return scanner;
+    } catch (AccumuloSecurityException ex) {
+      return null;
+    } catch (TableNotFoundException ex) {
+      return new NullScanner();
+    }
+  }
+
+  private long addSpans(Scanner scanner, SpanTree tree, long start) {
+    for (Entry<Key,Value> entry : scanner) {
+      RemoteSpan span = TraceFormatter.getRemoteSpan(entry);
+      tree.addNode(span);
+      start = min(start, span.start);
+    }
+    return start;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/AllTimeTabletResults.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/AllTimeTabletResults.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/AllTimeTabletResults.java
new file mode 100644
index 0000000..a2f5416
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/AllTimeTabletResults.java
@@ -0,0 +1,67 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+/**
+ *
+ * Generates a tablets all time results
+ *
+ * @since 2.0.0
+ *
+ */
+public class AllTimeTabletResults {
+
+  // Variable names become JSON keys
+  public String operation;
+  public int success, failure;
+  public Double queueStdDev, avgQueueTime, avgTime;
+  public double timeSpent, stdDev;
+
+  public AllTimeTabletResults() {}
+
+  /**
+   * Stores all time results of a tablet
+   *
+   * @param operation
+   *          Type of operation
+   * @param success
+   *          Number of successes
+   * @param failure
+   *          Number of failures
+   * @param avgQueueTime
+   *          Average queue time
+   * @param queueStdDev
+   *          Standard deviation of queue
+   * @param avgTime
+   *          Average time
+   * @param stdDev
+   *          Standard deviation
+   * @param timeSpent
+   *          Time spent in operation
+   */
+  public AllTimeTabletResults(String operation, int success, int failure, Double avgQueueTime, Double queueStdDev, Double avgTime, double stdDev,
+      double timeSpent) {
+    this.operation = operation;
+    this.success = success;
+    this.failure = failure;
+    this.avgQueueTime = avgQueueTime;
+    this.avgTime = avgTime;
+    this.queueStdDev = queueStdDev;
+    this.stdDev = stdDev;
+    this.timeSpent = timeSpent;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServerInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServerInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServerInformation.java
new file mode 100644
index 0000000..e09f3d7
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServerInformation.java
@@ -0,0 +1,48 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ *
+ * Generates a bad tserver information
+ *
+ * @since 2.0.0
+ *
+ */
+public class BadTabletServerInformation {
+
+  // Variable names become JSON keys
+  @XmlAttribute
+  public String id, status;
+
+  public BadTabletServerInformation() {}
+
+  /**
+   * Stores a bad tserver
+   *
+   * @param id
+   *          ID of the tserver
+   * @param status
+   *          Status of the tserver
+   */
+  public BadTabletServerInformation(String id, String status) {
+    this.id = id;
+    this.status = status;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServers.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServers.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServers.java
new file mode 100644
index 0000000..55928b9
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/BadTabletServers.java
@@ -0,0 +1,51 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Generates a list of bad tservers
+ *
+ * @since 2.0.0
+ *
+ */
+public class BadTabletServers {
+
+  // Variable names become JSON keys
+  public List<BadTabletServerInformation> badTabletServer;
+
+  /**
+   * Initializes bad tserver list
+   */
+  public BadTabletServers() {
+    badTabletServer = new ArrayList<>();
+  }
+
+  /**
+   * Adds a new bad tserver to the list
+   *
+   * @param badTabletServer
+   *          Bad tserver to add
+   */
+  public void addBadServer(BadTabletServerInformation badTabletServer) {
+    this.badTabletServer.add(badTabletServer);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentOperations.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentOperations.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentOperations.java
new file mode 100644
index 0000000..12d9fff
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentOperations.java
@@ -0,0 +1,79 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+/**
+ *
+ * Generates the current operations for the tablet
+ *
+ * @since 2.0.0
+ *
+ */
+public class CurrentOperations {
+
+  // Variable names become JSON keys
+  public String name, tablet, tableID;
+  public long entries;
+  public double ingest, query;
+  public Double minorStdDev, minorAvgES, majorStdDev, majorAvgES, minorAvg, majorAvg;
+
+  public CurrentOperations() {}
+
+  /**
+   * Stores the current operations of the tablet
+   *
+   * @param name
+   *          Table name
+   * @param ID
+   *          Table ID
+   * @param tablet
+   *          Tablet string
+   * @param entries
+   *          Number of entries
+   * @param ingest
+   *          Number of ingest
+   * @param query
+   *          Number of queries
+   * @param minorAvg
+   *          Minor compaction average
+   * @param minorStdDev
+   *          Minor compaction standard deviation
+   * @param minorAvgES
+   *          Minor compaction average ES
+   * @param majorAvg
+   *          Major compaction average
+   * @param majorStdDev
+   *          Major compaction standard deviation
+   * @param majorAvgES
+   *          Major compaction average ES
+   */
+  public CurrentOperations(String name, String ID, String tablet, long entries, double ingest, double query, Double minorAvg, Double minorStdDev,
+      Double minorAvgES, Double majorAvg, Double majorStdDev, Double majorAvgES) {
+    this.name = name;
+    this.tableID = ID;
+    this.tablet = tablet;
+    this.entries = entries;
+    this.ingest = ingest;
+    this.query = query;
+    this.minorStdDev = minorStdDev;
+    this.minorAvgES = minorAvgES;
+    this.majorStdDev = majorStdDev;
+    this.majorAvgES = majorAvgES;
+    this.minorAvg = minorAvg;
+    this.majorAvg = majorAvg;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentTabletResults.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentTabletResults.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentTabletResults.java
new file mode 100644
index 0000000..1af44e8
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/CurrentTabletResults.java
@@ -0,0 +1,51 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+/**
+ *
+ * Generates the current results of the tablet
+ *
+ * @since 2.0.0
+ *
+ */
+public class CurrentTabletResults {
+
+  // Variable names become JSON keys
+  public Double currentMinorAvg, currentMinorStdDev, currentMajorAvg, currentMajorStdDev;
+
+  public CurrentTabletResults() {}
+
+  /**
+   * Stores new current results for the tablet
+   *
+   * @param currentMinorAvg
+   *          minor compaction average
+   * @param currentMinorStdDev
+   *          minor compaction standard deviation
+   * @param currentMajorAvg
+   *          major compaction average
+   * @param currentMajorStdDev
+   *          major compaction standard deviation
+   */
+  public CurrentTabletResults(Double currentMinorAvg, Double currentMinorStdDev, Double currentMajorAvg, Double currentMajorStdDev) {
+    this.currentMinorAvg = currentMinorAvg;
+    this.currentMinorStdDev = currentMinorStdDev;
+    this.currentMajorAvg = currentMajorAvg;
+    this.currentMajorStdDev = currentMajorStdDev;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerInformation.java
new file mode 100644
index 0000000..5d73ff7
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerInformation.java
@@ -0,0 +1,57 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ *
+ * Generates a dead tserver information
+ *
+ * @since 2.0.0
+ *
+ */
+public class DeadServerInformation {
+
+  // Variable names become JSON keys
+  @XmlAttribute
+  public String server;
+
+  @XmlAttribute
+  public long lastStatus;
+
+  @XmlAttribute
+  public String status;
+
+  public DeadServerInformation() {}
+
+  /**
+   * Stores a new dead tserver
+   *
+   * @param server
+   *          Location of the tserver
+   * @param lastStatus
+   *          Last know status of the tserver
+   * @param status
+   *          Current status of the tserver
+   */
+  public DeadServerInformation(String server, long lastStatus, String status) {
+    this.server = server;
+    this.lastStatus = lastStatus;
+    this.status = status;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerList.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerList.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerList.java
new file mode 100644
index 0000000..00f9a8f
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/DeadServerList.java
@@ -0,0 +1,50 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Generates a list of dead tservers
+ *
+ * @since 2.0.0
+ *
+ */
+public class DeadServerList {
+
+  // Variable names become JSON keys
+  public List<DeadServerInformation> deadTabletServer;
+
+  /**
+   * Initializes the dead tserver list
+   */
+  public DeadServerList() {
+    deadTabletServer = new ArrayList<>();
+  }
+
+  /**
+   * Adds a new dead tserver to the list
+   *
+   * @param deadTabletServer
+   *          Dead tserver to add
+   */
+  public void addDeadServer(DeadServerInformation deadTabletServer) {
+    this.deadTabletServer.add(deadTabletServer);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerShuttingDownInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerShuttingDownInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerShuttingDownInformation.java
new file mode 100644
index 0000000..17edd60
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerShuttingDownInformation.java
@@ -0,0 +1,45 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ *
+ * Generates a tserver shutting down
+ *
+ * @since 2.0.0
+ *
+ */
+public class ServerShuttingDownInformation {
+
+  // Variable names become JSON keys
+  @XmlAttribute
+  public String id;
+
+  public ServerShuttingDownInformation() {}
+
+  /**
+   * Stores ID of the tserver shutting down
+   *
+   * @param id
+   *          ID of the tserver shutting down
+   */
+  public ServerShuttingDownInformation(String id) {
+    this.id = id;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStat.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStat.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStat.java
new file mode 100644
index 0000000..db0943c
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStat.java
@@ -0,0 +1,54 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+/**
+ *
+ * Stores the server stats
+ *
+ * @since 2.0.0
+ *
+ */
+public class ServerStat {
+
+  // Variable names become JSON keys
+  public int max;
+  public boolean adjustMax;
+  public float significance;
+  public String description, name;
+  public boolean derived;
+
+  public ServerStat() {}
+
+  public ServerStat(int max, boolean adjustMax, float significance, String description, String name) {
+    this.max = max;
+    this.adjustMax = adjustMax;
+    this.significance = significance;
+    this.description = description;
+    this.derived = false;
+    this.name = name;
+  }
+
+  public ServerStat(int max, boolean adjustMax, float significance, String description, boolean derived, String name) {
+    this.max = max;
+    this.adjustMax = adjustMax;
+    this.significance = significance;
+    this.description = description;
+    this.derived = derived;
+    this.name = name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStats.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStats.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStats.java
new file mode 100644
index 0000000..342932c
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServerStats.java
@@ -0,0 +1,50 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Stores maximum and minimum numbers for server stats in a list
+ *
+ * @since 2.0.0
+ *
+ */
+public class ServerStats {
+
+  // Variable names become JSON keys
+  public List<ServerStat> serverStats;
+
+  /**
+   * Initializes stats list
+   */
+  public ServerStats() {
+    serverStats = new ArrayList<>();
+  }
+
+  /**
+   * Adds a new stat to the list
+   *
+   * @param stat
+   *          Stat to add
+   */
+  public void addStats(ServerStat stat) {
+    serverStats.add(stat);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServersShuttingDown.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServersShuttingDown.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServersShuttingDown.java
new file mode 100644
index 0000000..15c1459
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/ServersShuttingDown.java
@@ -0,0 +1,50 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * Generates a list of servers shutting down
+ *
+ * @since 2.0.0
+ *
+ */
+public class ServersShuttingDown {
+
+  // Variable names become JSON keys
+  public List<ServerShuttingDownInformation> server;
+
+  /**
+   * Initalizes tservers list
+   */
+  public ServersShuttingDown() {
+    server = new ArrayList<>();
+  }
+
+  /**
+   * Adds a new tserver to the list
+   *
+   * @param server
+   *          TServer to add
+   */
+  public void addServerShuttingDown(ServerShuttingDownInformation server) {
+    this.server.add(server);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServer.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServer.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServer.java
new file mode 100644
index 0000000..5abb754
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServer.java
@@ -0,0 +1,49 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import org.apache.accumulo.core.master.thrift.TableInfo;
+import org.apache.accumulo.core.master.thrift.TabletServerStatus;
+
+/**
+ *
+ * To use for XML Resource
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServer {
+
+  // Variable names become JSON keys
+  public TabletServerInformation server;
+
+  public TabletServer() {
+    server = new TabletServerInformation();
+  }
+
+  public TabletServer(TabletServerInformation server) {
+    this.server = server;
+  }
+
+  public TabletServer(TabletServerStatus status) {
+    server = new TabletServerInformation(status);
+  }
+
+  public void updateTabletServerInfo(TabletServerStatus status, TableInfo summary) {
+    server.updateTabletServerInfo(status, summary);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerDetailInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerDetailInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerDetailInformation.java
new file mode 100644
index 0000000..7d3db3d
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerDetailInformation.java
@@ -0,0 +1,55 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+/**
+ *
+ * Generates tserver detail as JSON object
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServerDetailInformation {
+
+  // Variable names become JSON keys
+  public int hostedTablets, minors, majors, splits;
+  public long entries;
+
+  public TabletServerDetailInformation() {}
+
+  /**
+   * Store new tserver details
+   *
+   * @param hostedTablets
+   *          Number of hosted tablets
+   * @param entries
+   *          Number of entries
+   * @param minors
+   *          Number of minor compactions
+   * @param majors
+   *          Number of major compactions
+   * @param splits
+   *          Number of splits
+   */
+  public TabletServerDetailInformation(int hostedTablets, long entries, int minors, int majors, int splits) {
+    this.hostedTablets = hostedTablets;
+    this.entries = entries;
+    this.minors = minors;
+    this.majors = majors;
+    this.splits = splits;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerInformation.java
new file mode 100644
index 0000000..c859da1
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerInformation.java
@@ -0,0 +1,143 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAttribute;
+
+import org.apache.accumulo.core.master.thrift.RecoveryStatus;
+import org.apache.accumulo.core.master.thrift.TableInfo;
+import org.apache.accumulo.core.master.thrift.TabletServerStatus;
+import org.apache.accumulo.monitor.Monitor;
+import org.apache.accumulo.monitor.rest.api.table.CompactionsList;
+import org.apache.accumulo.monitor.rest.api.table.CompactionsTypes;
+import org.apache.accumulo.monitor.rest.api.trace.RecoveryStatusInformation;
+import org.apache.accumulo.server.util.TableInfoUtil;
+
+/**
+ *
+ * Generates tserver information
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServerInformation {
+
+  // Variable names become JSON keys
+  @XmlAttribute(name = "id")
+  public String server;
+
+  public String hostname;
+  public long lastContact;
+  public double osload;
+
+  public CompactionsTypes compactions;
+
+  public int tablets;
+  public double ingest, query, ingestMB, queryMB;
+  public Integer scans; // For backwards compatibility, has same information as scansRunning
+  public Double scansessions;
+  public Double scanssessions; // For backwards compatibility
+  public long holdtime;
+
+  // New variables
+
+  public String ip;
+  private Integer scansRunning, scansQueued, minorRunning, minorQueued, majorRunning, majorQueued;
+  private CompactionsList scansCompacting, major, minor; // if scans is removed, change scansCompacting to scans
+  public long entries, lookups, indexCacheHits, indexCacheRequests, dataCacheHits, dataCacheRequests;
+  public double indexCacheHitRate, dataCacheHitRate;
+  public List<RecoveryStatusInformation> logRecoveries;
+
+  public TabletServerInformation() {}
+
+  /**
+   * Generate tserver information from thrift status
+   *
+   * @param thriftStatus
+   *          Thrift status to obtain information
+   */
+  public TabletServerInformation(TabletServerStatus thriftStatus) {
+    TableInfo summary = TableInfoUtil.summarizeTableStats(thriftStatus);
+    updateTabletServerInfo(thriftStatus, summary);
+  }
+
+  /**
+   * Generate tserver information from thrift status and table summary
+   *
+   * @param thriftStatus
+   *          Thrift status to obtain information
+   * @param summary
+   *          Table info summary
+   */
+  public void updateTabletServerInfo(TabletServerStatus thriftStatus, TableInfo summary) {
+
+    long now = System.currentTimeMillis();
+
+    this.server = this.ip = this.hostname = thriftStatus.name;
+    this.tablets = summary.tablets;
+    this.lastContact = now - thriftStatus.lastContact;
+    this.entries = summary.recs;
+    this.ingest = summary.ingestRate;
+    this.query = summary.queryRate;
+
+    this.holdtime = thriftStatus.holdTime;
+
+    this.scansRunning = summary.scans != null ? summary.scans.running : null;
+    this.scansQueued = summary.scans != null ? summary.scans.queued : null;
+
+    this.scans = this.scansRunning;
+
+    this.scansCompacting = new CompactionsList(this.scansRunning, this.scansQueued);
+
+    this.minorRunning = summary.minors != null ? summary.minors.running : null;
+    this.minorQueued = summary.minors != null ? summary.minors.running : null;
+
+    this.minor = new CompactionsList(this.minorRunning, this.minorQueued);
+
+    this.majorRunning = summary.majors != null ? summary.majors.running : null;
+    this.majorQueued = summary.majors != null ? summary.majors.running : null;
+
+    this.major = new CompactionsList(this.majorRunning, this.majorQueued);
+
+    this.compactions = new CompactionsTypes(scansCompacting, major, minor);
+
+    this.osload = thriftStatus.osLoad;
+    this.lookups = thriftStatus.lookups;
+
+    this.dataCacheHits = thriftStatus.dataCacheHits;
+    this.dataCacheRequests = thriftStatus.dataCacheRequest;
+    this.indexCacheHits = thriftStatus.indexCacheHits;
+    this.indexCacheRequests = thriftStatus.indexCacheRequest;
+
+    this.indexCacheHitRate = this.indexCacheHits / (double) Math.max(this.indexCacheRequests, 1);
+    this.dataCacheHitRate = this.dataCacheHits / (double) Math.max(this.dataCacheRequests, 1);
+
+    this.ingestMB = summary.ingestByteRate;
+    this.queryMB = summary.queryByteRate;
+
+    this.scansessions = Monitor.getLookupRate();
+    this.scanssessions = this.scansessions; // For backwards compatibility
+
+    this.logRecoveries = new ArrayList<>(thriftStatus.logSorts.size());
+    for (RecoveryStatus recovery : thriftStatus.logSorts) {
+      logRecoveries.add(new RecoveryStatusInformation(recovery));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerResource.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerResource.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerResource.java
new file mode 100644
index 0000000..b04f9ec
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerResource.java
@@ -0,0 +1,334 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.lang.management.ManagementFactory;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.impl.ClientContext;
+import org.apache.accumulo.core.client.impl.Tables;
+import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.data.impl.KeyExtent;
+import org.apache.accumulo.core.master.thrift.MasterMonitorInfo;
+import org.apache.accumulo.core.master.thrift.RecoveryStatus;
+import org.apache.accumulo.core.master.thrift.TabletServerStatus;
+import org.apache.accumulo.core.rpc.ThriftUtil;
+import org.apache.accumulo.core.tabletserver.thrift.ActionStats;
+import org.apache.accumulo.core.tabletserver.thrift.TabletClientService;
+import org.apache.accumulo.core.tabletserver.thrift.TabletStats;
+import org.apache.accumulo.core.trace.Tracer;
+import org.apache.accumulo.core.util.AddressUtil;
+import org.apache.accumulo.core.zookeeper.ZooUtil;
+import org.apache.accumulo.monitor.Monitor;
+import org.apache.accumulo.monitor.rest.api.BasicResource;
+import org.apache.accumulo.monitor.rest.api.master.MasterResource;
+import org.apache.accumulo.server.client.HdfsZooInstance;
+import org.apache.accumulo.server.master.state.DeadServerList;
+import org.apache.accumulo.server.util.ActionStatsUpdator;
+
+import com.google.common.net.HostAndPort;
+
+/**
+ *
+ * Generates tserver lists as JSON objects
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServerResource extends BasicResource {
+
+  // Variable names become JSON keys
+  private TabletStats total, historical;
+
+  /**
+   * Generates tserver summary
+   *
+   * @return tserver summary
+   */
+  @GET
+  public TabletServers getTserverSummary() {
+    MasterMonitorInfo mmi = Monitor.getMmi();
+    if (null == mmi) {
+      throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
+    }
+
+    TabletServers tserverInfo = new TabletServers(mmi.tServerInfo.size());
+    for (TabletServerStatus status : mmi.tServerInfo) {
+      tserverInfo.addTablet(new TabletServer(status));
+    }
+
+    tserverInfo.addBadTabletServer(new MasterResource().getTables());
+
+    return tserverInfo;
+  }
+
+  /**
+   * REST call to clear dead servers from list
+   *
+   * @param server
+   *          Dead server to clear
+   */
+  @POST
+  @Consumes(MediaType.TEXT_PLAIN)
+  public void clearDeadServer(@QueryParam("server") String server) throws Exception {
+    DeadServerList obit = new DeadServerList(ZooUtil.getRoot(Monitor.getContext().getInstance()) + Constants.ZDEADTSERVERS);
+    obit.delete(server);
+  }
+
+  /**
+   * Generates a recovery tserver list
+   *
+   * @return Recovery tserver list
+   */
+  @Path("/recovery")
+  @GET
+  public Map<String,List<Map<String,String>>> getTserverRecovery() {
+
+    Map<String,List<Map<String,String>>> jsonObj = new HashMap<String,List<Map<String,String>>>();
+    List<Map<String,String>> recoveryList = new ArrayList<>();
+    Map<String,String> recoveryObj = new HashMap<String,String>();
+
+    MasterMonitorInfo mmi = Monitor.getMmi();
+    if (null == mmi) {
+      throw new WebApplicationException(Status.INTERNAL_SERVER_ERROR);
+    }
+
+    for (TabletServerStatus server : mmi.tServerInfo) {
+      if (server.logSorts != null) {
+        for (RecoveryStatus recovery : server.logSorts) {
+          recoveryObj.put("server", AddressUtil.parseAddress(server.name, false).getHostText());
+          recoveryObj.put("log", recovery.name);
+          recoveryObj.put("time", Long.toString((long) recovery.runtime));
+          recoveryObj.put("copySort", Double.toString(recovery.progress));
+
+          recoveryList.add(recoveryObj);
+        }
+      }
+    }
+
+    jsonObj.put("recoveryList", recoveryList);
+
+    return jsonObj;
+  }
+
+  /**
+   * Generates details for the selected tserver
+   *
+   * @param tserverAddr
+   *          TServer name
+   * @return TServer details
+   */
+  @Path("/{address}")
+  @GET
+  public TabletServerSummary getTserverDetails(@PathParam("address") String tserverAddr) throws Exception {
+
+    String tserverAddress = tserverAddr;
+
+    boolean tserverExists = false;
+    if (tserverAddress != null && tserverAddress.isEmpty() == false) {
+      for (TabletServerStatus ts : Monitor.getMmi().getTServerInfo()) {
+        if (tserverAddress.equals(ts.getName())) {
+          tserverExists = true;
+          break;
+        }
+      }
+    }
+
+    if (tserverAddress == null || tserverAddress.isEmpty() || tserverExists == false) {
+
+      return null;
+    }
+
+    double totalElapsedForAll = 0;
+    double splitStdDev = 0;
+    double minorStdDev = 0;
+    double minorQueueStdDev = 0;
+    double majorStdDev = 0;
+    double majorQueueStdDev = 0;
+    double currentMinorAvg = 0;
+    double currentMajorAvg = 0;
+    double currentMinorStdDev = 0;
+    double currentMajorStdDev = 0;
+    total = new TabletStats(null, new ActionStats(), new ActionStats(), new ActionStats(), 0, 0, 0, 0);
+    HostAndPort address = HostAndPort.fromString(tserverAddress);
+    historical = new TabletStats(null, new ActionStats(), new ActionStats(), new ActionStats(), 0, 0, 0, 0);
+    List<TabletStats> tsStats = new ArrayList<>();
+
+    try {
+      ClientContext context = Monitor.getContext();
+      TabletClientService.Client client = ThriftUtil.getClient(new TabletClientService.Client.Factory(), address, context);
+      try {
+        for (String tableId : Monitor.getMmi().tableMap.keySet()) {
+          tsStats.addAll(client.getTabletStats(Tracer.traceInfo(), context.rpcCreds(), tableId));
+        }
+        historical = client.getHistoricalStats(Tracer.traceInfo(), context.rpcCreds());
+      } finally {
+        ThriftUtil.returnClient(client);
+      }
+    } catch (Exception e) {
+      return null;
+    }
+
+    List<CurrentOperations> currentOps = doCurrentOperations(tsStats);
+
+    if (total.minors.num != 0)
+      currentMinorAvg = (long) (total.minors.elapsed / total.minors.num);
+    if (total.minors.elapsed != 0 && total.minors.num != 0)
+      currentMinorStdDev = stddev(total.minors.elapsed, total.minors.num, total.minors.sumDev);
+    if (total.majors.num != 0)
+      currentMajorAvg = total.majors.elapsed / total.majors.num;
+    if (total.majors.elapsed != 0 && total.majors.num != 0 && total.majors.elapsed > total.majors.num)
+      currentMajorStdDev = stddev(total.majors.elapsed, total.majors.num, total.majors.sumDev);
+
+    ActionStatsUpdator.update(total.minors, historical.minors);
+    ActionStatsUpdator.update(total.majors, historical.majors);
+    totalElapsedForAll += total.majors.elapsed + historical.splits.elapsed + total.minors.elapsed;
+
+    minorStdDev = stddev(total.minors.elapsed, total.minors.num, total.minors.sumDev);
+    minorQueueStdDev = stddev(total.minors.queueTime, total.minors.num, total.minors.queueSumDev);
+    majorStdDev = stddev(total.majors.elapsed, total.majors.num, total.majors.sumDev);
+    majorQueueStdDev = stddev(total.majors.queueTime, total.majors.num, total.majors.queueSumDev);
+    splitStdDev = stddev(historical.splits.num, historical.splits.elapsed, historical.splits.sumDev);
+
+    TabletServerDetailInformation details = doDetails(address, tsStats.size());
+
+    List<AllTimeTabletResults> allTime = doAllTimeResults(majorQueueStdDev, minorQueueStdDev, totalElapsedForAll, splitStdDev, majorStdDev, minorStdDev);
+
+    CurrentTabletResults currentRes = doCurrentTabletResults(currentMinorAvg, currentMinorStdDev, currentMajorAvg, currentMajorStdDev);
+
+    TabletServerSummary tserverDetails = new TabletServerSummary(details, allTime, currentRes, currentOps);
+
+    return tserverDetails;
+  }
+
+  private static final int concurrentScans = Monitor.getContext().getConfiguration().getCount(Property.TSERV_READ_AHEAD_MAXCONCURRENT);
+
+  /**
+   * Generates the server stats
+   *
+   * @return Server stat list
+   */
+  @Path("/serverStats")
+  @GET
+  public ServerStats getServerStats() {
+
+    ServerStats stats = new ServerStats();
+
+    stats.addStats(new ServerStat(ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors(), true, 100, "OS Load", "osload"));
+    stats.addStats(new ServerStat(1000, true, 1, "Ingest Entries", "ingest"));
+    stats.addStats(new ServerStat(10000, true, 1, "Scan Entries", "query"));
+    stats.addStats(new ServerStat(10, true, 10, "Ingest MB", "ingestMB"));
+    stats.addStats(new ServerStat(5, true, 10, "Scan MB", "queryMB"));
+    stats.addStats(new ServerStat(concurrentScans * 2, false, 1, "Running Scans", "scans"));
+    stats.addStats(new ServerStat(50, true, 10, "Scan Sessions", "scansessions"));
+    stats.addStats(new ServerStat(60000, false, 1, "Hold Time", "holdtime"));
+    stats.addStats(new ServerStat(1, false, 100, "Overall Avg", true, "allavg"));
+    stats.addStats(new ServerStat(1, false, 100, "Overall Max", true, "allmax"));
+
+    return stats;
+  }
+
+  private TabletServerDetailInformation doDetails(HostAndPort address, int numTablets) {
+
+    return new TabletServerDetailInformation(numTablets, total.numEntries, total.minors.status, total.majors.status, historical.splits.status);
+  }
+
+  private List<AllTimeTabletResults> doAllTimeResults(double majorQueueStdDev, double minorQueueStdDev, double totalElapsedForAll, double splitStdDev,
+      double majorStdDev, double minorStdDev) {
+
+    List<AllTimeTabletResults> allTime = new ArrayList<>();
+
+    // Minor Compaction Operation
+    allTime.add(new AllTimeTabletResults("Minor&nbsp;Compaction", total.minors.num, total.minors.fail,
+        total.minors.num != 0 ? (total.minors.queueTime / total.minors.num) : null, minorQueueStdDev,
+        total.minors.num != 0 ? (total.minors.elapsed / total.minors.num) : null, minorStdDev, total.minors.elapsed));
+
+    // Major Compaction Operation
+    allTime.add(new AllTimeTabletResults("Major&nbsp;Compaction", total.majors.num, total.majors.fail,
+        total.majors.num != 0 ? (total.majors.queueTime / total.majors.num) : null, majorQueueStdDev,
+        total.majors.num != 0 ? (total.majors.elapsed / total.majors.num) : null, majorStdDev, total.majors.elapsed));
+    // Split Operation
+    allTime.add(new AllTimeTabletResults("Split", historical.splits.num, historical.splits.fail, null, null,
+        historical.splits.num != 0 ? (historical.splits.elapsed / historical.splits.num) : null, splitStdDev, historical.splits.elapsed));
+
+    return allTime;
+  }
+
+  private CurrentTabletResults doCurrentTabletResults(double currentMinorAvg, double currentMinorStdDev, double currentMajorAvg, double currentMajorStdDev) {
+
+    return new CurrentTabletResults(currentMinorAvg, currentMinorStdDev, currentMajorAvg, currentMajorStdDev);
+  }
+
+  private List<CurrentOperations> doCurrentOperations(List<TabletStats> tsStats) throws Exception {
+
+    Map<String,String> tidToNameMap = Tables.getIdToNameMap(HdfsZooInstance.getInstance());
+
+    List<CurrentOperations> currentOperations = new ArrayList<>();
+
+    for (TabletStats info : tsStats) {
+      if (info.extent == null) {
+        historical = info;
+        continue;
+      }
+      total.numEntries += info.numEntries;
+      ActionStatsUpdator.update(total.minors, info.minors);
+      ActionStatsUpdator.update(total.majors, info.majors);
+
+      KeyExtent extent = new KeyExtent(info.extent);
+      String tableId = extent.getTableId();
+      MessageDigest digester = MessageDigest.getInstance("MD5");
+      if (extent.getEndRow() != null && extent.getEndRow().getLength() > 0) {
+        digester.update(extent.getEndRow().getBytes(), 0, extent.getEndRow().getLength());
+      }
+      String obscuredExtent = Base64.getEncoder().encodeToString(digester.digest());
+      String displayExtent = String.format("[%s]", obscuredExtent);
+
+      String tableName = Tables.getPrintableTableNameFromId(tidToNameMap, tableId);
+
+      currentOperations.add(new CurrentOperations(tableName, tableId, displayExtent, info.numEntries, info.ingestRate, info.queryRate,
+          info.minors.num != 0 ? info.minors.elapsed / info.minors.num : null, stddev(info.minors.elapsed, info.minors.num, info.minors.sumDev),
+          info.minors.elapsed != 0 ? info.minors.count / info.minors.elapsed : null, info.majors.num != 0 ? info.majors.elapsed / info.majors.num : null,
+          stddev(info.majors.elapsed, info.majors.num, info.majors.sumDev), info.majors.elapsed != 0 ? info.majors.count / info.majors.elapsed : null));
+    }
+
+    return currentOperations;
+  }
+
+  private static double stddev(double elapsed, double num, double sumDev) {
+    if (num != 0) {
+      double average = elapsed / num;
+      return Math.sqrt((sumDev / num) - (average * average));
+    }
+    return 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerSummary.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerSummary.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerSummary.java
new file mode 100644
index 0000000..70b0363
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerSummary.java
@@ -0,0 +1,67 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.List;
+
+/**
+ *
+ * Generates a summary for the tserver
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServerSummary {
+
+  // Variable names become json keys
+  public TabletServerDetailInformation details;
+  public List<AllTimeTabletResults> allTimeTabletResults;
+  public CurrentTabletResults currentTabletOperationResults;
+  public List<CurrentOperations> currentOperations;
+
+  public TabletServerSummary() {}
+
+  /**
+   * Generates tserver information
+   *
+   * @param details
+   *          TServer details
+   * @param allTimeResults
+   *          TServer all time results
+   * @param currentResults
+   *          TServer current results
+   * @param currentOperations
+   *          TServer current operations
+   */
+  public TabletServerSummary(TabletServerDetailInformation details, List<AllTimeTabletResults> allTimeResults, CurrentTabletResults currentResults,
+      List<CurrentOperations> currentOperations) {
+    this.details = details;
+    this.allTimeTabletResults = allTimeResults;
+    this.currentTabletOperationResults = currentResults;
+    this.currentOperations = currentOperations;
+  }
+
+  /**
+   * Adds new current operations for the tserver
+   *
+   * @param currentOperations
+   *          Current Operation to add
+   */
+  public void addcurrentOperations(CurrentOperations currentOperations) {
+    this.currentOperations.add(currentOperations);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerWithTableInformation.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerWithTableInformation.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerWithTableInformation.java
new file mode 100644
index 0000000..203ad31
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServerWithTableInformation.java
@@ -0,0 +1,46 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import org.apache.accumulo.monitor.rest.api.table.TableInformation;
+
+/**
+ *
+ * Generates a tserver with table information
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServerWithTableInformation {
+
+  // Variable names become JSON keys
+  public TabletServerInformation tserver;
+  public TableInformation table;
+
+  /**
+   * Stores a new tserver
+   *
+   * @param tserverInfo
+   *          Tserver to add
+   * @param tableInfo
+   *          Table information
+   */
+  public TabletServerWithTableInformation(TabletServerInformation tserverInfo, TableInformation tableInfo) {
+    this.tserver = tserverInfo;
+    this.table = tableInfo;
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServers.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServers.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServers.java
new file mode 100644
index 0000000..155a71a
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/tserver/TabletServers.java
@@ -0,0 +1,66 @@
+/*
+ * 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.monitor.rest.api.tserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.accumulo.monitor.rest.api.master.MasterInformation;
+
+/**
+ *
+ * Generates a list of servers, bad servers, and dead servers
+ *
+ * @since 2.0.0
+ *
+ */
+public class TabletServers {
+
+  // Variable names become JSON keys
+  public List<TabletServerInformation> servers;
+  public List<BadTabletServerInformation> badServers;
+  public List<DeadServerInformation> deadServers;
+
+  public TabletServers() {
+    servers = new ArrayList<>();
+  }
+
+  public TabletServers(int size) {
+    servers = new ArrayList<>(size);
+  }
+
+  /**
+   * Adds bad and dead servers to the list
+   *
+   * @param info
+   *          Master information to get bad and dead server information
+   */
+  public void addBadTabletServer(MasterInformation info) {
+    badServers = info.badTabletServers.badTabletServer;
+    deadServers = info.deadTabletServers.deadTabletServer;
+  }
+
+  /**
+   * Adds new tservers to the list
+   *
+   * @param tablet
+   *          New tserver
+   */
+  public void addTablet(TabletServer tablet) {
+    servers.add(tablet.server);
+  }
+}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/0ca5cd33/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/xml/Totals.java
----------------------------------------------------------------------
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/xml/Totals.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/xml/Totals.java
new file mode 100644
index 0000000..52b92a9
--- /dev/null
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/api/xml/Totals.java
@@ -0,0 +1,53 @@
+/*
+ * 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.monitor.rest.api.xml;
+
+/**
+ *
+ * Generates the totals for XML summary
+ *
+ * @since 2.0.0
+ *
+ */
+public class Totals {
+
+  // Variable names become JSON keys
+  public double ingestrate, queryrate, diskrate = 0.0;
+  public long numentries;
+
+  public Totals() {
+    ingestrate = 0.0;
+    queryrate = 0.0;
+    numentries = 0l;
+  }
+
+  /**
+   * Initializes totals
+   *
+   * @param ingestrate
+   *          Total ingest rate
+   * @param queryrate
+   *          Total query rate
+   * @param numentries
+   *          Total number of entries
+   */
+  public Totals(double ingestrate, double queryrate, long numentries) {
+    this.ingestrate = ingestrate;
+    this.queryrate = queryrate;
+    this.numentries = numentries;
+  }
+}


Mime
View raw message