private void doDeadTserverList(HttpServletRequest req, StringBuilder sb) {
   MasterMonitorInfo mmi = Monitor.getMmi();
   if (mmi != null) {
     List<DeadServer> obit = mmi.deadTabletServers;
     Table deadTServerList = new Table("deaddtservers", "Dead&nbsp;Tablet&nbsp;Servers", "error");
     deadTServerList.setSubCaption("The following tablet servers are no longer reachable.");
     doDeadServerTable(req, sb, deadTServerList, obit);
   }
 }
 private void doCurrentTabletOps(
     HttpServletRequest req,
     StringBuilder sb,
     double currentMinorAvg,
     double currentMinorStdDev,
     double currentMajorAvg,
     double currentMajorStdDev) {
   Table currentTabletOps =
       new Table("currentTabletOps", "Current&nbsp;Tablet&nbsp;Operation&nbsp;Results");
   currentTabletOps.addSortableColumn("Minor&nbsp;Average", new SecondType(), null);
   currentTabletOps.addSortableColumn("Minor&nbsp;Std&nbsp;Dev", new SecondType(), null);
   currentTabletOps.addSortableColumn("Major&nbsp;Avg", new SecondType(), null);
   currentTabletOps.addSortableColumn("Major&nbsp;Std&nbsp;Dev", new SecondType(), null);
   currentTabletOps.addRow(
       currentMinorAvg, currentMinorStdDev, currentMajorAvg, currentMajorStdDev);
   currentTabletOps.generate(req, sb);
 }
 private void doBadTserverList(HttpServletRequest req, StringBuilder sb) {
   if (Monitor.getMmi() != null && !Monitor.getMmi().badTServers.isEmpty()) {
     Table badTServerList =
         new Table("badtservers", "Non-Functioning&nbsp;Tablet&nbsp;Servers", "error");
     badTServerList.setSubCaption(
         "The following tablet servers reported a status other than Online.");
     badTServerList.addSortableColumn("Tablet&nbsp;Server");
     badTServerList.addSortableColumn("Tablet&nbsp;Server&nbsp;Status");
     for (Entry<String, Byte> badserver : Monitor.getMmi().badTServers.entrySet())
       badTServerList.addRow(
           badserver.getKey(), TabletServerState.getStateById(badserver.getValue()).name());
     badTServerList.generate(req, sb);
   }
 }
 private void doDetailTable(
     HttpServletRequest req,
     StringBuilder sb,
     InetSocketAddress address,
     int numTablets,
     TabletStats total,
     TabletStats historical) {
   Table detailTable = new Table("tServerDetail", "Details");
   detailTable.setSubCaption(address.getHostName() + ":" + address.getPort());
   detailTable.addSortableColumn("Hosted&nbsp;Tablets", new NumberType<Integer>(), null);
   detailTable.addSortableColumn("Entries", new NumberType<Long>(), null);
   detailTable.addSortableColumn("Minor&nbsp;Compacting", new NumberType<Integer>(), null);
   detailTable.addSortableColumn("Major&nbsp;Compacting", new NumberType<Integer>(), null);
   detailTable.addSortableColumn("Splitting", new NumberType<Integer>(), null);
   detailTable.addRow(
       numTablets,
       total.numEntries,
       total.minors.status,
       total.majors.status,
       historical.splits.status);
   detailTable.generate(req, sb);
 }
 public static void doDeadServerTable(
     HttpServletRequest req, StringBuilder sb, Table deadTServerList, List<DeadServer> obit) {
   if (obit != null && !obit.isEmpty()) {
     deadTServerList.addSortableColumn("Server");
     deadTServerList.addSortableColumn(
         "Last&nbsp;Updated", new DateTimeType(DateFormat.MEDIUM, DateFormat.SHORT), null);
     deadTServerList.addSortableColumn("Event");
     deadTServerList.addUnsortableColumn("Clear");
     for (DeadServer dead : obit)
       deadTServerList.addRow(
           TServerLinkType.displayName(dead.server),
           dead.lastStatus,
           dead.status,
           "<a href='/op?action=clearDeadServer&redir="
               + currentPage(req)
               + "&server="
               + encode(dead.server)
               + "'>clear</a>");
     deadTServerList.generate(req, sb);
   }
 }
  @Override
  protected void pageBody(HttpServletRequest req, HttpServletResponse response, StringBuilder sb)
      throws Exception {
    String tserverAddress = req.getParameter("s");

    // Check to make sure tserver is a known address
    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) {
      doBadTserverList(req, sb);

      doDeadTserverList(req, sb);

      ArrayList<TabletServerStatus> tservers = new ArrayList<TabletServerStatus>();
      if (Monitor.getMmi() != null) tservers.addAll(Monitor.getMmi().tServerInfo);

      Table tServerList = new Table("tservers", "Tablet&nbsp;Servers");
      tServerList.setSubCaption(
          "Click on the <span style='color: #0000ff;'>server address</span> to view detailed performance statistics for that server.");

      doTserverList(req, sb, tservers, null, tServerList);
      return;
    }

    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;
    TabletStats total =
        new TabletStats(null, new ActionStats(), new ActionStats(), new ActionStats(), 0, 0, 0, 0);

    InetSocketAddress address = AddressUtil.parseAddress(tserverAddress, -1);
    TabletStats historical =
        new TabletStats(null, new ActionStats(), new ActionStats(), new ActionStats(), 0, 0, 0, 0);
    List<TabletStats> tsStats = new ArrayList<TabletStats>();
    try {
      TabletClientService.Client client =
          ThriftUtil.getClient(
              new TabletClientService.Client.Factory(), address, Monitor.getSystemConfiguration());
      try {
        for (String tableId : Monitor.getMmi().tableMap.keySet()) {
          tsStats.addAll(
              client.getTabletStats(
                  Tracer.traceInfo(),
                  SystemCredentials.get().toThrift(Monitor.getInstance()),
                  tableId));
        }
        historical =
            client.getHistoricalStats(
                Tracer.traceInfo(), SystemCredentials.get().toThrift(Monitor.getInstance()));
      } finally {
        ThriftUtil.returnClient(client);
      }
    } catch (Exception e) {
      banner(sb, "error", "No Such Tablet ServerAvailable");
      log.error(e, e);
      return;
    }

    Table perTabletResults = new Table("perTabletResults", "Detailed&nbsp;Current&nbsp;Operations");
    perTabletResults.setSubCaption("Per-tablet&nbsp;Details");
    perTabletResults.addSortableColumn("Table", new TableLinkType(), null);
    perTabletResults.addSortableColumn("Tablet");
    perTabletResults.addSortableColumn("Entries", new NumberType<Long>(), null);
    perTabletResults.addSortableColumn("Ingest", new NumberType<Long>(), null);
    perTabletResults.addSortableColumn("Query", new NumberType<Long>(), null);
    perTabletResults.addSortableColumn("Minor&nbsp;Avg", new SecondType(), null);
    perTabletResults.addSortableColumn("Minor&nbsp;Std&nbsp;Dev", new SecondType(), null);
    perTabletResults.addSortableColumn("Minor&nbsp;Avg&nbsp;e/s", new NumberType<Double>(), null);
    perTabletResults.addSortableColumn("Major&nbsp;Avg", new SecondType(), null);
    perTabletResults.addSortableColumn("Major&nbsp;Std&nbsp;Dev", new SecondType(), null);
    perTabletResults.addSortableColumn("Major&nbsp;Avg&nbsp;e/s", new NumberType<Double>(), null);

    for (TabletStats info : tsStats) {
      if (info.extent == null) {
        historical = info;
        continue;
      }
      total.numEntries += info.numEntries;
      TabletStatsKeeper.update(total.minors, info.minors);
      TabletStatsKeeper.update(total.majors, info.majors);

      KeyExtent extent = new KeyExtent(info.extent);
      String tableId = extent.getTableId().toString();
      MessageDigest digester = MessageDigest.getInstance("MD5");
      if (extent.getEndRow() != null && extent.getEndRow().getLength() > 0) {
        digester.update(extent.getEndRow().getBytes(), 0, extent.getEndRow().getLength());
      }
      String obscuredExtent = new String(Base64.encodeBase64(digester.digest()));
      String displayExtent = String.format("<code>[%s]</code>", obscuredExtent);

      TableRow row = perTabletResults.prepareRow();
      row.add(tableId);
      row.add(displayExtent);
      row.add(info.numEntries);
      row.add(info.ingestRate);
      row.add(info.queryRate);
      row.add(info.minors.num != 0 ? info.minors.elapsed / info.minors.num : null);
      row.add(stddev(info.minors.elapsed, info.minors.num, info.minors.sumDev));
      row.add(info.minors.elapsed != 0 ? info.minors.count / info.minors.elapsed : null);
      row.add(info.majors.num != 0 ? info.majors.elapsed / info.majors.num : null);
      row.add(stddev(info.majors.elapsed, info.majors.num, info.majors.sumDev));
      row.add(info.majors.elapsed != 0 ? info.majors.count / info.majors.elapsed : null);
      perTabletResults.addRow(row);
    }

    // Calculate current averages oldServer adding in historical data
    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);

    // After these += operations, these variables are now total for current
    // tablets and historical tablets
    TabletStatsKeeper.update(total.minors, historical.minors);
    TabletStatsKeeper.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);

    doDetailTable(req, sb, address, tsStats.size(), total, historical);
    doAllTimeTable(
        req,
        sb,
        total,
        historical,
        majorQueueStdDev,
        minorQueueStdDev,
        totalElapsedForAll,
        splitStdDev,
        majorStdDev,
        minorStdDev);
    doCurrentTabletOps(
        req, sb, currentMinorAvg, currentMinorStdDev, currentMajorAvg, currentMajorStdDev);
    perTabletResults.generate(req, sb);
  }
  static void doTserverList(
      HttpServletRequest req,
      StringBuilder sb,
      List<TabletServerStatus> tservers,
      String tableId,
      Table tServerList) {
    int guessHighLoad = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
    long now = System.currentTimeMillis();

    double avgLastContact = 0.;
    for (TabletServerStatus status : tservers) {
      avgLastContact += (now - status.lastContact);
    }
    final long MINUTES = 3 * 60 * 1000;
    tServerList.addSortableColumn("Server", new TServerLinkType(), null);
    tServerList.addSortableColumn(
        "Hosted&nbsp;Tablets", new NumberType<Integer>(0, Integer.MAX_VALUE), null);
    tServerList.addSortableColumn(
        "Last&nbsp;Contact",
        new DurationType(0l, (long) Math.min(avgLastContact * 4, MINUTES)),
        null);
    tServerList.addSortableColumn(
        "Entries", new NumberType<Long>(), "The number of key/value pairs.");
    tServerList.addSortableColumn(
        "Ingest",
        new NumberType<Long>(),
        "The number of key/value pairs inserted. (Note that deletes are also 'inserted')");
    tServerList.addSortableColumn(
        "Query",
        new NumberType<Long>(),
        "The number of key/value pairs returned to clients. (Not the number of scans)");
    tServerList.addSortableColumn(
        "Hold&nbsp;Time",
        new DurationType(),
        "The amount of time ingest is suspended waiting for data to be written to disk.");
    tServerList.addSortableColumn(
        "Running<br />Scans",
        new CompactionsType("scans"),
        "The number of scans running and queued on this tablet server.");
    tServerList.addSortableColumn(
        "Minor<br />Compactions",
        new CompactionsType("minor"),
        "The number of minor compactions running and (queued waiting for resources). Minor compactions are the operations where entries are flushed from memory to disk.");
    tServerList.addSortableColumn(
        "Major<br />Compactions",
        new CompactionsType("major"),
        "The number of major compactions running and (queued waiting for resources). "
            + "Major compactions are the operations where many smaller files are grouped into a larger file, eliminating duplicates and cleaning up deletes.");
    tServerList.addSortableColumn(
        "Index Cache<br />Hit Rate", new PercentageType(), "The recent index cache hit rate.");
    tServerList.addSortableColumn(
        "Data Cache<br />Hit Rate", new PercentageType(), "The recent data cache hit rate.");
    tServerList.addSortableColumn(
        "OS&nbsp;Load",
        new NumberType<Double>(0., guessHighLoad * 1., 0., guessHighLoad * 3.),
        "The Unix one minute load average. The average number of processes in the run queue over a one minute interval.");

    log.debug("tableId: " + tableId);
    for (TabletServerStatus status : tservers) {
      if (status == null) status = NO_STATUS;
      TableInfo summary = Monitor.summarizeTableStats(status);
      if (tableId != null) summary = status.tableMap.get(tableId);
      if (summary == null) continue;
      TableRow row = tServerList.prepareRow();
      row.add(status); // add for server name
      row.add(summary.tablets);
      row.add(now - status.lastContact);
      row.add(summary.recs);
      row.add(summary.ingestRate);
      row.add(summary.queryRate);
      row.add(status.holdTime);
      row.add(summary); // add for scans
      row.add(summary); // add for minor compactions
      row.add(summary); // add for major compactions
      double indexCacheHitRate =
          status.indexCacheHits / (double) Math.max(status.indexCacheRequest, 1);
      row.add(indexCacheHitRate);
      double dataCacheHitRate =
          status.dataCacheHits / (double) Math.max(status.dataCacheRequest, 1);
      row.add(dataCacheHitRate);
      row.add(status.osLoad);
      tServerList.addRow(row);
    }
    tServerList.generate(req, sb);
  }
  private void doAllTimeTable(
      HttpServletRequest req,
      StringBuilder sb,
      TabletStats total,
      TabletStats historical,
      double majorQueueStdDev,
      double minorQueueStdDev,
      double totalElapsedForAll,
      double splitStdDev,
      double majorStdDev,
      double minorStdDev) {

    Table opHistoryDetails =
        new Table("opHistoryDetails", "All-Time&nbsp;Tablet&nbsp;Operation&nbsp;Results");
    opHistoryDetails.addSortableColumn("Operation");
    opHistoryDetails.addSortableColumn("Success", new NumberType<Integer>(), null);
    opHistoryDetails.addSortableColumn("Failure", new NumberType<Integer>(), null);
    opHistoryDetails.addSortableColumn("Average<br />Queue&nbsp;Time", new SecondType(), null);
    opHistoryDetails.addSortableColumn(
        "Std.&nbsp;Dev.<br />Queue&nbsp;Time", new SecondType(), null);
    opHistoryDetails.addSortableColumn("Average<br />Time", new SecondType(), null);
    opHistoryDetails.addSortableColumn("Std.&nbsp;Dev.<br />Time", new SecondType(), null);
    opHistoryDetails.addSortableColumn(
        "Percentage&nbsp;Time&nbsp;Spent", new ProgressChartType(totalElapsedForAll), null);

    opHistoryDetails.addRow(
        "Split",
        historical.splits.num,
        historical.splits.fail,
        null,
        null,
        historical.splits.num != 0 ? (historical.splits.elapsed / historical.splits.num) : null,
        splitStdDev,
        historical.splits.elapsed);
    opHistoryDetails.addRow(
        "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);
    opHistoryDetails.addRow(
        "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);
    opHistoryDetails.generate(req, sb);
  }