Skip to content

Commit

Permalink
Report type now configurable, closes bmatheny#11
Browse files Browse the repository at this point in the history
  • Loading branch information
bmatheny committed Apr 25, 2013
1 parent 913b1a2 commit 6acec02
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 26 deletions.
2 changes: 1 addition & 1 deletion NOTICE
@@ -1,4 +1,4 @@
Copyright 2013 Blake Matheny.
Copyright 2013 Tumblr

Licensed 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

Expand Down
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -15,6 +15,7 @@ This is on a machine saturating a 1Gb network link.
-p, --port=PORT Network port to capture memcache traffic on (default 11211)
-r, --refresh=INTERVAL Refresh the stats display every INTERVAL ms (default 500)
-l, --logfile=FILE Output logs to FILE
-R, --report=REPORT Output data in REPORT format (CSV or curses, default curses)

-h, --help This help
-v, --verbose Increase verbosity. May be used multiple times.
Expand Down Expand Up @@ -51,8 +52,8 @@ memkeys was developed on CentOS 5.8 with the following software tools:
GNU gmake : 3.81
ld : 2.17.50.0.6-20
coreutils : 5.97
libtool : 1.5.22
autoconf : 2.61
libtool : 2.4.2
autoconf : 2.68
automake : 1.9.6

The following library versions were used:
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
@@ -1,5 +1,5 @@
# Initialize autoconf
AC_PREREQ([2.59])
AC_PREREQ([2.68])
AC_INIT([memkeys], [0.1], [bmatheny@mobocracy.net])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_AUX_DIR([config])
Expand Down
8 changes: 7 additions & 1 deletion src/Makefile.am
Expand Up @@ -16,6 +16,11 @@ AM_CFLAGS += -O2
AM_CXXFLAGS += -O2
endif

if DEVELOPMENT
AM_CFLAGS += -Wextra
AM_CXXFLAGS += -Wextra
endif

bin_PROGRAMS = memkeys

memkeys_SOURCES = \
Expand All @@ -36,8 +41,9 @@ memkeys_SOURCES = \
net/pcap.h net/pcap.cpp \
net/packet.h net/packet.cpp \
net/pcap_live.h net/pcap_live.cpp \
report/report_type.h report/report_type.cpp \
report/report.h report/report.cpp \
report/text.h report/text.cpp \
report/csv.h report/csv.cpp \
report/curses.h report/curses.cpp \
net/memcache_command.h net/memcache_command.cpp \
net/capture_engine.h net/capture_engine.cpp \
Expand Down
9 changes: 7 additions & 2 deletions src/cli.cpp
Expand Up @@ -17,9 +17,10 @@ static const struct option longopts[] = {
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"logfile", required_argument, 0, 'l'}
{"logfile", required_argument, 0, 'l'},
{"report", required_argument, 0, 'R'}
};
static const char * argp = "d:i:l:p:r:hvV";
static const char * argp = "d:i:l:p:r:R:hvV";

using namespace std;

Expand All @@ -34,6 +35,7 @@ string Cli::help(const char * progname)
txt << mkHelpDoc(longopts[2], "Network port to capture memcache traffic on (default 11211)", "PORT");
txt << mkHelpDoc(longopts[3], "Refresh the stats display every INTERVAL ms (default 500)", "INTERVAL");
txt << mkHelpDoc(longopts[7], "Output logs to FILE", "FILE");
txt << mkHelpDoc(longopts[8], "Output data in REPORT format (CSV or curses, default curses)", "REPORT");
txt << endl;
txt << mkHelpDoc(longopts[4], "This help", "");
txt << mkHelpDoc(longopts[5], "Increase verbosity. May be used multiple times.", "");
Expand Down Expand Up @@ -69,6 +71,9 @@ void Cli::parse(int argc, char ** argv, Config * cfg)
case 'r':
cfg->setRefreshInterval(::atoi(optarg));
break;
case 'R':
cfg->setReportType(optarg);
break;
case 'h':
cout << Cli::help(progname);
exit(EXIT_SUCCESS);
Expand Down
8 changes: 4 additions & 4 deletions src/common.h
Expand Up @@ -35,12 +35,12 @@
#include <stdexcept>
#include <string>

#include "util/util.h"
#include "logging/logging.h"
#include "config.h"

// Need for typecasting in to_string for older versions of g++
typedef long long unsigned int llui_t;
typedef long long int llsi_t;

#include "util/util.h"
#include "logging/logging.h"
#include "config.h"

#endif
13 changes: 12 additions & 1 deletion src/config.cpp
Expand Up @@ -97,6 +97,16 @@ uint16_t Config::getRefreshInterval() const
return refreshInterval;
}

/**
* Which report should be used by default?
*/
void Config::setReportType(const std::string &value) {
reportType = ReportType::fromString(value);
}
ReportType Config::getReportType() const {
return reportType;
}

/**
* Manage how verbose we get.
*/
Expand Down Expand Up @@ -157,7 +167,8 @@ Config::Config()
refreshInterval(500),
_snapLength(1518),
logger(Logger::getLogger("config")),
logfile()
logfile(),
reportType(ReportType::NCURSES)
{}

void Config::adjustLoggerLevel(const Level &newLevel)
Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Expand Up @@ -3,6 +3,7 @@

#include <string>
#include "logging/logger.h"
#include "report/report_type.h"

