McStatsReply stats_reply()

in mcrouter/stats.cpp [654:781]


McStatsReply stats_reply(ProxyBase* proxy, folly::StringPiece group_str) {
  auto lockGuard = proxy->stats().lock();

  StatsReply reply;

  if (group_str == "version") {
    reply.addStat("mcrouter-version", MCROUTER_PACKAGE_STRING);
    return reply.getReply();
  }

  auto groups = stat_parse_group_str(group_str);
  if (groups == unknown_stats) {
    McStatsReply errorReply(carbon::Result::CLIENT_ERROR);
    errorReply.message_ref() = "bad stats command";
    return errorReply;
  }

  std::vector<stat_t> stats(num_stats);

  prepare_stats(proxy->router(), stats.data());

  for (unsigned int ii = 0; ii < num_stats; ii++) {
    stat_t* stat = &stats[ii];
    if (stat->group & groups) {
      if (stat->group & rate_stats) {
        reply.addStat(stat->name, rate_stat_to_str(proxy, ii));
      } else if (stat->group & max_stats) {
        reply.addStat(stat->name, max_stat_to_str(proxy, ii));
      } else if (stat->group & max_max_stats) {
        reply.addStat(stat->name, max_max_stat_to_str(proxy, ii));
      } else {
        reply.addStat(stat->name, stat_to_str(stat, nullptr));
      }
    }
  }
  append_pool_stats(proxy->router(), stats);

  if (groups & (basic_stats | all_stats | detailed_stats | ods_stats)) {
    folly::dynamic requestStats(folly::dynamic::object());
    const auto& router = proxy->router();
    for (size_t i = 0; i < router.opts().num_proxies; ++i) {
      const auto proxyRequestStats =
          router.getProxyBase(i)->dumpRequestStats(false /* filterZeroes */);
      for (const auto& k : proxyRequestStats.keys()) {
        requestStats.setDefault(k, 0) += proxyRequestStats[k];
      }
    }

    for (const auto& k : requestStats.keys()) {
      if (requestStats[k].isInt()) {
        reply.addStat(
            k.asString(), folly::to<std::string>(requestStats[k].asInt()));
      } else if (requestStats[k].isDouble()) {
        reply.addStat(
            k.asString(), folly::to<std::string>(requestStats[k].asDouble()));
      } else {
        MC_LOG_FAILURE(
            proxy->router().opts(),
            failure::Category::kOther,
            folly::sformat("Couldn't serialize Carbon stat {}", k.asString()));
      }
    }
  }

  if (groups & server_stats) {
    folly::StringKeyedUnorderedMap<ServerStat> serverStats;
    auto& router = proxy->router();
    for (size_t i = 0; i < router.opts().num_proxies; ++i) {
      router.getProxyBase(i)->destinationMap()->foreachDestinationSynced(
          [&serverStats](const ProxyDestinationBase& pdstn) {
            ProxyDestinationKey key(pdstn);
            auto& stat = serverStats[key.str()];
            stat.isHardTko = pdstn.tracker()->isHardTko();
            stat.isSoftTko = pdstn.tracker()->isSoftTko();
            if (pdstn.stats().results) {
              for (size_t j = 0;
                   j < static_cast<size_t>(carbon::Result::NUM_RESULTS);
                   ++j) {
                stat.results[j] += (*pdstn.stats().results)[j];
              }
            }
            ++stat.states[(size_t)pdstn.stats().state];

            if (pdstn.stats().avgLatency.hasValue()) {
              stat.sumLatencies += pdstn.stats().avgLatency.value();
              ++stat.cntLatencies;
            }

            if (pdstn.stats().retransPerKByte >= 0.0) {
              const auto val = pdstn.stats().retransPerKByte;
              stat.sumRetransPerKByte += val;
              stat.maxRetransPerKByte = std::max(stat.maxRetransPerKByte, val);
              stat.minRetransPerKByte = std::min(stat.minRetransPerKByte, val);
              ++stat.cntRetransPerKByte;
            }
            auto reqStats = pdstn.getRequestStats();
            stat.pendingRequestsCount += reqStats.numPending;
            stat.inflightRequestsCount += reqStats.numInflight;
          });
    }
    for (const auto& it : serverStats) {
      reply.addStat(it.first, it.second.toString());
    }
  }

  if (groups & suspect_server_stats) {
    auto suspectServers = proxy->router().tkoTrackerMap().getSuspectServers();
    for (const auto& it : suspectServers) {
      reply.addStat(
          it.first,
          folly::format(
              "status:{} num_failures:{}",
              it.second.first ? "tko" : "down",
              it.second.second)
              .str());
    }
  }

  if (groups & external_stats) {
    const auto externalStats =
        proxy->router().externalStatsHandler().getStats();
    for (const auto& kv : externalStats) {
      reply.addStat(kv.first, kv.second);
    }
  }

  return reply.getReply();
}