namespace mckeys {

Expand Down Expand Up @@ -31,6 +32,9 @@ class Config
void setRefreshInterval(const int interval);
uint16_t getRefreshInterval() const;

void setReportType(const std::string &value);
ReportType getReportType() const;

int getSnapLength() const
{ return _snapLength; }

Expand All @@ -56,6 +60,7 @@ class Config
int _snapLength;
LoggerPtr logger;
std::string logfile;
ReportType reportType;
};

} // end namespace
Expand Down
3 changes: 1 addition & 2 deletions src/net/capture_engine.cpp
Expand Up @@ -2,7 +2,6 @@
#include "net/net.h"
#include "report/report.h"
#include "report/curses.h"
#include "report/text.h"

#include <vector>

Expand All @@ -16,7 +15,7 @@ CaptureEngine::CaptureEngine(const Config * config, const Pcap * session)
session(session),
barrier(new mqueue<Elem>()),
stats(new Stats(config, barrier)),
report(new CursesReport(config, session, stats)), // FIXME this should be configurable
report(config->getReportType().makeReport(config, session, stats)),
_is_terminated(false),
barrier_lock()
{
Expand Down
17 changes: 9 additions & 8 deletions src/report/text.cpp → src/report/csv.cpp
@@ -1,16 +1,16 @@
#include "common.h"
#include "report/text.h"
#include "report/csv.h"

namespace mckeys {

using namespace std;

TextReport::TextReport(const Config* cfg, Stats* stats)
: Report(cfg, Logger::getLogger("textReport")),
CsvReport::CsvReport(const Config* cfg, const Pcap* session, Stats* stats)
: Report(cfg, Logger::getLogger("csvReport")),
stats(stats)
{
if (state.checkAndSet(state_NEW, state_STARTING)) {
report_thread = thread(&TextReport::render, this);
report_thread = thread(&CsvReport::render, this);
} else {
logger->warning(CONTEXT, "Incorrect API usage");
}
Expand All @@ -20,17 +20,18 @@ static void printHeader() {
cout << "key,count,elapsed,rate,size,bandwidth" << endl;
}

void TextReport::render()
void CsvReport::render()
{
static bool first = false;
struct timespec ts = UtilTime::millisToTimespec(config->getRefreshInterval());

if (!state.checkAndSet(state_STARTING, state_RUNNING)) {
logger->error(CONTEXT, "render already started");
return;
}

while(state.isRunning()) {
deque<Stat> q = stats->getLeaders<SortByCount>();
deque<Stat> q = stats->getLeaders(mode_REQRATE, sort_DESC);
uint32_t qsize = q.size();
logger->debug(CONTEXT, "Rendering report with %u data points", qsize);
if (qsize > 0) {
Expand All @@ -42,11 +43,11 @@ void TextReport::render()
}
renderStats(q);
}
sleep(5);
nanosleep(&ts, NULL);
}
}

void TextReport::renderStats(deque<Stat> q) {
void CsvReport::renderStats(deque<Stat> q) {
for (deque<Stat>::iterator it = q.begin(); it != q.end(); ++it) {
Stat stat = *it;
cout << stat.getKey() << ",";
Expand Down
9 changes: 5 additions & 4 deletions src/report/text.h → src/report/csv.h
@@ -1,16 +1,17 @@
#ifndef _REPORT_TEXT_H
#define _REPORT_TEXT_H
#ifndef _REPORT_CSV_H
#define _REPORT_CSV_H

#include "config.h"
#include "net/pcap.h"
#include "report/report.h"
#include "util/stats.h"

namespace mckeys {

class TextReport : public Report
class CsvReport : public Report
{
public:
TextReport(const Config* cfg, Stats* stats);
CsvReport(const Config* cfg, const Pcap* session, Stats* stats);
virtual void render();

protected:
Expand Down
53 changes: 53 additions & 0 deletions src/report/report_type.cpp
@@ -0,0 +1,53 @@
#include <stdexcept>

#include "common.h"
#include "report/report_type.h"
#include "report/csv.h"
#include "report/curses.h"

namespace mckeys {

using namespace std;

// protected constructor
ReportType::ReportType(const string &name) : name(name)
{}

// static values
ReportType ReportType::CSV = ReportType("CSV");
ReportType ReportType::NCURSES = ReportType("CURSES");

// static methods
ReportType ReportType::fromString(const string &name) {
string reportName = "";
for (uint32_t i = 0; i < name.length(); i++) {
reportName += toupper(name.at(i));
}
if (reportName == "CURSES") {
return ReportType::NCURSES;
} else if (reportName == "CSV") {
return ReportType::CSV;
} else {
throw range_error("No such report type with name " + name);
}
}

// public methods
string ReportType::getName() const {
return name;
}
bool ReportType::operator==(const ReportType &other) const {
return (getName() == other.getName());
}

Report* ReportType::makeReport(const Config* cfg, const Pcap* sess, Stats* stats) {
if (cfg->getReportType() == ReportType::NCURSES) {
return new CursesReport(cfg, sess, stats);
} else if (cfg->getReportType() == ReportType::CSV) {
return new CsvReport(cfg, sess, stats);
} else {
throw range_error("Unsupported report type " + cfg->getReportType().getName());
}
}

} // end namespace
35 changes: 35 additions & 0 deletions src/report/report_type.h
@@ -0,0 +1,35 @@
#ifndef _REPORT_REPORT_TYPE_H
#define _REPORT_REPORT_TYPE_H

#include <string>

namespace mckeys {

// forward declarations because shit we have some recursive dependencies
class Config;
class Pcap;
class Stats;
class Report;

class ReportType
{
public:
static ReportType NCURSES;
static ReportType CSV;

static ReportType fromString(const std::string &name);

Report* makeReport(const Config* cfg, const Pcap* sess, Stats* stats);
std::string getName() const;

bool operator==(const ReportType &other) const;

protected:
std::string name;
ReportType(const std::string &name);

};

} // end namespace

#endif

0 comments on commit 6acec02

Please sign in to comment.